Objtool is failing to extract text annotations which reference
.altinstr_replacement instructions:

  1) Alternative replacement fake symbols are NOTYPE rather than FUNC,
     and they don't have sym->included set, thus they aren't recognized
     by should_keep_special_sym().

  2) .discard.annotate_insn gets processed before .altinstr_replacement,
     so the referenced (fake) symbols don't have clones yet.

Fix the first issue by checking for a valid clone instead of
sym->included and by accepting NOTYPE symbols when processing
.discard.annotate_insn.

Fix the second issue by deferring text annotation processing until after
the other special sections have been cloned.

Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing 
object files")
Signed-off-by: Josh Poimboeuf <[email protected]>
---
 tools/objtool/klp-diff.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 3303664a39d7..22942f394745 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -1452,6 +1452,7 @@ static int create_fake_symbols(struct elf *elf)
 /* Keep a special section entry if it references an included function */
 static bool should_keep_special_sym(struct elf *elf, struct symbol *sym)
 {
+       bool annotate_insn = !strcmp(sym->sec->name, ".discard.annotate_insn");
        struct reloc *reloc;
 
        if (is_sec_sym(sym) || !sym->sec->rsec)
@@ -1461,7 +1462,16 @@ static bool should_keep_special_sym(struct elf *elf, 
struct symbol *sym)
                if (convert_reloc_sym(elf, reloc))
                        continue;
 
-               if (is_func_sym(reloc->sym) && reloc->sym->included)
+               if (!reloc->sym->clone || is_undef_sym(reloc->sym->clone))
+                       continue;
+
+               /*
+                * Keep special section references to cloned functions.
+                * In some cases annotate_insn can also reference cloned alt
+                * replacement fake symbols; keep those references as well.
+                */
+               if (is_func_sym(reloc->sym) ||
+                   (annotate_insn && is_notype_sym(reloc->sym)))
                        return true;
        }
 
@@ -1605,15 +1615,28 @@ static int clone_special_section(struct elfs *e, struct 
section *patched_sec)
 /* Extract only the needed bits from special sections */
 static int clone_special_sections(struct elfs *e)
 {
-       struct section *patched_sec;
+       struct section *sec, *annotate_insn = NULL;
 
-       for_each_sec(e->patched, patched_sec) {
-               if (is_special_section(patched_sec)) {
-                       if (clone_special_section(e, patched_sec))
+       for_each_sec(e->patched, sec) {
+               if (is_special_section(sec)) {
+                       if (!strcmp(sec->name, ".discard.annotate_insn")) {
+                               annotate_insn = sec;
+                               continue;
+                       }
+                       if (clone_special_section(e, sec))
                                return -1;
                }
        }
 
+       /*
+        * Do .discard.annotate_insn last, it can reference other special
+        * sections (alt replacements) so they need to be cloned first.
+        */
+       if (annotate_insn) {
+               if (clone_special_section(e, annotate_insn))
+                       return -1;
+       }
+
        return 0;
 }
 
-- 
2.53.0


Reply via email to