Skip to content

Commit

Permalink
linux-user: Use ImageSource in load_symbols
Browse files Browse the repository at this point in the history
Aside from the section headers, we're unlikely to hit the
ImageSource cache on guest executables.  But the interface
for imgsrc_read_* is better.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Oct 30, 2023
1 parent 3bd0238 commit 86cf82d
Showing 1 changed file with 45 additions and 36 deletions.
81 changes: 45 additions & 36 deletions linux-user/elfload.c
Original file line number Diff line number Diff line change
Expand Up @@ -2201,7 +2201,8 @@ static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
#ifdef USE_ELF_CORE_DUMP
static int elf_core_dump(int, const CPUArchState *);
#endif /* USE_ELF_CORE_DUMP */
static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
abi_ulong load_bias);

/* Verify the portions of EHDR within E_IDENT for the target.
This can be performed before bswapping the entire header. */
Expand Down Expand Up @@ -3473,7 +3474,7 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
}

if (qemu_log_enabled()) {
load_symbols(ehdr, src->fd, load_bias);
load_symbols(ehdr, src, load_bias);
}

debuginfo_report_elf(image_name, src->fd, load_bias);
Expand Down Expand Up @@ -3564,19 +3565,20 @@ static int symcmp(const void *s0, const void *s1)
}

/* Best attempt to load symbols from this ELF object. */
static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
static void load_symbols(struct elfhdr *hdr, const ImageSource *src,
abi_ulong load_bias)
{
int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
uint64_t segsz;
struct elf_shdr *shdr;
g_autofree struct elf_shdr *shdr = NULL;
char *strings = NULL;
struct syminfo *s = NULL;
struct elf_sym *new_syms, *syms = NULL;
struct elf_sym *syms = NULL;
struct elf_sym *new_syms;
uint64_t segsz;

shnum = hdr->e_shnum;
i = shnum * sizeof(struct elf_shdr);
shdr = (struct elf_shdr *)alloca(i);
if (pread(fd, shdr, i, hdr->e_shoff) != i) {
shdr = imgsrc_read_alloc(hdr->e_shoff, shnum * sizeof(struct elf_shdr),
src, NULL);
if (shdr == NULL) {
return;
}

Expand All @@ -3594,31 +3596,33 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)

found:
/* Now know where the strtab and symtab are. Snarf them. */
s = g_try_new(struct syminfo, 1);
if (!s) {
goto give_up;
}

segsz = shdr[str_idx].sh_size;
s->disas_strtab = strings = g_try_malloc(segsz);
if (!strings ||
pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) {
strings = g_try_malloc(segsz);
if (!strings) {
goto give_up;
}

segsz = shdr[sym_idx].sh_size;
syms = g_try_malloc(segsz);
if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) {
if (!imgsrc_read(strings, shdr[str_idx].sh_offset, segsz, src, NULL)) {
goto give_up;
}

segsz = shdr[sym_idx].sh_size;
if (segsz / sizeof(struct elf_sym) > INT_MAX) {
/* Implausibly large symbol table: give up rather than ploughing
* on with the number of symbols calculation overflowing
/*
* Implausibly large symbol table: give up rather than ploughing
* on with the number of symbols calculation overflowing.
*/
goto give_up;
}
nsyms = segsz / sizeof(struct elf_sym);
syms = g_try_malloc(segsz);
if (!syms) {
goto give_up;
}
if (!imgsrc_read(syms, shdr[sym_idx].sh_offset, segsz, src, NULL)) {
goto give_up;
}

for (i = 0; i < nsyms; ) {
bswap_sym(syms + i);
/* Throw away entries which we do not need. */
Expand All @@ -3643,10 +3647,12 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
goto give_up;
}

/* Attempt to free the storage associated with the local symbols
that we threw away. Whether or not this has any effect on the
memory allocation depends on the malloc implementation and how
many symbols we managed to discard. */
/*
* Attempt to free the storage associated with the local symbols
* that we threw away. Whether or not this has any effect on the
* memory allocation depends on the malloc implementation and how
* many symbols we managed to discard.
*/
new_syms = g_try_renew(struct elf_sym, syms, nsyms);
if (new_syms == NULL) {
goto give_up;
Expand All @@ -3655,20 +3661,23 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)

qsort(syms, nsyms, sizeof(*syms), symcmp);

s->disas_num_syms = nsyms;
{
struct syminfo *s = g_new(struct syminfo, 1);

s->disas_strtab = strings;
s->disas_num_syms = nsyms;
#if ELF_CLASS == ELFCLASS32
s->disas_symtab.elf32 = syms;
s->disas_symtab.elf32 = syms;
#else
s->disas_symtab.elf64 = syms;
s->disas_symtab.elf64 = syms;
#endif
s->lookup_symbol = lookup_symbolxx;
s->next = syminfos;
syminfos = s;

s->lookup_symbol = lookup_symbolxx;
s->next = syminfos;
syminfos = s;
}
return;

give_up:
g_free(s);
give_up:
g_free(strings);
g_free(syms);
}
Expand Down

0 comments on commit 86cf82d

Please sign in to comment.