objtool: Decode jump_entry::key addend
authorPeter Zijlstra <peterz@infradead.org>
Thu, 6 May 2021 19:34:02 +0000 (21:34 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 12 May 2021 12:54:55 +0000 (14:54 +0200)
Teach objtool about the the low bits in the struct static_key pointer.

That is, the low two bits of @key in:

  struct jump_entry {
s32 code;
s32 target;
long key;
  }

as found in the __jump_table section. Since @key has a relocation to
the variable (to be resolved by the linker), the low two bits will be
reflected in the relocation's addend.

As such, find the reloc and store the addend, such that we can access
these bits.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20210506194158.028024143@infradead.org
tools/objtool/arch/x86/include/arch/special.h
tools/objtool/include/objtool/special.h
tools/objtool/special.c

index 14271cca0c740372aeea4fe40c60c8f7305a3676..f2918f789a0a3d122a4a4255cb7a158469047e96 100644 (file)
@@ -9,6 +9,7 @@
 #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
index 8a09f4e9d480e5cc6a03eddffb938cf54675d066..dc4721e190023296af0e09761d0e1f40b32ddd8c 100644 (file)
@@ -27,6 +27,7 @@ struct special_alt {
        unsigned long new_off;
 
        unsigned int orig_len, new_len; /* group only */
+       u8 key_addend;
 };
 
 int special_get_alts(struct elf *elf, struct list_head *alts);
index 07b21cfabf5c098365773f96f9cee5ad7d9511ed..bc925cf19e2dee7a3087829f4800ac71e0c6f6ca 100644 (file)
@@ -23,6 +23,7 @@ struct special_entry {
        unsigned char size, orig, new;
        unsigned char orig_len, new_len; /* group only */
        unsigned char feature; /* ALTERNATIVE macro CPU feature */
+       unsigned char key; /* jump_label key */
 };
 
 struct special_entry entries[] = {
@@ -42,6 +43,7 @@ struct special_entry entries[] = {
                .size = JUMP_ENTRY_SIZE,
                .orig = JUMP_ORIG_OFFSET,
                .new = JUMP_NEW_OFFSET,
+               .key = JUMP_KEY_OFFSET,
        },
        {
                .sec = "__ex_table",
@@ -122,6 +124,18 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
                        alt->new_off -= 0x7ffffff0;
        }
 
+       if (entry->key) {
+               struct reloc *key_reloc;
+
+               key_reloc = find_reloc_by_dest(elf, sec, offset + entry->key);
+               if (!key_reloc) {
+                       WARN_FUNC("can't find key reloc",
+                                 sec, offset + entry->key);
+                       return -1;
+               }
+               alt->key_addend = key_reloc->addend;
+       }
+
        return 0;
 }