Skip to content

Commit ef47cc0

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
objtool: Add elf_create_reloc() helper
We have 4 instances of adding a relocation. Create a common helper to avoid growing even more. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Miroslav Benes <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 3a64760 commit ef47cc0

File tree

4 files changed

+85
-119
lines changed

4 files changed

+85
-119
lines changed

tools/objtool/check.c

Lines changed: 16 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,7 @@ static int add_dead_ends(struct objtool_file *file)
433433

434434
static int create_static_call_sections(struct objtool_file *file)
435435
{
436-
struct section *sec, *reloc_sec;
437-
struct reloc *reloc;
436+
struct section *sec;
438437
struct static_call_site *site;
439438
struct instruction *insn;
440439
struct symbol *key_sym;
@@ -460,8 +459,7 @@ static int create_static_call_sections(struct objtool_file *file)
460459
if (!sec)
461460
return -1;
462461

463-
reloc_sec = elf_create_reloc_section(file->elf, sec, SHT_RELA);
464-
if (!reloc_sec)
462+
if (!elf_create_reloc_section(file->elf, sec, SHT_RELA))
465463
return -1;
466464

467465
idx = 0;
@@ -471,25 +469,11 @@ static int create_static_call_sections(struct objtool_file *file)
471469
memset(site, 0, sizeof(struct static_call_site));
472470

473471
/* populate reloc for 'addr' */
474-
reloc = malloc(sizeof(*reloc));
475-
476-
if (!reloc) {
477-
perror("malloc");
478-
return -1;
479-
}
480-
memset(reloc, 0, sizeof(*reloc));
481-
482-
insn_to_reloc_sym_addend(insn->sec, insn->offset, reloc);
483-
if (!reloc->sym) {
484-
WARN_FUNC("static call tramp: missing containing symbol",
485-
insn->sec, insn->offset);
472+
if (elf_add_reloc_to_insn(file->elf, sec,
473+
idx * sizeof(struct static_call_site),
474+
R_X86_64_PC32,
475+
insn->sec, insn->offset))
486476
return -1;
487-
}
488-
489-
reloc->type = R_X86_64_PC32;
490-
reloc->offset = idx * sizeof(struct static_call_site);
491-
reloc->sec = reloc_sec;
492-
elf_add_reloc(file->elf, reloc);
493477

494478
/* find key symbol */
495479
key_name = strdup(insn->call_dest->name);
@@ -526,18 +510,11 @@ static int create_static_call_sections(struct objtool_file *file)
526510
free(key_name);
527511

528512
/* populate reloc for 'key' */
529-
reloc = malloc(sizeof(*reloc));
530-
if (!reloc) {
531-
perror("malloc");
513+
if (elf_add_reloc(file->elf, sec,
514+
idx * sizeof(struct static_call_site) + 4,
515+
R_X86_64_PC32, key_sym,
516+
is_sibling_call(insn) * STATIC_CALL_SITE_TAIL))
532517
return -1;
533-
}
534-
memset(reloc, 0, sizeof(*reloc));
535-
reloc->sym = key_sym;
536-
reloc->addend = is_sibling_call(insn) ? STATIC_CALL_SITE_TAIL : 0;
537-
reloc->type = R_X86_64_PC32;
538-
reloc->offset = idx * sizeof(struct static_call_site) + 4;
539-
reloc->sec = reloc_sec;
540-
elf_add_reloc(file->elf, reloc);
541518

542519
idx++;
543520
}
@@ -547,8 +524,7 @@ static int create_static_call_sections(struct objtool_file *file)
547524

