#include <linux/hashtable.h>
#include <linux/kernel.h>
#include <linux/static_call_types.h>
+#include <linux/string.h>
struct alternative {
struct alternative *next;
struct section *rsec;
struct reloc *reloc;
struct instruction *insn;
- s64 addend;
+ unsigned long offset;
/*
* Check for manually annotated dead ends.
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;
}
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;
}
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");
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;
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;