Commit 431dbabf authored by Josh Poimboeuf's avatar Josh Poimboeuf
Browse files

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: default avatarPetr Mladek <pmladek@suse.com>
Tested-by: default avatarJoe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
parent 243e9638
Loading
Loading
Loading
Loading
+47 −19
Original line number Diff line number Diff line
@@ -18,10 +18,11 @@
#include <errno.h>
#include <linux/interval_tree_generic.h>
#include <objtool/builtin.h>

#include <objtool/elf.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)
{
	return jhash(str, strlen(str), 0);
@@ -763,8 +764,6 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab,
	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 section *sec, unsigned int bind,
				 unsigned int type, unsigned long offset,
@@ -1100,11 +1099,9 @@ struct elf *elf_open_read(const char *name, int flags)
	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;
	Elf_Scn *s;
	int len;
	unsigned int offset;

	if (!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;
	}

	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) {
		ERROR_ELF("elf_getscn");
		return -1;
		return NULL;
	}

	data = elf_newdata(s);
	if (!data) {
	sec->data = elf_newdata(s);
	if (!sec->data) {
		ERROR_ELF("elf_newdata");
		return -1;
		return NULL;
	}

	sec->data->d_buf = calloc(1, size);
	if (!sec->data->d_buf) {
		ERROR_GLIBC("calloc");
		return NULL;
	}

	data->d_buf = strdup(str);
	data->d_size = strlen(str) + 1;
	data->d_align = 1;
	if (data)
		memcpy(sec->data->d_buf, data, size);

	len = strtab->sh.sh_size;
	strtab->sh.sh_size += data->d_size;
	sec->data->d_size = size;
	sec->data->d_align = 1;

	mark_sec_changed(elf, strtab, true);
	offset = ALIGN_UP(sec->sh.sh_size, sec->sh.sh_addralign);
	sec->sh.sh_size = offset + size;

	mark_sec_changed(elf, sec, true);

	return len;
	return sec->data->d_buf;
}

struct section *elf_create_section(struct elf *elf, const char *name,
+7 −3
Original line number Diff line number Diff line
@@ -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,
					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,
				      unsigned long offset,
@@ -148,9 +152,9 @@ struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec,
				      struct symbol *sym,
				      s64 addend);

int elf_write_insn(struct elf *elf, struct section *sec,
		   unsigned long offset, unsigned int len,
		   const char *insn);
int elf_write_insn(struct elf *elf, struct section *sec, unsigned long offset,
		   unsigned int len, const char *insn);

int elf_write(struct elf *elf);
void elf_close(struct elf *elf);