548525
static int create_mcount_loc_sections(struct objtool_file *file)
549526
{
550-
struct section *sec, *reloc_sec;
551-
struct reloc *reloc;
527+
struct section *sec;
552528
unsigned long *loc;
553529
struct instruction *insn;
554530
int idx;
@@ -571,8 +547,7 @@ static int create_mcount_loc_sections(struct objtool_file *file)
571547
if (!sec)
572548
return -1;
573549

574-
reloc_sec = elf_create_reloc_section(file->elf, sec, SHT_RELA);
575-
if (!reloc_sec)
550+
if (!elf_create_reloc_section(file->elf, sec, SHT_RELA))
576551
return -1;
577552

578553
idx = 0;
@@ -581,32 +556,11 @@ static int create_mcount_loc_sections(struct objtool_file *file)
581556
loc = (unsigned long *)sec->data->d_buf + idx;
582557
memset(loc, 0, sizeof(unsigned long));
583558

584-
reloc = malloc(sizeof(*reloc));
585-
if (!reloc) {
586-
perror("malloc");
559+
if (elf_add_reloc_to_insn(file->elf, sec,
560+
idx * sizeof(unsigned long),
561+
R_X86_64_64,
562+
insn->sec, insn->offset))
587563
return -1;
588-
}
589-
memset(reloc, 0, sizeof(*reloc));
590-
591-
if (insn->sec->sym) {
592-
reloc->sym = insn->sec->sym;
593-
reloc->addend = insn->offset;
594-
} else {
595-
reloc->sym = find_symbol_containing(insn->sec, insn->offset);
596-
597-
if (!reloc->sym) {
598-
WARN("missing symbol for insn at offset 0x%lx\n",
599-
insn->offset);
600-
return -1;
601-
}
602-
603-
reloc->addend = insn->offset - reloc->sym->offset;
604-
}
605-
606-
reloc->type = R_X86_64_64;
607-
reloc->offset = idx * sizeof(unsigned long);
608-
reloc->sec = reloc_sec;
609-
elf_add_reloc(file->elf, reloc);
610564

611565
idx++;
612566
}

tools/objtool/elf.c

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -211,32 +211,6 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
211211
return find_reloc_by_dest_range(elf, sec, offset, 1);
212212
}
213213

214-
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
215-
struct reloc *reloc)
216-
{
217-
if (sec->sym) {
218-
reloc->sym = sec->sym;
219-
reloc->addend = offset;
220-
return;
221-
}
222-
223-
/*
224-
* The Clang assembler strips section symbols, so we have to reference
225-
* the function symbol instead:
226-
*/
227-
reloc->sym = find_symbol_containing(sec, offset);
228-
if (!reloc->sym) {
229-
/*
230-
* Hack alert. This happens when we need to reference the NOP
231-
* pad insn immediately after the function.
232-
*/
233-
reloc->sym = find_symbol_containing(sec, offset - 1);
234-
}
235-
236-
if (reloc->sym)
237-
reloc->addend = offset - reloc->sym->offset;
238-
}
239-
240214
static int read_sections(struct elf *elf)
241215
{
242216
Elf_Scn *s = NULL;
@@ -473,14 +447,66 @@ static int read_symbols(struct elf *elf)
473447
return -1;
474448
}
475449

476-
void elf_add_reloc(struct elf *elf, struct reloc *reloc)
450+
int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
451+
unsigned int type, struct symbol *sym, int addend)
477452
{
478-
struct section *sec = reloc->sec;
453+
struct reloc *reloc;
454+
455+
reloc = malloc(sizeof(*reloc));
456+
if (!reloc) {
457+
perror("malloc");
458+
return -1;
459+
}
460+
memset(reloc, 0, sizeof(*reloc));
479461

480-
list_add_tail(&reloc->list, &sec->reloc_list);
462+
reloc->sec = sec->reloc;
463+
reloc->offset = offset;
464+
reloc->type = type;
465+
reloc->sym = sym;
466+
reloc->addend = addend;
467+
468+
list_add_tail(&reloc->list, &sec->reloc->reloc_list);
481469
elf_hash_add(elf->reloc_hash, &reloc->hash, reloc_hash(reloc));
482470

483-
sec->changed = true;
471+
sec->reloc->changed = true;
472+
473+
return 0;
474+
}
475+
476+
int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
477+
unsigned long offset, unsigned int type,
478+
struct section *insn_sec, unsigned long insn_off)
479+
{
480+
struct symbol *sym;
481+
int addend;
482+
483+
if (insn_sec->sym) {
484+
sym = insn_sec->sym;
485+
addend = insn_off;
486+
487+
} else {
488+
/*
489+
* The Clang assembler strips section symbols, so we have to
490+
* reference the function symbol instead:
491+
*/
492+
sym = find_symbol_containing(insn_sec, insn_off);
493+
if (!sym) {
494+
/*
495+
* Hack alert. This happens when we need to reference
496+
* the NOP pad insn immediately after the function.
497+
*/
498+
sym = find_symbol_containing(insn_sec, insn_off - 1);
499+
}
500+
501+
if (!sym) {
502+
WARN("can't find symbol containing %s+0x%lx", insn_sec->name, insn_off);
503+
return -1;
504+
}
505+
506+
addend = insn_off - sym->offset;
507+
}
508+
509+
return elf_add_reloc(elf, sec, offset, type, sym, addend);
484510
}
485511

