diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/objtool/check.c | 38 | ||||
-rw-r--r-- | tools/objtool/check.h | 4 | ||||
-rw-r--r-- | tools/objtool/elf.c | 1 | ||||
-rw-r--r-- | tools/objtool/elf.h | 3 |
4 files changed, 37 insertions, 9 deletions
diff --git a/tools/objtool/check.c b/tools/objtool/check.c index 2928939b98ec..0414a0d52262 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c | |||
@@ -836,7 +836,7 @@ static int add_switch_table(struct objtool_file *file, struct instruction *insn, | |||
836 | struct symbol *pfunc = insn->func->pfunc; | 836 | struct symbol *pfunc = insn->func->pfunc; |
837 | unsigned int prev_offset = 0; | 837 | unsigned int prev_offset = 0; |
838 | 838 | ||
839 | list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) { | 839 | list_for_each_entry_from(rela, &table->rela_sec->rela_list, list) { |
840 | if (rela == next_table) | 840 | if (rela == next_table) |
841 | break; | 841 | break; |
842 | 842 | ||
@@ -926,6 +926,7 @@ static struct rela *find_switch_table(struct objtool_file *file, | |||
926 | { | 926 | { |
927 | struct rela *text_rela, *rodata_rela; | 927 | struct rela *text_rela, *rodata_rela; |
928 | struct instruction *orig_insn = insn; | 928 | struct instruction *orig_insn = insn; |
929 | struct section *rodata_sec; | ||
929 | unsigned long table_offset; | 930 | unsigned long table_offset; |
930 | 931 | ||
931 | /* | 932 | /* |
@@ -953,10 +954,13 @@ static struct rela *find_switch_table(struct objtool_file *file, | |||
953 | /* look for a relocation which references .rodata */ | 954 | /* look for a relocation which references .rodata */ |
954 | text_rela = find_rela_by_dest_range(insn->sec, insn->offset, | 955 | text_rela = find_rela_by_dest_range(insn->sec, insn->offset, |
955 | insn->len); | 956 | insn->len); |
956 | if (!text_rela || text_rela->sym != file->rodata->sym) | 957 | if (!text_rela || text_rela->sym->type != STT_SECTION || |
958 | !text_rela->sym->sec->rodata) | ||
957 | continue; | 959 | continue; |
958 | 960 | ||
959 | table_offset = text_rela->addend; | 961 | table_offset = text_rela->addend; |
962 | rodata_sec = text_rela->sym->sec; | ||
963 | |||
960 | if (text_rela->type == R_X86_64_PC32) | 964 | if (text_rela->type == R_X86_64_PC32) |
961 | table_offset += 4; | 965 | table_offset += 4; |
962 | 966 | ||
@@ -964,10 +968,10 @@ static struct rela *find_switch_table(struct objtool_file *file, | |||
964 | * Make sure the .rodata address isn't associated with a | 968 | * Make sure the .rodata address isn't associated with a |
965 | * symbol. gcc jump tables are anonymous data. | 969 | * symbol. gcc jump tables are anonymous data. |
966 | */ | 970 | */ |
967 | if (find_symbol_containing(file->rodata, table_offset)) | 971 | if (find_symbol_containing(rodata_sec, table_offset)) |
968 | continue; | 972 | continue; |
969 | 973 | ||
970 | rodata_rela = find_rela_by_dest(file->rodata, table_offset); | 974 | rodata_rela = find_rela_by_dest(rodata_sec, table_offset); |
971 | if (rodata_rela) { | 975 | if (rodata_rela) { |
972 | /* | 976 | /* |
973 | * Use of RIP-relative switch jumps is quite rare, and | 977 | * Use of RIP-relative switch jumps is quite rare, and |
@@ -1052,7 +1056,7 @@ static int add_switch_table_alts(struct objtool_file *file) | |||
1052 | struct symbol *func; | 1056 | struct symbol *func; |
1053 | int ret; | 1057 | int ret; |
1054 | 1058 | ||
1055 | if (!file->rodata || !file->rodata->rela) | 1059 | if (!file->rodata) |
1056 | return 0; | 1060 | return 0; |
1057 | 1061 | ||
1058 | for_each_sec(file, sec) { | 1062 | for_each_sec(file, sec) { |
@@ -1198,10 +1202,33 @@ static int read_retpoline_hints(struct objtool_file *file) | |||
1198 | return 0; | 1202 | return 0; |
1199 | } | 1203 | } |
1200 | 1204 | ||
1205 | static void mark_rodata(struct objtool_file *file) | ||
1206 | { | ||
1207 | struct section *sec; | ||
1208 | bool found = false; | ||
1209 | |||
1210 | /* | ||
1211 | * This searches for the .rodata section or multiple .rodata.func_name | ||
1212 | * sections if -fdata-sections is being used. The .str.1.1 and .str.1.8 | ||
1213 | * rodata sections are ignored as they don't contain jump tables. | ||
1214 | */ | ||
1215 | for_each_sec(file, sec) { | ||
1216 | if (!strncmp(sec->name, ".rodata", 7) && | ||
1217 | !strstr(sec->name, ".str1.")) { | ||
1218 | sec->rodata = true; | ||
1219 | found = true; | ||
1220 | } | ||
1221 | } | ||
1222 | |||
1223 | file->rodata = found; | ||
1224 | } | ||
1225 | |||
1201 | static int decode_sections(struct objtool_file *file) | 1226 | static int decode_sections(struct objtool_file *file) |
1202 | { | 1227 | { |
1203 | int ret; | 1228 | int ret; |
1204 | 1229 | ||
1230 | mark_rodata(file); | ||
1231 | |||
1205 | ret = decode_instructions(file); | 1232 | ret = decode_instructions(file); |
1206 | if (ret) | 1233 | if (ret) |
1207 | return ret; | 1234 | return ret; |
@@ -2171,7 +2198,6 @@ int check(const char *_objname, bool orc) | |||
2171 | INIT_LIST_HEAD(&file.insn_list); | 2198 | INIT_LIST_HEAD(&file.insn_list); |
2172 | hash_init(file.insn_hash); | 2199 | hash_init(file.insn_hash); |
2173 | file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); | 2200 | file.whitelist = find_section_by_name(file.elf, ".discard.func_stack_frame_non_standard"); |
2174 | file.rodata = find_section_by_name(file.elf, ".rodata"); | ||
2175 | file.c_file = find_section_by_name(file.elf, ".comment"); | 2201 | file.c_file = find_section_by_name(file.elf, ".comment"); |
2176 | file.ignore_unreachables = no_unreachable; | 2202 | file.ignore_unreachables = no_unreachable; |
2177 | file.hints = false; | 2203 | file.hints = false; |
diff --git a/tools/objtool/check.h b/tools/objtool/check.h index 95700a2bcb7c..e6e8a655b556 100644 --- a/tools/objtool/check.h +++ b/tools/objtool/check.h | |||
@@ -60,8 +60,8 @@ struct objtool_file { | |||
60 | struct elf *elf; | 60 | struct elf *elf; |
61 | struct list_head insn_list; | 61 | struct list_head insn_list; |
62 | DECLARE_HASHTABLE(insn_hash, 16); | 62 | DECLARE_HASHTABLE(insn_hash, 16); |
63 | struct section *rodata, *whitelist; | 63 | struct section *whitelist; |
64 | bool ignore_unreachables, c_file, hints; | 64 | bool ignore_unreachables, c_file, hints, rodata; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | int check(const char *objname, bool orc); | 67 | int check(const char *objname, bool orc); |
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index 7ec85d567598..f7082de1ee82 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c | |||
@@ -379,6 +379,7 @@ static int read_relas(struct elf *elf) | |||
379 | rela->offset = rela->rela.r_offset; | 379 | rela->offset = rela->rela.r_offset; |
380 | symndx = GELF_R_SYM(rela->rela.r_info); | 380 | symndx = GELF_R_SYM(rela->rela.r_info); |
381 | rela->sym = find_symbol_by_index(elf, symndx); | 381 | rela->sym = find_symbol_by_index(elf, symndx); |
382 | rela->rela_sec = sec; | ||
382 | if (!rela->sym) { | 383 | if (!rela->sym) { |
383 | WARN("can't find rela entry symbol %d for %s", | 384 | WARN("can't find rela entry symbol %d for %s", |
384 | symndx, sec->name); | 385 | symndx, sec->name); |
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h index de5cd2ddded9..bc97ed86b9cd 100644 --- a/tools/objtool/elf.h +++ b/tools/objtool/elf.h | |||
@@ -48,7 +48,7 @@ struct section { | |||
48 | char *name; | 48 | char *name; |
49 | int idx; | 49 | int idx; |
50 | unsigned int len; | 50 | unsigned int len; |
51 | bool changed, text; | 51 | bool changed, text, rodata; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | struct symbol { | 54 | struct symbol { |
@@ -68,6 +68,7 @@ struct rela { | |||
68 | struct list_head list; | 68 | struct list_head list; |
69 | struct hlist_node hash; | 69 | struct hlist_node hash; |
70 | GElf_Rela rela; | 70 | GElf_Rela rela; |
71 | struct section *rela_sec; | ||
71 | struct symbol *sym; | 72 | struct symbol *sym; |
72 | unsigned int type; | 73 | unsigned int type; |
73 | unsigned long offset; | 74 | unsigned long offset; |