From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D4BCBCD484C for ; Wed, 13 May 2026 03:35:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=U9MK8IcThNhi0X5Mrl5i58AxiVZzu+KeREc+YRIc/B0=; b=TJrNjMfy+yzPlaXqZynSJjsLNM /iTkl4cjcovifWWcvjoF2nodZ5AsLZPWnAnJF4p4JM93/+Qu6OIMfAya32L8gyS4siAJEyzRG4EB0 NrjqIa3pj4HKwXK/gE47SPHqcpyO56Ld6Xvp5Xft1t8LYvy6Ph3aOn0rI0MAK+ixcz9ZdCfWyo19g WHDSC/2j77UkWYHaapHYVoJ1F7+xqZfWA8wDG3lg2VahQfig4BP3oinYHsUprnfQdfmFQkirD8b/q p8ID+WYWYw8Iv48dPobWgAM53qXgYDc8GPCNSpA6g7E+Jy3HmgC4sXf+3HobjHIxGqSEkO8wD9oyj /SJ7nWjw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wN0NU-000000014eA-1jU3; Wed, 13 May 2026 03:35:22 +0000 Received: from tor.source.kernel.org ([172.105.4.254]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wN0Ms-000000013p5-3qa0 for linux-arm-kernel@lists.infradead.org; Wed, 13 May 2026 03:34:43 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 5F47F6014B; Wed, 13 May 2026 03:34:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 93600C2BD05; Wed, 13 May 2026 03:34:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778643282; bh=htHqB9fjsGibk8/Z1/tD3h7Th9hfmcAsTtcWLppiK1Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=q4HXYBQfDbsS3xc4rWOUDVob/S753MbJPQSsyHoZ4EOjjBpG/IzSukXz1Zj408rjL 2BeqM97CC8XfbQNqidurYnTbH1K43YJZc/MmjUEHSj/AHJqYbSHvg/Khptr4jjurIf CD7Fw/Ds9bOq3ilEsrUIEZB8ECU3Fr46B4iheY+Q+x85oCYc3onOrLMfdwPk4/5Ps+ b3vru/f/s9BJCKF/4JiW6RK/BQakv0z9nweJ7LH5M1Z69nTrqTGrw7cOCYf05Zdrcr Ak46d8O2T3uC0ZIA66NIUedvx2q/J3CzdBlfS7mnBhHAH19r/R+JGPe0LJtV/ILZHg klRDxwAkq78lg== From: Josh Poimboeuf To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, Peter Zijlstra , Joe Lawrence , Song Liu , Catalin Marinas , Will Deacon , linux-arm-kernel@lists.infradead.org, Mark Rutland , Miroslav Benes , Petr Mladek Subject: [PATCH v3 19/21] objtool/klp: Introduce objtool for arm64 Date: Tue, 12 May 2026 20:33:53 -0700 Message-ID: <5b66146373b1ff1aba1318fd51867dea2eb882f6.1778642121.git.jpoimboe@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add basic support for arm64 on objtool. Only "objtool klp" subcommands are currently supported. Signed-off-by: Josh Poimboeuf --- arch/arm64/Kconfig | 2 + tools/objtool/Makefile | 4 + tools/objtool/arch/arm64/Build | 2 + tools/objtool/arch/arm64/decode.c | 177 ++++++++++++++++++ .../arch/arm64/include/arch/cfi_regs.h | 11 ++ tools/objtool/arch/arm64/include/arch/elf.h | 15 ++ .../objtool/arch/arm64/include/arch/special.h | 21 +++ tools/objtool/arch/arm64/special.c | 21 +++ 8 files changed, 253 insertions(+) create mode 100644 tools/objtool/arch/arm64/Build create mode 100644 tools/objtool/arch/arm64/decode.c create mode 100644 tools/objtool/arch/arm64/include/arch/cfi_regs.h create mode 100644 tools/objtool/arch/arm64/include/arch/elf.h create mode 100644 tools/objtool/arch/arm64/include/arch/special.h create mode 100644 tools/objtool/arch/arm64/special.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index fe60738e5943b..101080fd4f99e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -210,9 +210,11 @@ config ARM64 select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_IOREMAP_PROT select HAVE_IRQ_TIME_ACCOUNTING + select HAVE_KLP_BUILD select HAVE_LIVEPATCH select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI + select HAVE_OBJTOOL select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS_NMI if ARM64_PSEUDO_NMI select HAVE_PERF_REGS diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index a4484fd22a96d..94aabeee97367 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -11,6 +11,10 @@ ifeq ($(SRCARCH),loongarch) BUILD_ORC := y endif +ifeq ($(SRCARCH),arm64) + ARCH_HAS_KLP := y +endif + ifeq ($(ARCH_HAS_KLP),y) HAVE_XXHASH = $(shell printf "$(pound)include \nXXH3_state_t *state;int main() {}" | \ $(HOSTCC) $(HOSTCFLAGS) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n) diff --git a/tools/objtool/arch/arm64/Build b/tools/objtool/arch/arm64/Build new file mode 100644 index 0000000000000..d24d5636a5b84 --- /dev/null +++ b/tools/objtool/arch/arm64/Build @@ -0,0 +1,2 @@ +objtool-y += decode.o +objtool-y += special.o diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c new file mode 100644 index 0000000000000..47658c76e1af0 --- /dev/null +++ b/tools/objtool/arch/arm64/decode.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include + +const char *arch_reg_name[CFI_NUM_REGS] = {}; + +int arch_ftrace_match(const char *name) +{ + return 0; +} + +s64 arch_insn_adjusted_addend(struct instruction *insn, struct reloc *reloc) +{ + return reloc_addend(reloc); +} + +bool arch_callee_saved_reg(unsigned char reg) +{ + return false; +} + +int arch_decode_hint_reg(u8 sp_reg, int *base) +{ + exit(-1); +} + +const char *arch_nop_insn(int len) +{ + exit(-1); +} + +const char *arch_ret_insn(int len) +{ + exit(-1); +} + +int arch_decode_instruction(struct objtool_file *file, const struct section *sec, + unsigned long offset, unsigned int maxlen, + struct instruction *insn) +{ + u32 ins; + + if (maxlen < 4) { + ERROR_INSN(insn, "can't decode instruction"); + return -1; + } + + /* arm64 instructions are always LE, thus no bswap_if_needed() */ + ins = le32toh(*(u32 *)(sec->data->d_buf + offset)); + + /* + * These are the bare minimum needed for static branch detection and + * checksum calculations. + */ + if (ins == 0xd503201f) { + /* NOP: static branch */ + insn->type = INSN_NOP; + } else if ((ins & 0xfc000000) == 0x14000000) { + /* B: static branch, intra-TU sibling call */ + insn->type = INSN_JUMP_UNCONDITIONAL; + insn->immediate = sign_extend64(ins & 0x03ffffff, 25); + } else if ((ins & 0xfc000000) == 0x94000000) { + /* BL: intra-TU call */ + insn->type = INSN_CALL; + insn->immediate = sign_extend64(ins & 0x03ffffff, 25); + } else if ((ins & 0xff000000) == 0x54000000) { + /* B.cond: intra-TU sibling call */ + insn->type = INSN_JUMP_CONDITIONAL; + insn->immediate = sign_extend64((ins >> 5) & 0x7ffff, 18); + } else if ((ins & 0x7e000000) == 0x34000000) { + /* CBZ/CBNZ: intra-TU sibling call */ + insn->type = INSN_JUMP_CONDITIONAL; + insn->immediate = sign_extend64((ins >> 5) & 0x7ffff, 18); + } else if ((ins & 0x7e000000) == 0x36000000) { + /* TBZ/TBNZ: intra-TU sibling call */ + insn->type = INSN_JUMP_CONDITIONAL; + insn->immediate = sign_extend64((ins >> 5) & 0x3fff, 13); + } else { + insn->type = INSN_OTHER; + } + + insn->len = 4; + return 0; +} + +size_t arch_jump_opcode_bytes(struct objtool_file *file, struct instruction *insn, + unsigned char *buf) +{ + u32 ins; + + ins = le32toh(*(u32 *)(insn->sec->data->d_buf + insn->offset)); + + switch (insn->type) { + case INSN_JUMP_UNCONDITIONAL: + case INSN_CALL: + ins &= ~0x03ffffff; + break; + case INSN_JUMP_CONDITIONAL: + if ((ins & 0xff000000) == 0x54000000) + ins &= ~0x00ffffe0; /* B.cond */ + else if ((ins & 0x7e000000) == 0x34000000) + ins &= ~0x00ffffe0; /* CBZ/CBNZ */ + else + ins &= ~0x0007ffe0; /* TBZ/TBNZ */ + break; + default: + break; + } + + ins = htole32(ins); + memcpy(buf, &ins, 4); + return 4; +} + +u64 arch_adjusted_addend(struct reloc *reloc) +{ + return reloc_addend(reloc); +} + +unsigned long arch_jump_destination(struct instruction *insn) +{ + return insn->offset + (insn->immediate << 2); +} + +bool arch_pc_relative_reloc(struct reloc *reloc) +{ + switch (reloc_type(reloc)) { + case R_AARCH64_PREL64: + case R_AARCH64_PREL32: + case R_AARCH64_PREL16: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_ADR_PREL_PG_HI21_NC: + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: + case R_AARCH64_TSTBR14: + return true; + default: + return false; + } +} + +void arch_initial_func_cfi_state(struct cfi_init_state *state) +{ + state->cfa.base = CFI_UNDEFINED; +} + +unsigned int arch_reloc_size(struct reloc *reloc) +{ + switch (reloc_type(reloc)) { + case R_AARCH64_ABS64: + case R_AARCH64_PREL64: + return 8; + case R_AARCH64_PREL16: + return 2; + default: + return 4; + } +} + +#ifdef DISAS +int arch_disas_info_init(struct disassemble_info *dinfo) +{ + return disas_info_init(dinfo, bfd_arch_aarch64, + bfd_mach_arm_unknown, bfd_mach_aarch64, + NULL); +} +#endif /* DISAS */ diff --git a/tools/objtool/arch/arm64/include/arch/cfi_regs.h b/tools/objtool/arch/arm64/include/arch/cfi_regs.h new file mode 100644 index 0000000000000..49c81cbb6646d --- /dev/null +++ b/tools/objtool/arch/arm64/include/arch/cfi_regs.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _OBJTOOL_ARCH_CFI_REGS_H +#define _OBJTOOL_ARCH_CFI_REGS_H + +/* These aren't actually used for arm64 */ +#define CFI_BP 0 +#define CFI_SP 0 +#define CFI_RA 0 +#define CFI_NUM_REGS 2 + +#endif /* _OBJTOOL_ARCH_CFI_REGS_H */ diff --git a/tools/objtool/arch/arm64/include/arch/elf.h b/tools/objtool/arch/arm64/include/arch/elf.h new file mode 100644 index 0000000000000..418b90885c501 --- /dev/null +++ b/tools/objtool/arch/arm64/include/arch/elf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _OBJTOOL_ARCH_ELF_H +#define _OBJTOOL_ARCH_ELF_H + +#define R_NONE R_AARCH64_NONE +#define R_ABS64 R_AARCH64_ABS64 +#define R_ABS32 R_AARCH64_ABS32 +#define R_DATA32 R_AARCH64_PREL32 +#define R_DATA64 R_AARCH64_PREL64 +#define R_TEXT32 R_AARCH64_PREL32 +#define R_TEXT64 R_AARCH64_PREL64 + +#define ARCH_HAS_INLINE_ALTS 1 + +#endif /* _OBJTOOL_ARCH_ELF_H */ diff --git a/tools/objtool/arch/arm64/include/arch/special.h b/tools/objtool/arch/arm64/include/arch/special.h new file mode 100644 index 0000000000000..8ae804a83ea49 --- /dev/null +++ b/tools/objtool/arch/arm64/include/arch/special.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _OBJTOOL_ARCH_SPECIAL_H +#define _OBJTOOL_ARCH_SPECIAL_H + +#define EX_ENTRY_SIZE 12 +#define EX_ORIG_OFFSET 0 +#define EX_NEW_OFFSET 4 + +#define JUMP_ENTRY_SIZE 16 +#define JUMP_ORIG_OFFSET 0 +#define JUMP_NEW_OFFSET 4 +#define JUMP_KEY_OFFSET 8 + +#define ALT_ENTRY_SIZE 12 +#define ALT_ORIG_OFFSET 0 +#define ALT_NEW_OFFSET 4 +#define ALT_FEATURE_OFFSET 8 +#define ALT_ORIG_LEN_OFFSET 10 +#define ALT_NEW_LEN_OFFSET 11 + +#endif /* _OBJTOOL_ARCH_SPECIAL_H */ diff --git a/tools/objtool/arch/arm64/special.c b/tools/objtool/arch/arm64/special.c new file mode 100644 index 0000000000000..6ddecd362f3dd --- /dev/null +++ b/tools/objtool/arch/arm64/special.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include + +bool arch_support_alt_relocation(struct special_alt *special_alt, + struct instruction *insn, + struct reloc *reloc) +{ + return true; +} + +struct reloc *arch_find_switch_table(struct objtool_file *file, + struct instruction *insn, + unsigned long *table_size) +{ + return NULL; +} + +const char *arch_cpu_feature_name(int feature_number) +{ + return NULL; +} -- 2.53.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 11DF5CD484C for ; Wed, 13 May 2026 03:35:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=U9MK8IcThNhi0X5Mrl5i58AxiVZzu+KeREc+YRIc/B0=; b=VmfZe+3ak2b7t/vdAR3V1wnpLy XW4lwRYr4HTFEDX1BpvA9E+MWvp+w6h6f7g0hdTiJn+W2QyHW59DDGG0SL3Lz0h3bcdT65YxS7iKa jQF3RBgGj7KfDRNxibFKde7dijeXPXw8g3pioFwFMV/v6ggaWRc/q6V19rehKa55WKaRENR8BOmmP NvVzxBozdePMibKxlOJVfb9tCu1xcZRtlicNoO1MR6odJubMl+vgox+a4GZXRW6HHJ1ulFd3LMKa4 lAb1eJrHEMp0wHEg55cpyAogZ0svYrblI2YXtkpv0jo0Ge2tZQ3GkrWYuGdlyu+/dzVJrRlOMWmeh 7LsrIb1g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wN0Nu-000000015P5-2ugq; Wed, 13 May 2026 03:35:46 +0000 Received: from sea.source.kernel.org ([2600:3c0a:e001:78e:0:1991:8:25]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wN0N7-000000014CB-2dtP for linux-arm-kernel@lists.infradead.org; Wed, 13 May 2026 03:34:58 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 87734444F3; Wed, 13 May 2026 03:34:57 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A7F6C2BCFA; Wed, 13 May 2026 03:34:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1778643297; bh=htHqB9fjsGibk8/Z1/tD3h7Th9hfmcAsTtcWLppiK1Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QPtJ57Ss2C5oeJm5PngBvSj5BfCbp3P4yplAqZ8VoEjLZJSGSZXibJTMM/OfA7MH3 grKttNw5o5/7mZFYsP5lonZ44tZFyZjsLC32PPnktBGsVnvgBxYWfsPTtRUWLjN26a PWQMk3M4oUc7lO90sI+G1cd6PXJNumU8xsaYABLQ25QrGIEWErfxQz7whWRctsMPGn ozD5FYtkW/EKryooEDN6mdJWXb8FFDnhTnuK0HYFoo0nRtvhtzSRUl8s40dMNqcmWe arBHvnTXsm800E9L4UvHnKyadiXmLcy7VWkac0ejFNx5P4rBDvepNVQNuFbCYjyfsh ZsAoKd6Iqfnmg== From: Josh Poimboeuf To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, Peter Zijlstra , Joe Lawrence , Song Liu , Catalin Marinas , Will Deacon , linux-arm-kernel@lists.infradead.org, Mark Rutland , Miroslav Benes , Petr Mladek Subject: [PATCH v3 19/21] objtool/klp: Introduce objtool for arm64 Date: Tue, 12 May 2026 20:34:15 -0700 Message-ID: <5b66146373b1ff1aba1318fd51867dea2eb882f6.1778642121.git.jpoimboe@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260512_203457_714079_2338E50A X-CRM114-Status: GOOD ( 19.47 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Message-ID: <20260513033415.ze1wUzHIPTZijw7YtTSnT99cRYzp_IIeR_dibFK55PA@z> Add basic support for arm64 on objtool. Only "objtool klp" subcommands are currently supported. Signed-off-by: Josh Poimboeuf --- arch/arm64/Kconfig | 2 + tools/objtool/Makefile | 4 + tools/objtool/arch/arm64/Build | 2 + tools/objtool/arch/arm64/decode.c | 177 ++++++++++++++++++ .../arch/arm64/include/arch/cfi_regs.h | 11 ++ tools/objtool/arch/arm64/include/arch/elf.h | 15 ++ .../objtool/arch/arm64/include/arch/special.h | 21 +++ tools/objtool/arch/arm64/special.c | 21 +++ 8 files changed, 253 insertions(+) create mode 100644 tools/objtool/arch/arm64/Build create mode 100644 tools/objtool/arch/arm64/decode.c create mode 100644 tools/objtool/arch/arm64/include/arch/cfi_regs.h create mode 100644 tools/objtool/arch/arm64/include/arch/elf.h create mode 100644 tools/objtool/arch/arm64/include/arch/special.h create mode 100644 tools/objtool/arch/arm64/special.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index fe60738e5943b..101080fd4f99e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -210,9 +210,11 @@ config ARM64 select HAVE_HW_BREAKPOINT if PERF_EVENTS select HAVE_IOREMAP_PROT select HAVE_IRQ_TIME_ACCOUNTING + select HAVE_KLP_BUILD select HAVE_LIVEPATCH select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI + select HAVE_OBJTOOL select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS_NMI if ARM64_PSEUDO_NMI select HAVE_PERF_REGS diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index a4484fd22a96d..94aabeee97367 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -11,6 +11,10 @@ ifeq ($(SRCARCH),loongarch) BUILD_ORC := y endif +ifeq ($(SRCARCH),arm64) + ARCH_HAS_KLP := y +endif + ifeq ($(ARCH_HAS_KLP),y) HAVE_XXHASH = $(shell printf "$(pound)include \nXXH3_state_t *state;int main() {}" | \ $(HOSTCC) $(HOSTCFLAGS) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n) diff --git a/tools/objtool/arch/arm64/Build b/tools/objtool/arch/arm64/Build new file mode 100644 index 0000000000000..d24d5636a5b84 --- /dev/null +++ b/tools/objtool/arch/arm64/Build @@ -0,0 +1,2 @@ +objtool-y += decode.o +objtool-y += special.o diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c new file mode 100644 index 0000000000000..47658c76e1af0 --- /dev/null +++ b/tools/objtool/arch/arm64/decode.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include +#include +#include +#include + +const char *arch_reg_name[CFI_NUM_REGS] = {}; + +int arch_ftrace_match(const char *name) +{ + return 0; +} + +s64 arch_insn_adjusted_addend(struct instruction *insn, struct reloc *reloc) +{ + return reloc_addend(reloc); +} + +bool arch_callee_saved_reg(unsigned char reg) +{ + return false; +} + +int arch_decode_hint_reg(u8 sp_reg, int *base) +{ + exit(-1); +} + +const char *arch_nop_insn(int len) +{ + exit(-1); +} + +const char *arch_ret_insn(int len) +{ + exit(-1); +} + +int arch_decode_instruction(struct objtool_file *file, const struct section *sec, + unsigned long offset, unsigned int maxlen, + struct instruction *insn) +{ + u32 ins; + + if (maxlen < 4) { + ERROR_INSN(insn, "can't decode instruction"); + return -1; + } + + /* arm64 instructions are always LE, thus no bswap_if_needed() */ + ins = le32toh(*(u32 *)(sec->data->d_buf + offset)); + + /* + * These are the bare minimum needed for static branch detection and + * checksum calculations. + */ + if (ins == 0xd503201f) { + /* NOP: static branch */ + insn->type = INSN_NOP; + } else if ((ins & 0xfc000000) == 0x14000000) { + /* B: static branch, intra-TU sibling call */ + insn->type = INSN_JUMP_UNCONDITIONAL; + insn->immediate = sign_extend64(ins & 0x03ffffff, 25); + } else if ((ins & 0xfc000000) == 0x94000000) { + /* BL: intra-TU call */ + insn->type = INSN_CALL; + insn->immediate = sign_extend64(ins & 0x03ffffff, 25); + } else if ((ins & 0xff000000) == 0x54000000) { + /* B.cond: intra-TU sibling call */ + insn->type = INSN_JUMP_CONDITIONAL; + insn->immediate = sign_extend64((ins >> 5) & 0x7ffff, 18); + } else if ((ins & 0x7e000000) == 0x34000000) { + /* CBZ/CBNZ: intra-TU sibling call */ + insn->type = INSN_JUMP_CONDITIONAL; + insn->immediate = sign_extend64((ins >> 5) & 0x7ffff, 18); + } else if ((ins & 0x7e000000) == 0x36000000) { + /* TBZ/TBNZ: intra-TU sibling call */ + insn->type = INSN_JUMP_CONDITIONAL; + insn->immediate = sign_extend64((ins >> 5) & 0x3fff, 13); + } else { + insn->type = INSN_OTHER; + } + + insn->len = 4; + return 0; +} + +size_t arch_jump_opcode_bytes(struct objtool_file *file, struct instruction *insn, + unsigned char *buf) +{ + u32 ins; + + ins = le32toh(*(u32 *)(insn->sec->data->d_buf + insn->offset)); + + switch (insn->type) { + case INSN_JUMP_UNCONDITIONAL: + case INSN_CALL: + ins &= ~0x03ffffff; + break; + case INSN_JUMP_CONDITIONAL: + if ((ins & 0xff000000) == 0x54000000) + ins &= ~0x00ffffe0; /* B.cond */ + else if ((ins & 0x7e000000) == 0x34000000) + ins &= ~0x00ffffe0; /* CBZ/CBNZ */ + else + ins &= ~0x0007ffe0; /* TBZ/TBNZ */ + break; + default: + break; + } + + ins = htole32(ins); + memcpy(buf, &ins, 4); + return 4; +} + +u64 arch_adjusted_addend(struct reloc *reloc) +{ + return reloc_addend(reloc); +} + +unsigned long arch_jump_destination(struct instruction *insn) +{ + return insn->offset + (insn->immediate << 2); +} + +bool arch_pc_relative_reloc(struct reloc *reloc) +{ + switch (reloc_type(reloc)) { + case R_AARCH64_PREL64: + case R_AARCH64_PREL32: + case R_AARCH64_PREL16: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_ADR_PREL_PG_HI21_NC: + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: + case R_AARCH64_CONDBR19: + case R_AARCH64_TSTBR14: + return true; + default: + return false; + } +} + +void arch_initial_func_cfi_state(struct cfi_init_state *state) +{ + state->cfa.base = CFI_UNDEFINED; +} + +unsigned int arch_reloc_size(struct reloc *reloc) +{ + switch (reloc_type(reloc)) { + case R_AARCH64_ABS64: + case R_AARCH64_PREL64: + return 8; + case R_AARCH64_PREL16: + return 2; + default: + return 4; + } +} + +#ifdef DISAS +int arch_disas_info_init(struct disassemble_info *dinfo) +{ + return disas_info_init(dinfo, bfd_arch_aarch64, + bfd_mach_arm_unknown, bfd_mach_aarch64, + NULL); +} +#endif /* DISAS */ diff --git a/tools/objtool/arch/arm64/include/arch/cfi_regs.h b/tools/objtool/arch/arm64/include/arch/cfi_regs.h new file mode 100644 index 0000000000000..49c81cbb6646d --- /dev/null +++ b/tools/objtool/arch/arm64/include/arch/cfi_regs.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _OBJTOOL_ARCH_CFI_REGS_H +#define _OBJTOOL_ARCH_CFI_REGS_H + +/* These aren't actually used for arm64 */ +#define CFI_BP 0 +#define CFI_SP 0 +#define CFI_RA 0 +#define CFI_NUM_REGS 2 + +#endif /* _OBJTOOL_ARCH_CFI_REGS_H */ diff --git a/tools/objtool/arch/arm64/include/arch/elf.h b/tools/objtool/arch/arm64/include/arch/elf.h new file mode 100644 index 0000000000000..418b90885c501 --- /dev/null +++ b/tools/objtool/arch/arm64/include/arch/elf.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _OBJTOOL_ARCH_ELF_H +#define _OBJTOOL_ARCH_ELF_H + +#define R_NONE R_AARCH64_NONE +#define R_ABS64 R_AARCH64_ABS64 +#define R_ABS32 R_AARCH64_ABS32 +#define R_DATA32 R_AARCH64_PREL32 +#define R_DATA64 R_AARCH64_PREL64 +#define R_TEXT32 R_AARCH64_PREL32 +#define R_TEXT64 R_AARCH64_PREL64 + +#define ARCH_HAS_INLINE_ALTS 1 + +#endif /* _OBJTOOL_ARCH_ELF_H */ diff --git a/tools/objtool/arch/arm64/include/arch/special.h b/tools/objtool/arch/arm64/include/arch/special.h new file mode 100644 index 0000000000000..8ae804a83ea49 --- /dev/null +++ b/tools/objtool/arch/arm64/include/arch/special.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _OBJTOOL_ARCH_SPECIAL_H +#define _OBJTOOL_ARCH_SPECIAL_H + +#define EX_ENTRY_SIZE 12 +#define EX_ORIG_OFFSET 0 +#define EX_NEW_OFFSET 4 + +#define JUMP_ENTRY_SIZE 16 +#define JUMP_ORIG_OFFSET 0 +#define JUMP_NEW_OFFSET 4 +#define JUMP_KEY_OFFSET 8 + +#define ALT_ENTRY_SIZE 12 +#define ALT_ORIG_OFFSET 0 +#define ALT_NEW_OFFSET 4 +#define ALT_FEATURE_OFFSET 8 +#define ALT_ORIG_LEN_OFFSET 10 +#define ALT_NEW_LEN_OFFSET 11 + +#endif /* _OBJTOOL_ARCH_SPECIAL_H */ diff --git a/tools/objtool/arch/arm64/special.c b/tools/objtool/arch/arm64/special.c new file mode 100644 index 0000000000000..6ddecd362f3dd --- /dev/null +++ b/tools/objtool/arch/arm64/special.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include + +bool arch_support_alt_relocation(struct special_alt *special_alt, + struct instruction *insn, + struct reloc *reloc) +{ + return true; +} + +struct reloc *arch_find_switch_table(struct objtool_file *file, + struct instruction *insn, + unsigned long *table_size) +{ + return NULL; +} + +const char *arch_cpu_feature_name(int feature_number) +{ + return NULL; +} -- 2.53.0