linux-user: Use ImageSource in load_elf_image
Change parse_elf_properties as well, as the bprm_buf argument ties the two functions closely. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
40d487eecf
commit
3bd0238638
@ -3102,10 +3102,9 @@ static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
|
||||
}
|
||||
|
||||
/* Process NT_GNU_PROPERTY_TYPE_0. */
|
||||
static bool parse_elf_properties(int image_fd,
|
||||
static bool parse_elf_properties(const ImageSource *src,
|
||||
struct image_info *info,
|
||||
const struct elf_phdr *phdr,
|
||||
char bprm_buf[BPRM_BUF_SIZE],
|
||||
Error **errp)
|
||||
{
|
||||
union {
|
||||
@ -3133,14 +3132,8 @@ static bool parse_elf_properties(int image_fd,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
|
||||
memcpy(¬e, bprm_buf + phdr->p_offset, n);
|
||||
} else {
|
||||
ssize_t len = pread(image_fd, ¬e, n, phdr->p_offset);
|
||||
if (len != n) {
|
||||
error_setg_errno(errp, errno, "Error reading file header");
|
||||
return false;
|
||||
}
|
||||
if (!imgsrc_read(¬e, phdr->p_offset, n, src, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3186,30 +3179,34 @@ static bool parse_elf_properties(int image_fd,
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an ELF image into the address space.
|
||||
/**
|
||||
* load_elf_image: Load an ELF image into the address space.
|
||||
* @image_name: the filename of the image, to use in error messages.
|
||||
* @src: the ImageSource from which to read.
|
||||
* @info: info collected from the loaded image.
|
||||
* @ehdr: the ELF header, not yet bswapped.
|
||||
* @pinterp_name: record any PT_INTERP string found.
|
||||
*
|
||||
* On return: @info values will be filled in, as necessary or available.
|
||||
*/
|
||||
|
||||
IMAGE_NAME is the filename of the image, to use in error messages.
|
||||
IMAGE_FD is the open file descriptor for the image.
|
||||
|
||||
BPRM_BUF is a copy of the beginning of the file; this of course
|
||||
contains the elf file header at offset 0. It is assumed that this
|
||||
buffer is sufficiently aligned to present no problems to the host
|
||||
in accessing data at aligned offsets within the buffer.
|
||||
|
||||
On return: INFO values will be filled in, as necessary or available. */
|
||||
|
||||
static void load_elf_image(const char *image_name, int image_fd,
|
||||
static void load_elf_image(const char *image_name, const ImageSource *src,
|
||||
struct image_info *info, struct elfhdr *ehdr,
|
||||
char **pinterp_name,
|
||||
char bprm_buf[BPRM_BUF_SIZE])
|
||||
char **pinterp_name)
|
||||
{
|
||||
struct elf_phdr *phdr;
|
||||
g_autofree struct elf_phdr *phdr = NULL;
|
||||
abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
|
||||
int i, retval, prot_exec;
|
||||
int i, prot_exec;
|
||||
Error *err = NULL;
|
||||
|
||||
/* First of all, some simple consistency checks */
|
||||
memcpy(ehdr, bprm_buf, sizeof(*ehdr));
|
||||
/*
|
||||
* First of all, some simple consistency checks.
|
||||
* Note that we rely on the bswapped ehdr staying in bprm_buf,
|
||||
* for later use by load_elf_binary and create_elf_tables.
|
||||
*/
|
||||
if (!imgsrc_read(ehdr, 0, sizeof(*ehdr), src, &err)) {
|
||||
goto exit_errmsg;
|
||||
}
|
||||
if (!elf_check_ident(ehdr)) {
|
||||
error_setg(&err, "Invalid ELF image for this architecture");
|
||||
goto exit_errmsg;
|
||||
@ -3220,15 +3217,11 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
goto exit_errmsg;
|
||||
}
|
||||
|
||||
i = ehdr->e_phnum * sizeof(struct elf_phdr);
|
||||
if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
|
||||
phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
|
||||
} else {
|
||||
phdr = (struct elf_phdr *) alloca(i);
|
||||
retval = pread(image_fd, phdr, i, ehdr->e_phoff);
|
||||
if (retval != i) {
|
||||
goto exit_read;
|
||||
}
|
||||
phdr = imgsrc_read_alloc(ehdr->e_phoff,
|
||||
ehdr->e_phnum * sizeof(struct elf_phdr),
|
||||
src, &err);
|
||||
if (phdr == NULL) {
|
||||
goto exit_errmsg;
|
||||
}
|
||||
bswap_phdr(phdr, ehdr->e_phnum);
|
||||
|
||||
@ -3265,17 +3258,10 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
goto exit_errmsg;
|
||||
}
|
||||
|
||||
interp_name = g_malloc(eppnt->p_filesz);
|
||||
|
||||
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
|
||||
memcpy(interp_name, bprm_buf + eppnt->p_offset,
|
||||
eppnt->p_filesz);
|
||||
} else {
|
||||
retval = pread(image_fd, interp_name, eppnt->p_filesz,
|
||||
eppnt->p_offset);
|
||||
if (retval != eppnt->p_filesz) {
|
||||
goto exit_read;
|
||||
}
|
||||
interp_name = imgsrc_read_alloc(eppnt->p_offset, eppnt->p_filesz,
|
||||
src, &err);
|
||||
if (interp_name == NULL) {
|
||||
goto exit_errmsg;
|
||||
}
|
||||
if (interp_name[eppnt->p_filesz - 1] != 0) {
|
||||
error_setg(&err, "Invalid PT_INTERP entry");
|
||||
@ -3283,7 +3269,7 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
}
|
||||
*pinterp_name = g_steal_pointer(&interp_name);
|
||||
} else if (eppnt->p_type == PT_GNU_PROPERTY) {
|
||||
if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
|
||||
if (!parse_elf_properties(src, info, eppnt, &err)) {
|
||||
goto exit_errmsg;
|
||||
}
|
||||
} else if (eppnt->p_type == PT_GNU_STACK) {
|
||||
@ -3436,9 +3422,9 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
* but no backing file segment.
|
||||
*/
|
||||
if (eppnt->p_filesz != 0) {
|
||||
error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
|
||||
error = imgsrc_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
|
||||
elf_prot, MAP_PRIVATE | MAP_FIXED,
|
||||
image_fd, eppnt->p_offset - vaddr_po);
|
||||
src, eppnt->p_offset - vaddr_po);
|
||||
if (error == -1) {
|
||||
goto exit_mmap;
|
||||
}
|
||||
@ -3470,20 +3456,11 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
#ifdef TARGET_MIPS
|
||||
} else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
|
||||
Mips_elf_abiflags_v0 abiflags;
|
||||
if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
|
||||
error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
|
||||
|
||||
if (!imgsrc_read(&abiflags, eppnt->p_offset, sizeof(abiflags),
|
||||
src, &err)) {
|
||||
goto exit_errmsg;
|
||||
}
|
||||
if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
|
||||
memcpy(&abiflags, bprm_buf + eppnt->p_offset,
|
||||
sizeof(Mips_elf_abiflags_v0));
|
||||
} else {
|
||||
retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
|
||||
eppnt->p_offset);
|
||||
if (retval != sizeof(Mips_elf_abiflags_v0)) {
|
||||
goto exit_read;
|
||||
}
|
||||
}
|
||||
bswap_mips_abiflags(&abiflags);
|
||||
info->fp_abi = abiflags.fp_abi;
|
||||
#endif
|
||||
@ -3496,23 +3473,16 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
}
|
||||
|
||||
if (qemu_log_enabled()) {
|
||||
load_symbols(ehdr, image_fd, load_bias);
|
||||
load_symbols(ehdr, src->fd, load_bias);
|
||||
}
|
||||
|
||||
debuginfo_report_elf(image_name, image_fd, load_bias);
|
||||
debuginfo_report_elf(image_name, src->fd, load_bias);
|
||||
|
||||
mmap_unlock();
|
||||
|
||||
close(image_fd);
|
||||
close(src->fd);
|
||||
return;
|
||||
|
||||
exit_read:
|
||||
if (retval >= 0) {
|
||||
error_setg(&err, "Incomplete read of file header");
|
||||
} else {
|
||||
error_setg_errno(&err, errno, "Error reading file header");
|
||||
}
|
||||
goto exit_errmsg;
|
||||
exit_mmap:
|
||||
error_setg_errno(&err, errno, "Error mapping file");
|
||||
goto exit_errmsg;
|
||||
@ -3525,6 +3495,7 @@ static void load_elf_interp(const char *filename, struct image_info *info,
|
||||
char bprm_buf[BPRM_BUF_SIZE])
|
||||
{
|
||||
struct elfhdr ehdr;
|
||||
ImageSource src;
|
||||
int fd, retval;
|
||||
Error *err = NULL;
|
||||
|
||||
@ -3542,11 +3513,11 @@ static void load_elf_interp(const char *filename, struct image_info *info,
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (retval < BPRM_BUF_SIZE) {
|
||||
memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
|
||||
}
|
||||
src.fd = fd;
|
||||
src.cache = bprm_buf;
|
||||
src.cache_size = retval;
|
||||
|
||||
load_elf_image(filename, fd, info, &ehdr, NULL, bprm_buf);
|
||||
load_elf_image(filename, &src, info, &ehdr, NULL);
|
||||
}
|
||||
|
||||
static int symfind(const void *s0, const void *s1)
|
||||
@ -3755,8 +3726,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
|
||||
interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
|
||||
#endif
|
||||
|
||||
load_elf_image(bprm->filename, bprm->fd, info,
|
||||
&ehdr, &elf_interpreter, bprm->buf);
|
||||
load_elf_image(bprm->filename, &bprm->src, info, &ehdr, &elf_interpreter);
|
||||
|
||||
/* Do this so that we can load the interpreter, if need be. We will
|
||||
change some of these later */
|
||||
|
Loading…
Reference in New Issue
Block a user