summaryrefslogtreecommitdiffstats
path: root/tools/objtool/builtin-check.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/objtool/builtin-check.c')
-rw-r--r--tools/objtool/builtin-check.c60
1 files changed, 56 insertions, 4 deletions
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index e8a1f699058a..5fc52ee3264c 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -51,7 +51,7 @@ struct instruction {
51 unsigned int len, state; 51 unsigned int len, state;
52 unsigned char type; 52 unsigned char type;
53 unsigned long immediate; 53 unsigned long immediate;
54 bool alt_group, visited; 54 bool alt_group, visited, dead_end;
55 struct symbol *call_dest; 55 struct symbol *call_dest;
56 struct instruction *jump_dest; 56 struct instruction *jump_dest;
57 struct list_head alts; 57 struct list_head alts;
@@ -330,6 +330,54 @@ static int decode_instructions(struct objtool_file *file)
330} 330}
331 331
332/* 332/*
333 * Find all uses of the unreachable() macro, which are code path dead ends.
334 */
335static int add_dead_ends(struct objtool_file *file)
336{
337 struct section *sec;
338 struct rela *rela;
339 struct instruction *insn;
340 bool found;
341
342 sec = find_section_by_name(file->elf, ".rela__unreachable");
343 if (!sec)
344 return 0;
345
346 list_for_each_entry(rela, &sec->rela_list, list) {
347 if (rela->sym->type != STT_SECTION) {
348 WARN("unexpected relocation symbol type in .rela__unreachable");
349 return -1;
350 }
351 insn = find_insn(file, rela->sym->sec, rela->addend);
352 if (insn)
353 insn = list_prev_entry(insn, list);
354 else if (rela->addend == rela->sym->sec->len) {
355 found = false;
356 list_for_each_entry_reverse(insn, &file->insn_list, list) {
357 if (insn->sec == rela->sym->sec) {
358 found = true;
359 break;
360 }
361 }
362
363 if (!found) {
364 WARN("can't find unreachable insn at %s+0x%x",
365 rela->sym->sec->name, rela->addend);
366 return -1;
367 }
368 } else {
369 WARN("can't find unreachable insn at %s+0x%x",
370 rela->sym->sec->name, rela->addend);
371 return -1;
372 }
373
374 insn->dead_end = true;
375 }
376
377 return 0;
378}
379
380/*
333 * Warnings shouldn't be reported for ignored functions. 381 * Warnings shouldn't be reported for ignored functions.
334 */ 382 */
335static void add_ignores(struct objtool_file *file) 383static void add_ignores(struct objtool_file *file)
@@ -843,6 +891,10 @@ static int decode_sections(struct objtool_file *file)
843 if (ret) 891 if (ret)
844 return ret; 892 return ret;
845 893
894 ret = add_dead_ends(file);
895 if (ret)
896 return ret;
897
846 add_ignores(file); 898 add_ignores(file);
847 899
848 ret = add_jump_destinations(file); 900 ret = add_jump_destinations(file);
@@ -1037,13 +1089,13 @@ static int validate_branch(struct objtool_file *file,
1037 1089
1038 return 0; 1090 return 0;
1039 1091
1040 case INSN_BUG:
1041 return 0;
1042
1043 default: 1092 default:
1044 break; 1093 break;
1045 } 1094 }
1046 1095
1096 if (insn->dead_end)
1097 return 0;
1098
1047 insn = next_insn_same_sec(file, insn); 1099 insn = next_insn_same_sec(file, insn);
1048 if (!insn) { 1100 if (!insn) {
1049 WARN("%s: unexpected end of section", sec->name); 1101 WARN("%s: unexpected end of section", sec->name);