In preparation for adding arm64 support for "objtool klp checksum/diff"
to enable livepatch module generation, annotate special section entries.

This will allow objtool to determine the size and location of the
entries and to extract them when needed.

A new ANNOTATE_DATA_SPECIAL_END annotation is added to mark the end of
special data blocks, which is needed because arm64's replacement
instructions are emitted in .text rather than .altinstr_replacement, so
there's otherwise no way to determine where the last replacement block
ends.

Signed-off-by: Josh Poimboeuf <[email protected]>
---
 arch/arm64/include/asm/alternative-macros.h | 27 ++++++++++++++++-----
 arch/arm64/include/asm/asm-bug.h            |  2 ++
 arch/arm64/include/asm/asm-extable.h        | 21 ++++++++++------
 arch/arm64/include/asm/jump_label.h         |  2 ++
 arch/arm64/kernel/asm-offsets.c             |  5 ++++
 include/linux/annotate.h                    | 14 ++++++++++-
 include/linux/objtool_types.h               |  1 +
 tools/include/linux/objtool_types.h         |  1 +
 tools/objtool/klp-diff.c                    |  5 +++-
 9 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/alternative-macros.h 
b/arch/arm64/include/asm/alternative-macros.h
index 8624166248528..ba86d655af1d7 100644
--- a/arch/arm64/include/asm/alternative-macros.h
+++ b/arch/arm64/include/asm/alternative-macros.h
@@ -3,11 +3,16 @@
 #define __ASM_ALTERNATIVE_MACROS_H
 
 #include <linux/const.h>
+#include <linux/annotate.h>
 #include <vdso/bits.h>
 
 #include <asm/cpucaps.h>
 #include <asm/insn-def.h>
 
+#ifndef COMPILE_OFFSETS
+#include <asm/asm-offsets.h>
+#endif
+
 /*
  * Binutils 2.27.0 can't handle a 'UL' suffix on constants, so for the assembly
  * macros below we must use we must use `(1 << ARM64_CB_SHIFT)`.
@@ -58,15 +63,18 @@
        "661:\n\t"                                                      \
        oldinstr "\n"                                                   \
        "662:\n"                                                        \
-       ".pushsection .altinstructions,\"a\"\n"                         \
+       ".pushsection .altinstructions,\"aM\", @progbits, "             \
+                     __stringify(ALT_INSTR_SIZE) "\n"                  \
        ALTINSTR_ENTRY(cpucap)                                          \
        ".popsection\n"                                                 \
        ".subsection 1\n"                                               \
+       ANNOTATE_DATA_SPECIAL "\n"                                      \
        "663:\n\t"                                                      \
        newinstr "\n"                                                   \
        "664:\n\t"                                                      \
        ".org   . - (664b-663b) + (662b-661b)\n\t"                      \
        ".org   . - (662b-661b) + (664b-663b)\n\t"                      \
+       ANNOTATE_DATA_SPECIAL_END "\n\t"                                        
\
        ".previous\n"                                                   \
        ".endif\n"
 
@@ -75,7 +83,8 @@
        "661:\n\t"                                                      \
        oldinstr "\n"                                                   \
        "662:\n"                                                        \
-       ".pushsection .altinstructions,\"a\"\n"                         \
+       ".pushsection .altinstructions,\"aM\", @progbits, "             \
+                     __stringify(ALT_INSTR_SIZE) "\n"                  \
        ALTINSTR_ENTRY_CB(cpucap, cb)                                   \
        ".popsection\n"                                                 \
        "663:\n\t"                                                      \
@@ -102,13 +111,15 @@
 .macro alternative_insn insn1, insn2, cap, enable = 1
        .if \enable
 661:   \insn1
-662:   .pushsection .altinstructions, "a"
+662:   .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE
        altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
        .popsection
        .subsection 1
+       ANNOTATE_DATA_SPECIAL
 663:   \insn2
 664:   .org    . - (664b-663b) + (662b-661b)
        .org    . - (662b-661b) + (664b-663b)
+       ANNOTATE_DATA_SPECIAL_END
        .previous
        .endif
 .endm
@@ -137,7 +148,7 @@
  */
 .macro alternative_if_not cap
        .set .Lasm_alt_mode, 0
-       .pushsection .altinstructions, "a"
+       .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE
        altinstruction_entry 661f, 663f, \cap, 662f-661f, 664f-663f
        .popsection
 661:
@@ -145,17 +156,18 @@
 
 .macro alternative_if cap
        .set .Lasm_alt_mode, 1
-       .pushsection .altinstructions, "a"
+       .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE
        altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
        .popsection
        .subsection 1
        .align 2        /* So GAS knows label 661 is suitably aligned */
+       ANNOTATE_DATA_SPECIAL
 661:
 .endm
 
 .macro alternative_cb cap, cb
        .set .Lasm_alt_mode, 0
-       .pushsection .altinstructions, "a"
+       .pushsection .altinstructions, "aM", @progbits, ALT_INSTR_SIZE
        altinstruction_entry 661f, \cb, (1 << ARM64_CB_SHIFT) | \cap, 
