Merge tag 'objtool-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Dec 2020 17:08:23 +0000 (09:08 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Dec 2020 17:08:23 +0000 (09:08 -0800)
Pull objtool fix from Ingo Molnar:
 "Fix a segfault that occurs when built with Clang"

* tag 'objtool-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Fix seg fault with Clang non-section symbols

tools/objtool/check.c
tools/objtool/elf.c
tools/objtool/elf.h
tools/objtool/orc_gen.c

index c6ab445..5f8d3ee 100644 (file)
@@ -467,13 +467,20 @@ static int create_static_call_sections(struct objtool_file *file)
 
                /* populate reloc for 'addr' */
                reloc = malloc(sizeof(*reloc));
+
                if (!reloc) {
                        perror("malloc");
                        return -1;
                }
                memset(reloc, 0, sizeof(*reloc));
-               reloc->sym = insn->sec->sym;
-               reloc->addend = insn->offset;
+
+               insn_to_reloc_sym_addend(insn->sec, insn->offset, reloc);
+               if (!reloc->sym) {
+                       WARN_FUNC("static call tramp: missing containing symbol",
+                                 insn->sec, insn->offset);
+                       return -1;
+               }
+
                reloc->type = R_X86_64_PC32;
                reloc->offset = idx * sizeof(struct static_call_site);
                reloc->sec = reloc_sec;
index 4e1d746..be89c74 100644 (file)
@@ -262,6 +262,32 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
        return find_reloc_by_dest_range(elf, sec, offset, 1);
 }
 
+void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
+                             struct reloc *reloc)
+{
+       if (sec->sym) {
+               reloc->sym = sec->sym;
+               reloc->addend = offset;
+               return;
+       }
+
+       /*
+        * The Clang assembler strips section symbols, so we have to reference
+        * the function symbol instead:
+        */
+       reloc->sym = find_symbol_containing(sec, offset);
+       if (!reloc->sym) {
+               /*
+                * Hack alert.  This happens when we need to reference the NOP
+                * pad insn immediately after the function.
+                */
+               reloc->sym = find_symbol_containing(sec, offset - 1);
+       }
+
+       if (reloc->sym)
+               reloc->addend = offset - reloc->sym->offset;
+}
+
 static int read_sections(struct elf *elf)
 {
        Elf_Scn *s = NULL;
index 807f8c6..e6890cc 100644 (file)
@@ -140,6 +140,8 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
                                     unsigned long offset, unsigned int len);
 struct symbol *find_func_containing(struct section *sec, unsigned long offset);
+void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
+                             struct reloc *reloc);
 int elf_rebuild_reloc_section(struct elf *elf, struct section *sec);
 
 #define for_each_sec(file, sec)                                                \
index 235663b..9ce68b3 100644 (file)
@@ -105,30 +105,11 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
        }
        memset(reloc, 0, sizeof(*reloc));
 
-       if (insn_sec->sym) {
-               reloc->sym = insn_sec->sym;
-               reloc->addend = insn_off;
-       } else {
-               /*
-                * The Clang assembler doesn't produce section symbols, so we
-                * have to reference the function symbol instead:
-                */
-               reloc->sym = find_symbol_containing(insn_sec, insn_off);
-               if (!reloc->sym) {
-                       /*
-                        * Hack alert.  This happens when we need to reference
-                        * the NOP pad insn immediately after the function.
-                        */
-                       reloc->sym = find_symbol_containing(insn_sec,
-                                                          insn_off - 1);
-               }
-               if (!reloc->sym) {
-                       WARN("missing symbol for insn at offset 0x%lx\n",
-                            insn_off);
-                       return -1;
-               }
-
-               reloc->addend = insn_off - reloc->sym->offset;
+       insn_to_reloc_sym_addend(insn_sec, insn_off, reloc);
+       if (!reloc->sym) {
+               WARN("missing symbol for insn at offset 0x%lx",
+                    insn_off);
+               return -1;
        }
 
        reloc->type = R_X86_64_PC32;