Received: by 2002:a05:7412:da14:b0:e2:908c:2ebd with SMTP id fe20csp1878900rdb; Mon, 9 Oct 2023 06:04:24 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEAMgx3YbmFz4DZVeTqhSpcqPdZkKFFGJ0MJBiLxCs09VfvKiAWILP0yoeM7xWVCUotR01M X-Received: by 2002:a05:6a20:5496:b0:133:8784:15f7 with SMTP id i22-20020a056a20549600b00133878415f7mr15971089pzk.14.1696856664287; Mon, 09 Oct 2023 06:04:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696856664; cv=none; d=google.com; s=arc-20160816; b=mymDwyWZ6rcq4rNJk4raObaXjLf9C8TvzCR70Ey87j2/o7k0L77yUDRlraOr9mDTtx 9Y2mMLrpzneTI5McJPQLoKRYNmvr1rKQgVPYHyNM1zClK2K4dD/1FNLGfyN/6MHbmKtV 2CD+rUBPsFQzOJMx3pH6SSHeHbF+BBmkUydagWOVMmk2iJKB+tfhsooh1bNo/wQnefJ4 PwLAV31ECLG5k5kNz4/iTxTh6OnqjDTj4vNmDDvegVUl3rFGoAJw+TKp8fpY7GafqiFw 4L8HWm58JIQKwJiTLwqpRPi9hchqjp0Fd+nJC4jtKsyLqYAO4FiSBQXqc2KkMzeWC4M+ RBtQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=O/EZI7Fnq2ATwR12pAmTAUFflUC9JLtEfgFddQm7M9U=; fh=3j/20F2LKXrdRGvNzW5us/B/H+CmIg1AkSVATQRCgiM=; b=ixhlL7iLX2SBfVu0aopyyhS2BJVgCZRzxSF7M0Weju/J1+N+R7sXBgXomy7UexOXsc wABAv88Dg8u2yNqSFdPsCQ5laU8JPeqLjculQ6flyBSvv/5b8kROuQg3wTNs1whrkS1h ttiTxBmODNtwGuFx0eTF+FzHcladnevGaGPz1eb/bCbJQC8ZaGoQQLxerVbpj1iDE4LB hn+hskzxqn2GaP1a2SOGmvSqDl0yNrebQ2GzGPEBfSTNoSkIxNuO4cyQLcsvi1zVy6hH W0/nYqgtRPlF6XV29osPbEfswiAhNhRrkfDEucDElkwYULCdbq2vgfBFlr8f9dTM5obi Y21w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from agentk.vger.email (agentk.vger.email. [2620:137:e000::3:2]) by mx.google.com with ESMTPS id t8-20020a6564c8000000b00578d6a88716si9119264pgv.3.2023.10.09.06.04.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Oct 2023 06:04:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) client-ip=2620:137:e000::3:2; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by agentk.vger.email (Postfix) with ESMTP id 6D40C80BEB20; Mon, 9 Oct 2023 06:04:20 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at agentk.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1376677AbjJIND0 (ORCPT + 99 others); Mon, 9 Oct 2023 09:03:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53684 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1376636AbjJINDU (ORCPT ); Mon, 9 Oct 2023 09:03:20 -0400 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DB97CAB for ; Mon, 9 Oct 2023 06:03:17 -0700 (PDT) Received: from loongson.cn (unknown [113.200.148.30]) by gateway (Coremail) with SMTP id _____8DxFegU+iNlLE4wAA--.33988S3; Mon, 09 Oct 2023 21:03:16 +0800 (CST) Received: from linux.localdomain (unknown [113.200.148.30]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Cxzt4P+iNlksscAA--.62948S6; Mon, 09 Oct 2023 21:03:15 +0800 (CST) From: Tiezhu Yang To: Josh Poimboeuf , Peter Zijlstra , Huacai Chen Cc: loongarch@lists.linux.dev, linux-kernel@vger.kernel.org, loongson-kernel@lists.loongnix.cn Subject: [PATCH v2 4/8] objtool/LoongArch: Enable orc to be built Date: Mon, 9 Oct 2023 21:03:06 +0800 Message-Id: <1696856590-30298-5-git-send-email-yangtiezhu@loongson.cn> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1696856590-30298-1-git-send-email-yangtiezhu@loongson.cn> References: <1696856590-30298-1-git-send-email-yangtiezhu@loongson.cn> X-CM-TRANSID: AQAAf8Cxzt4P+iNlksscAA--.62948S6 X-CM-SenderInfo: p1dqw3xlh2x3gn0dqz5rrqw2lrqou0/ X-Coremail-Antispam: 1Uk129KBj93XoWxuw1ruF1UXryfuw1kKw47Jrc_yoW3Zw15pF 1UCrZrJr47XF1fAw1xKa1fWrW5Kws7Ww1vvrnxu34jv3yIqw1rJrs7KryqqF9rWws3W3y7 uF4agF109a1DZabCm3ZEXasCq-sJn29KB7ZKAUJUUUU7529EdanIXcx71UUUUU7KY7ZEXa sCq-sGcSsGvfJ3Ic02F40EFcxC0VAKzVAqx4xG6I80ebIjqfuFe4nvWSU5nxnvy29KBjDU 0xBIdaVrnRJUUUBIb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I20VC2zVCF04k26cxKx2 IYs7xG6rWj6s0DM7CIcVAFz4kK6r1Y6r17M28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48v e4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI 0_Gr0_Cr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVW8Jr0_Cr1UM2kKe7AKxVWUXVWUAwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07 AIYIkI8VC2zVCFFI0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWU tVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7V AKI48JMxkF7I0En4kS14v26r126r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY 6r1j6r4UMxCIbckI1I0E14v26r1Y6r17MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7 xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42IY6xII jxv20xvE14v26ryj6F1UMIIF0xvE2Ix0cI8IcVCY1x0267AKxVW8JVWxJwCI42IY6xAIw2 0EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x02 67AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7IU0epB3UUUUU== X-Spam-Status: No, score=2.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_SBL_CSS,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on agentk.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (agentk.vger.email [0.0.0.0]); Mon, 09 Oct 2023 06:04:20 -0700 (PDT) X-Spam-Level: ** Implement arch-specific init_orc_entry(), reg_name(), orc_type_name(), print_reg() and orc_print_dump(), then set BUILD_ORC as y to build the orc related files. Co-developed-by: Jinyang He Signed-off-by: Jinyang He Co-developed-by: Youling Tang Signed-off-by: Youling Tang Signed-off-by: Tiezhu Yang --- tools/arch/loongarch/include/asm/orc_types.h | 58 ++++++++++ tools/objtool/Makefile | 4 + tools/objtool/arch/loongarch/Build | 1 + tools/objtool/arch/loongarch/decode.c | 16 +++ tools/objtool/arch/loongarch/orc.c | 155 +++++++++++++++++++++++++++ 5 files changed, 234 insertions(+) create mode 100644 tools/arch/loongarch/include/asm/orc_types.h create mode 100644 tools/objtool/arch/loongarch/orc.c diff --git a/tools/arch/loongarch/include/asm/orc_types.h b/tools/arch/loongarch/include/asm/orc_types.h new file mode 100644 index 0000000..1d37e62 --- /dev/null +++ b/tools/arch/loongarch/include/asm/orc_types.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _ORC_TYPES_H +#define _ORC_TYPES_H + +#include + +/* + * The ORC_REG_* registers are base registers which are used to find other + * registers on the stack. + * + * ORC_REG_PREV_SP, also known as DWARF Call Frame Address (CFA), is the + * address of the previous frame: the caller's SP before it called the current + * function. + * + * ORC_REG_UNDEFINED means the corresponding register's value didn't change in + * the current frame. + * + * The most commonly used base registers are SP and BP -- which the previous SP + * is usually based on -- and PREV_SP and UNDEFINED -- which the previous BP is + * usually based on. + * + * The rest of the base registers are needed for special cases like entry code + * and GCC realigned stacks. + */ +#define ORC_REG_UNDEFINED 0 +#define ORC_REG_PREV_SP 1 +#define ORC_REG_SP 2 +#define ORC_REG_BP 3 +#define ORC_REG_MAX 4 + +#define ORC_TYPE_UNDEFINED 0 +#define ORC_TYPE_END_OF_STACK 1 +#define ORC_TYPE_CALL 2 +#define ORC_TYPE_REGS 3 +#define ORC_TYPE_REGS_PARTIAL 4 + +#ifndef __ASSEMBLY__ +/* + * This struct is more or less a vastly simplified version of the DWARF Call + * Frame Information standard. It contains only the necessary parts of DWARF + * CFI, simplified for ease of access by the in-kernel unwinder. It tells the + * unwinder how to find the previous SP and BP (and sometimes entry regs) on + * the stack for a given code address. Each instance of the struct corresponds + * to one or more code locations. + */ +struct orc_entry { + s16 sp_offset; + s16 bp_offset; + s16 ra_offset; + unsigned int sp_reg:4; + unsigned int bp_reg:4; + unsigned int ra_reg:4; + unsigned int type:3; + unsigned int signal:1; +}; +#endif /* __ASSEMBLY__ */ + +#endif /* _ORC_TYPES_H */ diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index 83b100c..bf7f7f8 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -57,6 +57,10 @@ ifeq ($(SRCARCH),x86) BUILD_ORC := y endif +ifeq ($(SRCARCH),loongarch) + BUILD_ORC := y +endif + export BUILD_ORC export srctree OUTPUT CFLAGS SRCARCH AWK include $(srctree)/tools/build/Makefile.include diff --git a/tools/objtool/arch/loongarch/Build b/tools/objtool/arch/loongarch/Build index d24d563..1d4b784 100644 --- a/tools/objtool/arch/loongarch/Build +++ b/tools/objtool/arch/loongarch/Build @@ -1,2 +1,3 @@ objtool-y += decode.o objtool-y += special.o +objtool-y += orc.o diff --git a/tools/objtool/arch/loongarch/decode.c b/tools/objtool/arch/loongarch/decode.c index 3a426e4..1c96759 100644 --- a/tools/objtool/arch/loongarch/decode.c +++ b/tools/objtool/arch/loongarch/decode.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include int arch_ftrace_match(char *name) { @@ -38,6 +40,20 @@ bool arch_callee_saved_reg(unsigned char reg) int arch_decode_hint_reg(u8 sp_reg, int *base) { + switch (sp_reg) { + case ORC_REG_UNDEFINED: + *base = CFI_UNDEFINED; + break; + case ORC_REG_SP: + *base = CFI_SP; + break; + case ORC_REG_BP: + *base = CFI_FP; + break; + default: + return -1; + } + return 0; } diff --git a/tools/objtool/arch/loongarch/orc.c b/tools/objtool/arch/loongarch/orc.c new file mode 100644 index 0000000..7d7ecee --- /dev/null +++ b/tools/objtool/arch/loongarch/orc.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include + +#include +#include +#include +#include + +int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi, struct instruction *insn) +{ + struct cfi_reg *bp = &cfi->regs[CFI_BP]; + struct cfi_reg *ra = &cfi->regs[CFI_RA]; + + memset(orc, 0, sizeof(*orc)); + + if (!cfi) { + /* + * This is usually either unreachable nops/traps (which don't + * trigger unreachable instruction warnings), or + * STACK_FRAME_NON_STANDARD functions. + */ + orc->type = ORC_TYPE_UNDEFINED; + return 0; + } + + switch (cfi->type) { + case UNWIND_HINT_TYPE_UNDEFINED: + orc->type = ORC_TYPE_UNDEFINED; + return 0; + case UNWIND_HINT_TYPE_END_OF_STACK: + orc->type = ORC_TYPE_END_OF_STACK; + return 0; + case UNWIND_HINT_TYPE_CALL: + orc->type = ORC_TYPE_CALL; + break; + case UNWIND_HINT_TYPE_REGS: + orc->type = ORC_TYPE_REGS; + break; + case UNWIND_HINT_TYPE_REGS_PARTIAL: + orc->type = ORC_TYPE_REGS_PARTIAL; + break; + default: + WARN_INSN(insn, "unknown unwind hint type %d", cfi->type); + return -1; + } + + orc->signal = cfi->signal; + + switch (cfi->cfa.base) { + case CFI_SP: + orc->sp_reg = ORC_REG_SP; + break; + case CFI_BP: + orc->sp_reg = ORC_REG_BP; + break; + default: + WARN_INSN(insn, "unknown CFA base reg %d", cfi->cfa.base); + return -1; + } + + switch (bp->base) { + case CFI_UNDEFINED: + orc->bp_reg = ORC_REG_UNDEFINED; + orc->bp_offset = 0; + break; + case CFI_CFA: + orc->bp_reg = ORC_REG_PREV_SP; + orc->bp_offset = bp->offset; + break; + case CFI_BP: + orc->bp_reg = ORC_REG_BP; + break; + default: + WARN_INSN(insn, "unknown BP base reg %d", bp->base); + return -1; + } + + switch (ra->base) { + case CFI_UNDEFINED: + orc->ra_reg = ORC_REG_UNDEFINED; + orc->ra_offset = 0; + break; + case CFI_CFA: + orc->ra_reg = ORC_REG_PREV_SP; + orc->ra_offset = ra->offset; + break; + case CFI_BP: + orc->ra_reg = ORC_REG_BP; + break; + default: + WARN_INSN(insn, "unknown RA base reg %d", ra->base); + return -1; + } + + orc->sp_offset = cfi->cfa.offset; + + return 0; +} + +static const char *reg_name(unsigned int reg) +{ + switch (reg) { + case ORC_REG_SP: + return "sp"; + case ORC_REG_BP: + return "fp"; + case ORC_REG_PREV_SP: + return "prevsp"; + default: + return "?"; + } +} + +static const char *orc_type_name(unsigned int type) +{ + switch (type) { + case UNWIND_HINT_TYPE_CALL: + return "call"; + case UNWIND_HINT_TYPE_REGS: + return "regs"; + case UNWIND_HINT_TYPE_REGS_PARTIAL: + return "regs (partial)"; + default: + return "?"; + } +} + +static void print_reg(unsigned int reg, int offset) +{ + if (reg == ORC_REG_UNDEFINED) + printf(" (und) "); + else + printf("%s + %3d", reg_name(reg), offset); + +} + +void orc_print_dump(struct elf *dummy_elf, struct orc_entry *orc, int i) +{ + printf("type:%s", orc_type_name(orc[i].type)); + + printf(" sp:"); + + print_reg(orc[i].sp_reg, bswap_if_needed(dummy_elf, orc[i].sp_offset)); + + printf(" bp:"); + + print_reg(orc[i].bp_reg, bswap_if_needed(dummy_elf, orc[i].bp_offset)); + + printf(" ra:"); + + print_reg(orc[i].ra_reg, bswap_if_needed(dummy_elf, orc[i].ra_offset)); + + printf(" signal:%d\n", orc[i].signal); +} -- 2.1.0