Skip to content

Commit d5ab2bc

Browse files
seehearfeelchenhuacai
authored andcommitted
objtool: Check local label in add_dead_ends()
When update the latest upstream gcc and binutils, it generates more objtool warnings on LoongArch, like this: init/main.o: warning: objtool: unexpected relocation symbol type in .rela.discard.unreachable We can see that the reloc sym name is local label instead of section in relocation section '.rela.discard.unreachable', in this case, the reloc sym type is STT_NOTYPE instead of STT_SECTION. As suggested by Peter Zijlstra, we add a "local_label" member in struct symbol, then set it as true if symbol type is STT_NOTYPE and symbol name starts with ".L" string in classify_symbols(). Let's check reloc->sym->local_label to not return -1 in add_dead_ends(), and also use reloc->sym->offset instead of reloc addend which is 0 to find the corresponding instruction. At the same time, let's replace the variable "addend" with "offset" to reflect the reality. Here are some detailed info: [fedora@linux 6.8.test]$ gcc --version gcc (GCC) 14.0.1 20240129 (experimental) [fedora@linux 6.8.test]$ as --version GNU assembler (GNU Binutils) 2.42.50.20240129 [fedora@linux 6.8.test]$ readelf -r init/main.o | grep -A 2 "rela.discard.unreachable" Relocation section '.rela.discard.unreachable' at offset 0x6028 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend 000000000000 00d900000063 R_LARCH_32_PCREL 00000000000002c4 .L500^B1 + 0 Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 3c7266c commit d5ab2bc

File tree

2 files changed

+24
-17
lines changed

2 files changed

+24
-17
lines changed

tools/objtool/check.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/hashtable.h>
2121
#include <linux/kernel.h>
2222
#include <linux/static_call_types.h>
23+
#include <linux/string.h>
2324

2425
struct alternative {
2526
struct alternative *next;
@@ -584,7 +585,7 @@ static int add_dead_ends(struct objtool_file *file)
584585
struct section *rsec;
585586
struct reloc *reloc;
586587
struct instruction *insn;
587-
s64 addend;
588+
unsigned long offset;
588589

589590
/*
590591
* Check for manually annotated dead ends.
@@ -594,27 +595,28 @@ static int add_dead_ends(struct objtool_file *file)
594595
goto reachable;
595596

596597
for_each_reloc(rsec, reloc) {
597-
598-
if (reloc->sym->type != STT_SECTION) {
598+
if (reloc->sym->type == STT_SECTION) {
599+
offset = reloc_addend(reloc);
600+
} else if (reloc->sym->local_label) {
601+
offset = reloc->sym->offset;
602+
} else {
599603
WARN("unexpected relocation symbol type in %s", rsec->name);
600604
return -1;
601605
}
602606

603-
addend = reloc_addend(reloc);
604-
605-
insn = find_insn(file, reloc->sym->sec, addend);
607+
insn = find_insn(file, reloc->sym->sec, offset);
606608
if (insn)
607609
insn = prev_insn_same_sec(file, insn);
608-
else if (addend == reloc->sym->sec->sh.sh_size) {
610+
else if (offset == reloc->sym->sec->sh.sh_size) {
609611
insn = find_last_insn(file, reloc->sym->sec);
610612
if (!insn) {
611613
WARN("can't find unreachable insn at %s+0x%" PRIx64,
612-
reloc->sym->sec->name, addend);
614+
reloc->sym->sec->name, offset);
613615
return -1;
614616
}
615617
} else {
616618
WARN("can't find unreachable insn at %s+0x%" PRIx64,
617-
reloc->sym->sec->name, addend);
619+
reloc->sym->sec->name, offset);
618620
return -1;
619621
}
620622

@@ -633,27 +635,28 @@ static int add_dead_ends(struct objtool_file *file)
633635
return 0;
634636

635637
for_each_reloc(rsec, reloc) {
636-
637-
if (reloc->sym->type != STT_SECTION) {
638+
if (reloc->sym->type == STT_SECTION) {
639+
offset = reloc_addend(reloc);
640+
} else if (reloc->sym->local_label) {
641+
offset = reloc->sym->offset;
642+
} else {
638643
WARN("unexpected relocation symbol type in %s", rsec->name);
639644
return -1;
640645
}
641646

642-
addend = reloc_addend(reloc);
643-
644-
insn = find_insn(file, reloc->sym->sec, addend);
647+
insn = find_insn(file, reloc->sym->sec, offset);
645648
if (insn)
646649
insn = prev_insn_same_sec(file, insn);
647-
else if (addend == reloc->sym->sec->sh.sh_size) {
650+
else if (offset == reloc->sym->sec->sh.sh_size) {
648651
insn = find_last_insn(file, reloc->sym->sec);
649652
if (!insn) {
650653
WARN("can't find reachable insn at %s+0x%" PRIx64,
651-
reloc->sym->sec->name, addend);
654+
reloc->sym->sec->name, offset);
652655
return -1;
653656
}
654657
} else {
655658
WARN("can't find reachable insn at %s+0x%" PRIx64,
656-
reloc->sym->sec->name, addend);
659+
reloc->sym->sec->name, offset);
657660
return -1;
658661
}
659662

@@ -2522,6 +2525,9 @@ static int classify_symbols(struct objtool_file *file)
25222525
struct symbol *func;
25232526

25242527
for_each_sym(file, func) {
2528+
if (func->type == STT_NOTYPE && strstarts(func->name, ".L"))
2529+
func->local_label = true;
2530+
25252531
if (func->bind != STB_GLOBAL)
25262532
continue;
25272533

tools/objtool/include/objtool/elf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct symbol {
6767
u8 profiling_func : 1;
6868
u8 warned : 1;
6969
u8 embedded_insn : 1;
70+
u8 local_label : 1;
7071
struct list_head pv_target;
7172
struct reloc *relocs;
7273
};

0 commit comments

Comments
 (0)