aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/objtool/check.c38
-rw-r--r--tools/objtool/check.h4
-rw-r--r--tools/objtool/elf.c1
-rw-r--r--tools/objtool/elf.h3
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
1205static 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
1201static int decode_sections(struct objtool_file *file) 1226static 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
67int check(const char *objname, bool orc); 67int 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
54struct symbol { 54struct 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;