From patchwork Thu Nov 2 06:56:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying Huang X-Patchwork-Id: 78906 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 373F2385802F for ; Thu, 2 Nov 2023 06:56:38 +0000 (GMT) X-Original-To: elfutils-devel@sourceware.org Delivered-To: elfutils-devel@sourceware.org Received: from s01.bc.larksuite.com (s01.bc.larksuite.com [209.127.230.19]) by sourceware.org (Postfix) with UTF8SMTPS id 8AC383858D38 for ; Thu, 2 Nov 2023 06:56:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8AC383858D38 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=oss.cipunited.com Authentication-Results: sourceware.org; spf=none smtp.mailfrom=oss.cipunited.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 8AC383858D38 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.127.230.19 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698908191; cv=none; b=oI49m+ZEg1XOWdp0ehDcNrcHJoj/U5eulj1qvN1V2ycDh9g9zpRFfHJe73leaqvf5a71yoWfWeyykaqkPhxX3X83jGfWCDy1J9bOTqemKG2CUrnXGunK9Ut6yfuap4IO6mJszpQ36pr1ns8AnbZR/GnTGAx3OMOiWlhbWr9nyYg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698908191; c=relaxed/simple; bh=4bbnowXrxsa8aq8Hpw+HcsXjMMcd3S69Gy0WBAJ3SkU=; h=DKIM-Signature:Subject:Mime-Version:To:From:Message-Id:Date; b=NWbzW4ggey3JUxHlA5QsG6ZKV3eb5P+xcgcIVSFE5mBKrbdFxh9iuupdu7b+B9z6MZowsiGUQzGvfRSsjkL0o3wTirB7B2ndFwJ0AroUMf91rSQgdJZ+YendXaS/UQX3hyUz8GHK8byje8LHDhhccbBC2cPmgEJOROfCUjX8dvg= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=feishu2303200042; d=oss.cipunited.com; t=1698908184; h=from:subject:mime-version:from:date:message-id:subject:to:cc: reply-to:content-type:mime-version:in-reply-to:message-id; bh=LC3dDq8NPKFLqNLzi+J1ZoiPl+9sPdSQFYUEMNLZDzY=; b=1DwxUZh8nMJYO4PzSRpilwKVOuF+q+oi6mVMCylzojDvY1cRr6dH2EWdG8kEp2rPxQdAvR 1nfl88txdxjQUxBNiZdOKuGZYc6KN2p6QangN45wY5n6W33+lSm/yne90utqox7ABPP2vP vwh9L8S4wpwZjH3z50MQq0Fnyhcz1l7bUHKg2IHi4lzz7n/fMOqByF3YYlg+NzivomOBTG JuQTnUqWrnRxC2rfg6T2GElc13rADJsaElkLOdyFnI9LuEnsTcXcd0f8M5VYW8B8W3N2Lr OlW9MeV1Eyi/w+gi+MYO/FszShUB9tS1Yu5VAkY/j2BDPPA/7adnmeCzXiajTA== Subject: [PATCH v2 4/5] stack: Fix stack unwind failure on mips Mime-Version: 1.0 In-Reply-To: <20231102065602.3128526-1-ying.huang@oss.cipunited.com> To: References: <20231102065602.3128526-1-ying.huang@oss.cipunited.com> X-Lms-Return-Path: Cc: , "Ying Huang" From: "Ying Huang" Message-Id: <20231102065602.3128526-5-ying.huang@oss.cipunited.com> X-Mailer: git-send-email 2.30.2 Date: Thu, 2 Nov 2023 14:56:01 +0800 X-Original-From: Ying Huang X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: elfutils-devel@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Elfutils-devel mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: elfutils-devel-bounces+patchwork=sourceware.org@sourceware.org From: Ying Huang Add abi_cfi, set_initial_registers_tid, unwind on mips. --- backends/Makefile.am | 3 +- backends/mips_cfi.c | 68 +++++++++++++++++++++++++++++++++ backends/mips_init.c | 4 ++ backends/mips_initreg.c | 61 ++++++++++++++++++++++++++++++ backends/mips_unwind.c | 84 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 backends/mips_cfi.c create mode 100644 backends/mips_initreg.c create mode 100644 backends/mips_unwind.c diff --git a/backends/Makefile.am b/backends/Makefile.am index ad95526e..5e7b7f21 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -102,7 +102,8 @@ loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \ arc_SRCS = arc_init.c arc_symbol.c -mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c +mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ + mips_cfi.c mips_unwind.c libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ diff --git a/backends/mips_cfi.c b/backends/mips_cfi.c new file mode 100644 index 00000000..64cee1a9 --- /dev/null +++ b/backends/mips_cfi.c @@ -0,0 +1,68 @@ +/* MIPS ABI-specified defaults for DWARF CFI. + Copyright (C) 2009 Red Hat, Inc. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#define BACKEND mips_ +#include "libebl_CPU.h" + +int +mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) +{ + static const uint8_t abi_cfi[] = + { + DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0), + /* Callee-saved regs. */ + DW_CFA_same_value, ULEB128_7 (16), /* s0 */ + DW_CFA_same_value, ULEB128_7 (17), /* s1 */ + DW_CFA_same_value, ULEB128_7 (18), /* s2 */ + DW_CFA_same_value, ULEB128_7 (19), /* s3 */ + DW_CFA_same_value, ULEB128_7 (20), /* s4 */ + DW_CFA_same_value, ULEB128_7 (21), /* s5 */ + DW_CFA_same_value, ULEB128_7 (22), /* s6 */ + DW_CFA_same_value, ULEB128_7 (23), /* s7 */ + DW_CFA_same_value, ULEB128_7 (28), /* gp */ + DW_CFA_same_value, ULEB128_7 (29), /* sp */ + DW_CFA_same_value, ULEB128_7 (30), /* fp */ + + DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0), + }; + + abi_info->initial_instructions = abi_cfi; + abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi]; + abi_info->data_alignment_factor = 8; + + abi_info->return_address_register = 31; /* %ra */ + + return 0; +} diff --git a/backends/mips_init.c b/backends/mips_init.c index e883b7e4..a6ed8a47 100644 --- a/backends/mips_init.c +++ b/backends/mips_init.c @@ -58,5 +58,9 @@ mips_init (Elf *elf __attribute__ ((unused)), HOOK (eh, check_object_attribute); HOOK (eh, check_special_symbol); HOOK (eh, check_reloc_target_type); + HOOK (eh, set_initial_registers_tid); + HOOK (eh, abi_cfi); + HOOK (eh, unwind); + eh->frame_nregs = 71; return eh; } diff --git a/backends/mips_initreg.c b/backends/mips_initreg.c new file mode 100644 index 00000000..87c879f5 --- /dev/null +++ b/backends/mips_initreg.c @@ -0,0 +1,61 @@ +/* Fetch live process registers from TID. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__) +# include +# include +#include +#endif + +#define BACKEND mips_ +#include "libebl_CPU.h" + + +bool +mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), + ebl_tid_registers_t *setfunc __attribute__ ((unused)), + void *arg __attribute__ ((unused))) +{ +#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__) + return false; +#else /* __mips__ */ +/* For PTRACE_GETREGS */ + + struct pt_regs gregs; + if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0) + return false; + if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg)) + return false; + return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg); +#endif /* __mips__ */ +} diff --git a/backends/mips_unwind.c b/backends/mips_unwind.c new file mode 100644 index 00000000..4168d4ef --- /dev/null +++ b/backends/mips_unwind.c @@ -0,0 +1,84 @@ +/* Get previous frame state for an existing frame state. + Copyright (C) 2016 The Qt Company Ltd. + Copyright (C) 2023 CIP United Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define BACKEND mips_ +#define SP_REG 29 +#define FP_REG 30 +#define LR_REG 31 +#define FP_OFFSET 0 +#define LR_OFFSET 8 +#define SP_OFFSET 16 + +#include "libebl_CPU.h" + +/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */ + +bool +EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)), + ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc, + ebl_pid_memory_read_t *readfunc, void *arg, + bool *signal_framep __attribute__ ((unused))) +{ + Dwarf_Word fp, lr, sp; + + if (!getfunc(LR_REG, 1, &lr, arg)) + return false; + + if (lr == 0 || !setfunc(-1, 1, &lr, arg)) + return false; + + if (!getfunc(FP_REG, 1, &fp, arg)) + fp = 0; + + if (!getfunc(SP_REG, 1, &sp, arg)) + sp = 0; + + Dwarf_Word newLr, newFp, newSp; + + if (!readfunc(fp + LR_OFFSET, &newLr, arg)) + newLr = 0; + + if (!readfunc(fp + FP_OFFSET, &newFp, arg)) + newFp = 0; + + newSp = fp + SP_OFFSET; + + // These are not fatal if they don't work. They will just prevent unwinding at the next frame. + setfunc(LR_REG, 1, &newLr, arg); + setfunc(FP_REG, 1, &newFp, arg); + setfunc(SP_REG, 1, &newSp, arg); + + // If the fp is invalid, we might still have a valid lr. + // But if the fp is valid, then the stack should be moving in the right direction. + return fp == 0 || newSp > sp; +}