def load(self, filename, env):
        """
        Loads and an ELF program in memory and prepares the initial CPU state.
        Creates the stack and loads the environment variables and the arguments in it.

        :param filename: pathname of the file to be executed. (used for auxv)
        :param list env: A list of env variables. (used for extracting vars that control ld behavior)
        :raises error:
            - 'Not matching cpu': if the program is compiled for a different architecture
            - 'Not matching memory': if the program is compiled for a different address size
        :todo: define va_randomize and read_implies_exec personality
        """
        # load elf See binfmt_elf.c
        # read the ELF object file
        cpu = self.current
        elf = self.elf
        arch = self.arch
        env = dict(var.split('=') for var in env if '=' in var)
        addressbitsize = {'x86': 32, 'x64': 64, 'ARM': 32}[elf.get_machine_arch()]
        logger.debug("Loading %s as a %s elf", filename, arch)

        assert elf.header.e_type in ['ET_DYN', 'ET_EXEC', 'ET_CORE']

        # Get interpreter elf
        interpreter = None
        for elf_segment in elf.iter_segments():
            if elf_segment.header.p_type != 'PT_INTERP':
                continue
            interpreter_filename = elf_segment.data()[:-1]
            logger.info(f'Interpreter filename: {interpreter_filename}')
            if os.path.exists(interpreter_filename.decode('utf-8')):
                interpreter = ELFFile(open(interpreter_filename, 'rb'))
            elif 'LD_LIBRARY_PATH' in env:
                for mpath in env['LD_LIBRARY_PATH'].split(":"):
                    interpreter_path_filename = os.path.join(mpath, os.path.basename(interpreter_filename))
                    logger.info(f"looking for interpreter {interpreter_path_filename}")
                    if os.path.exists(interpreter_path_filename):
                        interpreter = ELFFile(open(interpreter_path_filename, 'rb'))
                        break
            break
        if interpreter is not None:
            assert interpreter.get_machine_arch() == elf.get_machine_arch()
            assert interpreter.header.e_type in ['ET_DYN', 'ET_EXEC']

        # Stack Executability
        executable_stack = False
        for elf_segment in elf.iter_segments():
            if elf_segment.header.p_type != 'PT_GNU_STACK':
                continue
            if elf_segment.header.p_flags & 0x01:
                executable_stack = True
            else:
                executable_stack = False
            break

        base = 0
        elf_bss = 0
        end_code = 0
        end_data = 0
        elf_brk = 0
        self.load_addr = 0

        for elf_segment in elf.iter_segments():
            if elf_segment.header.p_type != 'PT_LOAD':
                continue

            align = 0x1000  # elf_segment.header.p_align

            ELF_PAGEOFFSET = elf_segment.header.p_vaddr & (align - 1)

            flags = elf_segment.header.p_flags
            memsz = elf_segment.header.p_memsz + ELF_PAGEOFFSET
            offset = elf_segment.header.p_offset - ELF_PAGEOFFSET
            filesz = elf_segment.header.p_filesz + ELF_PAGEOFFSET
            vaddr = elf_segment.header.p_vaddr - ELF_PAGEOFFSET
            memsz = cpu.memory._ceil(memsz)
            if base == 0 and elf.header.e_type == 'ET_DYN':
                assert vaddr == 0
                if addressbitsize == 32:
                    base = 0x56555000
                else:
                    base = 0x555555554000

            perms = perms_from_elf(flags)
            hint = base + vaddr
            if hint == 0:
                hint = None

            logger.debug(f"Loading elf offset: {offset:08x} addr:{base + vaddr:08x} {base + vaddr + memsz:08x} {perms}")
            base = cpu.memory.mmapFile(hint, memsz, perms, elf_segment.stream.name, offset) - vaddr

            if self.load_addr == 0:
                self.load_addr = base + vaddr

            k = base + vaddr + filesz
            if k > elf_bss:
                elf_bss = k
            if (flags & 4) and end_code < k:  # PF_X
                end_code = k
            if end_data < k:
                end_data = k
            k = base + vaddr + memsz
            if k > elf_brk:
                elf_brk = k

        elf_entry = elf.header.e_entry
        if elf.header.e_type == 'ET_DYN':
            elf_entry += self.load_addr
        entry = elf_entry
        real_elf_brk = elf_brk

        # We need to explicitly clear bss, as fractional pages will have data from the file
        bytes_to_clear = elf_brk - elf_bss
        if bytes_to_clear > 0:
            logger.debug(f"Zeroing main elf fractional pages. From bss({elf_bss:x}) to brk({elf_brk:x}), {bytes_to_clear} bytes.")
            cpu.write_bytes(elf_bss, '\x00' * bytes_to_clear, force=True)

        stack_size = 0x21000

        if addressbitsize == 32:
            stack_top = 0xc0000000
        else:
            stack_top = 0x800000000000
        stack_base = stack_top - stack_size
        stack = cpu.memory.mmap(stack_base, stack_size, 'rwx', name='stack') + stack_size
        assert stack_top == stack

        reserved = cpu.memory.mmap(base + vaddr + memsz, 0x1000000, '   ')
        interpreter_base = 0
        if interpreter is not None:
            base = 0
            elf_bss = 0
            end_code = 0
            end_data = 0
            elf_brk = 0
            entry = interpreter.header.e_entry
            for elf_segment in interpreter.iter_segments():
                if elf_segment.header.p_type != 'PT_LOAD':
                    continue
                align = 0x1000  # elf_segment.header.p_align
                vaddr = elf_segment.header.p_vaddr
                filesz = elf_segment.header.p_filesz
                flags = elf_segment.header.p_flags
                offset = elf_segment.header.p_offset
                memsz = elf_segment.header.p_memsz

                ELF_PAGEOFFSET = (vaddr & (align - 1))
                memsz = memsz + ELF_PAGEOFFSET
                offset = offset - ELF_PAGEOFFSET
                filesz = filesz + ELF_PAGEOFFSET
                vaddr = vaddr - ELF_PAGEOFFSET
                memsz = cpu.memory._ceil(memsz)

                if base == 0 and interpreter.header.e_type == 'ET_DYN':
                    assert vaddr == 0
                    total_size = self._interp_total_size(interpreter)
                    base = stack_base - total_size

                if base == 0:
                    assert vaddr == 0
                perms = perms_from_elf(flags)
                hint = base + vaddr
                if hint == 0:
                    hint = None

                base = cpu.memory.mmapFile(hint, memsz, perms, elf_segment.stream.name, offset)
                base -= vaddr
                logger.debug(
                    f"Loading interpreter offset: {offset:08x} "
                    f"addr:{base + vaddr:08x} "
                    f"{base + vaddr + memsz:08x} "
                    f"{(flags & 1 and 'r' or ' ')}"
                    f"{(flags & 2 and 'w' or ' ')}"
                    f"{(flags & 4 and 'x' or ' ')}"
                )

                k = base + vaddr + filesz
                if k > elf_bss:
                    elf_bss = k
                if (flags & 4) and end_code < k:  # PF_X
                    end_code = k
                if end_data < k:
                    end_data = k
                k = base + vaddr + memsz
                if k > elf_brk:
                    elf_brk = k

            if interpreter.header.e_type == 'ET_DYN':
                entry += base
            interpreter_base = base

            bytes_to_clear = elf_brk - elf_bss
            if bytes_to_clear > 0:
                logger.debug(f"Zeroing interpreter elf fractional pages. From bss({elf_bss:x}) to brk({elf_brk:x}), {bytes_to_clear} bytes.")
                cpu.write_bytes(elf_bss, '\x00' * bytes_to_clear, force=True)

        # free reserved brk space
        cpu.memory.munmap(reserved, 0x1000000)

        # load vdso
        #vdso_addr = load_vdso(addressbitsize)

        cpu.STACK = stack
        cpu.PC = entry

        logger.debug(f"Entry point: {entry:016x}")
        logger.debug(f"Stack start: {stack:016x}")
        logger.debug(f"Brk: {real_elf_brk:016x}")
        logger.debug(f"Mappings:")
        for m in str(cpu.memory).split('\n'):
            logger.debug(f"  {m}")
        self.base = base
        self.elf_bss = elf_bss
        self.end_code = end_code
        self.end_data = end_data
        self.elf_brk = real_elf_brk
        self.brk = real_elf_brk

        at_random = cpu.push_bytes('A' * 16)
        at_execfn = cpu.push_bytes(f'{filename}\x00')

        self.auxv = {
            'AT_PHDR': self.load_addr + elf.header.e_phoff,  # Program headers for program
            'AT_PHENT': elf.header.e_phentsize,       # Size of program header entry
            'AT_PHNUM': elf.header.e_phnum,           # Number of program headers
            'AT_PAGESZ': cpu.memory.page_size,         # System page size
            'AT_BASE': interpreter_base,             # Base address of interpreter
            'AT_FLAGS': elf.header.e_flags,           # Flags
            'AT_ENTRY': elf_entry,                    # Entry point of program
            'AT_UID': 1000,                         # Real uid
            'AT_EUID': 1000,                         # Effective uid
            'AT_GID': 1000,                         # Real gid
            'AT_EGID': 1000,                         # Effective gid
            'AT_CLKTCK': 100,                          # Frequency of times()
            'AT_HWCAP': 0,                            # Machine-dependent hints about processor capabilities.
            'AT_RANDOM': at_random,                    # Address of 16 random bytes.
            'AT_EXECFN': at_execfn,                    # Filename of executable.
        }
