From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from va-1-17.ptr.blmpb.com (va-1-17.ptr.blmpb.com [209.127.230.17]) by sourceware.org (Postfix) with ESMTPS id 444A43858428 for ; Tue, 5 Mar 2024 09:52:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 444A43858428 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 444A43858428 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.127.230.17 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709632327; cv=none; b=L8Zq0uw2GrshCj0Umlj2Ct5PVq9P48uX3kP7TcXKJBj8RJnyxinUWInMxjj9EaIdzCOP9aLKwWpErC0VIfnoVZq4gNdeqa2QLUoHfDLw7C4ZfC1+aCZRAwvhKDTTSoWpAhb739iqUKVGaphV8ZX8NN8WUpmYiYOSPz8ZYOvkf9w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1709632327; c=relaxed/simple; bh=QgjxaVMsln5PpqyUakuyv6SlivHY3Qono3xOfsQUFPI=; h=DKIM-Signature:To:From:Message-Id:Mime-Version:Subject:Date; b=W8ICro6PPbnufoZDsb3aUt5b/d8cb0C9lpEqOy79InyuJf5BWvYWOM/s59exTr5L3QRkJBbTjrx9PYy+asHHtmYfngo7Mqj8o/7zLhGBNP5FX2+BiLpbJcPukRAreRgZ95lHYdd2PKD2c/bC2PGc8xfAuVtvhU5GHmcLF3Lznjk= 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=1709632315; h=from:subject:mime-version:from:date:message-id:subject:to:cc: reply-to:content-type:mime-version:in-reply-to:message-id; bh=qdmbziX7jRtI/VLEIfCFr1rbiBgaun0R4Fls2eWssTU=; b=oKW+VMMP+giln/WPirhzOSq5Sa0xYm6t6BekYF8DQ0vLszGovuj9S57mmTRIE/IigV/ose WSRELuyG8kKUzvyZtnoiGGdRneIPA4UAavOkX+61ugz93qzhMInIZ7b9aRZfRkRioYsyOu N4a69JW+MywVk+A5H+wvWxjMw1U6PMSpUjPRDVoHLM+hI0Qz/ECYdJOM/kkMqK8CTw4anC 5emLk93ooNP1vtaL1bGZtGGyipRbzZclMGnVNZd0/s/Kj0ConlbOgoBxh0BBZmthSpkqJx II4amgzCAtoL5aWl/GYo5ytJM0XreovL6j70zXxPrHPSNhjX6M7KK0m3M3B9og== To: From: "Ying Huang" Message-Id: <20240305095122.889077-6-ying.huang@oss.cipunited.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.39.2 Cc: "Ying Huang" X-Original-From: Ying Huang Content-Type: text/plain; charset=UTF-8 Subject: [PATCH v3 5/6] stack: Fix stack unwind failure on mips Date: Tue, 5 Mar 2024 17:51:21 +0800 Received: from localhost.localdomain ([123.161.203.50]) by smtp.feishu.cn with ESMTPS; Tue, 05 Mar 2024 17:51:53 +0800 Content-Transfer-Encoding: 7bit X-Lms-Return-Path: X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,GIT_PATCH_0,KAM_SHORT,MSGID_FROM_MTA_HEADER,NO_DNS_FOR_FROM,SPF_HELO_NONE,SPF_NONE,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 List-Id: From: Ying Huang Add abi_cfi, set_initial_registers_tid, unwind on mips. Signed-off-by: Ying Huang --- 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..60cf8111 --- /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) 2024 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 521e6e51..1a2456b1 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..21e7dedb --- /dev/null +++ b/backends/mips_initreg.c @@ -0,0 +1,61 @@ +/* Fetch live process registers from TID. + Copyright (C) 2024 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..9acf87a7 --- /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) 2024 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; +} -- 2.39.2