Commit 9dee8689 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'objtool-core-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool updates from Ingo Molnar:

 - Add support for non-rela relocations, in preparation to merge
   'recordmcount' functionality into objtool

 - Fix assumption that broke under --ffunction-sections (LTO) builds

 - Misc cleanups

* tag 'objtool-core-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Add support for relocations without addends
  objtool: Rename rela to reloc
  objtool: Use sh_info to find the base for .rela sections
  objtool: Do not assume order of parent/child functions
parents 9ba19ccd d832c005
...@@ -82,7 +82,7 @@ bool arch_callee_saved_reg(unsigned char reg); ...@@ -82,7 +82,7 @@ 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);
const char *arch_nop_insn(int len); const char *arch_nop_insn(int len);
......
...@@ -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;
} }
......
This diff is collapsed.
...@@ -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;
......
This diff is collapsed.
...@@ -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 long offset; unsigned long offset;
...@@ -84,7 +87,7 @@ struct elf { ...@@ -84,7 +87,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
...@@ -111,19 +114,19 @@ static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) ...@@ -111,19 +114,19 @@ 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_insn(struct elf *elf, struct section *sec, int elf_write_insn(struct elf *elf, struct section *sec,
unsigned long offset, unsigned int len, unsigned long offset, unsigned int len,
const char *insn); const char *insn);
int elf_write_rela(struct elf *elf, struct rela *rela); int elf_write_reloc(struct elf *elf, struct reloc *reloc);
int elf_write(struct elf *elf); int elf_write(struct elf *elf);
void elf_close(struct elf *elf); void elf_close(struct elf *elf);
...@@ -132,11 +135,11 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); ...@@ -132,11 +135,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 elf *elf, struct section *sec); int elf_rebuild_reloc_section(struct elf *elf, 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(file->elf, ip_relasec)) if (elf_rebuild_reloc_section(file->elf, 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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment