From 324eeca7a85dcef4a10c822f9500565ec32054b0 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 6 Dec 2023 01:11:56 -0800 Subject: [PATCH] load_elf: match linux better for statically-linked binaries we still need more auxv entries, but the rest should match close enough now. --- src/openpower/decoder/isa/mem.py | 109 ++++++++++++++++++++++------ src/openpower/syscalls/ppc_flags.py | 1 + 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/src/openpower/decoder/isa/mem.py b/src/openpower/decoder/isa/mem.py index 2b8c5279..fc308cc8 100644 --- a/src/openpower/decoder/isa/mem.py +++ b/src/openpower/decoder/isa/mem.py @@ -1181,37 +1181,100 @@ def load_elf(mem, elf_file, args=(), env=(), stack_size=DEFAULT_INIT_STACK_SZ): result = mem.mmap_syscall( stack_low, stack_size, prot, flags, fd=-1, offset=0, is_mmap2=False) raise_if_syscall_err(result) - gprs = {} - if len(args): - raise NotImplementedError("allocate argv on the stack") - else: - argv = 0 - if len(env): - raise NotImplementedError("allocate envp on the stack") - else: - envp = 0 - if heap_start > 0: - mem.heap_range = range(heap_start, heap_start) # empty heap to start - - # FIXME: incorrect, should point to the aux vector allocated on the stack + env_bytes = bytearray() + env_offsets = [] + for env_entry in env: + env_offsets.append(len(env_bytes)) + if isinstance(env_entry, str): + env_entry = env_entry.encode() + else: + env_entry = bytes(env_entry) + if b"\0" in env_entry: + raise ValueError("env var byte-string can't contain NUL") + if b"=" not in env_entry: + raise ValueError("env var is missing =") + env_bytes += env_entry + env_bytes += b"\0" + + stack_top -= len(env_bytes) + env_bytes_addr = stack_top + if len(env_bytes): + mem.get_ctypes(env_bytes_addr, len(env_bytes), True)[:] = env_bytes + + args = tuple(args) + if len(args) == 0: + args = ("program",) # glibc depends on argc != 0 + args_bytes = bytearray() + arg_offsets = [] + for arg in args: + arg_offsets.append(len(args_bytes)) + if isinstance(arg, str): + arg = arg.encode() + else: + arg = bytes(arg) + if b"\0" in arg: + raise ValueError("argument byte-string can't contain NUL") + args_bytes += arg + args_bytes += b"\0" + args_bytes += b"\0" + stack_top -= len(args_bytes) + args_bytes_addr = stack_top + mem.get_ctypes(args_bytes_addr, len(args_bytes), True)[:] = args_bytes + + stack_top -= stack_top % 8 # align stack top for auxv + + auxv_t = struct.Struct(" 0: + mem.heap_range = range(heap_start, heap_start) # empty heap to start # TODO: dynamically-linked binaries need to use the entry-point of ld.so pc = elf_file.header['e_entry'] gprs[1] = stack_top - gprs[3] = len(args) # argc - gprs[4] = argv - gprs[5] = envp - gprs[5] = auxv + gprs[3] = 0 # argc -- apparently just zeroed by linux + gprs[4] = 0 # argv -- apparently just zeroed by linux + gprs[5] = 0 # envp -- apparently just zeroed by linux + gprs[6] = 0 # auxv -- apparently just zeroed by linux gprs[7] = 0 # termination function pointer gprs[12] = pc fpscr = 0 diff --git a/src/openpower/syscalls/ppc_flags.py b/src/openpower/syscalls/ppc_flags.py index 13da5ec2..7f2fe507 100644 --- a/src/openpower/syscalls/ppc_flags.py +++ b/src/openpower/syscalls/ppc_flags.py @@ -21,6 +21,7 @@ def parse_defines(flags, compiler): #include #include #include +#include """ if isinstance(compiler, str): compiler = [compiler] -- 2.30.2