objtool/arm64: Port klp-build to arm64
Subsystems (7)
Josh Poimboeuf
maintainercover objtool/arm64: Port klp-build to arm64
Port objtool and the klp-build tooling (for building livepatch modules) to arm64.
Note this doesn't bring all the objtool bells and whistles to arm64, nor any of the CFG reverse engineering. This only adds the bare minimum needed for 'objtool --checksum'.
And note that objtool still doesn't get enabled at all for normal arm64 kernel builds, so this doesn't affect any users other than those running klp-build directly.
Josh Poimboeuf (14):
objtool: Fix data alignment in elf_add_data()
objtool: Fix ERROR_INSN() error message
arm64: Annotate intra-function calls
arm64: head: Move boot header to .head.data
arm64: Fix EFI linking with -fdata-sections
crypto: arm64: Move data to .rodata
objtool: Extricate checksum calculation from validate_branch()
objtool: Allow setting --mnop without --mcount
kbuild: Only run objtool if there is at least one command
objtool: Ignore jumps to the end of the function for non-CFG arches
objtool: Allow empty alternatives
objtool: Reuse consecutive string references
objtool: Introduce objtool for arm64
klp-build: Support cross-compilation
arch/arm64/Kconfig | 2 + arch/arm64/kernel/entry.S | 2 + arch/arm64/kernel/head.S | 2 +- arch/arm64/kernel/proton-pack.c | 12 +- arch/arm64/kernel/vmlinux.lds.S | 2 +- arch/x86/boot/startup/Makefile | 2 +- include/asm-generic/vmlinux.lds.h | 2 +- include/linux/init.h | 1 + lib/crypto/arm64/sha2-armv8.pl | 11 +- scripts/Makefile.build | 4 +- scripts/Makefile.lib | 46 +++---- scripts/Makefile.vmlinux_o | 15 +-- scripts/livepatch/klp-build | 11 +- tools/objtool/Makefile | 4 + tools/objtool/arch/arm64/Build | 2 + tools/objtool/arch/arm64/decode.c | 116 ++++++++++++++++++ .../arch/arm64/include/arch/cfi_regs.h | 11 ++ tools/objtool/arch/arm64/include/arch/elf.h | 13 ++ .../objtool/arch/arm64/include/arch/special.h | 21 ++++ tools/objtool/arch/arm64/special.c | 21 ++++ tools/objtool/builtin-check.c | 5 - tools/objtool/check.c | 83 +++++++++---- tools/objtool/elf.c | 11 +- tools/objtool/include/objtool/checksum.h | 6 +- tools/objtool/include/objtool/warn.h | 2 +- 25 files changed, 323 insertions(+), 84 deletions(-) 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
Signature · 1 line
2.53.0
Josh Poimboeuf
maintainerPATCH 1/14 objtool: Fix data alignment in elf_add_data()
Any data added to a section needs to be aligned in accordance with the section's sh_addralign value. Particularly strings added to a .str1.8 section. Otherwise you may get some funky strings.
--- tools/objtool/elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/objtool/elf.c +1 -1
@@ -1375,7 +1375,7 @@ void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_memcpy (sec->data->d_buf, data, size); sec->data->d_size = size; - sec->data->d_align =1 ; + sec->data->d_align = sec->sh.sh_addralign; offset =ALIGN (sec->sh.sh_size, sec->sh.sh_addralign); sec->sh.sh_size = offset + size;
Signature · 1 line
2.53.0
[tip: objtool/urgent] objtool: Fix data alignment in elf_add_data()
The following commit has been merged into the objtool/urgent branch of tip:
The following commit has been merged into the objtool/urgent branch of tip:
Commit-ID: 356e4b2f5b80f757965f3f4d0219c81fca91b6f2 Gitweb: https://git.kernel.org/tip/356e4b2f5b80f757965f3f4d0219c81fca91b6f2 Author: Josh Poimboeuf <[email protected]> AuthorDate: Wed, 04 Mar 2026 19:31:20 -08:00 Committer: Josh Poimboeuf <[email protected]> CommitterDate: Fri, 06 Mar 2026 07:53:36 -08:00
objtool: Fix data alignment in elf_add_data()
Any data added to a section needs to be aligned in accordance with the section's sh_addralign value. Particularly strings added to a .str1.8 section. Otherwise you may get some funky strings.
--- tools/objtool/elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/objtool/elf.c +1 -1
@@ -1375,7 +1375,7 @@ void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_memcpy (sec->data->d_buf, data, size); sec->data->d_size = size; - sec->data->d_align =1 ; + sec->data->d_align = sec->sh.sh_addralign; offset =ALIGN (sec->sh.sh_size, sec->sh.sh_addralign); sec->sh.sh_size = offset + size;
Josh Poimboeuf
maintainerPATCH 2/14 objtool: Fix ERROR_INSN() error message
In reply to Josh PoimboeufConfusingly, ERROR_INSN() shows "warning:" instead of "error:". Fix that.
--- tools/objtool/include/objtool/warn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/objtool/include/objtool/warn.h +1 -1
@@ -107,7 +107,7 @@ static inline char *offstr(struct section *sec, unsigned long offset)#define ERROR_ELF (format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__)#define ERROR_GLIBC (format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__)#define ERROR_FUNC (sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__) -#define ERROR_INSN (insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__) +#define ERROR_INSN (insn, format, ...) ERROR_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__)extern bool debug;extern int indent;
Signature · 1 line
2.53.0
[tip: objtool/urgent] objtool: Fix ERROR_INSN() error message
The following commit has been merged into the objtool/urgent branch of tip:
The following commit has been merged into the objtool/urgent branch of tip:
Commit-ID: 1fd1dc41724319406b0aff221a352a400b0ddfc5 Gitweb: https://git.kernel.org/tip/1fd1dc41724319406b0aff221a352a400b0ddfc5 Author: Josh Poimboeuf <[email protected]> AuthorDate: Wed, 04 Mar 2026 19:31:21 -08:00 Committer: Josh Poimboeuf <[email protected]> CommitterDate: Fri, 06 Mar 2026 07:53:37 -08:00
objtool: Fix ERROR_INSN() error message
Confusingly, ERROR_INSN() shows "warning:" instead of "error:". Fix that.
--- tools/objtool/include/objtool/warn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/objtool/include/objtool/warn.h +1 -1
@@ -107,7 +107,7 @@ static inline char *offstr(struct section *sec, unsigned long offset)#define ERROR_ELF (format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__)#define ERROR_GLIBC (format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__)#define ERROR_FUNC (sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__) -#define ERROR_INSN (insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__) +#define ERROR_INSN (insn, format, ...) ERROR_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__)extern bool debug;extern int indent;
Josh Poimboeuf
maintainerPATCH 3/14 arm64: Annotate intra-function calls
In reply to Josh PoimboeufIn preparation for enabling objtool on arm64, annotate intra-function calls.
--- arch/arm64/kernel/entry.S | 2 ++ arch/arm64/kernel/proton-pack.c | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-)
arch/arm64/kernel/entry.S +2 -0
@@ -10,6 +10,7 @@ #include <linux/arm-smccc.h> #include <linux/init.h> #include <linux/linkage.h> +#include <linux/annotate.h> #include <asm/alternative.h> #include <asm/assembler.h>
@@ -707,6 +708,7 @@ alternative_else_nop_endif * entry onto the return stack and using a RET instruction to * enter the full-fat kernel vectors. */ + ANNOTATE_INTRA_FUNCTION_CALL bl 2f b . 2:
arch/arm64/kernel/proton-pack.c +7 -5
@@ -24,6 +24,7 @@#include <linux/nospec.h> #include <linux/prctl.h> #include <linux/sched/task_stack.h> +#include <linux/annotate.h> #include <asm/debug-monitors.h> #include <asm/insn.h>
@@ -245,11 +246,12 @@ static noinstr void qcom_link_stack_sanitisation(void) {u64 tmp; - asmvolatile ("mov %0, x30 \n" -".rept 16 \n" -"bl . + 4 \n" -".endr \n" -"mov x30, %0 \n" + asmvolatile ("mov %0, x30 \n" +".rept 16 \n" +ANNOTATE_INTRA_FUNCTION_CALL " \n" +"bl . + 4 \n" +".endr \n" +"mov x30, %0 \n" :"=&r" (tmp)); }
Signature · 1 line
2.53.0
Re: [PATCH 03/14] arm64: Annotate intra-function calls
Quoted 5 lines · Josh Poimboeuf
In preparation for enabling objtool on arm64, annotate intra-function calls.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 4/14 arm64: head: Move boot header to .head.data
In reply to Josh PoimboeufThe arm64 boot header is mostly data. Move it to a data section to prevent objtool and other tools from trying to disassemble it. The final linked result is the same.
--- arch/arm64/kernel/head.S | 2 +- include/asm-generic/vmlinux.lds.h | 2 +- include/linux/init.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-)
arch/arm64/kernel/head.S +1 -1
@@ -54,7 +54,7 @@ * that are useful before the MMU is enabled. The allocations are described * in the entry routines. */ - __HEAD + __HEADDATA /* * DO NOT MODIFY. Image header expected by Linux boot-loaders. */
include/asm-generic/vmlinux.lds.h +1 -1
@@ -663,7 +663,7 @@ __static_call_text_end = .;/* Section used for early init (in .S files) */ -#define HEAD_TEXT KEEP(*(.head.text)) +#define HEAD_TEXT KEEP(*(.head.data .head.text))#define HEAD_TEXT_SECTION \ .head.text : AT(ADDR(.head.text) - LOAD_OFFSET) { \
include/linux/init.h +1 -0
@@ -90,6 +90,7 @@/* For assembly routines */ #define __HEAD .section ".head.text","ax" +#define __HEADDATA .section ".head.data","aw"#define __INIT .section ".init.text","ax"#define __FINIT .previous
Signature · 1 line
2.53.0
Re: [PATCH 04/14] arm64: head: Move boot header to .head.data
Quoted 6 lines · Josh Poimboeuf
The arm64 boot header is mostly data. Move it to a data section to prevent objtool and other tools from trying to disassemble it. The final linked result is the same.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 5/14 arm64: Fix EFI linking with -fdata-sections
In reply to Josh PoimboeufWhen building with func-fdata-sections, the .init.bss section gets split up into a bunch of .init.bss.<var> sections. Make sure they get linked into .init.data.
--- arch/arm64/kernel/vmlinux.lds.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kernel/vmlinux.lds.S +1 -1
@@ -269,7 +269,7 @@ SECTIONS INIT_CALLS CON_INITCALL INIT_RAM_FS - *(.init.altinstructions .init.bss) /* from the EFI stub */ + *(.init.altinstructions .init.bss .init.bss.*) /* from the EFI stub */ } .exit.data : { EXIT_DATA
Signature · 1 line
2.53.0
Re: [PATCH 05/14] arm64: Fix EFI linking with -fdata-sections
Quoted 6 lines · Josh Poimboeuf
When building with func-fdata-sections, the .init.bss section gets split up into a bunch of .init.bss.<var> sections. Make sure they get linked into .init.data.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 6/14 crypto: arm64: Move data to .rodata
In reply to Josh PoimboeufData embedded in .text pollutes i-cache and confuses objtool and other tools that try to disassemble it. Move it to .rodata.
--- lib/crypto/arm64/sha2-armv8.pl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
lib/crypto/arm64/sha2-armv8.pl +8 -3
@@ -237,7 +237,8 @@ $code.=<<___; ldp $E,$F,[$ctx,#4*$SZ] add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input ldp $G,$H,[$ctx,#6*$SZ] - adr $Ktbl,.LK$BITS + adrp $Ktbl,.LK$BITS + add $Ktbl,$Ktbl,:lo12:.LK$BITS stp $ctx,$num,[x29,#96] .Loop:
@@ -286,6 +287,7 @@ $code.=<<___; ret .size $func,.-$func +.pushsection .rodata .align 6 .type .LK$BITS,%object .LK$BITS:
@@ -365,6 +367,7 @@ $code.=<<___; #endif .asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>" .align 2 +.popsection ___ if ($SZ==4) {
@@ -385,7 +388,8 @@ sha256_block_armv8: add x29,sp,#0 ld1.32 {$ABCD,$EFGH},[$ctx] - adr $Ktbl,.LK256 + adrp $Ktbl,.LK256 + add $Ktbl,$Ktbl,:lo12:.LK256 .Loop_hw: ld1 {@MSG[0]-@MSG[3]},[$inp],#64
@@ -648,7 +652,8 @@ sha256_block_neon: mov x29, sp sub sp,sp,#16*4 - adr $Ktbl,.LK256 + adrp $Ktbl,.LK256 + add $Ktbl,$Ktbl,:lo12:.LK256 add $num,$inp,$num,lsl#6 // len to point at the end of inp ld1.8 {@X[0]},[$inp], #16
Signature · 1 line
2.53.0
Josh Poimboeuf
maintainerPATCH 7/14 objtool: Extricate checksum calculation from validate_branch()
In reply to Josh PoimboeufIn preparation for porting the checksum code to other arches, make its functionality independent from validate_branch().
--- tools/objtool/check.c | 71 +++++++++++++++++------- tools/objtool/include/objtool/checksum.h | 6 +- 2 files changed, 53 insertions(+), 24 deletions(-)
tools/objtool/check.c +52 -19
@@ -2633,8 +2633,7 @@ static bool validate_branch_enabled(void) {return opts.stackval || opts.orc || - opts.uaccess || - opts.checksum; + opts.uaccess; }static int decode_sections (struct objtool_file *file)
@@ -3649,6 +3648,7 @@ static bool skip_alt_group(struct instruction *insn)return alt_insn->type ==INSN_CLAC || alt_insn->type ==INSN_STAC ; } +#ifdef BUILD_KLP static int checksum_debug_init (struct objtool_file *file) {char *dup, *s;
@@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, struct instruction *insn) {struct reloc *reloc =insn_reloc (file, insn); +struct alternative *alt;unsigned long offset;struct symbol *sym; +for (alt = insn->alts; alt; alt = alt->next) { +struct alt_group *alt_group = alt->insn->alt_group; + +checksum_update (func, insn, &alt->type,sizeof (alt->type)); + +if (alt_group && alt_group->orig_group) { +struct instruction *alt_insn; + +checksum_update (func, insn, &alt_group->feature,sizeof (alt_group->feature)); + +for (alt_insn = alt->insn; alt_insn; alt_insn =next_insn_same_sec (file, alt_insn)) { +checksum_update_insn (file, func, alt_insn); +if (alt_insn == alt_group->last_insn) +break ; + } + }else { +checksum_update (func, insn, &alt->insn->offset,sizeof (alt->insn->offset)); + } + } +if (insn->fake)return ;
@@ -3702,9 +3723,11 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,if (!reloc) {struct symbol *call_dest =insn_call_dest (insn); -if (call_dest) +if (call_dest) { +/* intra-TU call without reloc */ checksum_update (func, insn, call_dest->demangled_name,strlen (call_dest->demangled_name)); + }return ; }
@@ -3731,6 +3754,29 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,checksum_update (func, insn, &offset,sizeof (offset)); } +static int calculate_checksums (struct objtool_file *file) +{ +struct instruction *insn; +struct symbol *func; + +if (checksum_debug_init (file)) +return -1 ; + +for_each_sym (file->elf, func) { +if (!is_func_sym (func)) +continue ; + +checksum_init (func); + +func_for_each_insn (file, func, insn) +checksum_update_insn (file, func, insn); + +checksum_finish (func); + } +return 0 ; +} +#endif /* BUILD_KLP */ +static int validate_branch (struct objtool_file *file,struct symbol *func,struct instruction *insn,struct insn_state state); static int do_validate_branch(struct objtool_file *file, struct symbol *func,
@@ -4012,9 +4058,6 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func, insn->trace =0 ; next_insn =next_insn_to_validate (file, insn); -if (opts.checksum && func && insn->sec) -checksum_update_insn (file, func, insn); -if (func &&insn_func (insn) && func !=insn_func (insn)->pfunc) {/* Ignore KCFI type preambles, which always fall through */ if (is_prefix_func (func))
@@ -4080,9 +4123,6 @@ static int validate_unwind_hint(struct objtool_file *file,struct symbol *func =insn_func (insn);int ret; -if (opts.checksum) -checksum_init (func); - ret =validate_branch (file, func, insn, *state);if (ret)BT_INSN (insn,"<=== (hint)" );
@@ -4525,9 +4565,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec, func =insn_func (insn); -if (opts.checksum) -checksum_init (func); -if (opts.trace && !fnmatch (opts.trace, sym->name,0 )) {trace_enable ();TRACE ("%s: validation begin\n" , sym->name);
@@ -4540,9 +4577,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec,TRACE ("%s: validation %s\n\n" , sym->name, ret ?"failed" :"end" );trace_disable (); -if (opts.checksum) -checksum_finish (func); -return ret; }
@@ -4997,10 +5031,6 @@ int check(struct objtool_file *file)cfi_hash_add (&init_cfi);cfi_hash_add (&func_cfi); - ret =checksum_debug_init (file); -if (ret) - goto out; - ret =decode_sections (file);if (ret) goto out;
@@ -5091,6 +5121,9 @@ int check(struct objtool_file *file) warnings +=check_abs_references (file);if (opts.checksum) { + ret =calculate_checksums (file); +if (ret) + goto out; ret =create_sym_checksum_section (file);if (ret) goto out;
tools/objtool/include/objtool/checksum.h +1 -5
@@ -32,11 +32,7 @@ static inline void checksum_finish(struct symbol *func)#else /* !BUILD_KLP */ -static inline void checksum_init (struct symbol *func) {} -static inline void checksum_update (struct symbol *func, -struct instruction *insn, -const void *data,size_t size) {} -static inline void checksum_finish (struct symbol *func) {} +static inline int calculate_checksums (struct objtool_file *file) {return -ENOSYS ; }#endif /* !BUILD_KLP */
Signature · 1 line
2.53.0
Miroslav Benes
maintainerRe: [PATCH 07/14] objtool: Extricate checksum calculation from validate_branch()
Hi,
Quoted 18 lines
tools/objtool/check.c +11
-0@@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, struct instruction *insn) {struct reloc *reloc =insn_reloc (file, insn); +struct alternative *alt;unsigned long offset;struct symbol *sym; +for (alt = insn->alts; alt; alt = alt->next) { +struct alt_group *alt_group = alt->insn->alt_group; + +checksum_update (func, insn, &alt->type,sizeof (alt->type)); + +if (alt_group && alt_group->orig_group) { +struct instruction *alt_insn; + +checksum_update (func, insn, &alt_group->feature,sizeof (alt_group->feature)); +
tools/objtool/check.c static void checksum_update_insn(struct objtool_file *file, struct symbol *func, · line 3717
Quoted 10 lines
tools/objtool/check.c +10
-0+for (alt_insn = alt->insn; alt_insn; alt_insn =next_insn_same_sec (file, alt_insn)) { +checksum_update_insn (file, func, alt_insn); +if (alt_insn == alt_group->last_insn) +break ; + } + }else { +checksum_update (func, insn, &alt->insn->offset,sizeof (alt->insn->offset)); + } + } +
does this hunk belong to the patch? Unless I am missing something, it might be worth a separate one.
Miroslav
Josh Poimboeuf
maintainerRe: [PATCH 07/14] objtool: Extricate checksum calculation from validate_branch()
Quoted 25 lines · Miroslav Benes
Hi,
Quoted 23 lines
tools/objtool/check.c +16
-0@@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, struct instruction *insn) {struct reloc *reloc =insn_reloc (file, insn); +struct alternative *alt;unsigned long offset;struct symbol *sym; +for (alt = insn->alts; alt; alt = alt->next) { +struct alt_group *alt_group = alt->insn->alt_group; + +checksum_update (func, insn, &alt->type,sizeof (alt->type)); + +if (alt_group && alt_group->orig_group) { +struct instruction *alt_insn; + +checksum_update (func, insn, &alt_group->feature,sizeof (alt_group->feature)); + +for (alt_insn = alt->insn; alt_insn; alt_insn =next_insn_same_sec (file, alt_insn)) { +checksum_update_insn (file, func, alt_insn); +if (alt_insn == alt_group->last_insn) +break ; + }
Quoted 8 lines
tools/objtool/check.c static void checksum_update_insn(struct objtool_file *file, struct symbol *func, · line 3717
Quoted 5 lines
tools/objtool/check.c +5
-0+ }else { +checksum_update (func, insn, &alt->insn->offset,sizeof (alt->insn->offset)); + } + } +does this hunk belong to the patch? Unless I am missing something, it might be worth a separate one.
It belongs, but I should have clarified that in the patch description.
This hunk wasn't needed before because validate_branch() already iterates all the alternatives, so it was calling checksum_update_insn() for every instruction in the function, including the alternatives.
Now that it's no longer called by validate_branch(), checksum_update_insn() has to manually iterate the alternatives.
Signature · 1 line
Josh
Miroslav Benes
maintainerRe: [PATCH 07/14] objtool: Extricate checksum calculation from validate_branch()
Quoted 35 lines · Josh Poimboeuf
Quoted 25 lines · Miroslav Benes
Hi,
Quoted 23 lines
tools/objtool/check.c +16
-0@@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, struct instruction *insn) {struct reloc *reloc =insn_reloc (file, insn); +struct alternative *alt;unsigned long offset;struct symbol *sym; +for (alt = insn->alts; alt; alt = alt->next) { +struct alt_group *alt_group = alt->insn->alt_group; + +checksum_update (func, insn, &alt->type,sizeof (alt->type)); + +if (alt_group && alt_group->orig_group) { +struct instruction *alt_insn; + +checksum_update (func, insn, &alt_group->feature,sizeof (alt_group->feature)); + +for (alt_insn = alt->insn; alt_insn; alt_insn =next_insn_same_sec (file, alt_insn)) { +checksum_update_insn (file, func, alt_insn); +if (alt_insn == alt_group->last_insn) +break ; + }Quoted 8 lines
tools/objtool/check.c static void checksum_update_insn(struct objtool_file *file, struct symbol *func, · line 3717
Quoted 5 lines
tools/objtool/check.c +5
-0+ }else { +checksum_update (func, insn, &alt->insn->offset,sizeof (alt->insn->offset)); + } + } +does this hunk belong to the patch? Unless I am missing something, it might be worth a separate one.
Quoted 8 lines
It belongs, but I should have clarified that in the patch description.
This hunk wasn't needed before because
validate_branch()already iterates all the alternatives, so it was callingchecksum_update_insn()for every instruction in the function, including the alternatives.Now that it's no longer called by
validate_branch(),checksum_update_insn()has to manually iterate the alternatives.
After writing the email I had a suspicion it must have been something like above but failed to find it. Now I see that next_insn_to_validate() called in do_validate_branch() handles exactly that. Thanks for the pointer. The patch looks good to me then (and the rest as well as far as I can judge).
I must admit that objtool has gotten so complex that I have a hard time to track everything in the code :).
Regards
Miroslav
Josh Poimboeuf
maintainerRe: [PATCH 07/14] objtool: Extricate checksum calculation from validate_branch()
Quoted 43 lines · Miroslav Benes
Quoted 41 lines · Josh Poimboeuf
Quoted 25 lines · Miroslav Benes
Hi,
Quoted 23 lines
tools/objtool/check.c +16
-0@@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, struct instruction *insn) {struct reloc *reloc =insn_reloc (file, insn); +struct alternative *alt;unsigned long offset;struct symbol *sym; +for (alt = insn->alts; alt; alt = alt->next) { +struct alt_group *alt_group = alt->insn->alt_group; + +checksum_update (func, insn, &alt->type,sizeof (alt->type)); + +if (alt_group && alt_group->orig_group) { +struct instruction *alt_insn; + +checksum_update (func, insn, &alt_group->feature,sizeof (alt_group->feature)); + +for (alt_insn = alt->insn; alt_insn; alt_insn =next_insn_same_sec (file, alt_insn)) { +checksum_update_insn (file, func, alt_insn); +if (alt_insn == alt_group->last_insn) +break ; + }Quoted 8 lines
tools/objtool/check.c static void checksum_update_insn(struct objtool_file *file, struct symbol *func, · line 3717
Quoted 5 lines
tools/objtool/check.c +5
-0+ }else { +checksum_update (func, insn, &alt->insn->offset,sizeof (alt->insn->offset)); + } + } +does this hunk belong to the patch? Unless I am missing something, it might be worth a separate one.
It belongs, but I should have clarified that in the patch description.
This hunk wasn't needed before because
validate_branch()already iterates all the alternatives, so it was callingchecksum_update_insn()for every instruction in the function, including the alternatives.
Quoted 7 lines
Quoted 2 lines
Now that it's no longer called by
validate_branch(),checksum_update_insn()has to manually iterate the alternatives.After writing the email I had a suspicion it must have been something like above but failed to find it. Now I see that
next_insn_to_validate()called indo_validate_branch()handles exactly that. Thanks for the pointer. The patch looks good to me then (and the rest as well as far as I can judge).
Actually, next_insn_to_validate() helps with an edge case for directing code flow from the end of an alternative back to the original code.
The code which traverses the alternatives is in validate_insn():
if (insn->alts) {
for (alt = insn->alts; alt; alt = alt->next) {
TRACE_ALT_BEGIN(insn, alt, alt_name);
ret = validate_branch(file, func, alt->insn, *statep);
TRACE_ALT_END(insn, alt, alt_name);
if (ret) {
BT_INSN(insn, "(alt)");
return ret;
}
}
TRACE_ALT_INFO_NOADDR(insn, "/ ", "DEFAULT");
}Quoted 2 lines
I must admit that objtool has gotten so complex that I have a hard time to track everything in the code :).
The code hasn't changed *too* much, it's just that validate_branch() got split up more when the tracing code went in, so things are organized a bit differently. Most of that code is now in validate_insn().
Signature · 1 line
Josh
Josh Poimboeuf
maintainerPATCH 8/14 objtool: Allow setting --mnop without --mcount
In reply to Josh PoimboeufInstead of returning an error for --mnop without --mcount, just silently ignore it. This will help simplify kbuild's handling of objtool args.
--- tools/objtool/builtin-check.c | 5 ----- 1 file changed, 5 deletions(-)
tools/objtool/builtin-check.c +0 -5
@@ -145,11 +145,6 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[])static bool opts_valid (void ) { -if (opts.mnop && !opts.mcount) { -ERROR ("--mnop requires --mcount" ); -return false; - } -if (opts.noinstr && !opts.link) {ERROR ("--noinstr requires --link" );return false;
Signature · 1 line
2.53.0
Re: [PATCH 08/14] objtool: Allow setting --mnop without --mcount
Quoted 5 lines · Josh Poimboeuf
Instead of returning an error for --mnop without --mcount, just silently ignore it. This will help simplify kbuild's handling of objtool args.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 9/14 kbuild: Only run objtool if there is at least one command
In reply to Josh PoimboeufSplit the objtool args into commands and options, such that if no commands have been enabled, objtool doesn't run.
This is in preparation in enabling objtool and klp-build for arm64.
--- arch/x86/boot/startup/Makefile | 2 +- scripts/Makefile.build | 4 +-- scripts/Makefile.lib | 46 ++++++++++++++++++---------------- scripts/Makefile.vmlinux_o | 15 ++++------- 4 files changed, 33 insertions(+), 34 deletions(-)
arch/x86/boot/startup/Makefile +1 -1
@@ -36,7 +36,7 @@ $(patsubst %.o,$(obj)/%.o,$(lib-y)): OBJECT_FILES_NON_STANDARD := y # relocations, even if other objtool actions are being deferred. # $(pi-objs): objtool-enabled = 1 -$(pi-objs): objtool-args = $(if $(delay-objtool),--dry-run,$(objtool-args-y)) --noabs +$(pi-objs): objtool-args = $(if $(delay-objtool),--dry-run,$(objtool-cmds-y) $(objtool-opts-y)) --noabs # # Confine the startup code by prefixing all symbols with __pi_ (for position
scripts/Makefile.build +2 -2
@@ -277,7 +277,7 @@ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),$(is-kernel-object)) ifdef CONFIG_OBJTOOL -$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) +$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(objtool-cmds-y),$(if $(delay-objtool),$(is-single-obj-m),y))) endif ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
@@ -499,7 +499,7 @@ define rule_ld_multi_m $(call cmd,gen_objtooldep) endef -$(multi-obj-m): private objtool-enabled := $(delay-objtool) +$(multi-obj-m): private objtool-enabled := $(if $(objtool-cmds-y),$(delay-objtool)) $(multi-obj-m): private part-of-module := y $(multi-obj-m): %.o: %.mod FORCE $(call if_changed_rule,ld_multi_m)
scripts/Makefile.lib +25 -21
59 lines not on this page · raw message
scripts/Makefile.vmlinux_o +5 -10
@@ -36,18 +36,13 @@ endif # For !delay-objtool + CONFIG_NOINSTR_VALIDATION, it runs on both translation # units and vmlinux.o, with the latter only used for noinstr/unret validation. -objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION)) - -ifeq ($(delay-objtool),y) -vmlinux-objtool-args-y += $(objtool-args-y) -else -vmlinux-objtool-args-$(CONFIG_OBJTOOL_WERROR) += --werror +ifneq ($(delay-objtool),y) +objtool-cmds-y = +objtool-opts-y += --link endif -vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \ - $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret) - -objtool-args = $(vmlinux-objtool-args-y) --link +objtool-cmds-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \ + $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret) # Link of vmlinux.o used for section mismatch analysis # ---------------------------------------------------------------------------
Signature · 1 line
2.53.0
Re: [PATCH 09/14] kbuild: Only run objtool if there is at least one command
Quoted 6 lines · Josh Poimboeuf
Split the objtool args into commands and options, such that if no commands have been enabled, objtool doesn't run.
This is in preparation in enabling objtool and klp-build for arm64.
Signed-off-by Josh Poimboeuf <[email protected]>
I assume this will go with the rest of the series.
Quoted 138 lines
--- arch/x86/boot/startup/Makefile | 2 +- scripts/Makefile.build | 4 +-- scripts/Makefile.lib | 46 ++++++++++++++++++---------------- scripts/Makefile.vmlinux_o | 15 ++++------- 4 files changed, 33 insertions(+), 34 deletions(-)arch/x86/boot/startup/Makefile +1
-1@@ -36,7 +36,7 @@ $(patsubst %.o,$(obj)/%.o,$(lib-y)): OBJECT_FILES_NON_STANDARD := y # relocations, even if other objtool actions are being deferred. # $(pi-objs): objtool-enabled = 1 -$(pi-objs): objtool-args = $(if $(delay-objtool),--dry-run,$(objtool-args-y)) --noabs +$(pi-objs): objtool-args = $(if $(delay-objtool),--dry-run,$(objtool-cmds-y) $(objtool-opts-y)) --noabs # # Confine the startup code by prefixing all symbols with __pi_ (for positionscripts/Makefile.build +2
-2@@ -277,7 +277,7 @@ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),$(is-kernel-object)) ifdef CONFIG_OBJTOOL -$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) +$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(objtool-cmds-y),$(if $(delay-objtool),$(is-single-obj-m),y))) endif ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)@@ -499,7 +499,7 @@ define rule_ld_multi_m $(call cmd,gen_objtooldep) endef -$(multi-obj-m): private objtool-enabled := $(delay-objtool) +$(multi-obj-m): private objtool-enabled := $(if $(objtool-cmds-y),$(delay-objtool)) $(multi-obj-m): private part-of-module := y $(multi-obj-m): %.o: %.mod FORCE $(call if_changed_rule,ld_multi_m)scripts/Makefile.lib +25
-21@@ -183,27 +183,31 @@ ifdef CONFIG_OBJTOOL objtool := $(objtree)/tools/objtool/objtool -objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label -objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr -objtool-args-$(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) += --hacks=skylake -objtool-args-$(CONFIG_X86_KERNEL_IBT) += --ibt -objtool-args-$(CONFIG_FINEIBT) += --cfi -objtool-args-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL) += --mcount -ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL -objtool-args-$(CONFIG_HAVE_OBJTOOL_NOP_MCOUNT) += --mnop -endif -objtool-args-$(CONFIG_UNWINDER_ORC) += --orc -objtool-args-$(CONFIG_MITIGATION_RETPOLINE) += --retpoline -objtool-args-$(CONFIG_MITIGATION_RETHUNK) += --rethunk -objtool-args-$(CONFIG_MITIGATION_SLS) += --sls -objtool-args-$(CONFIG_STACK_VALIDATION) += --stackval -objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call -objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess -objtool-args-$(or $(CONFIG_GCOV_KERNEL),$(CONFIG_KCOV)) += --no-unreachable -objtool-args-$(CONFIG_PREFIX_SYMBOLS) += --prefix=$(CONFIG_FUNCTION_PADDING_BYTES) -objtool-args-$(CONFIG_OBJTOOL_WERROR) += --werror +# objtool commands +objtool-cmds-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label +objtool-cmds-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr +objtool-cmds-$(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) += --hacks=skylake +objtool-cmds-$(CONFIG_X86_KERNEL_IBT) += --ibt +objtool-cmds-$(CONFIG_FINEIBT) += --cfi +objtool-cmds-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL) += --mcount +objtool-cmds-$(CONFIG_UNWINDER_ORC) += --orc +objtool-cmds-$(CONFIG_MITIGATION_RETPOLINE) += --retpoline +objtool-cmds-$(CONFIG_MITIGATION_RETHUNK) += --rethunk +objtool-cmds-$(CONFIG_MITIGATION_SLS) += --sls +objtool-cmds-$(CONFIG_STACK_VALIDATION) += --stackval +objtool-cmds-$(CONFIG_HAVE_STATIC_CALL_INLINE) += --static-call +objtool-cmds-$(CONFIG_HAVE_UACCESS_VALIDATION) += --uaccess +objtool-cmds-$(CONFIG_PREFIX_SYMBOLS) += --prefix=$(CONFIG_FUNCTION_PADDING_BYTES) +objtool-cmds-y += $(OBJTOOL_ARGS) -objtool-args = $(objtool-args-y) \ +# objtool options +ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL +objtool-opts-$(CONFIG_HAVE_OBJTOOL_NOP_MCOUNT) += --mnop +endif +objtool-opts-$(or $(CONFIG_GCOV_KERNEL),$(CONFIG_KCOV)) += --no-unreachable +objtool-opts-$(CONFIG_OBJTOOL_WERROR) += --werror + +objtool-args = $(objtool-cmds-y) $(objtool-opts-y) \ $(if $(delay-objtool), --link) \ $(if $(part-of-module), --module)@@ -212,7 +216,7 @@ delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT),$(CONFIG_KLP_ cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool-args) $@) cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) -objtool-enabled := y +objtool-enabled = $(if $(objtool-cmds-y),y) endif # CONFIG_OBJTOOLscripts/Makefile.vmlinux_o +5
-10@@ -36,18 +36,13 @@ endif # For !delay-objtool + CONFIG_NOINSTR_VALIDATION, it runs on both translation # units and vmlinux.o, with the latter only used for noinstr/unret validation. -objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION)) - -ifeq ($(delay-objtool),y) -vmlinux-objtool-args-y += $(objtool-args-y) -else -vmlinux-objtool-args-$(CONFIG_OBJTOOL_WERROR) += --werror +ifneq ($(delay-objtool),y) +objtool-cmds-y = +objtool-opts-y += --link endif -vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \ - $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret) - -objtool-args = $(vmlinux-objtool-args-y) --link +objtool-cmds-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \ + $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret) # Link of vmlinux.o used for section mismatch analysis # ---------------------------------------------------------------------------Signature · 1 line
2.53.0
Josh Poimboeuf
maintainerPATCH 10/14 objtool: Ignore jumps to the end of the function for non-CFG arches
In reply to Josh PoimboeufSometimes Clang arm64 code jumps to the end of the function for UB. No need to make that an error, arm64 doesn't reverse engineer the CFG anyway.
--- tools/objtool/check.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
tools/objtool/check.c +5 -3
@@ -1630,10 +1630,12 @@ static int add_jump_destinations(struct objtool_file *file)/* * GCOV/KCOV dead code can jump to the end of * the function/section. +* +* Clang on arm64 also does this sometimes for +* undefined behavior. */ -if (file->ignore_unreachables && func && - dest_sec == insn->sec && - dest_off == func->offset + func->len) +if ((file->ignore_unreachables || (!opts.stackval && !opts.orc)) && + func && dest_sec == insn->sec && dest_off == func->offset + func->len)continue ; ERROR_INSN(insn, "can't find jump dest instruction at %s",
Signature · 1 line
2.53.0
Re: [PATCH 10/14] objtool: Ignore jumps to the end of the function for non-CFG arches
Quoted 6 lines · Josh Poimboeuf
Sometimes Clang arm64 code jumps to the end of the function for UB. No need to make that an error, arm64 doesn't reverse engineer the CFG anyway.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 11/14 objtool: Allow empty alternatives
In reply to Josh Poimboeufarm64 can have empty alternatives, which are effectively no-ops. Ignore them.
--- tools/objtool/check.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
tools/objtool/check.c +1 -3
@@ -1994,10 +1994,8 @@ static int add_special_section_alts(struct objtool_file *file) }if (special_alt->group) { -if (!special_alt->orig_len) { -ERROR_INSN (orig_insn,"empty alternative entry" ); +if (!special_alt->orig_len)continue ; - }if (handle_group_alt (file, special_alt, orig_insn, &new_insn))return -1 ;
Signature · 1 line
2.53.0
Re: [PATCH 11/14] objtool: Allow empty alternatives
Quoted 5 lines · Josh Poimboeuf
arm64 can have empty alternatives, which are effectively no-ops. Ignore them.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 12/14 objtool: Reuse consecutive string references
In reply to Josh PoimboeufFor duplicate strings, elf_add_string() just blindly adds duplicates.
That can be a problem for arm64 which often uses two consecutive instructions (and corresponding relocations) to put an address into a register, like:
d8: 90000001 adrp x1, 0 <meminfo_proc_show> d8: R_AARCH64_ADR_PREL_PG_HI21 .rodata.meminfo_proc_show.str1.8 dc: 91000021 add x1, x1, #0x0 dc: R_AARCH64_ADD_ABS_LO12_NC .rodata.meminfo_proc_show.str1.8
Referencing two different string addresses in the adrp+add pair can result in a corrupt string addresses. Detect such consecutive reuses and force them to use the same string.
--- tools/objtool/elf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
tools/objtool/elf.c +8 -1
@@ -1321,6 +1321,8 @@ struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name)unsigned int elf_add_string (struct elf *elf,struct section *strtab,const char *str) { +static unsigned int last_off; +static const char *last_str;unsigned int offset;if (!strtab)
@@ -1329,17 +1331,22 @@ unsigned int elf_add_string(struct elf *elf, struct section *strtab, const charERROR ("can't find .strtab section" );return -1 ; } -if (!strtab->sh.sh_addralign) {ERROR ("'%s': invalid sh_addralign" , strtab->name);return -1 ; } +if (last_str && !strcmp (last_str, str)) +return last_off; + offset =ALIGN (strtab->sh.sh_size, strtab->sh.sh_addralign);if (!elf_add_data (elf, strtab, str,strlen (str) +1 ))return -1 ; + last_str = str; + last_off = offset; +return offset; }
Signature · 1 line
2.53.0
Re: [PATCH 12/14] objtool: Reuse consecutive string references
Quoted 7 lines · Josh Poimboeuf
For duplicate strings,
elf_add_string()just blindly adds duplicates.That can be a problem for arm64 which often uses two consecutive instructions (and corresponding relocations) to put an address into a register, like:
Quoted 8 lines
d8: 90000001 adrp x1, 0 <meminfo_proc_show> d8: R_AARCH64_ADR_PREL_PG_HI21 .rodata.meminfo_proc_show.str1.8 dc: 91000021 add x1, x1, #0x0 dc: R_AARCH64_ADD_ABS_LO12_NC .rodata.meminfo_proc_show.str1.8Referencing two different string addresses in the adrp+add pair can result in a corrupt string addresses. Detect such consecutive reuses and force them to use the same string.
Signed-off-by Josh Poimboeuf <[email protected]>
Josh Poimboeuf
maintainerPATCH 13/14 objtool: Introduce objtool for arm64
In reply to Josh PoimboeufAdd basic support for arm64 on objtool. Only --checksum is currently supported.
--- arch/arm64/Kconfig | 2 + tools/objtool/Makefile | 4 + tools/objtool/arch/arm64/Build | 2 + tools/objtool/arch/arm64/decode.c | 116 ++++++++++++++++++ .../arch/arm64/include/arch/cfi_regs.h | 11 ++ tools/objtool/arch/arm64/include/arch/elf.h | 13 ++ .../objtool/arch/arm64/include/arch/special.h | 21 ++++ tools/objtool/arch/arm64/special.c | 21 ++++ 8 files changed, 190 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
arch/arm64/Kconfig +2 -0
@@ -236,9 +236,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
tools/objtool/Makefile +4 -0
@@ -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 <xxhash.h>\nXXH3_state_t *state;int main() {}" | \ $(HOSTCC) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n)
tools/objtool/arch/arm64/Build new file +2 -0
@@ -0,0 +1,2 @@ +objtool-y += decode.o +objtool-y += special.o
tools/objtool/arch/arm64/decode.c new file +116 -0
116 lines not on this page · raw message
tools/objtool/arch/arm64/include/arch/cfi_regs.h new file +11 -0
@@ -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 */
tools/objtool/arch/arm64/include/arch/elf.h new file +13 -0
@@ -0,0 +1,13 @@ +/* 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 + +#endif /* _OBJTOOL_ARCH_ELF_H */
tools/objtool/arch/arm64/include/arch/special.h new file +21 -0
@@ -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 */
tools/objtool/arch/arm64/special.c new file +21 -0
@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <objtool/special.h> + +bool arch_support_alt_relocation (struct special_alt *special_alt, +struct instruction *insn, +struct reloc *reloc) +{ +return false; +} + +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 ; +}
Signature · 1 line
2.53.0
Josh Poimboeuf
maintainerPATCH 14/14 klp-build: Support cross-compilation
In reply to Josh PoimboeufAdd support for cross-compilation. The user must export ARCH, and either CROSS_COMPILE or LLVM.
--- scripts/livepatch/klp-build | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
scripts/livepatch/klp-build +10 -1
@@ -404,6 +404,14 @@ validate_patches() { revert_patches } +cross_compile_init() { + if [[ -v LLVM ]]; then + OBJCOPY=llvm-objcopy + else + OBJCOPY="${CROSS_COMPILE:-}objcopy" + fi +} + do_init() { # We're not yet smart enough to handle anything other than in-tree # builds in pwd.
@@ -420,6 +428,7 @@ do_init() { validate_config set_module_name set_kernelversion + cross_compile_init } # Refresh the patch hunk headers, specifically the line numbers and counts.
@@ -783,7 +792,7 @@ build_patch_module() { cp -f "$kmod_file" "$kmod_file.orig" # Work around issue where slight .config change makes corrupt BTF - objcopy --remove-section=.BTF "$kmod_file" + "$OBJCOPY" --remove-section=.BTF "$kmod_file" # Fix (and work around) linker wreckage for klp syms / relocs "$SRC/tools/objtool/objtool" klp post-link "$kmod_file" || die "objtool klp post-link failed"
Signature · 1 line
2.53.0
Song Liu
maintainerRe: [PATCH 14/14] klp-build: Support cross-compilation
Quoted 14 lines · Josh Poimboeuf
Add support for cross-compilation. The user must export ARCH, and either
CROSS_COMPILEor LLVM.Signed-off-by Josh Poimboeuf <[email protected]>--- scripts/livepatch/klp-build | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)scripts/livepatch/klp-build +0
-0
scripts/livepatch/klp-build validate_patches() { · line 413
Quoted 10 lines
scripts/livepatch/klp-build +7
-0@@ -404,6 +404,14 @@ validate_patches() { revert_patches } +cross_compile_init() { + if [[ -v LLVM ]]; then + OBJCOPY=llvm-objcopy + else + OBJCOPY="${CROSS_COMPILE:-}objcopy" + fi +}
Shall we show a specific warning if
- ARCH is set; and
- ARCH is not the same as (uname -m); and
- neither LLVM nor CROSS_COMPILE is set.
Thanks,
Song
Josh Poimboeuf
maintainerRe: [PATCH 14/14] klp-build: Support cross-compilation
Quoted 18 lines · Song Liu
Quoted 17 lines · Josh Poimboeuf
Add support for cross-compilation. The user must export ARCH, and either
CROSS_COMPILEor LLVM.Signed-off-by Josh Poimboeuf <[email protected]>--- scripts/livepatch/klp-build | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)scripts/livepatch/klp-build +0
-0@@ -404,6 +404,14 @@ validate_patches() { revert_patches }
Quoted 12 lines
scripts/livepatch/klp-build validate_patches() { · line 413
Quoted 7 lines
scripts/livepatch/klp-build +7
-0+cross_compile_init() { + if [[ -v LLVM ]]; then + OBJCOPY=llvm-objcopy + else + OBJCOPY="${CROSS_COMPILE:-}objcopy" + fi +}Shall we show a specific warning if
- ARCH is set; and
- ARCH is not the same as (uname -m); and
- neither LLVM norCROSS_COMPILEis set.
Yeah, I think that would be a good idea. Will do that for v2.
Signature · 1 line
Josh
Josh Poimboeuf
maintainerRe: [PATCH 14/14] klp-build: Support cross-compilation
Quoted 32 lines · Josh Poimboeuf
Quoted 18 lines · Song Liu
Quoted 17 lines · Josh Poimboeuf
Add support for cross-compilation. The user must export ARCH, and either
CROSS_COMPILEor LLVM.Signed-off-by Josh Poimboeuf <[email protected]>--- scripts/livepatch/klp-build | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)scripts/livepatch/klp-build +0
-0@@ -404,6 +404,14 @@ validate_patches() { revert_patches }Quoted 12 lines
scripts/livepatch/klp-build validate_patches() { · line 413
Quoted 7 lines
scripts/livepatch/klp-build +7
-0+cross_compile_init() { + if [[ -v LLVM ]]; then + OBJCOPY=llvm-objcopy + else + OBJCOPY="${CROSS_COMPILE:-}objcopy" + fi +}Shall we show a specific warning if
- ARCH is set; and
- ARCH is not the same as (uname -m); and
- neither LLVM norCROSS_COMPILEis set.
Quoted 1 line
Yeah, I think that would be a good idea. Will do that for v2.
So, in general ARCH is complicated. For example:
- ARCH=arm64 would never match "uname -m" (aarch64)
- ARCH=i386 would use the same gcc binary (no cross-compiler needed)
- I'm sure there are many other edge cases...
Instead of a manual error, it may be simpler to just let the build fail naturally if the user doesn't set the right ARCH.
Though, I think the check can be improved slightly, as ARCH is a reasonably good indicator that cross-compiling is happening. So I can at least add an ARCH check at the beginning like so?
cross_compile_init() {
if [[ ! -v ARCH ]]; then
OBJCOPY=objcopy
return 0
fi
if [[ -v LLVM ]]; then
OBJCOPY=llvm-objcopy
else
OBJCOPY="${CROSS_COMPILE:-}objcopy"
fi
}Signature · 1 line
Josh
Song Liu
maintainerRe: [PATCH 14/14] klp-build: Support cross-compilation
On Tue, Mar 17, 2026 at 10:52 AM Josh Poimboeuf <[email protected]> wrote:
[...]
Quoted 8 lines
Quoted 2 lines
Yeah, I think that would be a good idea. Will do that for v2.
So, in general ARCH is complicated. For example:
- ARCH=arm64 would never match "uname -m" (aarch64)
- ARCH=i386 would use the same gcc binary (no cross-compiler needed)
- I'm sure there are many other edge cases...
Agreed. I haven't worked with i386 for a long time, but I did notice the arm64 vs. aarch64 difference.
Quoted 7 lines
Instead of a manual error, it may be simpler to just let the build fail naturally if the user doesn't set the right ARCH.
Though, I think the check can be improved slightly, as ARCH is a reasonably good indicator that cross-compiling is happening. So I can at least add an ARCH check at the beginning like so?
Quoted 12 lines
cross_compile_init() {
if [[ ! -v ARCH ]]; then
OBJCOPY=objcopy
return 0
fi
if [[ -v LLVM ]]; then
OBJCOPY=llvm-objcopy
else
OBJCOPY="${CROSS_COMPILE:-}objcopy"
fi
}Do we need ARCH when CROSS_COMPILE is set? I was under the impression that CROSS_COMPILE doesn't require ARCH.
Thanks,
Song
Josh Poimboeuf
maintainerRe: [PATCH 14/14] klp-build: Support cross-compilation
Quoted 34 lines · Song Liu
On Tue, Mar 17, 2026 at 10:52 AM Josh Poimboeuf <[email protected]> wrote:
[...]Quoted 8 lines
Quoted 2 lines
Yeah, I think that would be a good idea. Will do that for v2.
So, in general ARCH is complicated. For example:
- ARCH=arm64 would never match "uname -m" (aarch64)
- ARCH=i386 would use the same gcc binary (no cross-compiler needed)
- I'm sure there are many other edge cases...Agreed. I haven't worked with i386 for a long time, but I did notice the arm64 vs. aarch64 difference.
Quoted 7 lines
Instead of a manual error, it may be simpler to just let the build fail naturally if the user doesn't set the right ARCH.
Though, I think the check can be improved slightly, as ARCH is a reasonably good indicator that cross-compiling is happening. So I can at least add an ARCH check at the beginning like so?
Quoted 12 lines
cross_compile_init() { if [[ ! -v ARCH ]]; then OBJCOPY=objcopy return 0 fi if [[ -v LLVM ]]; then OBJCOPY=llvm-objcopy else OBJCOPY="${CROSS_COMPILE:-}objcopy" fi }
Quoted 3 lines
Do we need ARCH when
CROSS_COMPILEis set? I was under the impression thatCROSS_COMPILEdoesn't require ARCH.
If CROSS_COMPILE is used without ARCH, it will just try to use the host
arch. I'm not sure if that's considered cross-compiling? I suppose it
should use the CROSS_COMPILE version of objcopy in that case? Though in practice it probably doesn't matter.
I guess the original version of the function is probably fine and we don't need to complicate matters.
Signature · 1 line
Josh
Song Liu
maintainerRe: [PATCH 14/14] klp-build: Support cross-compilation
On Tue, Mar 17, 2026 at 11:53 AM Josh Poimboeuf <[email protected]> wrote:
[...]
Quoted 5 lines
Quoted 4 lines
Do we need ARCH when
CROSS_COMPILEis set? I was under the impression thatCROSS_COMPILEdoesn't require ARCH.
Quoted 7 lines
If
CROSS_COMPILEis used without ARCH, it will just try to use the host
arch. I'm not sure if that's considered cross-compiling? I suppose it
should use theCROSS_COMPILEversion of objcopy in that case? Though in practice it probably doesn't matter.I guess the original version of the function is probably fine and we don't need to complicate matters.
Agreed that the original version works fine. Thanks for bearing with my nitpick on this.
Song
Song Liu
maintainerQuoted 11 lines · Josh Poimboeuf
Port objtool and the klp-build tooling (for building livepatch modules) to arm64.
Note this doesn't bring all the objtool bells and whistles to arm64, nor any of the CFG reverse engineering. This only adds the bare minimum needed for 'objtool --checksum'.
And note that objtool still doesn't get enabled at all for normal arm64 kernel builds, so this doesn't affect any users other than those running klp-build directly.
I run this test [1] with this set on arm64. Everything works as expected.
Thanks for enabling this.
Song
[1] https://lore.kernel.org/live-patching/[email protected]/