Skip to content

Commit c3cb6c1

Browse files
ardbiesheuvelPeter Zijlstra
authored andcommitted
objtool: Allow arch code to discover jump table size
In preparation for adding support for annotated jump tables, where ELF relocations and symbols are used to describe the locations of jump tables in the executable, refactor the jump table discovery logic so the table size can be returned from arch_find_switch_table(). Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/20241011170847.334429-12-ardb+git@google.com
1 parent e7e0eb5 commit c3cb6c1

File tree

6 files changed

+33
-16
lines changed

6 files changed

+33
-16
lines changed

tools/objtool/arch/loongarch/special.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ bool arch_support_alt_relocation(struct special_alt *special_alt,
99
}
1010

1111
struct reloc *arch_find_switch_table(struct objtool_file *file,
12-
struct instruction *insn)
12+
struct instruction *insn,
13+
unsigned long *table_size)
1314
{
1415
return NULL;
1516
}

tools/objtool/arch/powerpc/special.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ bool arch_support_alt_relocation(struct special_alt *special_alt,
1313
}
1414

1515
struct reloc *arch_find_switch_table(struct objtool_file *file,
16-
struct instruction *insn)
16+
struct instruction *insn,
17+
unsigned long *table_size)
1718
{
1819
exit(-1);
1920
}

tools/objtool/arch/x86/special.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ bool arch_support_alt_relocation(struct special_alt *special_alt,
109109
* NOTE: MITIGATION_RETPOLINE made it harder still to decode dynamic jumps.
110110
*/
111111
struct reloc *arch_find_switch_table(struct objtool_file *file,
112-
struct instruction *insn)
112+
struct instruction *insn,
113+
unsigned long *table_size)
113114
{
114115
struct reloc *text_reloc, *rodata_reloc;
115116
struct section *table_sec;
@@ -158,5 +159,6 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
158159
if (reloc_type(text_reloc) == R_X86_64_PC32)
159160
file->ignore_unreachables = true;
160161

162+
*table_size = 0;
161163
return rodata_reloc;
162164
}

tools/objtool/check.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,15 @@ static inline struct reloc *insn_jump_table(struct instruction *insn)
150150
return NULL;
151151
}
152152

153+
static inline unsigned long insn_jump_table_size(struct instruction *insn)
154+
{
155+
if (insn->type == INSN_JUMP_DYNAMIC ||
156+
insn->type == INSN_CALL_DYNAMIC)
157+
return insn->_jump_table_size;
158+
159+
return 0;
160+
}
161+
153162
static bool is_jump_table_jump(struct instruction *insn)
154163
{
155164
struct alt_group *alt_group = insn->alt_group;
@@ -1937,6 +1946,7 @@ static int add_special_section_alts(struct objtool_file *file)
19371946
static int add_jump_table(struct objtool_file *file, struct instruction *insn,
19381947
struct reloc *next_table)
19391948
{
1949+
unsigned long table_size = insn_jump_table_size(insn);
19401950
struct symbol *pfunc = insn_func(insn)->pfunc;
19411951
struct reloc *table = insn_jump_table(insn);
19421952
struct instruction *dest_insn;
@@ -1951,6 +1961,8 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
19511961
for_each_reloc_from(table->sec, reloc) {
19521962

19531963
/* Check for the end of the table: */
1964+
if (table_size && reloc_offset(reloc) - reloc_offset(table) >= table_size)
1965+
break;
19541966
if (reloc != table && reloc == next_table)
19551967
break;
19561968

@@ -1995,12 +2007,12 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
19952007
* find_jump_table() - Given a dynamic jump, find the switch jump table
19962008
* associated with it.
19972009
*/
1998-
static struct reloc *find_jump_table(struct objtool_file *file,
1999-
struct symbol *func,
2000-
struct instruction *insn)
2010+
static void find_jump_table(struct objtool_file *file, struct symbol *func,
2011+
struct instruction *insn)
20012012
{
20022013
struct reloc *table_reloc;
20032014
struct instruction *dest_insn, *orig_insn = insn;
2015+
unsigned long table_size;
20042016

20052017
/*
20062018
* Backward search using the @first_jump_src links, these help avoid
@@ -2021,17 +2033,17 @@ static struct reloc *find_jump_table(struct objtool_file *file,
20212033
insn->jump_dest->offset > orig_insn->offset))
20222034
break;
20232035

2024-
table_reloc = arch_find_switch_table(file, insn);
2036+
table_reloc = arch_find_switch_table(file, insn, &table_size);
20252037
if (!table_reloc)
20262038
continue;
20272039
dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc));
20282040
if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func)
20292041
continue;
20302042

2031-
return table_reloc;
2043+
orig_insn->_jump_table = table_reloc;
2044+
orig_insn->_jump_table_size = table_size;
2045+
break;
20322046
}
2033-
2034-
return NULL;
20352047
}
20362048

20372049
/*
@@ -2042,7 +2054,6 @@ static void mark_func_jump_tables(struct objtool_file *file,
20422054
struct symbol *func)
20432055
{
20442056
struct instruction *insn, *last = NULL;
2045-
struct reloc *reloc;
20462057

20472058
func_for_each_insn(file, func, insn) {
20482059
if (!last)
@@ -2065,9 +2076,7 @@ static void mark_func_jump_tables(struct objtool_file *file,
20652076
if (insn->type != INSN_JUMP_DYNAMIC)
20662077
continue;
20672078

2068-
reloc = find_jump_table(file, func, insn);
2069-
if (reloc)
2070-
insn->_jump_table = reloc;
2079+
find_jump_table(file, func, insn);
20712080
}
20722081
}
20732082

tools/objtool/include/objtool/check.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ struct instruction {
7171
struct instruction *first_jump_src;
7272
union {
7373
struct symbol *_call_dest;
74-
struct reloc *_jump_table;
74+
struct {
75+
struct reloc *_jump_table;
76+
unsigned long _jump_table_size;
77+
};
7578
};
7679
struct alternative *alts;
7780
struct symbol *sym;

tools/objtool/include/objtool/special.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ bool arch_support_alt_relocation(struct special_alt *special_alt,
3838
struct instruction *insn,
3939
struct reloc *reloc);
4040
struct reloc *arch_find_switch_table(struct objtool_file *file,
41-
struct instruction *insn);
41+
struct instruction *insn,
42+
unsigned long *table_size);
4243
#endif /* _SPECIAL_H */

0 commit comments

Comments
 (0)