mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
objtool: Generalize elf_create_section()
In preparation for the objtool klp diff subcommand, broaden the elf_create_section() interface to give callers more control and reduce duplication of some subtle setup logic. While at it, make elf_create_rela_section() global so sections can be created by the upcoming klp diff code. Acked-by: Petr Mladek <pmladek@suse.com> Tested-by: Joe Lawrence <joe.lawrence@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
parent
dd2c29aafd
commit
243e963853
|
|
@ -1138,51 +1138,53 @@ static int elf_add_string(struct elf *elf, struct section *strtab, const char *s
|
|||
}
|
||||
|
||||
struct section *elf_create_section(struct elf *elf, const char *name,
|
||||
size_t entsize, unsigned int nr)
|
||||
size_t size, size_t entsize,
|
||||
unsigned int type, unsigned int align,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct section *sec, *shstrtab;
|
||||
size_t size = entsize * nr;
|
||||
Elf_Scn *s;
|
||||
|
||||
sec = malloc(sizeof(*sec));
|
||||
if (!sec) {
|
||||
ERROR_GLIBC("malloc");
|
||||
if (name && find_section_by_name(elf, name)) {
|
||||
ERROR("section '%s' already exists", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sec = calloc(1, sizeof(*sec));
|
||||
if (!sec) {
|
||||
ERROR_GLIBC("calloc");
|
||||
return NULL;
|
||||
}
|
||||
memset(sec, 0, sizeof(*sec));
|
||||
|
||||
INIT_LIST_HEAD(&sec->symbol_list);
|
||||
|
||||
/* don't actually create the section, just the data structures */
|
||||
if (type == SHT_NULL)
|
||||
goto add;
|
||||
|
||||
s = elf_newscn(elf->elf);
|
||||
if (!s) {
|
||||
ERROR_ELF("elf_newscn");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sec->name = strdup(name);
|
||||
if (!sec->name) {
|
||||
ERROR_GLIBC("strdup");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sec->idx = elf_ndxscn(s);
|
||||
|
||||
sec->data = elf_newdata(s);
|
||||
if (!sec->data) {
|
||||
ERROR_ELF("elf_newdata");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sec->data->d_size = size;
|
||||
sec->data->d_align = 1;
|
||||
|
||||
if (size) {
|
||||
sec->data->d_buf = malloc(size);
|
||||
if (!sec->data->d_buf) {
|
||||
ERROR_GLIBC("malloc");
|
||||
sec->data = elf_newdata(s);
|
||||
if (!sec->data) {
|
||||
ERROR_ELF("elf_newdata");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sec->data->d_size = size;
|
||||
sec->data->d_align = 1;
|
||||
|
||||
sec->data->d_buf = calloc(1, size);
|
||||
if (!sec->data->d_buf) {
|
||||
ERROR_GLIBC("calloc");
|
||||
return NULL;
|
||||
}
|
||||
memset(sec->data->d_buf, 0, size);
|
||||
}
|
||||
|
||||
if (!gelf_getshdr(s, &sec->sh)) {
|
||||
|
|
@ -1192,34 +1194,44 @@ struct section *elf_create_section(struct elf *elf, const char *name,
|
|||
|
||||
sec->sh.sh_size = size;
|
||||
sec->sh.sh_entsize = entsize;
|
||||
sec->sh.sh_type = SHT_PROGBITS;
|
||||
sec->sh.sh_addralign = 1;
|
||||
sec->sh.sh_flags = SHF_ALLOC;
|
||||
sec->sh.sh_type = type;
|
||||
sec->sh.sh_addralign = align;
|
||||
sec->sh.sh_flags = flags;
|
||||
|
||||
/* Add section name to .shstrtab (or .strtab for Clang) */
|
||||
shstrtab = find_section_by_name(elf, ".shstrtab");
|
||||
if (!shstrtab)
|
||||
shstrtab = find_section_by_name(elf, ".strtab");
|
||||
if (!shstrtab) {
|
||||
ERROR("can't find .shstrtab or .strtab section");
|
||||
return NULL;
|
||||
if (name) {
|
||||
sec->name = strdup(name);
|
||||
if (!sec->name) {
|
||||
ERROR("strdup");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add section name to .shstrtab (or .strtab for Clang) */
|
||||
shstrtab = find_section_by_name(elf, ".shstrtab");
|
||||
if (!shstrtab) {
|
||||
shstrtab = find_section_by_name(elf, ".strtab");
|
||||
if (!shstrtab) {
|
||||
ERROR("can't find .shstrtab or .strtab");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
sec->sh.sh_name = elf_add_string(elf, shstrtab, sec->name);
|
||||
if (sec->sh.sh_name == -1)
|
||||
return NULL;
|
||||
|
||||
elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
|
||||
}
|
||||
sec->sh.sh_name = elf_add_string(elf, shstrtab, sec->name);
|
||||
if (sec->sh.sh_name == -1)
|
||||
return NULL;
|
||||
|
||||
add:
|
||||
list_add_tail(&sec->list, &elf->sections);
|
||||
elf_hash_add(section, &sec->hash, sec->idx);
|
||||
elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name));
|
||||
|
||||
mark_sec_changed(elf, sec, true);
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
static struct section *elf_create_rela_section(struct elf *elf,
|
||||
struct section *sec,
|
||||
unsigned int reloc_nr)
|
||||
struct section *elf_create_rela_section(struct elf *elf, struct section *sec,
|
||||
unsigned int reloc_nr)
|
||||
{
|
||||
struct section *rsec;
|
||||
char *rsec_name;
|
||||
|
|
@ -1232,22 +1244,23 @@ static struct section *elf_create_rela_section(struct elf *elf,
|
|||
strcpy(rsec_name, ".rela");
|
||||
strcat(rsec_name, sec->name);
|
||||
|
||||
rsec = elf_create_section(elf, rsec_name, elf_rela_size(elf), reloc_nr);
|
||||
rsec = elf_create_section(elf, rsec_name, reloc_nr * elf_rela_size(elf),
|
||||
elf_rela_size(elf), SHT_RELA, elf_addr_size(elf),
|
||||
SHF_INFO_LINK);
|
||||
free(rsec_name);
|
||||
if (!rsec)
|
||||
return NULL;
|
||||
|
||||
rsec->data->d_type = ELF_T_RELA;
|
||||
rsec->sh.sh_type = SHT_RELA;
|
||||
rsec->sh.sh_addralign = elf_addr_size(elf);
|
||||
rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx;
|
||||
rsec->sh.sh_info = sec->idx;
|
||||
rsec->sh.sh_flags = SHF_INFO_LINK;
|
||||
|
||||
rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
|
||||
if (!rsec->relocs) {
|
||||
ERROR_GLIBC("calloc");
|
||||
return NULL;
|
||||
if (reloc_nr) {
|
||||
rsec->data->d_type = ELF_T_RELA;
|
||||
rsec->relocs = calloc(sec_num_entries(rsec), sizeof(struct reloc));
|
||||
if (!rsec->relocs) {
|
||||
ERROR_GLIBC("calloc");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
sec->rsec = rsec;
|
||||
|
|
@ -1262,7 +1275,8 @@ struct section *elf_create_section_pair(struct elf *elf, const char *name,
|
|||
{
|
||||
struct section *sec;
|
||||
|
||||
sec = elf_create_section(elf, name, entsize, nr);
|
||||
sec = elf_create_section(elf, name, nr * entsize, entsize,
|
||||
SHT_PROGBITS, 1, SHF_ALLOC);
|
||||
if (!sec)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -117,11 +117,16 @@ struct elf {
|
|||
struct elf *elf_open_read(const char *name, int flags);
|
||||
|
||||
struct section *elf_create_section(struct elf *elf, const char *name,
|
||||
size_t entsize, unsigned int nr);
|
||||
size_t size, size_t entsize,
|
||||
unsigned int type, unsigned int align,
|
||||
unsigned int flags);
|
||||
struct section *elf_create_section_pair(struct elf *elf, const char *name,
|
||||
size_t entsize, unsigned int nr,
|
||||
unsigned int reloc_nr);
|
||||
|
||||
struct section *elf_create_rela_section(struct elf *elf, struct section *sec,
|
||||
unsigned int reloc_nr);
|
||||
|
||||
struct symbol *elf_create_symbol(struct elf *elf, const char *name,
|
||||
struct section *sec, unsigned int bind,
|
||||
unsigned int type, unsigned long offset,
|
||||
|
|
|
|||
|
|
@ -127,7 +127,11 @@ int orc_create(struct objtool_file *file)
|
|||
return -1;
|
||||
}
|
||||
orc_sec = elf_create_section(file->elf, ".orc_unwind",
|
||||
sizeof(struct orc_entry), nr);
|
||||
nr * sizeof(struct orc_entry),
|
||||
sizeof(struct orc_entry),
|
||||
SHT_PROGBITS,
|
||||
1,
|
||||
SHF_ALLOC);
|
||||
if (!orc_sec)
|
||||
return -1;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user