662f-661f, 0
        .popsection
 661:
@@ -168,7 +180,9 @@
 662:
        .if .Lasm_alt_mode==0
        .subsection 1
+       ANNOTATE_DATA_SPECIAL
        .else
+       ANNOTATE_DATA_SPECIAL_END
        .previous
        .endif
 663:
@@ -182,6 +196,7 @@
        .org    . - (664b-663b) + (662b-661b)
        .org    . - (662b-661b) + (664b-663b)
        .if .Lasm_alt_mode==0
+       ANNOTATE_DATA_SPECIAL_END
        .previous
        .endif
 .endm
diff --git a/arch/arm64/include/asm/asm-bug.h b/arch/arm64/include/asm/asm-bug.h
index a5f13801b7840..22e1a9df9851d 100644
--- a/arch/arm64/include/asm/asm-bug.h
+++ b/arch/arm64/include/asm/asm-bug.h
@@ -5,6 +5,7 @@
  */
 #define __ASM_ASM_BUG_H
 
+#include <linux/annotate.h>
 #include <asm/brk-imm.h>
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
@@ -24,6 +25,7 @@
 #define __BUG_ENTRY_START                              \
                .pushsection __bug_table,"aw";          \
                .align 2;                               \
+               __ANNOTATE_DATA_SPECIAL;                \
        14470:  .long 14471f - .;                       \
 
 #define __BUG_ENTRY_END                                        \
diff --git a/arch/arm64/include/asm/asm-extable.h 
b/arch/arm64/include/asm/asm-extable.h
index d67e2fdd1aee5..e81700edbb936 100644
--- a/arch/arm64/include/asm/asm-extable.h
+++ b/arch/arm64/include/asm/asm-extable.h
@@ -5,6 +5,10 @@
 #include <linux/bits.h>
 #include <asm/gpr-num.h>
 
+#ifndef COMPILE_OFFSETS
+#include <asm/asm-offsets.h>
+#endif
+
 #define EX_TYPE_NONE                   0
 #define EX_TYPE_BPF                    1
 #define EX_TYPE_UACCESS_ERR_ZERO       2
@@ -29,13 +33,13 @@
 
 #ifdef __ASSEMBLER__
 
-#define __ASM_EXTABLE_RAW(insn, fixup, type, data)     \
-       .pushsection    __ex_table, "a";                \
-       .align          2;                              \
-       .long           ((insn) - .);                   \
-       .long           ((fixup) - .);                  \
-       .short          (type);                         \
-       .short          (data);                         \
+#define __ASM_EXTABLE_RAW(insn, fixup, type, data)                     \
+       .pushsection    __ex_table, "aM", @progbits, EXTABLE_SIZE;      \
+       .align          2;                                              \
+       .long           ((insn) - .);                                   \
+       .long           ((fixup) - .);                                  \
+       .short          (type);                                         \
+       .short          (data);                                         \
        .popsection;
 
 #define EX_DATA_REG(reg, gpr)  \
@@ -82,7 +86,8 @@
 #include <linux/stringify.h>
 
 #define __ASM_EXTABLE_RAW(insn, fixup, type, data)     \
-       ".pushsection   __ex_table, \"a\"\n"            \
+       ".pushsection   __ex_table, \"aM\", @progbits, "\
+                       __stringify(EXTABLE_SIZE) "\n"  \
        ".align         2\n"                            \
        ".long          ((" insn ") - .)\n"             \
        ".long          ((" fixup ") - .)\n"            \
diff --git a/arch/arm64/include/asm/jump_label.h 
b/arch/arm64/include/asm/jump_label.h
index 0cb211d3607d3..4dacb28641d72 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -11,6 +11,7 @@
 #ifndef __ASSEMBLER__
 
 #include <linux/types.h>
+#include <linux/annotate.h>
 #include <asm/insn.h>
 
 #define HAVE_JUMP_LABEL_BATCH
@@ -19,6 +20,7 @@
 #define JUMP_TABLE_ENTRY(key, label)                   \
        ".pushsection   __jump_table, \"aw\"\n\t"       \
        ".align         3\n\t"                          \
+       ANNOTATE_DATA_SPECIAL "\n\t"                    \
        ".long          1b - ., " label " - .\n\t"      \
        ".quad          " key " - .\n\t"                \
        ".popsection\n\t"
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 44b92f582c127..76251586e31c7 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -23,6 +23,8 @@
 #include <asm/suspend.h>
 #include <linux/kbuild.h>
 #include <linux/arm-smccc.h>
+#include <asm/alternative.h>
+#include <asm/extable.h>
 
 int main(void)
 {
@@ -185,5 +187,8 @@ int main(void)
 #endif
   DEFINE(PIE_E0_ASM, PIE_E0);
   DEFINE(PIE_E1_ASM, PIE_E1);
+  BLANK();
+  DEFINE(ALT_INSTR_SIZE,               sizeof(struct alt_instr));
+  DEFINE(EXTABLE_SIZE,                 sizeof(struct exception_table_entry));
   return 0;
 }
