mirror of https://github.com/torvalds/linux.git
objtool: Add elf_create_data()
In preparation for the objtool klp diff subcommand, refactor elf_add_string() by adding a new elf_add_data() helper which allows the adding of arbitrary data to a section. Make both interfaces global so they can be used 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
243e963853
commit
431dbabf2d
|
|
@ -18,10 +18,11 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/interval_tree_generic.h>
|
#include <linux/interval_tree_generic.h>
|
||||||
#include <objtool/builtin.h>
|
#include <objtool/builtin.h>
|
||||||
|
|
||||||
#include <objtool/elf.h>
|
#include <objtool/elf.h>
|
||||||
#include <objtool/warn.h>
|
#include <objtool/warn.h>
|
||||||
|
|
||||||
|
#define ALIGN_UP(x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1))
|
||||||
|
|
||||||
static inline u32 str_hash(const char *str)
|
static inline u32 str_hash(const char *str)
|
||||||
{
|
{
|
||||||
return jhash(str, strlen(str), 0);
|
return jhash(str, strlen(str), 0);
|
||||||
|
|
@ -763,8 +764,6 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_add_string(struct elf *elf, struct section *strtab, const char *str);
|
|
||||||
|
|
||||||
struct symbol *elf_create_symbol(struct elf *elf, const char *name,
|
struct symbol *elf_create_symbol(struct elf *elf, const char *name,
|
||||||
struct section *sec, unsigned int bind,
|
struct section *sec, unsigned int bind,
|
||||||
unsigned int type, unsigned long offset,
|
unsigned int type, unsigned long offset,
|
||||||
|
|
@ -1100,11 +1099,9 @@ struct elf *elf_open_read(const char *name, int flags)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_add_string(struct elf *elf, struct section *strtab, const char *str)
|
unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str)
|
||||||
{
|
{
|
||||||
Elf_Data *data;
|
unsigned int offset;
|
||||||
Elf_Scn *s;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (!strtab)
|
if (!strtab)
|
||||||
strtab = find_section_by_name(elf, ".strtab");
|
strtab = find_section_by_name(elf, ".strtab");
|
||||||
|
|
@ -1113,28 +1110,59 @@ static int elf_add_string(struct elf *elf, struct section *strtab, const char *s
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = elf_getscn(elf->elf, strtab->idx);
|
if (!strtab->sh.sh_addralign) {
|
||||||
|
ERROR("'%s': invalid sh_addralign", strtab->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = ALIGN_UP(strtab->sh.sh_size, strtab->sh.sh_addralign);
|
||||||
|
|
||||||
|
if (!elf_add_data(elf, strtab, str, strlen(str) + 1))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
unsigned long offset;
|
||||||
|
Elf_Scn *s;
|
||||||
|
|
||||||
|
if (!sec->sh.sh_addralign) {
|
||||||
|
ERROR("'%s': invalid sh_addralign", sec->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = elf_getscn(elf->elf, sec->idx);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
ERROR_ELF("elf_getscn");
|
ERROR_ELF("elf_getscn");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = elf_newdata(s);
|
sec->data = elf_newdata(s);
|
||||||
if (!data) {
|
if (!sec->data) {
|
||||||
ERROR_ELF("elf_newdata");
|
ERROR_ELF("elf_newdata");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->d_buf = strdup(str);
|
sec->data->d_buf = calloc(1, size);
|
||||||
data->d_size = strlen(str) + 1;
|
if (!sec->data->d_buf) {
|
||||||
data->d_align = 1;
|
ERROR_GLIBC("calloc");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
len = strtab->sh.sh_size;
|
if (data)
|
||||||
strtab->sh.sh_size += data->d_size;
|
memcpy(sec->data->d_buf, data, size);
|
||||||
|
|
||||||
mark_sec_changed(elf, strtab, true);
|
sec->data->d_size = size;
|
||||||
|
sec->data->d_align = 1;
|
||||||
|
|
||||||
return len;
|
offset = ALIGN_UP(sec->sh.sh_size, sec->sh.sh_addralign);
|
||||||
|
sec->sh.sh_size = offset + size;
|
||||||
|
|
||||||
|
mark_sec_changed(elf, sec, true);
|
||||||
|
|
||||||
|
return sec->data->d_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct section *elf_create_section(struct elf *elf, const char *name,
|
struct section *elf_create_section(struct elf *elf, const char *name,
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,10 @@ struct symbol *elf_create_section_symbol(struct elf *elf, struct section *sec);
|
||||||
struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig,
|
struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig,
|
||||||
size_t size);
|
size_t size);
|
||||||
|
|
||||||
|
void *elf_add_data(struct elf *elf, struct section *sec, const void *data,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
|
unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str);
|
||||||
|
|
||||||
struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
|
struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec,
|
||||||
unsigned long offset,
|
unsigned long offset,
|
||||||
|
|
@ -148,9 +152,9 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
|
||||||
struct symbol *sym,
|
struct symbol *sym,
|
||||||
s64 addend);
|
s64 addend);
|
||||||
|
|
||||||
int elf_write_insn(struct elf *elf, struct section *sec,
|
int elf_write_insn(struct elf *elf, struct section *sec, unsigned long offset,
|
||||||
unsigned long offset, unsigned int len,
|
unsigned int len, const char *insn);
|
||||||
const char *insn);
|
|
||||||
int elf_write(struct elf *elf);
|
int elf_write(struct elf *elf);
|
||||||
void elf_close(struct elf *elf);
|
void elf_close(struct elf *elf);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue