Merge tag 'loongarch-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai...
[sfrench/cifs-2.6.git] / tools / objtool / check.c
index eb7e12ebc1d06afba3ddb9544ef8962f794ddd30..0b10ad00866867d9f4ba6787ca000f43bed230be 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/hashtable.h>
 #include <linux/kernel.h>
 #include <linux/static_call_types.h>
+#include <linux/string.h>
 
 struct alternative {
        struct alternative *next;
@@ -584,7 +585,7 @@ static int add_dead_ends(struct objtool_file *file)
        struct section *rsec;
        struct reloc *reloc;
        struct instruction *insn;
-       s64 addend;
+       unsigned long offset;
 
        /*
         * Check for manually annotated dead ends.
@@ -594,27 +595,28 @@ static int add_dead_ends(struct objtool_file *file)
                goto reachable;
 
        for_each_reloc(rsec, reloc) {
-
-               if (reloc->sym->type != STT_SECTION) {
+               if (reloc->sym->type == STT_SECTION) {
+                       offset = reloc_addend(reloc);
+               } else if (reloc->sym->local_label) {
+                       offset = reloc->sym->offset;
+               } else {
                        WARN("unexpected relocation symbol type in %s", rsec->name);
                        return -1;
                }
 
-               addend = reloc_addend(reloc);
-
-               insn = find_insn(file, reloc->sym->sec, addend);
+               insn = find_insn(file, reloc->sym->sec, offset);
                if (insn)
                        insn = prev_insn_same_sec(file, insn);
-               else if (addend == reloc->sym->sec->sh.sh_size) {
+               else if (offset == reloc->sym->sec->sh.sh_size) {
                        insn = find_last_insn(file, reloc->sym->sec);
                        if (!insn) {
                                WARN("can't find unreachable insn at %s+0x%" PRIx64,
-                                    reloc->sym->sec->name, addend);
+                                    reloc->sym->sec->name, offset);
                                return -1;
                        }
                } else {
                        WARN("can't find unreachable insn at %s+0x%" PRIx64,
-                            reloc->sym->sec->name, addend);
+                            reloc->sym->sec->name, offset);
                        return -1;
                }
 
@@ -633,27 +635,28 @@ reachable:
                return 0;
 
        for_each_reloc(rsec, reloc) {
-
-               if (reloc->sym->type != STT_SECTION) {
+               if (reloc->sym->type == STT_SECTION) {
+                       offset = reloc_addend(reloc);
+               } else if (reloc->sym->local_label) {
+                       offset = reloc->sym->offset;
+               } else {
                        WARN("unexpected relocation symbol type in %s", rsec->name);
                        return -1;
                }
 
-               addend = reloc_addend(reloc);
-
-               insn = find_insn(file, reloc->sym->sec, addend);
+               insn = find_insn(file, reloc->sym->sec, offset);
                if (insn)
                        insn = prev_insn_same_sec(file, insn);
-               else if (addend == reloc->sym->sec->sh.sh_size) {
+               else if (offset == reloc->sym->sec->sh.sh_size) {
                        insn = find_last_insn(file, reloc->sym->sec);
                        if (!insn) {
                                WARN("can't find reachable insn at %s+0x%" PRIx64,
-                                    reloc->sym->sec->name, addend);
+                                    reloc->sym->sec->name, offset);
                                return -1;
                        }
                } else {
                        WARN("can't find reachable insn at %s+0x%" PRIx64,
-                            reloc->sym->sec->name, addend);
+                            reloc->sym->sec->name, offset);
                        return -1;
                }
 
@@ -2224,6 +2227,7 @@ static int read_unwind_hints(struct objtool_file *file)
        struct unwind_hint *hint;
        struct instruction *insn;
        struct reloc *reloc;
+       unsigned long offset;
        int i;
 
        sec = find_section_by_name(file->elf, ".discard.unwind_hints");
@@ -2251,7 +2255,16 @@ static int read_unwind_hints(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
+               if (reloc->sym->type == STT_SECTION) {
+                       offset = reloc_addend(reloc);
+               } else if (reloc->sym->local_label) {
+                       offset = reloc->sym->offset;
+               } else {
+                       WARN("unexpected relocation symbol type in %s", sec->rsec->name);
+                       return -1;
+               }
+
+               insn = find_insn(file, reloc->sym->sec, offset);
                if (!insn) {
                        WARN("can't find insn for unwind_hints[%d]", i);
                        return -1;
@@ -2522,6 +2535,9 @@ static int classify_symbols(struct objtool_file *file)
        struct symbol *func;
 
        for_each_sym(file, func) {
+               if (func->type == STT_NOTYPE && strstarts(func->name, ".L"))
+                       func->local_label = true;
+
                if (func->bind != STB_GLOBAL)
                        continue;