def load(self, filename, env):
        """
        Loads and an ELF program in memory and prepares the initial CPU state.
        Creates the stack and loads the environment variables and the arguments in it.

        :param filename: pathname of the file to be executed. (used for auxv)
        :param list env: A list of env variables. (used for extracting vars that control ld behavior)
        :raises error:
            - 'Not matching cpu': if the program is compiled for a different architecture
            - 'Not matching memory': if the program is compiled for a different address size
        :todo: define va_randomize and read_implies_exec personality
        """
        # load elf See binfmt_elf.c
        # read the ELF object file
        cpu = self.current
        elf = self.elf
        arch = self.arch
        env = dict(var.split('=') for var in env if '=' in var)
        addressbitsize = {'x86': 32, 'x64': 64, 'ARM': 32}[elf.get_machine_arch()]
        logger.debug("Loading %s as a %s elf", filename, arch)

        assert elf.header.e_type in ['ET_DYN', 'ET_EXEC', 'ET_CORE']

        # Get interpreter elf
        interpreter = None
        for elf_segment in elf.iter_segments():
            if elf_segment.header.p_type != 'PT_INTERP':
                continue
            interpreter_filename = elf_segment.data()[:-1]
            logger.info(f'Interpreter filename: {interpreter_filename}')
            if os.path.exists(interpreter_filename.decode('utf-8')):
                interpreter = ELFFile(open(interpreter_filename, 'rb'))
            elif 'LD_LIBRARY_PATH' in env:
                for mpath in env['LD_LIBRARY_PATH'].split(":"):
                    interpreter_path_filename = os.path.join(mpath, os.path.basename(interpreter_filename))
                    logger.info(f"looking for interpreter {interpreter_path_filename}")
                    if os.path.exists(interpreter_path_filename):
                        interpreter = ELFFile(open(interpreter_path_filename, 'rb'))
                        break
            break
        if interpreter is not None:
            assert interpreter.get_machine_arch() == elf.get_machine_arch()
            assert interpreter.header.e_type in ['ET_DYN', 'ET_EXEC']

        # Stack Executability
        executable_stack = False
        for elf_segment in elf.iter_segments():
            if elf_segment.header.p_type != 'PT_GNU_STACK':
                continue
            if elf_segment.header.p_flags & 0x01:
                executable_stack = True
            else:
                executable_stack = False
            break

        base = 0
        elf_bss = 0
        end_code = 0
        end_data = 0
        elf_brk = 0
        self.load_addr = 0

        for elf_segment in elf.iter_segments():
            if elf_segment.header.p_type != 'PT_LOAD':
                continue

            align = 0x1000  # elf_segment.header.p_align

            ELF_PAGEOFFSET = elf_segment.header.p_vaddr & (align - 1)

            flags = elf_segment.header.p_flags
            memsz = elf_segment.header.p_memsz + ELF_PAGEOFFSET
            offset = elf_segment.header.p_offset - ELF_PAGEOFFSET
            filesz = elf_segment.header.p_filesz + ELF_PAGEOFFSET
            vaddr = elf_segment.header.p_vaddr - ELF_PAGEOFFSET
            memsz = cpu.memory._ceil(memsz)
            if base == 0 and elf.header.e_type == 'ET_DYN':
                assert vaddr == 0
                if addressbitsize == 32:
                    base = 0x56555000
                else:
                    base = 0x555555554000

            perms = perms_from_elf(flags)
            hint = base + vaddr
            if hint == 0:
                hint = None

            logger.debug(f"Loading elf offset: {offset:08x} addr:{base + vaddr:08x} {base + vaddr + memsz:08x} {perms}")
            base = cpu.memory.mmapFile(hint, memsz, perms, elf_segment.stream.name, offset) - vaddr

            if self.load_addr == 0:
                self.load_addr = base + vaddr

            k = base + vaddr + filesz
            if k > elf_bss:
                elf_bss = k
            if (flags & 4) and end_code < k:  # PF_X
                end_code = k
            if end_data < k:
                end_data = k
            k = base + vaddr + memsz
            if k > elf_brk:
                elf_brk = k

        elf_entry = elf.header.e_entry
        if elf.header.e_type == 'ET_DYN':
            elf_entry += self.load_addr
        entry = elf_entry
        real_elf_brk = elf_brk

        # We need to explicitly clear bss, as fractional pages will have data from the file
        bytes_to_clear = elf_brk - elf_bss
        if bytes_to_clear > 0:
            logger.debug(f"Zeroing main elf fractional pages. From bss({elf_bss:x}) to brk({elf_brk:x}), {bytes_to_clear} bytes.")
            cpu.write_bytes(elf_bss, '\x00' * bytes_to_clear, force=True)

        stack_size = 0x21000

        if addressbitsize == 32:
            stack_top = 0xc0000000
        else:
            stack_top = 0x800000000000
        stack_base = stack_top - stack_size
        stack = cpu.memory.mmap(stack_base, stack_size, 'rwx', name='stack') + stack_size
        assert stack_top == stack

        reserved = cpu.memory.mmap(base + vaddr + memsz, 0x1000000, '   ')
        interpreter_base = 0
        if interpreter is not None:
            base = 0
            elf_bss = 0
            end_code = 0
            end_data = 0
            elf_brk = 0
            entry = interpreter.header.e_entry
            for elf_segment in interpreter.iter_segments():
                if elf_segment.header.p_type != 'PT_LOAD':
                    continue
                align = 0x1000  # elf_segment.header.p_align
                vaddr = elf_segment.header.p_vaddr
                filesz = elf_segment.header.p_filesz
                flags = elf_segment.header.p_flags
                offset = elf_segment.header.p_offset
                memsz = elf_segment.header.p_memsz

                ELF_PAGEOFFSET = (vaddr & (align - 1))
                memsz = memsz + ELF_PAGEOFFSET
                offset = offset - ELF_PAGEOFFSET
                filesz = filesz + ELF_PAGEOFFSET
                vaddr = vaddr - ELF_PAGEOFFSET
                memsz = cpu.memory._ceil(memsz)

                if base == 0 and interpreter.header.e_type == 'ET_DYN':
                    assert vaddr == 0
                    total_size = self._interp_total_size(interpreter)
                    base = stack_base - total_size

                if base == 0:
                    assert vaddr == 0
                perms = perms_from_elf(flags)
                hint = base + vaddr
                if hint == 0:
                    hint = None

                base = cpu.memory.mmapFile(hint, memsz, perms, elf_segment.stream.name, offset)
                base -= vaddr
                logger.debug(
                    f"Loading interpreter offset: {offset:08x} "
                    f"addr:{base + vaddr:08x} "
                    f"{base + vaddr + memsz:08x} "
                    f"{(flags & 1 and 'r' or ' ')}"
                    f"{(flags & 2 and 'w' or ' ')}"
                    f"{(flags & 4 and 'x' or ' ')}"
                )

                k = base + vaddr + filesz
                if k > elf_bss:
                    elf_bss = k
                if (flags & 4) and end_code < k:  # PF_X
                    end_code = k
                if end_data < k:
                    end_data = k
                k = base + vaddr + memsz
                if k > elf_brk:
                    elf_brk = k

            if interpreter.header.e_type == 'ET_DYN':
                entry += base
            interpreter_base = base

            bytes_to_clear = elf_brk - elf_bss
            if bytes_to_clear > 0:
                logger.debug(f"Zeroing interpreter elf fractional pages. From bss({elf_bss:x}) to brk({elf_brk:x}), {bytes_to_clear} bytes.")
                cpu.write_bytes(elf_bss, '\x00' * bytes_to_clear, force=True)

        # free reserved brk space
        cpu.memory.munmap(reserved, 0x1000000)

        # load vdso
        #vdso_addr = load_vdso(addressbitsize)

        cpu.STACK = stack
        cpu.PC = entry

        logger.debug(f"Entry point: {entry:016x}")
        logger.debug(f"Stack start: {stack:016x}")
        logger.debug(f"Brk: {real_elf_brk:016x}")
        logger.debug(f"Mappings:")
        for m in str(cpu.memory).split('\n'):
            logger.debug(f"  {m}")
        self.base = base
        self.elf_bss = elf_bss
        self.end_code = end_code
        self.end_data = end_data
        self.elf_brk = real_elf_brk
        self.brk = real_elf_brk

        at_random = cpu.push_bytes('A' * 16)
        at_execfn = cpu.push_bytes(f'{filename}\x00')

        self.auxv = {
            'AT_PHDR': self.load_addr + elf.header.e_phoff,  # Program headers for program
            'AT_PHENT': elf.header.e_phentsize,       # Size of program header entry
            'AT_PHNUM': elf.header.e_phnum,           # Number of program headers
            'AT_PAGESZ': cpu.memory.page_size,         # System page size
            'AT_BASE': interpreter_base,             # Base address of interpreter
            'AT_FLAGS': elf.header.e_flags,           # Flags
            'AT_ENTRY': elf_entry,                    # Entry point of program
            'AT_UID': 1000,                         # Real uid
            'AT_EUID': 1000,                         # Effective uid
            'AT_GID': 1000,                         # Real gid
            'AT_EGID': 1000,                         # Effective gid
            'AT_CLKTCK': 100,                          # Frequency of times()
            'AT_HWCAP': 0,                            # Machine-dependent hints about processor capabilities.
            'AT_RANDOM': at_random,                    # Address of 16 random bytes.
            'AT_EXECFN': at_execfn,                    # Filename of executable.
        }
