objtool: optimize add_dead_ends for split sections
Instead of iterating through all instructions to find the last instruction each time .rela.discard.(un)reachable points beyond the section, use find_insn to locate the last instruction by looking at the last bytes of the section instead. Suggested-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Sami Tolvanen <samitolvanen@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/20200421220843.188260-3-samitolvanen@google.com
This commit is contained in:
parent
28fe1d7bf8
commit
6b5dd716da
@ -322,6 +322,19 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct instruction *find_last_insn(struct objtool_file *file,
|
||||
struct section *sec)
|
||||
{
|
||||
struct instruction *insn = NULL;
|
||||
unsigned int offset;
|
||||
unsigned int end = (sec->len > 10) ? sec->len - 10 : 0;
|
||||
|
||||
for (offset = sec->len - 1; offset >= end && !insn; offset--)
|
||||
insn = find_insn(file, sec, offset);
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark "ud2" instructions and manually annotated dead ends.
|
||||
*/
|
||||
@ -330,7 +343,6 @@ static int add_dead_ends(struct objtool_file *file)
|
||||
struct section *sec;
|
||||
struct rela *rela;
|
||||
struct instruction *insn;
|
||||
bool found;
|
||||
|
||||
/*
|
||||
* By default, "ud2" is a dead end unless otherwise annotated, because
|
||||
@ -356,15 +368,8 @@ static int add_dead_ends(struct objtool_file *file)
|
||||
if (insn)
|
||||
insn = list_prev_entry(insn, list);
|
||||
else if (rela->addend == rela->sym->sec->len) {
|
||||
found = false;
|
||||
list_for_each_entry_reverse(insn, &file->insn_list, list) {
|
||||
if (insn->sec == rela->sym->sec) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
insn = find_last_insn(file, rela->sym->sec);
|
||||
if (!insn) {
|
||||
WARN("can't find unreachable insn at %s+0x%x",
|
||||
rela->sym->sec->name, rela->addend);
|
||||
return -1;
|
||||
@ -398,15 +403,8 @@ reachable:
|
||||
if (insn)
|
||||
insn = list_prev_entry(insn, list);
|
||||
else if (rela->addend == rela->sym->sec->len) {
|
||||
found = false;
|
||||
list_for_each_entry_reverse(insn, &file->insn_list, list) {
|
||||
if (insn->sec == rela->sym->sec) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
insn = find_last_insn(file, rela->sym->sec);
|
||||
if (!insn) {
|
||||
WARN("can't find reachable insn at %s+0x%x",
|
||||
rela->sym->sec->name, rela->addend);
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user