提交 14bda4e5 编写于 作者: P Peter Zijlstra

Merge branch 'objtool/core' of...

Merge branch 'objtool/core' of git://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux into objtool/core
...@@ -82,6 +82,6 @@ bool arch_callee_saved_reg(unsigned char reg); ...@@ -82,6 +82,6 @@ bool arch_callee_saved_reg(unsigned char reg);
unsigned long arch_jump_destination(struct instruction *insn); unsigned long arch_jump_destination(struct instruction *insn);
unsigned long arch_dest_rela_offset(int addend); unsigned long arch_dest_reloc_offset(int addend);
#endif /* _ARCH_H */ #endif /* _ARCH_H */
...@@ -67,7 +67,7 @@ bool arch_callee_saved_reg(unsigned char reg) ...@@ -67,7 +67,7 @@ bool arch_callee_saved_reg(unsigned char reg)
} }
} }
unsigned long arch_dest_rela_offset(int addend) unsigned long arch_dest_reloc_offset(int addend)
{ {
return addend + 4; return addend + 4;
} }
......
...@@ -352,7 +352,7 @@ static struct instruction *find_last_insn(struct objtool_file *file, ...@@ -352,7 +352,7 @@ static struct instruction *find_last_insn(struct objtool_file *file,
static int add_dead_ends(struct objtool_file *file) static int add_dead_ends(struct objtool_file *file)
{ {
struct section *sec; struct section *sec;
struct rela *rela; struct reloc *reloc;
struct instruction *insn; struct instruction *insn;
/* /*
...@@ -370,24 +370,24 @@ static int add_dead_ends(struct objtool_file *file) ...@@ -370,24 +370,24 @@ static int add_dead_ends(struct objtool_file *file)
if (!sec) if (!sec)
goto reachable; goto reachable;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", sec->name); WARN("unexpected relocation symbol type in %s", sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (insn) if (insn)
insn = list_prev_entry(insn, list); insn = list_prev_entry(insn, list);
else if (rela->addend == rela->sym->sec->len) { else if (reloc->addend == reloc->sym->sec->len) {
insn = find_last_insn(file, rela->sym->sec); insn = find_last_insn(file, reloc->sym->sec);
if (!insn) { if (!insn) {
WARN("can't find unreachable insn at %s+0x%x", WARN("can't find unreachable insn at %s+0x%x",
rela->sym->sec->name, rela->addend); reloc->sym->sec->name, reloc->addend);
return -1; return -1;
} }
} else { } else {
WARN("can't find unreachable insn at %s+0x%x", WARN("can't find unreachable insn at %s+0x%x",
rela->sym->sec->name, rela->addend); reloc->sym->sec->name, reloc->addend);
return -1; return -1;
} }
...@@ -405,24 +405,24 @@ static int add_dead_ends(struct objtool_file *file) ...@@ -405,24 +405,24 @@ static int add_dead_ends(struct objtool_file *file)
if (!sec) if (!sec)
return 0; return 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", sec->name); WARN("unexpected relocation symbol type in %s", sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (insn) if (insn)
insn = list_prev_entry(insn, list); insn = list_prev_entry(insn, list);
else if (rela->addend == rela->sym->sec->len) { else if (reloc->addend == reloc->sym->sec->len) {
insn = find_last_insn(file, rela->sym->sec); insn = find_last_insn(file, reloc->sym->sec);
if (!insn) { if (!insn) {
WARN("can't find reachable insn at %s+0x%x", WARN("can't find reachable insn at %s+0x%x",
rela->sym->sec->name, rela->addend); reloc->sym->sec->name, reloc->addend);
return -1; return -1;
} }
} else { } else {
WARN("can't find reachable insn at %s+0x%x", WARN("can't find reachable insn at %s+0x%x",
rela->sym->sec->name, rela->addend); reloc->sym->sec->name, reloc->addend);
return -1; return -1;
} }
...@@ -440,26 +440,26 @@ static void add_ignores(struct objtool_file *file) ...@@ -440,26 +440,26 @@ static void add_ignores(struct objtool_file *file)
struct instruction *insn; struct instruction *insn;
struct section *sec; struct section *sec;
struct symbol *func; struct symbol *func;
struct rela *rela; struct reloc *reloc;
sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard"); sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
if (!sec) if (!sec)
return; return;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
switch (rela->sym->type) { switch (reloc->sym->type) {
case STT_FUNC: case STT_FUNC:
func = rela->sym; func = reloc->sym;
break; break;
case STT_SECTION: case STT_SECTION:
func = find_func_by_offset(rela->sym->sec, rela->addend); func = find_func_by_offset(reloc->sym->sec, reloc->addend);
if (!func) if (!func)
continue; continue;
break; break;
default: default:
WARN("unexpected relocation symbol type in %s: %d", sec->name, rela->sym->type); WARN("unexpected relocation symbol type in %s: %d", sec->name, reloc->sym->type);
continue; continue;
} }
...@@ -579,20 +579,20 @@ static void add_uaccess_safe(struct objtool_file *file) ...@@ -579,20 +579,20 @@ static void add_uaccess_safe(struct objtool_file *file)
static int add_ignore_alternatives(struct objtool_file *file) static int add_ignore_alternatives(struct objtool_file *file)
{ {
struct section *sec; struct section *sec;
struct rela *rela; struct reloc *reloc;
struct instruction *insn; struct instruction *insn;
sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts"); sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
if (!sec) if (!sec)
return 0; return 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", sec->name); WARN("unexpected relocation symbol type in %s", sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!insn) { if (!insn) {
WARN("bad .discard.ignore_alts entry"); WARN("bad .discard.ignore_alts entry");
return -1; return -1;
...@@ -610,7 +610,7 @@ static int add_ignore_alternatives(struct objtool_file *file) ...@@ -610,7 +610,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
static int add_jump_destinations(struct objtool_file *file) static int add_jump_destinations(struct objtool_file *file)
{ {
struct instruction *insn; struct instruction *insn;
struct rela *rela; struct reloc *reloc;
struct section *dest_sec; struct section *dest_sec;
unsigned long dest_off; unsigned long dest_off;
...@@ -621,19 +621,19 @@ static int add_jump_destinations(struct objtool_file *file) ...@@ -621,19 +621,19 @@ static int add_jump_destinations(struct objtool_file *file)
if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET) if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET)
continue; continue;
rela = find_rela_by_dest_range(file->elf, insn->sec, reloc = find_reloc_by_dest_range(file->elf, insn->sec,
insn->offset, insn->len); insn->offset, insn->len);
if (!rela) { if (!reloc) {
dest_sec = insn->sec; dest_sec = insn->sec;
dest_off = arch_jump_destination(insn); dest_off = arch_jump_destination(insn);
} else if (rela->sym->type == STT_SECTION) { } else if (reloc->sym->type == STT_SECTION) {
dest_sec = rela->sym->sec; dest_sec = reloc->sym->sec;
dest_off = arch_dest_rela_offset(rela->addend); dest_off = arch_dest_reloc_offset(reloc->addend);
} else if (rela->sym->sec->idx) { } else if (reloc->sym->sec->idx) {
dest_sec = rela->sym->sec; dest_sec = reloc->sym->sec;
dest_off = rela->sym->sym.st_value + dest_off = reloc->sym->sym.st_value +
arch_dest_rela_offset(rela->addend); arch_dest_reloc_offset(reloc->addend);
} else if (strstr(rela->sym->name, "_indirect_thunk_")) { } else if (strstr(reloc->sym->name, "_indirect_thunk_")) {
/* /*
* Retpoline jumps are really dynamic jumps in * Retpoline jumps are really dynamic jumps in
* disguise, so convert them accordingly. * disguise, so convert them accordingly.
...@@ -647,7 +647,7 @@ static int add_jump_destinations(struct objtool_file *file) ...@@ -647,7 +647,7 @@ static int add_jump_destinations(struct objtool_file *file)
continue; continue;
} else { } else {
/* external sibling call */ /* external sibling call */
insn->call_dest = rela->sym; insn->call_dest = reloc->sym;
continue; continue;
} }
...@@ -723,15 +723,15 @@ static int add_call_destinations(struct objtool_file *file) ...@@ -723,15 +723,15 @@ static int add_call_destinations(struct objtool_file *file)
{ {
struct instruction *insn; struct instruction *insn;
unsigned long dest_off; unsigned long dest_off;
struct rela *rela; struct reloc *reloc;
for_each_insn(file, insn) { for_each_insn(file, insn) {
if (insn->type != INSN_CALL) if (insn->type != INSN_CALL)
continue; continue;
rela = find_rela_by_dest_range(file->elf, insn->sec, reloc = find_reloc_by_dest_range(file->elf, insn->sec,
insn->offset, insn->len); insn->offset, insn->len);
if (!rela) { if (!reloc) {
dest_off = arch_jump_destination(insn); dest_off = arch_jump_destination(insn);
insn->call_dest = find_func_by_offset(insn->sec, dest_off); insn->call_dest = find_func_by_offset(insn->sec, dest_off);
if (!insn->call_dest) if (!insn->call_dest)
...@@ -751,19 +751,19 @@ static int add_call_destinations(struct objtool_file *file) ...@@ -751,19 +751,19 @@ static int add_call_destinations(struct objtool_file *file)
return -1; return -1;
} }
} else if (rela->sym->type == STT_SECTION) { } else if (reloc->sym->type == STT_SECTION) {
dest_off = arch_dest_rela_offset(rela->addend); dest_off = arch_dest_reloc_offset(reloc->addend);
insn->call_dest = find_func_by_offset(rela->sym->sec, insn->call_dest = find_func_by_offset(reloc->sym->sec,
dest_off); dest_off);
if (!insn->call_dest) { if (!insn->call_dest) {
WARN_FUNC("can't find call dest symbol at %s+0x%lx", WARN_FUNC("can't find call dest symbol at %s+0x%lx",
insn->sec, insn->offset, insn->sec, insn->offset,
rela->sym->sec->name, reloc->sym->sec->name,
dest_off); dest_off);
return -1; return -1;
} }
} else } else
insn->call_dest = rela->sym; insn->call_dest = reloc->sym;
/* /*
* Whatever stack impact regular CALLs have, should be undone * Whatever stack impact regular CALLs have, should be undone
...@@ -871,7 +871,7 @@ static int handle_group_alt(struct objtool_file *file, ...@@ -871,7 +871,7 @@ static int handle_group_alt(struct objtool_file *file,
*/ */
if ((insn->offset != special_alt->new_off || if ((insn->offset != special_alt->new_off ||
(insn->type != INSN_CALL && !is_static_jump(insn))) && (insn->type != INSN_CALL && !is_static_jump(insn))) &&
find_rela_by_dest_range(file->elf, insn->sec, insn->offset, insn->len)) { find_reloc_by_dest_range(file->elf, insn->sec, insn->offset, insn->len)) {
WARN_FUNC("unsupported relocation in alternatives section", WARN_FUNC("unsupported relocation in alternatives section",
insn->sec, insn->offset); insn->sec, insn->offset);
...@@ -1017,34 +1017,34 @@ static int add_special_section_alts(struct objtool_file *file) ...@@ -1017,34 +1017,34 @@ static int add_special_section_alts(struct objtool_file *file)
} }
static int add_jump_table(struct objtool_file *file, struct instruction *insn, static int add_jump_table(struct objtool_file *file, struct instruction *insn,
struct rela *table) struct reloc *table)
{ {
struct rela *rela = table; struct reloc *reloc = table;
struct instruction *dest_insn; struct instruction *dest_insn;
struct alternative *alt; struct alternative *alt;
struct symbol *pfunc = insn->func->pfunc; struct symbol *pfunc = insn->func->pfunc;
unsigned int prev_offset = 0; unsigned int prev_offset = 0;
/* /*
* Each @rela is a switch table relocation which points to the target * Each @reloc is a switch table relocation which points to the target
* instruction. * instruction.
*/ */
list_for_each_entry_from(rela, &table->sec->rela_list, list) { list_for_each_entry_from(reloc, &table->sec->reloc_list, list) {
/* Check for the end of the table: */ /* Check for the end of the table: */
if (rela != table && rela->jump_table_start) if (reloc != table && reloc->jump_table_start)
break; break;
/* Make sure the table entries are consecutive: */ /* Make sure the table entries are consecutive: */
if (prev_offset && rela->offset != prev_offset + 8) if (prev_offset && reloc->offset != prev_offset + 8)
break; break;
/* Detect function pointers from contiguous objects: */ /* Detect function pointers from contiguous objects: */
if (rela->sym->sec == pfunc->sec && if (reloc->sym->sec == pfunc->sec &&
rela->addend == pfunc->offset) reloc->addend == pfunc->offset)
break; break;
dest_insn = find_insn(file, rela->sym->sec, rela->addend); dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!dest_insn) if (!dest_insn)
break; break;
...@@ -1060,7 +1060,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, ...@@ -1060,7 +1060,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
alt->insn = dest_insn; alt->insn = dest_insn;
list_add_tail(&alt->list, &insn->alts); list_add_tail(&alt->list, &insn->alts);
prev_offset = rela->offset; prev_offset = reloc->offset;
} }
if (!prev_offset) { if (!prev_offset) {
...@@ -1115,11 +1115,11 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn, ...@@ -1115,11 +1115,11 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
* *
* NOTE: RETPOLINE made it harder still to decode dynamic jumps. * NOTE: RETPOLINE made it harder still to decode dynamic jumps.
*/ */
static struct rela *find_jump_table(struct objtool_file *file, static struct reloc *find_jump_table(struct objtool_file *file,
struct symbol *func, struct symbol *func,
struct instruction *insn) struct instruction *insn)
{ {
struct rela *text_rela, *table_rela; struct reloc *text_reloc, *table_reloc;
struct instruction *dest_insn, *orig_insn = insn; struct instruction *dest_insn, *orig_insn = insn;
struct section *table_sec; struct section *table_sec;
unsigned long table_offset; unsigned long table_offset;
...@@ -1144,16 +1144,16 @@ static struct rela *find_jump_table(struct objtool_file *file, ...@@ -1144,16 +1144,16 @@ static struct rela *find_jump_table(struct objtool_file *file,
break; break;
/* look for a relocation which references .rodata */ /* look for a relocation which references .rodata */
text_rela = find_rela_by_dest_range(file->elf, insn->sec, text_reloc = find_reloc_by_dest_range(file->elf, insn->sec,
insn->offset, insn->len); insn->offset, insn->len);
if (!text_rela || text_rela->sym->type != STT_SECTION || if (!text_reloc || text_reloc->sym->type != STT_SECTION ||
!text_rela->sym->sec->rodata) !text_reloc->sym->sec->rodata)
continue; continue;
table_offset = text_rela->addend; table_offset = text_reloc->addend;
table_sec = text_rela->sym->sec; table_sec = text_reloc->sym->sec;
if (text_rela->type == R_X86_64_PC32) if (text_reloc->type == R_X86_64_PC32)
table_offset += 4; table_offset += 4;
/* /*
...@@ -1170,14 +1170,14 @@ static struct rela *find_jump_table(struct objtool_file *file, ...@@ -1170,14 +1170,14 @@ static struct rela *find_jump_table(struct objtool_file *file,
continue; continue;
/* /*
* Each table entry has a rela associated with it. The rela * Each table entry has a reloc associated with it. The reloc
* should reference text in the same function as the original * should reference text in the same function as the original
* instruction. * instruction.
*/ */
table_rela = find_rela_by_dest(file->elf, table_sec, table_offset); table_reloc = find_reloc_by_dest(file->elf, table_sec, table_offset);
if (!table_rela) if (!table_reloc)
continue; continue;
dest_insn = find_insn(file, table_rela->sym->sec, table_rela->addend); dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
if (!dest_insn || !dest_insn->func || dest_insn->func->pfunc != func) if (!dest_insn || !dest_insn->func || dest_insn->func->pfunc != func)
continue; continue;
...@@ -1186,10 +1186,10 @@ static struct rela *find_jump_table(struct objtool_file *file, ...@@ -1186,10 +1186,10 @@ static struct rela *find_jump_table(struct objtool_file *file,
* indicates a rare GCC quirk/bug which can leave dead code * indicates a rare GCC quirk/bug which can leave dead code
* behind. * behind.
*/ */
if (text_rela->type == R_X86_64_PC32) if (text_reloc->type == R_X86_64_PC32)
file->ignore_unreachables = true; file->ignore_unreachables = true;
return table_rela; return table_reloc;
} }
return NULL; return NULL;
...@@ -1203,7 +1203,7 @@ static void mark_func_jump_tables(struct objtool_file *file, ...@@ -1203,7 +1203,7 @@ static void mark_func_jump_tables(struct objtool_file *file,
struct symbol *func) struct symbol *func)
{ {
struct instruction *insn, *last = NULL; struct instruction *insn, *last = NULL;
struct rela *rela; struct reloc *reloc;
func_for_each_insn(file, func, insn) { func_for_each_insn(file, func, insn) {
if (!last) if (!last)
...@@ -1226,10 +1226,10 @@ static void mark_func_jump_tables(struct objtool_file *file, ...@@ -1226,10 +1226,10 @@ static void mark_func_jump_tables(struct objtool_file *file,
if (insn->type != INSN_JUMP_DYNAMIC) if (insn->type != INSN_JUMP_DYNAMIC)
continue; continue;
rela = find_jump_table(file, func, insn); reloc = find_jump_table(file, func, insn);
if (rela) { if (reloc) {
rela->jump_table_start = true; reloc->jump_table_start = true;
insn->jump_table = rela; insn->jump_table = reloc;
} }
} }
} }
...@@ -1283,8 +1283,8 @@ static int add_jump_table_alts(struct objtool_file *file) ...@@ -1283,8 +1283,8 @@ static int add_jump_table_alts(struct objtool_file *file)
static int read_unwind_hints(struct objtool_file *file) static int read_unwind_hints(struct objtool_file *file)
{ {
struct section *sec, *relasec; struct section *sec, *relocsec;
struct rela *rela; struct reloc *reloc;
struct unwind_hint *hint; struct unwind_hint *hint;
struct instruction *insn; struct instruction *insn;
struct cfi_reg *cfa; struct cfi_reg *cfa;
...@@ -1294,8 +1294,8 @@ static int read_unwind_hints(struct objtool_file *file) ...@@ -1294,8 +1294,8 @@ static int read_unwind_hints(struct objtool_file *file)
if (!sec) if (!sec)
return 0; return 0;
relasec = sec->rela; relocsec = sec->reloc;
if (!relasec) { if (!relocsec) {
WARN("missing .rela.discard.unwind_hints section"); WARN("missing .rela.discard.unwind_hints section");
return -1; return -1;
} }
...@@ -1310,13 +1310,13 @@ static int read_unwind_hints(struct objtool_file *file) ...@@ -1310,13 +1310,13 @@ static int read_unwind_hints(struct objtool_file *file)
for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) { for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
hint = (struct unwind_hint *)sec->data->d_buf + i; hint = (struct unwind_hint *)sec->data->d_buf + i;
rela = find_rela_by_dest(file->elf, sec, i * sizeof(*hint)); reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
if (!rela) { if (!reloc) {
WARN("can't find rela for unwind_hints[%d]", i); WARN("can't find reloc for unwind_hints[%d]", i);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!insn) { if (!insn) {
WARN("can't find insn for unwind_hints[%d]", i); WARN("can't find insn for unwind_hints[%d]", i);
return -1; return -1;
...@@ -1374,19 +1374,19 @@ static int read_retpoline_hints(struct objtool_file *file) ...@@ -1374,19 +1374,19 @@ static int read_retpoline_hints(struct objtool_file *file)
{ {
struct section *sec; struct section *sec;
struct instruction *insn; struct instruction *insn;
struct rela *rela; struct reloc *reloc;
sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe"); sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
if (!sec) if (!sec)
return 0; return 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", sec->name); WARN("unexpected relocation symbol type in %s", sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!insn) { if (!insn) {
WARN("bad .discard.retpoline_safe entry"); WARN("bad .discard.retpoline_safe entry");
return -1; return -1;
...@@ -1409,19 +1409,19 @@ static int read_instr_hints(struct objtool_file *file) ...@@ -1409,19 +1409,19 @@ static int read_instr_hints(struct objtool_file *file)
{ {
struct section *sec; struct section *sec;
struct instruction *insn; struct instruction *insn;
struct rela *rela; struct reloc *reloc;
sec = find_section_by_name(file->elf, ".rela.discard.instr_end"); sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
if (!sec) if (!sec)
return 0; return 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", sec->name); WARN("unexpected relocation symbol type in %s", sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!insn) { if (!insn) {
WARN("bad .discard.instr_end entry"); WARN("bad .discard.instr_end entry");
return -1; return -1;
...@@ -1434,13 +1434,13 @@ static int read_instr_hints(struct objtool_file *file) ...@@ -1434,13 +1434,13 @@ static int read_instr_hints(struct objtool_file *file)
if (!sec) if (!sec)
return 0; return 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", sec->name); WARN("unexpected relocation symbol type in %s", sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!insn) { if (!insn) {
WARN("bad .discard.instr_begin entry"); WARN("bad .discard.instr_begin entry");
return -1; return -1;
...@@ -1456,22 +1456,22 @@ static int read_intra_function_calls(struct objtool_file *file) ...@@ -1456,22 +1456,22 @@ static int read_intra_function_calls(struct objtool_file *file)
{ {
struct instruction *insn; struct instruction *insn;
struct section *sec; struct section *sec;
struct rela *rela; struct reloc *reloc;
sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls"); sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
if (!sec) if (!sec)
return 0; return 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
unsigned long dest_off; unsigned long dest_off;
if (rela->sym->type != STT_SECTION) { if (reloc->sym->type != STT_SECTION) {
WARN("unexpected relocation symbol type in %s", WARN("unexpected relocation symbol type in %s",
sec->name); sec->name);
return -1; return -1;
} }
insn = find_insn(file, rela->sym->sec, rela->addend); insn = find_insn(file, reloc->sym->sec, reloc->addend);
if (!insn) { if (!insn) {
WARN("bad .discard.intra_function_call entry"); WARN("bad .discard.intra_function_call entry");
return -1; return -1;
......
...@@ -37,7 +37,7 @@ struct instruction { ...@@ -37,7 +37,7 @@ struct instruction {
struct symbol *call_dest; struct symbol *call_dest;
struct instruction *jump_dest; struct instruction *jump_dest;
struct instruction *first_jump_src; struct instruction *first_jump_src;
struct rela *jump_table; struct reloc *jump_table;
struct list_head alts; struct list_head alts;
struct symbol *func; struct symbol *func;
struct list_head stack_ops; struct list_head stack_ops;
......
...@@ -228,26 +228,26 @@ struct symbol *find_symbol_by_name(const struct elf *elf, const char *name) ...@@ -228,26 +228,26 @@ struct symbol *find_symbol_by_name(const struct elf *elf, const char *name)
return NULL; return NULL;
} }
struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec, struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
unsigned long offset, unsigned int len) unsigned long offset, unsigned int len)
{ {
struct rela *rela, *r = NULL; struct reloc *reloc, *r = NULL;
unsigned long o; unsigned long o;
if (!sec->rela) if (!sec->reloc)
return NULL; return NULL;
sec = sec->rela; sec = sec->reloc;
for_offset_range(o, offset, offset + len) { for_offset_range(o, offset, offset + len) {
elf_hash_for_each_possible(elf->rela_hash, rela, hash, elf_hash_for_each_possible(elf->reloc_hash, reloc, hash,
sec_offset_hash(sec, o)) { sec_offset_hash(sec, o)) {
if (rela->sec != sec) if (reloc->sec != sec)
continue; continue;
if (rela->offset >= offset && rela->offset < offset + len) { if (reloc->offset >= offset && reloc->offset < offset + len) {
if (!r || rela->offset < r->offset) if (!r || reloc->offset < r->offset)
r = rela; r = reloc;
} }
} }
if (r) if (r)
...@@ -257,9 +257,9 @@ struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec, ...@@ -257,9 +257,9 @@ struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
return NULL; return NULL;
} }
struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset) struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset)
{ {
return find_rela_by_dest_range(elf, sec, offset, 1); return find_reloc_by_dest_range(elf, sec, offset, 1);
} }
static int read_sections(struct elf *elf) static int read_sections(struct elf *elf)
...@@ -288,7 +288,7 @@ static int read_sections(struct elf *elf) ...@@ -288,7 +288,7 @@ static int read_sections(struct elf *elf)
memset(sec, 0, sizeof(*sec)); memset(sec, 0, sizeof(*sec));
INIT_LIST_HEAD(&sec->symbol_list); INIT_LIST_HEAD(&sec->symbol_list);
INIT_LIST_HEAD(&sec->rela_list); INIT_LIST_HEAD(&sec->reloc_list);
s = elf_getscn(elf->elf, i); s = elf_getscn(elf->elf, i);
if (!s) { if (!s) {
...@@ -434,7 +434,13 @@ static int read_symbols(struct elf *elf) ...@@ -434,7 +434,13 @@ static int read_symbols(struct elf *elf)
size_t pnamelen; size_t pnamelen;
if (sym->type != STT_FUNC) if (sym->type != STT_FUNC)
continue; continue;
sym->pfunc = sym->cfunc = sym;
if (sym->pfunc == NULL)
sym->pfunc = sym;
if (sym->cfunc == NULL)
sym->cfunc = sym;
coldstr = strstr(sym->name, ".cold"); coldstr = strstr(sym->name, ".cold");
if (!coldstr) if (!coldstr)
continue; continue;
...@@ -482,71 +488,99 @@ static int read_symbols(struct elf *elf) ...@@ -482,71 +488,99 @@ static int read_symbols(struct elf *elf)
return -1; return -1;
} }
void elf_add_rela(struct elf *elf, struct rela *rela) void elf_add_reloc(struct elf *elf, struct reloc *reloc)
{ {
struct section *sec = rela->sec; struct section *sec = reloc->sec;
list_add_tail(&reloc->list, &sec->reloc_list);
elf_hash_add(elf->reloc_hash, &reloc->hash, reloc_hash(reloc));
}
list_add_tail(&rela->list, &sec->rela_list); static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
elf_hash_add(elf->rela_hash, &rela->hash, rela_hash(rela)); {
if (!gelf_getrel(sec->data, i, &reloc->rel)) {
WARN_ELF("gelf_getrel");
return -1;
}
reloc->type = GELF_R_TYPE(reloc->rel.r_info);
reloc->addend = 0;
reloc->offset = reloc->rel.r_offset;
*symndx = GELF_R_SYM(reloc->rel.r_info);
return 0;
} }
static int read_relas(struct elf *elf) static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)
{
if (!gelf_getrela(sec->data, i, &reloc->rela)) {
WARN_ELF("gelf_getrela");
return -1;
}
reloc->type = GELF_R_TYPE(reloc->rela.r_info);
reloc->addend = reloc->rela.r_addend;
reloc->offset = reloc->rela.r_offset;
*symndx = GELF_R_SYM(reloc->rela.r_info);
return 0;
}
static int read_relocs(struct elf *elf)
{ {
struct section *sec; struct section *sec;
struct rela *rela; struct reloc *reloc;
int i; int i;
unsigned int symndx; unsigned int symndx;
unsigned long nr_rela, max_rela = 0, tot_rela = 0; unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0;
list_for_each_entry(sec, &elf->sections, list) { list_for_each_entry(sec, &elf->sections, list) {
if (sec->sh.sh_type != SHT_RELA) if ((sec->sh.sh_type != SHT_RELA) &&
(sec->sh.sh_type != SHT_REL))
continue; continue;
sec->base = find_section_by_name(elf, sec->name + 5); sec->base = find_section_by_index(elf, sec->sh.sh_info);
if (!sec->base) { if (!sec->base) {
WARN("can't find base section for rela section %s", WARN("can't find base section for reloc section %s",
sec->name); sec->name);
return -1; return -1;
} }
sec->base->rela = sec; sec->base->reloc = sec;
nr_rela = 0; nr_reloc = 0;
for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) { for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) {
rela = malloc(sizeof(*rela)); reloc = malloc(sizeof(*reloc));
if (!rela) { if (!reloc) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
memset(rela, 0, sizeof(*rela)); memset(reloc, 0, sizeof(*reloc));
switch (sec->sh.sh_type) {
if (!gelf_getrela(sec->data, i, &rela->rela)) { case SHT_REL:
WARN_ELF("gelf_getrela"); if (read_rel_reloc(sec, i, reloc, &symndx))
return -1; return -1;
break;
case SHT_RELA:
if (read_rela_reloc(sec, i, reloc, &symndx))
return -1;
break;
default: return -1;
} }
reloc->sym = find_symbol_by_index(elf, symndx);
rela->type = GELF_R_TYPE(rela->rela.r_info); reloc->sec = sec;
rela->addend = rela->rela.r_addend; if (!reloc->sym) {
rela->offset = rela->rela.r_offset; WARN("can't find reloc entry symbol %d for %s",
symndx = GELF_R_SYM(rela->rela.r_info);
rela->sym = find_symbol_by_index(elf, symndx);
rela->sec = sec;
if (!rela->sym) {
WARN("can't find rela entry symbol %d for %s",
symndx, sec->name); symndx, sec->name);
return -1; return -1;
} }
elf_add_rela(elf, rela); elf_add_reloc(elf, reloc);
nr_rela++; nr_reloc++;
} }
max_rela = max(max_rela, nr_rela); max_reloc = max(max_reloc, nr_reloc);
tot_rela += nr_rela; tot_reloc += nr_reloc;
} }
if (stats) { if (stats) {
printf("max_rela: %lu\n", max_rela); printf("max_reloc: %lu\n", max_reloc);
printf("tot_rela: %lu\n", tot_rela); printf("tot_reloc: %lu\n", tot_reloc);
} }
return 0; return 0;
...@@ -572,7 +606,7 @@ struct elf *elf_open_read(const char *name, int flags) ...@@ -572,7 +606,7 @@ struct elf *elf_open_read(const char *name, int flags)
elf_hash_init(elf->symbol_name_hash); elf_hash_init(elf->symbol_name_hash);
elf_hash_init(elf->section_hash); elf_hash_init(elf->section_hash);
elf_hash_init(elf->section_name_hash); elf_hash_init(elf->section_name_hash);
elf_hash_init(elf->rela_hash); elf_hash_init(elf->reloc_hash);
elf->fd = open(name, flags); elf->fd = open(name, flags);
if (elf->fd == -1) { if (elf->fd == -1) {
...@@ -605,7 +639,7 @@ struct elf *elf_open_read(const char *name, int flags) ...@@ -605,7 +639,7 @@ struct elf *elf_open_read(const char *name, int flags)
if (read_symbols(elf)) if (read_symbols(elf))
goto err; goto err;
if (read_relas(elf)) if (read_relocs(elf))
goto err; goto err;
return elf; return elf;
...@@ -631,7 +665,7 @@ struct section *elf_create_section(struct elf *elf, const char *name, ...@@ -631,7 +665,7 @@ struct section *elf_create_section(struct elf *elf, const char *name,
memset(sec, 0, sizeof(*sec)); memset(sec, 0, sizeof(*sec));
INIT_LIST_HEAD(&sec->symbol_list); INIT_LIST_HEAD(&sec->symbol_list);
INIT_LIST_HEAD(&sec->rela_list); INIT_LIST_HEAD(&sec->reloc_list);
s = elf_newscn(elf->elf); s = elf_newscn(elf->elf);
if (!s) { if (!s) {
...@@ -716,25 +750,55 @@ struct section *elf_create_section(struct elf *elf, const char *name, ...@@ -716,25 +750,55 @@ struct section *elf_create_section(struct elf *elf, const char *name,
return sec; return sec;
} }
struct section *elf_create_rela_section(struct elf *elf, struct section *base) static struct section *elf_create_rel_reloc_section(struct elf *elf, struct section *base)
{
char *relocname;
struct section *sec;
relocname = malloc(strlen(base->name) + strlen(".rel") + 1);
if (!relocname) {
perror("malloc");
return NULL;
}
strcpy(relocname, ".rel");
strcat(relocname, base->name);
sec = elf_create_section(elf, relocname, sizeof(GElf_Rel), 0);
free(relocname);
if (!sec)
return NULL;
base->reloc = sec;
sec->base = base;
sec->sh.sh_type = SHT_REL;
sec->sh.sh_addralign = 8;
sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
sec->sh.sh_info = base->idx;
sec->sh.sh_flags = SHF_INFO_LINK;
return sec;
}
static struct section *elf_create_rela_reloc_section(struct elf *elf, struct section *base)
{ {
char *relaname; char *relocname;
struct section *sec; struct section *sec;
relaname = malloc(strlen(base->name) + strlen(".rela") + 1); relocname = malloc(strlen(base->name) + strlen(".rela") + 1);
if (!relaname) { if (!relocname) {
perror("malloc"); perror("malloc");
return NULL; return NULL;
} }
strcpy(relaname, ".rela"); strcpy(relocname, ".rela");
strcat(relaname, base->name); strcat(relocname, base->name);
sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0); sec = elf_create_section(elf, relocname, sizeof(GElf_Rela), 0);
free(relaname); free(relocname);
if (!sec) if (!sec)
return NULL; return NULL;
base->rela = sec; base->reloc = sec;
sec->base = base; sec->base = base;
sec->sh.sh_type = SHT_RELA; sec->sh.sh_type = SHT_RELA;
...@@ -746,39 +810,92 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base) ...@@ -746,39 +810,92 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
return sec; return sec;
} }
int elf_rebuild_rela_section(struct section *sec) struct section *elf_create_reloc_section(struct elf *elf,
struct section *base,
int reltype)
{ {
struct rela *rela; switch (reltype) {
int nr, idx = 0, size; case SHT_REL: return elf_create_rel_reloc_section(elf, base);
GElf_Rela *relas; case SHT_RELA: return elf_create_rela_reloc_section(elf, base);
default: return NULL;
}
}
nr = 0; static int elf_rebuild_rel_reloc_section(struct section *sec, int nr)
list_for_each_entry(rela, &sec->rela_list, list) {
nr++; struct reloc *reloc;
int idx = 0, size;
GElf_Rel *relocs;
/* Allocate a buffer for relocations */
size = nr * sizeof(*relocs);
relocs = malloc(size);
if (!relocs) {
perror("malloc");
return -1;
}
sec->data->d_buf = relocs;
sec->data->d_size = size;
sec->sh.sh_size = size;
size = nr * sizeof(*relas); idx = 0;
relas = malloc(size); list_for_each_entry(reloc, &sec->reloc_list, list) {
if (!relas) { relocs[idx].r_offset = reloc->offset;
relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
idx++;
}
return 0;
}
static int elf_rebuild_rela_reloc_section(struct section *sec, int nr)
{
struct reloc *reloc;
int idx = 0, size;
GElf_Rela *relocs;
/* Allocate a buffer for relocations with addends */
size = nr * sizeof(*relocs);
relocs = malloc(size);
if (!relocs) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
sec->data->d_buf = relas; sec->data->d_buf = relocs;
sec->data->d_size = size; sec->data->d_size = size;
sec->sh.sh_size = size; sec->sh.sh_size = size;
idx = 0; idx = 0;
list_for_each_entry(rela, &sec->rela_list, list) { list_for_each_entry(reloc, &sec->reloc_list, list) {
relas[idx].r_offset = rela->offset; relocs[idx].r_offset = reloc->offset;
relas[idx].r_addend = rela->addend; relocs[idx].r_addend = reloc->addend;
relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type); relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type);
idx++; idx++;
} }
return 0; return 0;
} }
int elf_rebuild_reloc_section(struct section *sec)
{
struct reloc *reloc;
int nr;
nr = 0;
list_for_each_entry(reloc, &sec->reloc_list, list)
nr++;
switch (sec->sh.sh_type) {
case SHT_REL: return elf_rebuild_rel_reloc_section(sec, nr);
case SHT_RELA: return elf_rebuild_rela_reloc_section(sec, nr);
default: return -1;
}
}
int elf_write(const struct elf *elf) int elf_write(const struct elf *elf)
{ {
struct section *sec; struct section *sec;
...@@ -815,7 +932,7 @@ void elf_close(struct elf *elf) ...@@ -815,7 +932,7 @@ void elf_close(struct elf *elf)
{ {
struct section *sec, *tmpsec; struct section *sec, *tmpsec;
struct symbol *sym, *tmpsym; struct symbol *sym, *tmpsym;
struct rela *rela, *tmprela; struct reloc *reloc, *tmpreloc;
if (elf->elf) if (elf->elf)
elf_end(elf->elf); elf_end(elf->elf);
...@@ -829,10 +946,10 @@ void elf_close(struct elf *elf) ...@@ -829,10 +946,10 @@ void elf_close(struct elf *elf)
hash_del(&sym->hash); hash_del(&sym->hash);
free(sym); free(sym);
} }
list_for_each_entry_safe(rela, tmprela, &sec->rela_list, list) { list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) {
list_del(&rela->list); list_del(&reloc->list);
hash_del(&rela->hash); hash_del(&reloc->hash);
free(rela); free(reloc);
} }
list_del(&sec->list); list_del(&sec->list);
free(sec); free(sec);
......
...@@ -32,8 +32,8 @@ struct section { ...@@ -32,8 +32,8 @@ struct section {
GElf_Shdr sh; GElf_Shdr sh;
struct rb_root symbol_tree; struct rb_root symbol_tree;
struct list_head symbol_list; struct list_head symbol_list;
struct list_head rela_list; struct list_head reloc_list;
struct section *base, *rela; struct section *base, *reloc;
struct symbol *sym; struct symbol *sym;
Elf_Data *data; Elf_Data *data;
char *name; char *name;
...@@ -58,10 +58,13 @@ struct symbol { ...@@ -58,10 +58,13 @@ struct symbol {
bool uaccess_safe; bool uaccess_safe;
}; };
struct rela { struct reloc {
struct list_head list; struct list_head list;
struct hlist_node hash; struct hlist_node hash;
GElf_Rela rela; union {
GElf_Rela rela;
GElf_Rel rel;
};
struct section *sec; struct section *sec;
struct symbol *sym; struct symbol *sym;
unsigned int type; unsigned int type;
...@@ -82,7 +85,7 @@ struct elf { ...@@ -82,7 +85,7 @@ struct elf {
DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS); DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS);
DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS); DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS);
DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS); DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS);
DECLARE_HASHTABLE(rela_hash, ELF_HASH_BITS); DECLARE_HASHTABLE(reloc_hash, ELF_HASH_BITS);
}; };
#define OFFSET_STRIDE_BITS 4 #define OFFSET_STRIDE_BITS 4
...@@ -109,15 +112,15 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) ...@@ -109,15 +112,15 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
return ol; return ol;
} }
static inline u32 rela_hash(struct rela *rela) static inline u32 reloc_hash(struct reloc *reloc)
{ {
return sec_offset_hash(rela->sec, rela->offset); return sec_offset_hash(reloc->sec, reloc->offset);
} }
struct elf *elf_open_read(const char *name, int flags); struct elf *elf_open_read(const char *name, int flags);
struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr); struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
struct section *elf_create_rela_section(struct elf *elf, struct section *base); struct section *elf_create_reloc_section(struct elf *elf, struct section *base, int reltype);
void elf_add_rela(struct elf *elf, struct rela *rela); void elf_add_reloc(struct elf *elf, struct reloc *reloc);
int elf_write(const struct elf *elf); int elf_write(const struct elf *elf);
void elf_close(struct elf *elf); void elf_close(struct elf *elf);
...@@ -126,11 +129,11 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); ...@@ -126,11 +129,11 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec, struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
unsigned long offset, unsigned int len); unsigned long offset, unsigned int len);
struct symbol *find_func_containing(struct section *sec, unsigned long offset); struct symbol *find_func_containing(struct section *sec, unsigned long offset);
int elf_rebuild_rela_section(struct section *sec); int elf_rebuild_reloc_section(struct section *sec);
#define for_each_sec(file, sec) \ #define for_each_sec(file, sec) \
list_for_each_entry(sec, &file->elf->sections, list) list_for_each_entry(sec, &file->elf->sections, list)
......
...@@ -80,56 +80,56 @@ int create_orc(struct objtool_file *file) ...@@ -80,56 +80,56 @@ int create_orc(struct objtool_file *file)
return 0; return 0;
} }
static int create_orc_entry(struct elf *elf, struct section *u_sec, struct section *ip_relasec, static int create_orc_entry(struct elf *elf, struct section *u_sec, struct section *ip_relocsec,
unsigned int idx, struct section *insn_sec, unsigned int idx, struct section *insn_sec,
unsigned long insn_off, struct orc_entry *o) unsigned long insn_off, struct orc_entry *o)
{ {
struct orc_entry *orc; struct orc_entry *orc;
struct rela *rela; struct reloc *reloc;
/* populate ORC data */ /* populate ORC data */
orc = (struct orc_entry *)u_sec->data->d_buf + idx; orc = (struct orc_entry *)u_sec->data->d_buf + idx;
memcpy(orc, o, sizeof(*orc)); memcpy(orc, o, sizeof(*orc));
/* populate rela for ip */ /* populate reloc for ip */
rela = malloc(sizeof(*rela)); reloc = malloc(sizeof(*reloc));
if (!rela) { if (!reloc) {
perror("malloc"); perror("malloc");
return -1; return -1;
} }
memset(rela, 0, sizeof(*rela)); memset(reloc, 0, sizeof(*reloc));
if (insn_sec->sym) { if (insn_sec->sym) {
rela->sym = insn_sec->sym; reloc->sym = insn_sec->sym;
rela->addend = insn_off; reloc->addend = insn_off;
} else { } else {
/* /*
* The Clang assembler doesn't produce section symbols, so we * The Clang assembler doesn't produce section symbols, so we
* have to reference the function symbol instead: * have to reference the function symbol instead:
*/ */
rela->sym = find_symbol_containing(insn_sec, insn_off); reloc->sym = find_symbol_containing(insn_sec, insn_off);
if (!rela->sym) { if (!reloc->sym) {
/* /*
* Hack alert. This happens when we need to reference * Hack alert. This happens when we need to reference
* the NOP pad insn immediately after the function. * the NOP pad insn immediately after the function.
*/ */
rela->sym = find_symbol_containing(insn_sec, reloc->sym = find_symbol_containing(insn_sec,
insn_off - 1); insn_off - 1);
} }
if (!rela->sym) { if (!reloc->sym) {
WARN("missing symbol for insn at offset 0x%lx\n", WARN("missing symbol for insn at offset 0x%lx\n",
insn_off); insn_off);
return -1; return -1;
} }
rela->addend = insn_off - rela->sym->offset; reloc->addend = insn_off - reloc->sym->offset;
} }
rela->type = R_X86_64_PC32; reloc->type = R_X86_64_PC32;
rela->offset = idx * sizeof(int); reloc->offset = idx * sizeof(int);
rela->sec = ip_relasec; reloc->sec = ip_relocsec;
elf_add_rela(elf, rela); elf_add_reloc(elf, reloc);
return 0; return 0;
} }
...@@ -137,7 +137,7 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti ...@@ -137,7 +137,7 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
int create_orc_sections(struct objtool_file *file) int create_orc_sections(struct objtool_file *file)
{ {
struct instruction *insn, *prev_insn; struct instruction *insn, *prev_insn;
struct section *sec, *u_sec, *ip_relasec; struct section *sec, *u_sec, *ip_relocsec;
unsigned int idx; unsigned int idx;
struct orc_entry empty = { struct orc_entry empty = {
...@@ -181,8 +181,8 @@ int create_orc_sections(struct objtool_file *file) ...@@ -181,8 +181,8 @@ int create_orc_sections(struct objtool_file *file)
if (!sec) if (!sec)
return -1; return -1;
ip_relasec = elf_create_rela_section(file->elf, sec); ip_relocsec = elf_create_reloc_section(file->elf, sec, SHT_RELA);
if (!ip_relasec) if (!ip_relocsec)
return -1; return -1;
/* create .orc_unwind section */ /* create .orc_unwind section */
...@@ -200,7 +200,7 @@ int create_orc_sections(struct objtool_file *file) ...@@ -200,7 +200,7 @@ int create_orc_sections(struct objtool_file *file)
if (!prev_insn || memcmp(&insn->orc, &prev_insn->orc, if (!prev_insn || memcmp(&insn->orc, &prev_insn->orc,
sizeof(struct orc_entry))) { sizeof(struct orc_entry))) {
if (create_orc_entry(file->elf, u_sec, ip_relasec, idx, if (create_orc_entry(file->elf, u_sec, ip_relocsec, idx,
insn->sec, insn->offset, insn->sec, insn->offset,
&insn->orc)) &insn->orc))
return -1; return -1;
...@@ -212,7 +212,7 @@ int create_orc_sections(struct objtool_file *file) ...@@ -212,7 +212,7 @@ int create_orc_sections(struct objtool_file *file)
/* section terminator */ /* section terminator */
if (prev_insn) { if (prev_insn) {
if (create_orc_entry(file->elf, u_sec, ip_relasec, idx, if (create_orc_entry(file->elf, u_sec, ip_relocsec, idx,
prev_insn->sec, prev_insn->sec,
prev_insn->offset + prev_insn->len, prev_insn->offset + prev_insn->len,
&empty)) &empty))
...@@ -222,7 +222,7 @@ int create_orc_sections(struct objtool_file *file) ...@@ -222,7 +222,7 @@ int create_orc_sections(struct objtool_file *file)
} }
} }
if (elf_rebuild_rela_section(ip_relasec)) if (elf_rebuild_reloc_section(ip_relocsec))
return -1; return -1;
return 0; return 0;
......
...@@ -72,7 +72,7 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry, ...@@ -72,7 +72,7 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
struct section *sec, int idx, struct section *sec, int idx,
struct special_alt *alt) struct special_alt *alt)
{ {
struct rela *orig_rela, *new_rela; struct reloc *orig_reloc, *new_reloc;
unsigned long offset; unsigned long offset;
offset = idx * entry->size; offset = idx * entry->size;
...@@ -118,30 +118,30 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry, ...@@ -118,30 +118,30 @@ static int get_alt_entry(struct elf *elf, struct special_entry *entry,
} }
} }
orig_rela = find_rela_by_dest(elf, sec, offset + entry->orig); orig_reloc = find_reloc_by_dest(elf, sec, offset + entry->orig);
if (!orig_rela) { if (!orig_reloc) {
WARN_FUNC("can't find orig rela", sec, offset + entry->orig); WARN_FUNC("can't find orig reloc", sec, offset + entry->orig);
return -1; return -1;
} }
if (orig_rela->sym->type != STT_SECTION) { if (orig_reloc->sym->type != STT_SECTION) {
WARN_FUNC("don't know how to handle non-section rela symbol %s", WARN_FUNC("don't know how to handle non-section reloc symbol %s",
sec, offset + entry->orig, orig_rela->sym->name); sec, offset + entry->orig, orig_reloc->sym->name);
return -1; return -1;
} }
alt->orig_sec = orig_rela->sym->sec; alt->orig_sec = orig_reloc->sym->sec;
alt->orig_off = orig_rela->addend; alt->orig_off = orig_reloc->addend;
if (!entry->group || alt->new_len) { if (!entry->group || alt->new_len) {
new_rela = find_rela_by_dest(elf, sec, offset + entry->new); new_reloc = find_reloc_by_dest(elf, sec, offset + entry->new);
if (!new_rela) { if (!new_reloc) {
WARN_FUNC("can't find new rela", WARN_FUNC("can't find new reloc",
sec, offset + entry->new); sec, offset + entry->new);
return -1; return -1;
} }
alt->new_sec = new_rela->sym->sec; alt->new_sec = new_reloc->sym->sec;
alt->new_off = (unsigned int)new_rela->addend; alt->new_off = (unsigned int)new_reloc->addend;
/* _ASM_EXTABLE_EX hack */ /* _ASM_EXTABLE_EX hack */
if (alt->new_off >= 0x7ffffff0) if (alt->new_off >= 0x7ffffff0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册