Special section entry sizes (ALT_ENTRY_SIZE, JUMP_ENTRY_SIZE,
EX_ENTRY_SIZE) are built into objtool from arch-specific headers.
When processing cached unit test objects that were built from a
different kernel version, these compiled-in sizes may not match the
objects' actual entry sizes, causing create_fake_symbols() to
incorrectly parse special sections.

Allow the user to override the compiled-in defaults via environment
variables of the same name.  When unset, behavior is unchanged.  This
will enable a klp-diff unit test runner to pass the correct entry sizes
from test metadata.

Assisted-by: Cursor:claude-4.6-opus
Signed-off-by: Joe Lawrence <[email protected]>
---
 tools/objtool/klp-diff.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index bd8d64f2f3f6..ebe4a2a087ca 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1749,6 +1749,22 @@ static int clone_sym_relocs(struct elfs *e, struct 
symbol *patched_sym)
 
 }
 
+static unsigned int entry_size_from_env(const char *name, unsigned int def)
+{
+       const char *str = getenv(name);
+       char *end;
+       unsigned long val;
+
+       if (!str)
+               return def;
+
+       val = strtoul(str, &end, 10);
+       if (*end || !val)
+               return def;
+
+       return val;
+}
+
 static int create_fake_symbol(struct elf *elf, struct section *sec,
                              unsigned long offset, size_t size)
 {
@@ -1871,6 +1887,21 @@ static int create_fake_symbols(struct elf *elf)
                }
 
                entry_size = sec->sh.sh_entsize;
+
+               /*
+                * Some special sections have multiple relocs per entry,
+                * so the reloc-based heuristic below doesn't work.  Use
+                * the arch-defined entry sizes for known special sections.
+                */
+               if (!entry_size) {
+                       if (!strcmp(sec->name, ".altinstructions"))
+                               entry_size = 
entry_size_from_env("ALT_ENTRY_SIZE", ALT_ENTRY_SIZE);
+                       else if (!strcmp(sec->name, "__jump_table"))
+                               entry_size = 
entry_size_from_env("JUMP_ENTRY_SIZE", JUMP_ENTRY_SIZE);
+                       else if (!strcmp(sec->name, "__ex_table"))
+                               entry_size = 
entry_size_from_env("EX_ENTRY_SIZE", EX_ENTRY_SIZE);
+               }
+
                if (!entry_size) {
                        entry_size = arch_reloc_size(sec->rsec->relocs);
                        if (sec_size(sec) != entry_size * 
sec_num_entries(sec->rsec)) {
-- 
2.53.0


Reply via email to