486512
static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx)

tools/objtool/include/objtool/elf.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ static inline u32 reloc_hash(struct reloc *reloc)
123123
struct elf *elf_open_read(const char *name, int flags);
124124
struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
125125
struct section *elf_create_reloc_section(struct elf *elf, struct section *base, int reltype);
126-
void elf_add_reloc(struct elf *elf, struct reloc *reloc);
126+
127+
int elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset,
128+
unsigned int type, struct symbol *sym, int addend);
129+
int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
130+
unsigned long offset, unsigned int type,
131+
struct section *insn_sec, unsigned long insn_off);
132+
127133
int elf_write_insn(struct elf *elf, struct section *sec,
128134
unsigned long offset, unsigned int len,
129135
const char *insn);
@@ -140,8 +146,6 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
140146
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
141147
unsigned long offset, unsigned int len);
142148
struct symbol *find_func_containing(struct section *sec, unsigned long offset);
143-
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
144-
struct reloc *reloc);
145149

146150
#define for_each_sec(file, sec) \
147151
list_for_each_entry(sec, &file->elf->sections, list)

tools/objtool/orc_gen.c

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,11 @@ static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi)
8282
}
8383

8484
static int write_orc_entry(struct elf *elf, struct section *orc_sec,
85-
struct section *ip_rsec, unsigned int idx,
85+
struct section *ip_sec, unsigned int idx,
8686
struct section *insn_sec, unsigned long insn_off,
8787
struct orc_entry *o)
8888
{
8989
struct orc_entry *orc;
90-
struct reloc *reloc;
9190

9291
/* populate ORC data */
9392
orc = (struct orc_entry *)orc_sec->data->d_buf + idx;
@@ -96,25 +95,9 @@ static int write_orc_entry(struct elf *elf, struct section *orc_sec,
9695
orc->bp_offset = bswap_if_needed(orc->bp_offset);
9796

9897
/* populate reloc for ip */
99-
reloc = malloc(sizeof(*reloc));
100-
if (!reloc) {
101-
perror("malloc");
98+
if (elf_add_reloc_to_insn(elf, ip_sec, idx * sizeof(int), R_X86_64_PC32,
99+
insn_sec, insn_off))
102100
return -1;
103-
}
104-
memset(reloc, 0, sizeof(*reloc));
105-
106-
insn_to_reloc_sym_addend(insn_sec, insn_off, reloc);
107-
if (!reloc->sym) {
108-
WARN("missing symbol for insn at offset 0x%lx",
109-
insn_off);
110-
return -1;
111-
}
112-
113-
reloc->type = R_X86_64_PC32;
114-
reloc->offset = idx * sizeof(int);
115-
reloc->sec = ip_rsec;
116-
117-
elf_add_reloc(elf, reloc);
118101

119102
return 0;
120103
}
@@ -153,7 +136,7 @@ static unsigned long alt_group_len(struct alt_group *alt_group)
153136

154137
int orc_create(struct objtool_file *file)
155138
{
156-
struct section *sec, *ip_rsec, *orc_sec;
139+
struct section *sec, *orc_sec;
157140
unsigned int nr = 0, idx = 0;
158141
struct orc_list_entry *entry;
159142
struct list_head orc_list;
@@ -242,13 +225,12 @@ int orc_create(struct objtool_file *file)
242225
sec = elf_create_section(file->elf, ".orc_unwind_ip", 0, sizeof(int), nr);
243226
if (!sec)
244227
return -1;
245-
ip_rsec = elf_create_reloc_section(file->elf, sec, SHT_RELA);
246-
if (!ip_rsec)
228+
if (!elf_create_reloc_section(file->elf, sec, SHT_RELA))
247229
return -1;
248230

249231
/* Write ORC entries to sections: */
250232
list_for_each_entry(entry, &orc_list, list) {
251-
if (write_orc_entry(file->elf, orc_sec, ip_rsec, idx++,
233+
if (write_orc_entry(file->elf, orc_sec, sec, idx++,
252234
entry->insn_sec, entry->insn_off,
253235
&entry->orc))
254236
return -1;

0 commit comments

Comments
 (0)