Skip to content

Commit e7c2bc3

Browse files
jpoimboeKAGA-KOKO
authored andcommitted
objtool: Refactor jump table code
Now that C jump tables are supported, call them "jump tables" instead of "switch tables". Also rename some other variables, add comments, and simplify the code flow a bit. Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Nick Desaulniers <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/cf951b0c0641628e0b9b81f7ceccd9bcabcb4bd8.1563413318.git.jpoimboe@redhat.com
1 parent 0c1ddd3 commit e7c2bc3

File tree

3 files changed

+46
-40
lines changed

3 files changed

+46
-40
lines changed

tools/objtool/check.c

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ static int add_jump_destinations(struct objtool_file *file)
627627
* However this code can't completely replace the
628628
* read_symbols() code because this doesn't detect the
629629
* case where the parent function's only reference to a
630-
* subfunction is through a switch table.
630+
* subfunction is through a jump table.
631631
*/
632632
if (!strstr(insn->func->name, ".cold.") &&
633633
strstr(insn->jump_dest->func->name, ".cold.")) {
@@ -899,20 +899,24 @@ static int add_special_section_alts(struct objtool_file *file)
899899
return ret;
900900
}
901901

902-
static int add_switch_table(struct objtool_file *file, struct instruction *insn,
902+
static int add_jump_table(struct objtool_file *file, struct instruction *insn,
903903
struct rela *table, struct rela *next_table)
904904
{
905905
struct rela *rela = table;
906-
struct instruction *alt_insn;
906+
struct instruction *dest_insn;
907907
struct alternative *alt;
908908
struct symbol *pfunc = insn->func->pfunc;
909909
unsigned int prev_offset = 0;
910910

911-
list_for_each_entry_from(rela, &table->rela_sec->rela_list, list) {
911+
/*
912+
* Each @rela is a switch table relocation which points to the target
913+
* instruction.
914+
*/
915+
list_for_each_entry_from(rela, &table->sec->rela_list, list) {
912916
if (rela == next_table)
913917
break;
914918

915-
/* Make sure the switch table entries are consecutive: */
919+
/* Make sure the table entries are consecutive: */
916920
if (prev_offset && rela->offset != prev_offset + 8)
917921
break;
918922

@@ -921,12 +925,12 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn,
921925
rela->addend == pfunc->offset)
922926
break;
923927

924-
alt_insn = find_insn(file, rela->sym->sec, rela->addend);
925-
if (!alt_insn)
928+
dest_insn = find_insn(file, rela->sym->sec, rela->addend);
929+
if (!dest_insn)
926930
break;
927931

928-
/* Make sure the jmp dest is in the function or subfunction: */
929-
if (alt_insn->func->pfunc != pfunc)
932+
/* Make sure the destination is in the same function: */
933+
if (dest_insn->func->pfunc != pfunc)
930934
break;
931935

932936
alt = malloc(sizeof(*alt));
@@ -935,7 +939,7 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn,
935939
return -1;
936940
}
937941

938-
alt->insn = alt_insn;
942+
alt->insn = dest_insn;
939943
list_add_tail(&alt->list, &insn->alts);
940944
prev_offset = rela->offset;
941945
}
@@ -950,7 +954,7 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn,
950954
}
951955

952956
/*
953-
* find_switch_table() - Given a dynamic jump, find the switch jump table in
957+
* find_jump_table() - Given a dynamic jump, find the switch jump table in
954958
* .rodata associated with it.
955959
*
956960
* There are 3 basic patterns:
@@ -992,13 +996,13 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn,
992996
*
993997
* NOTE: RETPOLINE made it harder still to decode dynamic jumps.
994998
*/
995-
static struct rela *find_switch_table(struct objtool_file *file,
999+
static struct rela *find_jump_table(struct objtool_file *file,
9961000
struct symbol *func,
9971001
struct instruction *insn)
9981002
{
999-
struct rela *text_rela, *rodata_rela;
1003+
struct rela *text_rela, *table_rela;
10001004
struct instruction *orig_insn = insn;
1001-
struct section *rodata_sec;
1005+
struct section *table_sec;
10021006
unsigned long table_offset;
10031007

10041008
/*
@@ -1031,7 +1035,7 @@ static struct rela *find_switch_table(struct objtool_file *file,
10311035
continue;
10321036

10331037
table_offset = text_rela->addend;
1034-
rodata_sec = text_rela->sym->sec;
1038+
table_sec = text_rela->sym->sec;
10351039

10361040
if (text_rela->type == R_X86_64_PC32)
10371041
table_offset += 4;
@@ -1045,29 +1049,31 @@ static struct rela *find_switch_table(struct objtool_file *file,
10451049
* need to be placed in the C_JUMP_TABLE_SECTION section. They
10461050
* have symbols associated with them.
10471051
*/
1048-
if (find_symbol_containing(rodata_sec, table_offset) &&
1049-
strcmp(rodata_sec->name, C_JUMP_TABLE_SECTION))
1052+
if (find_symbol_containing(table_sec, table_offset) &&
1053+
strcmp(table_sec->name, C_JUMP_TABLE_SECTION))
10501054
continue;
10511055

1052-
rodata_rela = find_rela_by_dest(rodata_sec, table_offset);
1053-
if (rodata_rela) {
1054-
/*
1055-
* Use of RIP-relative switch jumps is quite rare, and
1056-
* indicates a rare GCC quirk/bug which can leave dead
1057-
* code behind.
1058-
*/
1059-
if (text_rela->type == R_X86_64_PC32)
1060-
file->ignore_unreachables = true;
1056+
/* Each table entry has a rela associated with it. */
1057+
table_rela = find_rela_by_dest(table_sec, table_offset);
1058+
if (!table_rela)
1059+
continue;
10611060

1062-
return rodata_rela;
1063-
}
1061+
/*
1062+
* Use of RIP-relative switch jumps is quite rare, and
1063+
* indicates a rare GCC quirk/bug which can leave dead code
1064+
* behind.
1065+
*/
1066+
if (text_rela->type == R_X86_64_PC32)
1067+
file->ignore_unreachables = true;
1068+
1069+
return table_rela;
10641070
}
10651071

10661072
return NULL;
10671073
}
10681074

