|
@@ -836,7 +836,7 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn,
|
|
|
struct symbol *pfunc = insn->func->pfunc;
|
|
|
unsigned int prev_offset = 0;
|
|
|
|
|
|
- list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
|
|
|
+ list_for_each_entry_from(rela, &table->rela_sec->rela_list, list) {
|
|
|
if (rela == next_table)
|
|
|
break;
|
|
|
|
|
@@ -926,6 +926,7 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
|
|
{
|
|
|
struct rela *text_rela, *rodata_rela;
|
|
|
struct instruction *orig_insn = insn;
|
|
|
+ struct section *rodata_sec;
|
|
|
unsigned long table_offset;
|
|
|
|
|
|
/*
|
|
@@ -953,10 +954,13 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
|
|
/* look for a relocation which references .rodata */
|
|
|
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
|
|
|
insn->len);
|
|
|
- if (!text_rela || text_rela->sym != file->rodata->sym)
|
|
|
+ if (!text_rela || text_rela->sym->type != STT_SECTION ||
|
|
|
+ !text_rela->sym->sec->rodata)
|
|
|
continue;
|
|
|
|
|
|
table_offset = text_rela->addend;
|
|
|
+ rodata_sec = text_rela->sym->sec;
|
|
|
+
|
|
|
if (text_rela->type == R_X86_64_PC32)
|
|
|
table_offset += 4;
|
|
|
|
|
@@ -964,10 +968,10 @@ static struct rela *find_switch_table(struct objtool_file *file,
|
|
|
* Make sure the .rodata address isn't associated with a
|
|
|
* symbol. gcc jump tables are anonymous data.
|
|
|
*/
|
|
|
- if (find_symbol_containing(file->rodata, table_offset))
|
|
|
+ if (find_symbol_containing(rodata_sec, table_offset))
|
|
|
continue;
|
|
|
|
|
|
- rodata_rela = find_rela_by_dest(file->rodata, table_offset);
|
|
|
+ rodata_rela = find_rela_by_dest(rodata_sec, table_offset);
|
|
|
if (rodata_rela) {
|
|
|
/*
|
|
|
* Use of RIP-relative switch jumps is quite rare, and
|
|
@@ -1052,7 +1056,7 @@ static int add_switch_table_alts(struct objtool_file *file)
|
|
|
struct symbol *func;
|
|
|
int ret;
|
|
|
|
|
|
- if (!file->rodata || !file->rodata->rela)
|
|
|
+ if (!file->rodata)
|
|
|
return 0;
|
|
|
|
|
|
for_each_sec(file, sec) {
|
|
@@ -1198,10 +1202,33 @@ static int read_retpoline_hints(struct objtool_file *file)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void mark_rodata(struct objtool_file *file)
|
|
|
+{
|
|
|
+ struct section *sec;
|
|
|
+ bool found = false;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This searches for the .rodata section or multiple .rodata.func_name
|
|
|
+ * sections if -fdata-sections is being used. The .str.1.1 and .str.1.8
|
|
|
+ * rodata sections are ignored as they don't contain jump tables.
|
|
|
+ */
|
|
|
+ for_each_sec(file, sec) {
|
|
|
+ if (!strncmp(sec->name, ".rodata", 7) &&
|
|
|
+ !strstr(sec->name, ".str1.")) {
|
|
|
+ sec->rodata = true;
|
|
|
+ found = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ file->rodata = found;
|
|
|
+}
|
|
|
+
|
|
|
static int decode_sections(struct objtool_file *file)
|
|
|
{
|
|
|
int ret;
|
|
|
|
|
|
+ mark_rodata(file);
|
|
|
+
|
|
|
ret = decode_instructions(file);
|
|
|
if (ret)
|
|
|
return ret;
|
|
@@ -2171,7 +2198,6 @@ int check(const char *_objname, bool orc)
|
|
|
INIT_LIST_HEAD(&file.insn_list);
|
|
|
hash_init(file.insn_hash);
|
|
|
file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard");
|
|
|
- file.rodata = find_section_by_name(file.elf, ".rodata");
|
|
|
file.c_file = find_section_by_name(file.elf, ".comment");
|
|
|
file.ignore_unreachables = no_unreachable;
|
|
|
file.hints = false;
|