aboutsummaryrefslogtreecommitdiff
path: root/bsd-user/elfload.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2021-08-04 17:13:24 -0600
committerWarner Losh <imp@bsdimp.com>2021-09-10 14:13:06 -0600
commit98b34d354b5da78880cb39dc3a7db91c790f7c7d (patch)
tree45340ad0ade387478d3490060463112b02d97059 /bsd-user/elfload.c
parentc336094c5c4c1159b96b7bff074579f055e8aea2 (diff)
bsd-user: elf cleanup
Move OS-dependent defines into target_os_elf.h. Move the architectural dependent stuff into target_arch_elf.h. Adjust elfload.c to use target_create_elf_tables instead of create_elf_tables. Signed-off-by: Warner Losh <imp@bsdimp.com> Signed-off-by: Stacey Son <sson@FreeBSD.org> Signed-off-by: Kyle Evans <kevans@FreeBSD.org> Signed-off-by: Justin Hibbits <chmeeedalf@gmail.com> Signed-off-by: Alexander Kabaev <kan@FreeBSD.ORG> Acked-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Kyle Evans <kevans@FreeBSD.org>
Diffstat (limited to 'bsd-user/elfload.c')
-rw-r--r--bsd-user/elfload.c191
1 files changed, 24 insertions, 167 deletions
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 59465b71d4..6156f9775d 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -23,48 +23,17 @@
#include "disas/disas.h"
#include "qemu/path.h"
-#include "target_arch_elf.h"
-#include "target_os_thread.h"
-
-/* this flag is uneffective under linux too, should be deleted */
-#ifndef MAP_DENYWRITE
-#define MAP_DENYWRITE 0
-#endif
-
-/* should probably go in elf.h */
-#ifndef ELIBBAD
-#define ELIBBAD 80
-#endif
-
-#ifndef ELF_PLATFORM
-#define ELF_PLATFORM (NULL)
-#endif
-
-#ifndef ELF_HWCAP
-#define ELF_HWCAP 0
-#endif
+static abi_ulong target_auxents; /* Where the AUX entries are in target */
+static size_t target_auxents_sz; /* Size of AUX entries including AT_NULL */
-#ifdef TARGET_ABI32
-#undef ELF_CLASS
-#define ELF_CLASS ELFCLASS32
-#undef bswaptls
-#define bswaptls(ptr) bswap32s(ptr)
-#endif
+#include "target_os_elf.h"
+#include "target_os_stack.h"
+#include "target_os_thread.h"
#include "elf.h"
-/* max code+data+bss space allocated to elf interpreter */
-#define INTERP_MAP_SIZE (32 * 1024 * 1024)
-
-/* max code+data+bss+brk space allocated to ET_DYN executables */
-#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
-
-/* Necessary parameters */
-#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
-#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE - 1))
-#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE - 1))
-
-#define DLINFO_ITEMS 12
+abi_ulong target_stksiz;
+abi_ulong target_stkbas;
static inline void memcpy_fromfs(void *to, const void *from, unsigned long n)
{
@@ -195,43 +164,36 @@ static abi_ulong copy_elf_strings(int argc, char **argv, void **page,
return p;
}
-static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
- struct image_info *info)
+static void setup_arg_pages(struct bsd_binprm *bprm, struct image_info *info,
+ abi_ulong *stackp, abi_ulong *stringp)
{
- abi_ulong stack_base, size, error;
- int i;
+ abi_ulong stack_base, size;
+ abi_long addr;
/* Create enough stack to hold everything. If we don't use
* it for args, we'll use it for something else...
*/
size = target_dflssiz;
- if (size < MAX_ARG_PAGES * TARGET_PAGE_SIZE)
- size = MAX_ARG_PAGES * TARGET_PAGE_SIZE;
- error = target_mmap(0,
+ stack_base = TARGET_USRSTACK - size;
+ addr = target_mmap(stack_base,
size + qemu_host_page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON,
-1, 0);
- if (error == -1) {
+ if (addr == -1) {
perror("stk mmap");
exit(-1);
}
/* we reserve one extra page at the top of the stack as guard */
- target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
+ target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
- stack_base = error + size - MAX_ARG_PAGES * TARGET_PAGE_SIZE;
- p += stack_base;
+ target_stksiz = size;
+ target_stkbas = addr;
- for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
- if (bprm->page[i]) {
- info->rss++;
- /* FIXME - check return value of memcpy_to_target() for failure */
- memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
- g_free(bprm->page[i]);
- }
- stack_base += TARGET_PAGE_SIZE;
+ if (setup_initial_stack(bprm, stackp, stringp) != 0) {
+ perror("stk setup");
+ exit(-1);
}
- return p;
}
static void set_brk(abi_ulong start, abi_ulong end)
@@ -287,86 +249,6 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
}
}
-
-static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
- struct elfhdr * exec,
- abi_ulong load_addr,
- abi_ulong load_bias,
- abi_ulong interp_load_addr,
- struct image_info *info)
-{
- abi_ulong sp;
- int size;
- abi_ulong u_platform;
- const char *k_platform;
- const int n = sizeof(elf_addr_t);
-
- sp = p;
- u_platform = 0;
- k_platform = ELF_PLATFORM;
- if (k_platform) {
- size_t len = strlen(k_platform) + 1;
- sp -= (len + n - 1) & ~(n - 1);
- u_platform = sp;
- /* FIXME - check return value of memcpy_to_target() for failure */
- memcpy_to_target(sp, k_platform, len);
- }
- /*
- * Force 16 byte _final_ alignment here for generality.
- */
- sp = sp & ~(abi_ulong)15;
- size = (DLINFO_ITEMS + 1) * 2;
- if (k_platform)
- size += 2;
-#ifdef DLINFO_ARCH_ITEMS
- size += DLINFO_ARCH_ITEMS * 2;
-#endif
- size += envc + argc + 2;
- size += 1; /* argc itself */
- size *= n;
- if (size & 15)
- sp -= 16 - (size & 15);
-
- /* This is correct because Linux defines
- * elf_addr_t as Elf32_Off / Elf64_Off
- */
-#define NEW_AUX_ENT(id, val) do { \
- sp -= n; put_user_ual(val, sp); \
- sp -= n; put_user_ual(id, sp); \
- } while (0)
-
- NEW_AUX_ENT(AT_NULL, 0);
-
- /* There must be exactly DLINFO_ITEMS entries here. */
- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
- NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof(struct elf_phdr)));
- NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
- NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
- NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
- NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
- NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
- NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
- NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
- NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
- NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
- NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
- NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
- if (k_platform)
- NEW_AUX_ENT(AT_PLATFORM, u_platform);
-#ifdef ARCH_DLINFO
- /*
- * ARCH_DLINFO must come last so platform specific code can enforce
- * special alignment requirements on the AUXV if necessary (eg. PPC).
- */
- ARCH_DLINFO;
-#endif
-#undef NEW_AUX_ENT
-
- sp = loader_build_argptr(envc, argc, sp, p);
- return sp;
-}
-
-
static abi_ulong load_elf_interp(struct elfhdr *interp_elf_ex,
int interpreter_fd,
abi_ulong *interp_load_addr)
@@ -824,31 +706,10 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
info->mmap = 0;
elf_entry = (abi_ulong) elf_ex.e_entry;
- /*
- * In case where user has not explicitly set the guest_base, we
- * probe here that should we set it automatically.
- */
- if (!have_guest_base) {
- /*
- * Go through ELF program header table and find out whether
- * any of the segments drop below our current mmap_min_addr and
- * in that case set guest_base to corresponding address.
- */
- for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
- i++, elf_ppnt++) {
- if (elf_ppnt->p_type != PT_LOAD)
- continue;
- if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
- guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
- break;
- }
- }
- }
-
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
info->rss = 0;
- bprm->p = setup_arg_pages(bprm->p, bprm, info);
+ setup_arg_pages(bprm, info, &bprm->p, &bprm->stringp);
info->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
@@ -965,13 +826,9 @@ int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
#ifdef LOW_ELF_STACK
info->start_stack = bprm->p = elf_stack - 4;
#endif
- bprm->p = create_elf_tables(bprm->p,
- bprm->argc,
- bprm->envc,
- &elf_ex,
- load_addr, load_bias,
- interp_load_addr,
- info);
+ bprm->p = target_create_elf_tables(bprm->p, bprm->argc, bprm->envc,
+ bprm->stringp, &elf_ex, load_addr,
+ load_bias, interp_load_addr, info);
info->load_addr = reloc_func_desc;
info->start_brk = info->brk = elf_brk;
info->end_code = end_code;