def load ( self , filename , env ) : # load elf See binfmt_elf.c # read the ELF object file cpu = self . current elf = self . elf arch = self . arch env = dict ( var . split ( '=' ) for var in env if '=' in var ) addressbitsize = { 'x86' : 32 , 'x64' : 64 , 'ARM' : 32 } [ elf . get_machine_arch ( ) ] logger . debug ( "Loading %s as a %s elf" , filename , arch ) assert elf . header . e_type in [ 'ET_DYN' , 'ET_EXEC' , 'ET_CORE' ] # Get interpreter elf interpreter = None for elf_segment in elf . iter_segments ( ) : if elf_segment . header . p_type != 'PT_INTERP' : continue interpreter_filename = elf_segment . data ( ) [ : - 1 ] logger . info ( f'Interpreter filename: {interpreter_filename}' ) if os . path . exists ( interpreter_filename . decode ( 'utf-8' ) ) : interpreter = ELFFile ( open ( interpreter_filename , 'rb' ) ) elif 'LD_LIBRARY_PATH' in env : for mpath in env [ 'LD_LIBRARY_PATH' ] . split ( ":" ) : interpreter_path_filename = os . path . join ( mpath , os . path . basename ( interpreter_filename ) ) logger . info ( f"looking for interpreter {interpreter_path_filename}" ) if os . path . exists ( interpreter_path_filename ) : interpreter = ELFFile ( open ( interpreter_path_filename , 'rb' ) ) break break if interpreter is not None : assert interpreter . get_machine_arch ( ) == elf . get_machine_arch ( ) assert interpreter . header . e_type in [ 'ET_DYN' , 'ET_EXEC' ] # Stack Executability executable_stack = False for elf_segment in elf . iter_segments ( ) : if elf_segment . header . p_type != 'PT_GNU_STACK' : continue if elf_segment . header . p_flags & 0x01 : executable_stack = True else : executable_stack = False break base = 0 elf_bss = 0 end_code = 0 end_data = 0 elf_brk = 0 self . load_addr = 0 for elf_segment in elf . iter_segments ( ) : if elf_segment . header . p_type != 'PT_LOAD' : continue align = 0x1000 # elf_segment.header.p_align ELF_PAGEOFFSET = elf_segment . header . p_vaddr & ( align - 1 ) flags = elf_segment . header . p_flags memsz = elf_segment . header . p_memsz + ELF_PAGEOFFSET offset = elf_segment . header . p_offset - ELF_PAGEOFFSET filesz = elf_segment . header . p_filesz + ELF_PAGEOFFSET vaddr = elf_segment . header . p_vaddr - ELF_PAGEOFFSET memsz = cpu . memory . _ceil ( memsz ) if base == 0 and elf . header . e_type == 'ET_DYN' : assert vaddr == 0 if addressbitsize == 32 : base = 0x56555000 else : base = 0x555555554000 perms = perms_from_elf ( flags ) hint = base + vaddr if hint == 0 : hint = None logger . debug ( f"Loading elf offset: {offset:08x} addr:{base + vaddr:08x} {base + vaddr + memsz:08x} {perms}" ) base = cpu . memory . mmapFile ( hint , memsz , perms , elf_segment . stream . name , offset ) - vaddr if self . load_addr == 0 : self . load_addr = base + vaddr k = base + vaddr + filesz if k > elf_bss : elf_bss = k if ( flags & 4 ) and end_code < k : # PF_X end_code = k if end_data < k : end_data = k k = base + vaddr + memsz if k > elf_brk : elf_brk = k elf_entry = elf . header . e_entry if elf . header . e_type == 'ET_DYN' : elf_entry += self . load_addr entry = elf_entry real_elf_brk = elf_brk # We need to explicitly clear bss, as fractional pages will have data from the file bytes_to_clear = elf_brk - elf_bss if bytes_to_clear > 0 : logger . debug ( f"Zeroing main elf fractional pages. From bss({elf_bss:x}) to brk({elf_brk:x}), {bytes_to_clear} bytes." ) cpu . write_bytes ( elf_bss , '\x00' * bytes_to_clear , force = True ) stack_size = 0x21000 if addressbitsize == 32 : stack_top = 0xc0000000 else : stack_top = 0x800000000000 stack_base = stack_top - stack_size stack = cpu . memory . mmap ( stack_base , stack_size , 'rwx' , name = 'stack' ) + stack_size assert stack_top == stack reserved = cpu . memory . mmap ( base + vaddr + memsz , 0x1000000 , '   ' ) interpreter_base = 0 if interpreter is not None : base = 0 elf_bss = 0 end_code = 0 end_data = 0 elf_brk = 0 entry = interpreter . header . e_entry for elf_segment in interpreter . iter_segments ( ) : if elf_segment . header . p_type != 'PT_LOAD' : continue align = 0x1000 # elf_segment.header.p_align vaddr = elf_segment . header . p_vaddr filesz = elf_segment . header . p_filesz flags = elf_segment . header . p_flags offset = elf_segment . header . p_offset memsz = elf_segment . header . p_memsz ELF_PAGEOFFSET = ( vaddr & ( align - 1 ) ) memsz = memsz + ELF_PAGEOFFSET offset = offset - ELF_PAGEOFFSET filesz = filesz + ELF_PAGEOFFSET vaddr = vaddr - ELF_PAGEOFFSET memsz = cpu . memory . _ceil ( memsz ) if base == 0 and interpreter . header . e_type == 'ET_DYN' : assert vaddr == 0 total_size = self . _interp_total_size ( interpreter ) base = stack_base - total_size if base == 0 : assert vaddr == 0 perms = perms_from_elf ( flags ) hint = base + vaddr if hint == 0 : hint = None base = cpu . memory . mmapFile ( hint , memsz , perms , elf_segment . stream . name , offset ) base -= vaddr logger . debug ( f"Loading interpreter offset: {offset:08x} " f"addr:{base + vaddr:08x} " f"{base + vaddr + memsz:08x} " f"{(flags & 1 and 'r' or ' ')}" f"{(flags & 2 and 'w' or ' ')}" f"{(flags & 4 and 'x' or ' ')}" ) k = base + vaddr + filesz if k > elf_bss : elf_bss = k if ( flags & 4 ) and end_code < k : # PF_X end_code = k if end_data < k : end_data = k k = base + vaddr + memsz if k > elf_brk : elf_brk = k if interpreter . header . e_type == 'ET_DYN' : entry += base interpreter_base = base bytes_to_clear = elf_brk - elf_bss if bytes_to_clear > 0 : logger . debug ( f"Zeroing interpreter elf fractional pages. From bss({elf_bss:x}) to brk({elf_brk:x}), {bytes_to_clear} bytes." ) cpu . write_bytes ( elf_bss , '\x00' * bytes_to_clear , force = True ) # free reserved brk space cpu . memory . munmap ( reserved , 0x1000000 ) # load vdso #vdso_addr = load_vdso(addressbitsize) cpu . STACK = stack cpu . PC = entry logger . debug ( f"Entry point: {entry:016x}" ) logger . debug ( f"Stack start: {stack:016x}" ) logger . debug ( f"Brk: {real_elf_brk:016x}" ) logger . debug ( f"Mappings:" ) for m in str ( cpu . memory ) . split ( '\n' ) : logger . debug ( f"  {m}" ) self . base = base self . elf_bss = elf_bss self . end_code = end_code self . end_data = end_data self . elf_brk = real_elf_brk self . brk = real_elf_brk at_random = cpu . push_bytes ( 'A' * 16 ) at_execfn = cpu . push_bytes ( f'{filename}\x00' ) self . auxv = { 'AT_PHDR' : self . load_addr + elf . header . e_phoff , # Program headers for program 'AT_PHENT' : elf . header . e_phentsize , # Size of program header entry 'AT_PHNUM' : elf . header . e_phnum , # Number of program headers 'AT_PAGESZ' : cpu . memory . page_size , # System page size 'AT_BASE' : interpreter_base , # Base address of interpreter 'AT_FLAGS' : elf . header . e_flags , # Flags 'AT_ENTRY' : elf_entry , # Entry point of program 'AT_UID' : 1000 , # Real uid 'AT_EUID' : 1000 , # Effective uid 'AT_GID' : 1000 , # Real gid 'AT_EGID' : 1000 , # Effective gid 'AT_CLKTCK' : 100 , # Frequency of times() 'AT_HWCAP' : 0 , # Machine-dependent hints about processor capabilities. 'AT_RANDOM' : at_random , # Address of 16 random bytes. 'AT_EXECFN' : at_execfn , # Filename of executable. }
Loads and an ELF program in memory and prepares the initial CPU state.
        Creates the stack and loads the environment variables and the arguments in it.

        :param filename: pathname of the file to be executed. (used for auxv)
        :param list env: A list of env variables. (used for extracting vars that control ld behavior)
        :raises error:
            - 'Not matching cpu': if the program is compiled for a different architecture
            - 'Not matching memory': if the program is compiled for a different address size
        :todo: define va_randomize and read_implies_exec personality
Loads and an ELF program in memory and prepares the initial CPU state . Creates the stack and loads the environment variables and the arguments in it .