10691075

1070-
static int add_func_switch_tables(struct objtool_file *file,
1076+
static int add_func_jump_tables(struct objtool_file *file,
10711077
struct symbol *func)
10721078
{
10731079
struct instruction *insn, *last = NULL, *prev_jump = NULL;
@@ -1080,7 +1086,7 @@ static int add_func_switch_tables(struct objtool_file *file,
10801086

10811087
/*
10821088
* Store back-pointers for unconditional forward jumps such
1083-
* that find_switch_table() can back-track using those and
1089+
* that find_jump_table() can back-track using those and
10841090
* avoid some potentially confusing code.
10851091
*/
10861092
if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest &&
@@ -1095,17 +1101,17 @@ static int add_func_switch_tables(struct objtool_file *file,
10951101
if (insn->type != INSN_JUMP_DYNAMIC)
10961102
continue;
10971103

1098-
rela = find_switch_table(file, func, insn);
1104+
rela = find_jump_table(file, func, insn);
10991105
if (!rela)
11001106
continue;
11011107

11021108
/*
1103-
* We found a switch table, but we don't know yet how big it
1109+
* We found a jump table, but we don't know yet how big it
11041110
* is. Don't add it until we reach the end of the function or
1105-
* the beginning of another switch table in the same function.
1111+
* the beginning of another jump table in the same function.
11061112
*/
11071113
if (prev_jump) {
1108-
ret = add_switch_table(file, prev_jump, prev_rela, rela);
1114+
ret = add_jump_table(file, prev_jump, prev_rela, rela);
11091115
if (ret)
11101116
return ret;
11111117
}
@@ -1115,7 +1121,7 @@ static int add_func_switch_tables(struct objtool_file *file,
11151121
}
11161122

11171123
if (prev_jump) {
1118-
ret = add_switch_table(file, prev_jump, prev_rela, NULL);
1124+
ret = add_jump_table(file, prev_jump, prev_rela, NULL);
11191125
if (ret)
11201126
return ret;
11211127
}
@@ -1128,7 +1134,7 @@ static int add_func_switch_tables(struct objtool_file *file,
11281134
* section which contains a list of addresses within the function to jump to.
11291135
* This finds these jump tables and adds them to the insn->alts lists.
11301136
*/
1131-
static int add_switch_table_alts(struct objtool_file *file)
1137+
static int add_jump_table_alts(struct objtool_file *file)
11321138
{
11331139
struct section *sec;
11341140
struct symbol *func;
@@ -1142,7 +1148,7 @@ static int add_switch_table_alts(struct objtool_file *file)
11421148
if (func->type != STT_FUNC)
11431149
continue;
11441150

1145-
ret = add_func_switch_tables(file, func);
1151+
ret = add_func_jump_tables(file, func);
11461152
if (ret)
11471153
return ret;
11481154
}
@@ -1339,7 +1345,7 @@ static int decode_sections(struct objtool_file *file)
13391345
if (ret)
13401346
return ret;
13411347

1342-
ret = add_switch_table_alts(file);
1348+
ret = add_jump_table_alts(file);
13431349
if (ret)
13441350
return ret;
13451351

tools/objtool/elf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ static int read_relas(struct elf *elf)
385385
rela->offset = rela->rela.r_offset;
386386
symndx = GELF_R_SYM(rela->rela.r_info);
387387
rela->sym = find_symbol_by_index(elf, symndx);
388-
rela->rela_sec = sec;
388+
rela->sec = sec;
389389
if (!rela->sym) {
390390
WARN("can't find rela entry symbol %d for %s",
391391
symndx, sec->name);

tools/objtool/elf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct rela {
5757
struct list_head list;
5858
struct hlist_node hash;
5959
GElf_Rela rela;
60-
struct section *rela_sec;
60+
struct section *sec;
6161
struct symbol *sym;
6262
unsigned int type;
6363
unsigned long offset;

0 commit comments

Comments
 (0)