aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/objtool/arch.h5
-rw-r--r--tools/objtool/arch/x86/decode.c3
-rw-r--r--tools/objtool/builtin-check.c60
3 files changed, 58 insertions, 10 deletions
diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index f7350fcedc70..a59e061c0b4a 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -31,9 +31,8 @@
31#define INSN_CALL_DYNAMIC 8 31#define INSN_CALL_DYNAMIC 8
32#define INSN_RETURN 9 32#define INSN_RETURN 9
33#define INSN_CONTEXT_SWITCH 10 33#define INSN_CONTEXT_SWITCH 10
34#define INSN_BUG 11 34#define INSN_NOP 11
35#define INSN_NOP 12 35#define INSN_OTHER 12
36#define INSN_OTHER 13
37#define INSN_LAST INSN_OTHER 36#define INSN_LAST INSN_OTHER
38 37
39int arch_decode_instruction(struct elf *elf, struct section *sec, 38int arch_decode_instruction(struct elf *elf, struct section *sec,
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 039636ffb6c8..6ac99e3266eb 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -118,9 +118,6 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
118 op2 == 0x35) 118 op2 == 0x35)
119 /* sysenter, sysret */ 119 /* sysenter, sysret */
120 *type = INSN_CONTEXT_SWITCH; 120 *type = INSN_CONTEXT_SWITCH;
121 else if (op2 == 0x0b || op2 == 0xb9)
122 /* ud2 */
123 *type = INSN_BUG;
124 else if (op2 == 0x0d || op2 == 0x1f) 121 else if (op2 == 0x0d || op2 == 0x1f)
125 /* nopl/nopw */ 122 /* nopl/nopw */
126 *type = INSN_NOP; 123 *type = INSN_NOP;
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);