[PATCH] objtool: Refactor insn search in add_dead_ends()

From: Kamalesh Babulal
Date: Mon Oct 23 2017 - 01:02:03 EST


Move the search for instruction dead_end into helper function
__add_dead_ends(), instead of duplicating the search for unreachable
and reachable sections in add_dead_ends().

Cc: Ingo Molnar <mingo@xxxxxxxxxx>
Signed-off-by: Kamalesh Babulal <kamalesh@xxxxxxxxxxxxxxxxxx>
---
tools/objtool/check.c | 108 +++++++++++++++++++++++---------------------------
1 file changed, 50 insertions(+), 58 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index c0e26ad1fa7e..c82966b3ad96 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -303,36 +303,23 @@ static int decode_instructions(struct objtool_file *file)
return ret;
}

-/*
- * Mark "ud2" instructions and manually annotated dead ends.
- */
-static int add_dead_ends(struct objtool_file *file)
+static int __add_dead_ends(struct objtool_file *file, struct section *sec,
+ bool unreachable_sec)
{
- struct section *sec;
- struct rela *rela;
+ char warn_str[12] = "unreachable";
struct instruction *insn;
+ struct rela *rela;
bool found;

- /*
- * By default, "ud2" is a dead end unless otherwise annotated, because
- * GCC 7 inserts it for certain divide-by-zero cases.
- */
- for_each_insn(file, insn)
- if (insn->type == INSN_BUG)
- insn->dead_end = true;
-
- /*
- * Check for manually annotated dead ends.
- */
- sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
- if (!sec)
- goto reachable;
+ if (!unreachable_sec)
+ strcpy(warn_str, "reachable");

list_for_each_entry(rela, &sec->rela_list, list) {
if (rela->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", sec->name);
+ WARN("Unexpected relocation symbol type in %s", sec->name);
return -1;
}
+
insn = find_insn(file, rela->sym->sec, rela->addend);
if (insn)
insn = list_prev_entry(insn, list);
@@ -346,19 +333,54 @@ static int add_dead_ends(struct objtool_file *file)
}

if (!found) {
- WARN("can't find unreachable insn at %s+0x%x",
- rela->sym->sec->name, rela->addend);
+ WARN("can't find %s insn at %s+0x%x",
+ warn_str, rela->sym->sec->name,
+ rela->addend);
return -1;
}
} else {
- WARN("can't find unreachable insn at %s+0x%x",
- rela->sym->sec->name, rela->addend);
+ WARN("can't find %s insn at %s+0x%x",
+ warn_str, rela->sym->sec->name, rela->addend);
return -1;
}

- insn->dead_end = true;
+ /*
+ * reachable section's insn->dead_end are false.
+ */
+ insn->dead_end = unreachable_sec;
}

+ return 0;
+}
+
+/*
+ * Mark "ud2" instructions and manually annotated dead ends.
+ */
+static int add_dead_ends(struct objtool_file *file)
+{
+ struct section *sec;
+ struct instruction *insn;
+ int ret;
+
+ /*
+ * By default, "ud2" is a dead end unless otherwise annotated, because
+ * GCC 7 inserts it for certain divide-by-zero cases.
+ */
+ for_each_insn(file, insn)
+ if (insn->type == INSN_BUG)
+ insn->dead_end = true;
+
+ /*
+ * Check for manually annotated dead ends.
+ */
+ sec = find_section_by_name(file->elf, ".rela.discard.unreachable");
+ if (!sec)
+ goto reachable;
+
+ ret = __add_dead_ends(file, sec, true);
+ if (ret == -1)
+ return ret;
+
reachable:
/*
* These manually annotated reachable checks are needed for GCC 4.4,
@@ -370,38 +392,8 @@ static int add_dead_ends(struct objtool_file *file)
if (!sec)
return 0;

- list_for_each_entry(rela, &sec->rela_list, list) {
- if (rela->sym->type != STT_SECTION) {
- WARN("unexpected relocation symbol type in %s", sec->name);
- return -1;
- }
- insn = find_insn(file, rela->sym->sec, rela->addend);
- 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) {
- WARN("can't find reachable insn at %s+0x%x",
- rela->sym->sec->name, rela->addend);
- return -1;
- }
- } else {
- WARN("can't find reachable insn at %s+0x%x",
- rela->sym->sec->name, rela->addend);
- return -1;
- }
-
- insn->dead_end = false;
- }
-
- return 0;
+ ret = __add_dead_ends(file, sec, false);
+ return ret;
}

/*
--
2.7.4