diff --git a/include/linux/annotate.h b/include/linux/annotate.h
index 2f1599c9e5732..7f5aa15f353d6 100644
--- a/include/linux/annotate.h
+++ b/include/linux/annotate.h
@@ -3,6 +3,7 @@
 #define _LINUX_ANNOTATE_H
 
 #include <linux/objtool_types.h>
+#include <linux/stringify.h>
 
 #ifdef CONFIG_OBJTOOL
 
@@ -11,6 +12,10 @@
        .long label - ., type;                                          \
        .popsection
 
+#define __ASM_ANNOTATE_DATA(type)                                      \
+912:                                                                   \
+       __ASM_ANNOTATE(.discard.annotate_data, 912b, type)
+
 #ifndef __ASSEMBLY__
 
 #define ASM_ANNOTATE_LABEL(label, type)                                        
\
@@ -39,6 +44,9 @@
 #endif /* __ASSEMBLY__ */
 
 #else /* !CONFIG_OBJTOOL */
+
+#define __ASM_ANNOTATE_DATA(type)
+
 #ifndef __ASSEMBLY__
 #define ASM_ANNOTATE_LABEL(label, type) ""
 #define ASM_ANNOTATE(type)
@@ -106,10 +114,12 @@
 #define ANNOTATE_NOCFI_SYM(sym)                asm(ASM_ANNOTATE_LABEL(sym, 
ANNOTYPE_NOCFI))
 
 /*
- * Annotate a special section entry.  This emables livepatch module generation
+ * Annotate a special section entry.  This enables livepatch module generation
  * to find and extract individual special section entries as needed.
  */
 #define ANNOTATE_DATA_SPECIAL          ASM_ANNOTATE_DATA(ANNOTYPE_DATA_SPECIAL)
+#define __ANNOTATE_DATA_SPECIAL                
__ASM_ANNOTATE_DATA(ANNOTYPE_DATA_SPECIAL)
+#define ANNOTATE_DATA_SPECIAL_END      
ASM_ANNOTATE_DATA(ANNOTYPE_DATA_SPECIAL_END)
 
 #else /* __ASSEMBLY__ */
 #define ANNOTATE_NOENDBR               ANNOTATE type=ANNOTYPE_NOENDBR
@@ -122,6 +132,8 @@
 #define ANNOTATE_REACHABLE             ANNOTATE type=ANNOTYPE_REACHABLE
 #define ANNOTATE_NOCFI_SYM             ANNOTATE type=ANNOTYPE_NOCFI
 #define ANNOTATE_DATA_SPECIAL          ANNOTATE_DATA type=ANNOTYPE_DATA_SPECIAL
+#define __ANNOTATE_DATA_SPECIAL                
__ASM_ANNOTATE_DATA(ANNOTYPE_DATA_SPECIAL)
+#define ANNOTATE_DATA_SPECIAL_END      ANNOTATE_DATA 
type=ANNOTYPE_DATA_SPECIAL_END
 #endif /* __ASSEMBLY__ */
 
 #endif /* _LINUX_ANNOTATE_H */
diff --git a/include/linux/objtool_types.h b/include/linux/objtool_types.h
index c6def4049b1ae..744118ffd025f 100644
--- a/include/linux/objtool_types.h
+++ b/include/linux/objtool_types.h
@@ -68,5 +68,6 @@ struct unwind_hint {
 #define ANNOTYPE_NOCFI                 9
 
 #define ANNOTYPE_DATA_SPECIAL          1
+#define ANNOTYPE_DATA_SPECIAL_END      2
 
 #endif /* _LINUX_OBJTOOL_TYPES_H */
diff --git a/tools/include/linux/objtool_types.h 
b/tools/include/linux/objtool_types.h
index c6def4049b1ae..744118ffd025f 100644
--- a/tools/include/linux/objtool_types.h
+++ b/tools/include/linux/objtool_types.h
@@ -68,5 +68,6 @@ struct unwind_hint {
 #define ANNOTYPE_NOCFI                 9
 
 #define ANNOTYPE_DATA_SPECIAL          1
+#define ANNOTYPE_DATA_SPECIAL_END      2
 
 #endif /* _LINUX_OBJTOOL_TYPES_H */
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index f8787d7d14547..6a1cec57dc6a3 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1667,7 +1667,10 @@ static int create_fake_symbols(struct elf *elf)
                size = 0;
                next_reloc = reloc;
                for_each_reloc_continue(sec->rsec, next_reloc) {
-                       if (annotype(elf, sec, next_reloc) != 
ANNOTYPE_DATA_SPECIAL ||
+                       unsigned int next_type = annotype(elf, sec, next_reloc);
+
+                       if ((next_type != ANNOTYPE_DATA_SPECIAL &&
+                            next_type != ANNOTYPE_DATA_SPECIAL_END) ||
                            next_reloc->sym->sec != reloc->sym->sec)
                                continue;
 
-- 
2.53.0


Reply via email to