Create a symbol for each special section entry. This helps objtool extract needed entries. Signed-off-by: Josh Poimboeuf <jpoimboe@xxxxxxxxxx> --- arch/x86/include/asm/alternative.h | 50 ++++++++++++++++++++---------- arch/x86/include/asm/asm.h | 24 +++++++++----- arch/x86/include/asm/bug.h | 2 ++ arch/x86/include/asm/cpufeature.h | 2 ++ arch/x86/include/asm/jump_label.h | 2 ++ include/linux/objtool.h | 31 +++++++++++++++++- tools/objtool/check.c | 22 +++++++++++-- 7 files changed, 104 insertions(+), 29 deletions(-) diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index ba99ef75f56c..2617253bcb00 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -157,7 +157,9 @@ static inline int alternatives_text_reserved(void *start, void *end) #define ALT_CALL_INSTR "call BUG_func" #define b_replacement(num) "664"#num -#define e_replacement(num) "665"#num + +#define __e_replacement(num) __PASTE(665, num) +#define e_replacement(num) __stringify(__e_replacement(num)) #define alt_end_marker "663" #define alt_slen "662b-661b" @@ -203,15 +205,21 @@ static inline int alternatives_text_reserved(void *start, void *end) alt_end_marker ":\n" #define ALTINSTR_ENTRY(ft_flags, num) \ + FAKE_SYMBOL(__alt_, 681f) \ " .long 661b - .\n" /* label */ \ " .long " b_replacement(num)"f - .\n" /* new instruction */ \ " .4byte " __stringify(ft_flags) "\n" /* feature + flags */ \ " .byte " alt_total_slen "\n" /* source len */ \ - " .byte " alt_rlen(num) "\n" /* replacement len */ + " .byte " alt_rlen(num) "\n" /* replacement len */ \ + "681:\n" -#define ALTINSTR_REPLACEMENT(newinstr, num) /* replacement */ \ +#define ALTINSTR_REPLACEMENT(newinstr, num) \ "# ALT: replacement " #num "\n" \ - b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n" + FAKE_SYMBOL(__alt_instr_, __PASTE(__e_replacement(num), f)) \ + b_replacement(num) ":\n" \ + "\t" newinstr "\n" \ + e_replacement(num) ":\n" + /* alternative assembly primitive: */ #define ALTERNATIVE(oldinstr, newinstr, ft_flags) \ @@ -370,12 +378,20 @@ void nop_func(void); * enough information for the alternatives patching code to patch an * instruction. See apply_alternatives(). */ -.macro altinstr_entry orig alt ft_flags orig_len alt_len +.macro ALTINSTR_ENTRY orig alt ft_flags orig_len alt_len + FAKE_SYMBOL(__alt_, 681f) .long \orig - . .long \alt - . .4byte \ft_flags .byte \orig_len .byte \alt_len + 681: +.endm + +.macro ALTINSTR_REPLACEMENT newinstr + FAKE_SYMBOL(__alt_instr_, 681f) + \newinstr + 681: .endm .macro ALT_CALL_INSTR @@ -396,12 +412,12 @@ void nop_func(void); 142: .pushsection .altinstructions,"a" - altinstr_entry 140b,143f,\ft_flags,142b-140b,144f-143f + ALTINSTR_ENTRY 140b,143f,\ft_flags,142b-140b,144f-143f .popsection .pushsection .altinstr_replacement,"ax" 143: - \newinstr + ALTINSTR_REPLACEMENT "\newinstr" 144: .popsection .endm @@ -435,15 +451,15 @@ void nop_func(void); 142: .pushsection .altinstructions,"a" - altinstr_entry 140b,143f,\ft_flags1,142b-140b,144f-143f - altinstr_entry 140b,144f,\ft_flags2,142b-140b,145f-144f + ALTINSTR_ENTRY 140b,143f,\ft_flags1,142b-140b,144f-143f + ALTINSTR_ENTRY 140b,144f,\ft_flags2,142b-140b,145f-144f .popsection .pushsection .altinstr_replacement,"ax" 143: - \newinstr1 + ALTINSTR_REPLACEMENT "\newinstr1" 144: - \newinstr2 + ALTINSTR_REPLACEMENT "\newinstr2" 145: .popsection .endm @@ -457,18 +473,18 @@ void nop_func(void); 142: .pushsection .altinstructions,"a" - altinstr_entry 140b,143f,\ft_flags1,142b-140b,144f-143f - altinstr_entry 140b,144f,\ft_flags2,142b-140b,145f-144f - altinstr_entry 140b,145f,\ft_flags3,142b-140b,146f-145f + ALTINSTR_ENTRY 140b,143f,\ft_flags1,142b-140b,144f-143f + ALTINSTR_ENTRY 140b,144f,\ft_flags2,142b-140b,145f-144f + ALTINSTR_ENTRY 140b,145f,\ft_flags3,142b-140b,146f-145f .popsection .pushsection .altinstr_replacement,"ax" 143: - \newinstr1 + ALTINSTR_REPLACEMENT "\newinstr1" 144: - \newinstr2 + ALTINSTR_REPLACEMENT "\newinstr2" 145: - \newinstr3 + ALTINSTR_REPLACEMENT "\newinstr3" 146: .popsection .endm diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h index 2bec0c89a95c..c337240d342c 100644 --- a/arch/x86/include/asm/asm.h +++ b/arch/x86/include/asm/asm.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_ASM_H #define _ASM_X86_ASM_H +#include <linux/objtool.h> + #ifdef __ASSEMBLY__ # define __ASM_FORM(x, ...) x,## __VA_ARGS__ # define __ASM_FORM_RAW(x, ...) x,## __VA_ARGS__ @@ -149,9 +151,11 @@ static __always_inline __pure void *rip_rel_ptr(void *p) # define _ASM_EXTABLE_TYPE(from, to, type) \ .pushsection "__ex_table","a" ; \ .balign 4 ; \ + FAKE_SYMBOL(__ex_table_, 555f) ; \ .long (from) - . ; \ .long (to) - . ; \ .long type ; \ + 555: ; \ .popsection # ifdef CONFIG_KPROBES @@ -196,19 +200,23 @@ static __always_inline __pure void *rip_rel_ptr(void *p) # define _ASM_EXTABLE_TYPE(from, to, type) \ " .pushsection \"__ex_table\",\"a\"\n" \ " .balign 4\n" \ + FAKE_SYMBOL(__ex_table_, 555f) \ " .long (" #from ") - .\n" \ " .long (" #to ") - .\n" \ " .long " __stringify(type) " \n" \ + " 555:\n" \ " .popsection\n" -# define _ASM_EXTABLE_TYPE_REG(from, to, type, reg) \ - " .pushsection \"__ex_table\",\"a\"\n" \ - " .balign 4\n" \ - " .long (" #from ") - .\n" \ - " .long (" #to ") - .\n" \ - DEFINE_EXTABLE_TYPE_REG \ - "extable_type_reg reg=" __stringify(reg) ", type=" __stringify(type) " \n"\ - UNDEFINE_EXTABLE_TYPE_REG \ +# define _ASM_EXTABLE_TYPE_REG(from, to, type, reg) \ + " .pushsection \"__ex_table\",\"a\"\n" \ + " .balign 4\n" \ + FAKE_SYMBOL(__ex_table_, 555f) \ + " .long (" #from ") - .\n" \ + " .long (" #to ") - .\n" \ + DEFINE_EXTABLE_TYPE_REG \ + "extable_type_reg reg=" __stringify(reg) ", type=" __stringify(type) " \n" \ + UNDEFINE_EXTABLE_TYPE_REG \ + " 555:\n" \ " .popsection\n" /* For C file, we already have NOKPROBE_SYMBOL macro */ diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index a3ec87d198ac..86304d7d68f5 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -27,6 +27,7 @@ do { \ asm_inline volatile("1:\t" ins "\n" \ ".pushsection __bug_table,\"aw\"\n" \ + FAKE_SYMBOL(__bug_table_, . + %c3) \ "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ "\t" __BUG_REL(%c0) "\t# bug_entry::file\n" \ "\t.word %c1" "\t# bug_entry::line\n" \ @@ -45,6 +46,7 @@ do { \ do { \ asm_inline volatile("1:\t" ins "\n" \ ".pushsection __bug_table,\"aw\"\n" \ + FAKE_SYMBOL(__bug_table_, . + %c1) \ "2:\t" __BUG_REL(1b) "\t# bug_entry::bug_addr\n" \ "\t.word %c0" "\t# bug_entry::flags\n" \ "\t.org 2b+%c1\n" \ diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 0b9611da6c53..9decf644d55a 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -178,9 +178,11 @@ static __always_inline bool _static_cpu_has(u16 bit) asm goto(ALTERNATIVE_TERNARY("jmp 6f", %c[feature], "", "jmp %l[t_no]") ".pushsection .altinstr_aux,\"ax\"\n" "6:\n" + FAKE_SYMBOL(__alt_aux_, 681f) " testb %[bitnum], %a[cap_byte]\n" " jnz %l[t_yes]\n" " jmp %l[t_no]\n" + "681:\n" ".popsection\n" : : [feature] "i" (bit), [bitnum] "i" (1 << (bit & 7)), diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h index cbbef32517f0..731d7e69d244 100644 --- a/arch/x86/include/asm/jump_label.h +++ b/arch/x86/include/asm/jump_label.h @@ -15,9 +15,11 @@ #define JUMP_TABLE_ENTRY \ ".pushsection __jump_table, \"aw\" \n\t" \ _ASM_ALIGN "\n\t" \ + FAKE_SYMBOL(__jump_table_, 2f) \ ".long 1b - . \n\t" \ ".long %l[l_yes] - . \n\t" \ _ASM_PTR "%c0 + %c1 - .\n\t" \ + "2:\n\t" \ ".popsection \n\t" #ifdef CONFIG_HAVE_JUMP_LABEL_HACK diff --git a/include/linux/objtool.h b/include/linux/objtool.h index 5e66b6d26df5..ae5030cac10d 100644 --- a/include/linux/objtool.h +++ b/include/linux/objtool.h @@ -10,9 +10,27 @@ #ifndef __ASSEMBLY__ -#define UNWIND_HINT(type, sp_reg, sp_offset, signal) \ +#define DEFINE_FAKE_SYMBOL \ + ".macro fake_symbol name, end\n\t" \ + "#ifdef __x86_64__\n" \ + ".type \\name\\@, @object\n" \ + ".size \\name\\@, \\end - .\n" \ + "\\name\\@:\n" \ + "#endif\n" \ + ".endm\n\t" + +#define UNDEFINE_FAKE_SYMBOL \ + ".purgem fake_symbol\n\t" + +#define FAKE_SYMBOL(name, end) \ + DEFINE_FAKE_SYMBOL \ + "fake_symbol " __stringify(name) ", \"" __stringify(end) "\"\n\t" \ + UNDEFINE_FAKE_SYMBOL + +#define UNWIND_HINT(type, sp_reg, sp_offset, signal) \ "987: \n\t" \ ".pushsection .discard.unwind_hints\n\t" \ + FAKE_SYMBOL(__unwind_hint_, 988f) \ /* struct unwind_hint */ \ ".long 987b - .\n\t" \ ".short " __stringify(sp_offset) "\n\t" \ @@ -20,6 +38,7 @@ ".byte " __stringify(type) "\n\t" \ ".byte " __stringify(signal) "\n\t" \ ".balign 4 \n\t" \ + "988:\n\t" \ ".popsection\n\t" /* @@ -60,6 +79,14 @@ #else /* __ASSEMBLY__ */ +.macro fake_symbol name, end + .type \name\@, @object + .size \name\@, \end - . + \name\@: +.endm + +#define FAKE_SYMBOL(name, end) fake_symbol name, __stringify(end) + /* * This macro indicates that the following intra-function call is valid. * Any non-annotated intra-function call will cause objtool to issue a warning. @@ -94,6 +121,7 @@ .macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 .Lhere_\@: .pushsection .discard.unwind_hints + FAKE_SYMBOL(__unwind_hint_, .Lend_\@) /* struct unwind_hint */ .long .Lhere_\@ - . .short \sp_offset @@ -101,6 +129,7 @@ .byte \type .byte \signal .balign 4 + .Lend_\@: .popsection .endm diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 3c8d0903dfa7..5dd78a7f75c3 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -633,6 +633,18 @@ static void add_dead_ends(struct objtool_file *file) } } +static void create_fake_symbol(struct objtool_file *file, const char *name_pfx, + struct section *sec, unsigned long offset, + size_t size) +{ + char name[256]; + static int ctr; + + snprintf(name, 256, "%s_%d", name_pfx, ctr++); + + elf_create_symbol(file->elf, name, sec, STB_LOCAL, STT_OBJECT, offset, size); +} + static void create_static_call_sections(struct objtool_file *file) { struct static_call_site *site; @@ -664,10 +676,11 @@ static void create_static_call_sections(struct objtool_file *file) idx = 0; list_for_each_entry(insn, &file->static_call_list, call_node) { + unsigned long offset = idx * sizeof(*site); /* populate reloc for 'addr' */ - elf_init_reloc_text_sym(file->elf, sec, idx * sizeof(*site), - idx * 2, insn->sec, insn->offset); + elf_init_reloc_text_sym(file->elf, sec, offset, idx * 2, + insn->sec, insn->offset); /* find key symbol */ key_name = strdup(insn_call_dest(insn)->name); @@ -698,10 +711,13 @@ static void create_static_call_sections(struct objtool_file *file) free(key_name); /* populate reloc for 'key' */ - elf_init_reloc_data_sym(file->elf, sec, idx * sizeof(*site) + 4, + elf_init_reloc_data_sym(file->elf, sec, offset + 4, (idx * 2) + 1, key_sym, is_sibling_call(insn) * STATIC_CALL_SITE_TAIL); + create_fake_symbol(file, "__static_call_site_", sec, + offset, sizeof(*site)); + idx++; } } -- 2.45.2