aboutsummaryrefslogtreecommitdiffstats
path: root/tools/objtool/special.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2021-05-06 21:34:02 +0200
committerIngo Molnar <mingo@kernel.org>2021-05-12 14:54:55 +0200
commitcbf82a3dc241aea82b941a872ed5c52f6af527ea (patch)
treee47c96646bba61f34939a7807e371a7b00b87d0c /tools/objtool/special.c
parentjump_label, x86: Emit short JMP (diff)
downloadlinux-dev-cbf82a3dc241aea82b941a872ed5c52f6af527ea.tar.xz
linux-dev-cbf82a3dc241aea82b941a872ed5c52f6af527ea.zip
objtool: Decode jump_entry::key addend
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
Diffstat (limited to 'tools/objtool/special.c')
-rw-r--r--tools/objtool/special.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index 07b21cfabf5c..bc925cf19e2d 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -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;
}