From 72ca45e3004c96f0358866f6551e0b137c4cda38 Mon Sep 17 00:00:00 2001 From: Itamar Date: Mon, 23 Nov 2020 20:00:35 +0200 Subject: [PATCH] UserspaceEmulator: Support dynamically loaded programs When loading dynamic objects, the emulator loads the interpreter, generates an auxiliary vector and starts executing the loader. Additionally, this commits also makes the MallocTracer and backtrace symbolication work for dynamically loaded programs. --- DevTools/UserspaceEmulator/Emulator.cpp | 243 ++++++++++++++++---- DevTools/UserspaceEmulator/Emulator.h | 25 +- DevTools/UserspaceEmulator/MallocTracer.cpp | 20 +- DevTools/UserspaceEmulator/MmapRegion.cpp | 1 - DevTools/UserspaceEmulator/MmapRegion.h | 2 + DevTools/UserspaceEmulator/SoftCPU.cpp | 7 + DevTools/UserspaceEmulator/SoftCPU.h | 1 + DevTools/UserspaceEmulator/main.cpp | 10 +- Userland/DynamicLoader/main.cpp | 2 + 9 files changed, 247 insertions(+), 64 deletions(-) diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index f42d73844f..3ff9119b7b 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -31,7 +31,11 @@ #include "SoftCPU.h" #include #include +#include #include +#include +#include +#include #include #include #include @@ -55,7 +59,7 @@ # pragma GCC optimize("O3") #endif -//#define DEBUG_SPAM +// #define DEBUG_SPAM namespace UserspaceEmulator { @@ -70,20 +74,45 @@ Emulator& Emulator::the() return *s_the; } -Emulator::Emulator(const Vector& arguments, const Vector& environment, NonnullRefPtr elf) - : m_elf(move(elf)) +Emulator::Emulator(const String& executable_path, const Vector& arguments, const Vector& environment) + : m_executable_path(executable_path) + , m_arguments(arguments) + , m_environment(environment) , m_mmu(*this) , m_cpu(*this) { m_malloc_tracer = make(*this); ASSERT(!s_the); s_the = this; - setup_stack(arguments, environment); + // setup_stack(arguments, environment); register_signal_handlers(); setup_signal_trampoline(); } -void Emulator::setup_stack(const Vector& arguments, const Vector& environment) +Vector Emulator::generate_auxiliary_vector(FlatPtr load_base, FlatPtr entry_eip, String executable_path, int executable_fd) const +{ + // FIXME: This is not fully compatible with the auxiliary vector the kernel generates, this is just the bare + // minimum to get the loader going. + Vector auxv; + // PHDR/EXECFD + // PH* + auxv.append({ AuxiliaryValue::PageSize, PAGE_SIZE }); + auxv.append({ AuxiliaryValue::BaseAddress, (void*)load_base }); + + auxv.append({ AuxiliaryValue::Entry, (void*)entry_eip }); + + // FIXME: Don't hard code this? We might support other platforms later.. (e.g. x86_64) + auxv.append({ AuxiliaryValue::Platform, "i386" }); + + auxv.append({ AuxiliaryValue::ExecFilename, executable_path }); + + auxv.append({ AuxiliaryValue::ExecFileDescriptor, executable_fd }); + + auxv.append({ AuxiliaryValue::Null, 0L }); + return auxv; +} + +void Emulator::setup_stack(Vector aux_vector) { auto stack_region = make(stack_location, stack_size); stack_region->set_stack(true); @@ -92,18 +121,30 @@ void Emulator::setup_stack(const Vector& arguments, const Vector Vector argv_entries; - for (auto& argument : arguments) { + for (auto& argument : m_arguments) { m_cpu.push_string(argument.characters()); argv_entries.append(m_cpu.esp().value()); } Vector env_entries; - for (auto& variable : environment) { + for (auto& variable : m_environment) { m_cpu.push_string(variable.characters()); env_entries.append(m_cpu.esp().value()); } + for (auto& auxv : aux_vector) { + if (!auxv.optional_string.is_empty()) { + m_cpu.push_string(auxv.optional_string.characters()); + auxv.auxv.a_un.a_ptr = (void*)m_cpu.esp().value(); + } + } + + for (ssize_t i = aux_vector.size() - 1; i >= 0; --i) { + auto& value = aux_vector[i].auxv; + m_cpu.push_buffer((const u8*)&value, sizeof(value)); + } + m_cpu.push32(shadow_wrap_as_initialized(0)); // char** envp = { envv_entries..., nullptr } for (ssize_t i = env_entries.size() - 1; i >= 0; --i) m_cpu.push32(shadow_wrap_as_initialized(env_entries[i])); @@ -125,54 +166,70 @@ void Emulator::setup_stack(const Vector& arguments, const Vector bool Emulator::load_elf() { - m_elf->image().for_each_program_header([&](const ELF::Image::ProgramHeader& program_header) { + MappedFile mapped_executable(m_executable_path); + if (!mapped_executable.is_valid()) { + reportln("Unable to map {}", m_executable_path); + return false; + } + + ELF::Image executable_elf((const u8*)mapped_executable.data(), mapped_executable.size()); + + if (!executable_elf.is_dynamic()) { + // FIXME: Support static objects + ASSERT_NOT_REACHED(); + } + + String interpreter_path; + if (!ELF::validate_program_headers(*(Elf32_Ehdr*)mapped_executable.data(), mapped_executable.size(), (u8*)mapped_executable.data(), mapped_executable.size(), &interpreter_path)) { + reportln("failed to validate ELF file"); + return false; + } + + ASSERT(!interpreter_path.is_null()); + dbgln("interpreter: {}", interpreter_path); + + auto interpreter_file = make(interpreter_path); + ASSERT(interpreter_file->is_valid()); + ELF::Image interpreter_image((const u8*)interpreter_file->data(), interpreter_file->size()); + + constexpr FlatPtr interpreter_load_offset = 0x08000000; + interpreter_image.for_each_program_header([&](const ELF::Image::ProgramHeader& program_header) { + // Loader is not allowed to have its own TLS regions + ASSERT(program_header.type() != PT_TLS); + if (program_header.type() == PT_LOAD) { - auto region = make(program_header.vaddr().get(), program_header.size_in_memory()); + auto region = make(program_header.vaddr().offset(interpreter_load_offset).get(), program_header.size_in_memory()); if (program_header.is_executable() && !program_header.is_writable()) region->set_text(true); memcpy(region->data(), program_header.raw_data(), program_header.size_in_image()); memset(region->shadow_data(), 0x01, program_header.size_in_memory()); + if (program_header.is_executable()) { + m_loader_text_base = region->base(); + m_loader_text_size = region->size(); + } mmu().add_region(move(region)); return; } - if (program_header.type() == PT_TLS) { - auto tcb_region = make(0x20000000, program_header.size_in_memory()); - memcpy(tcb_region->data(), program_header.raw_data(), program_header.size_in_image()); - memset(tcb_region->shadow_data(), 0x01, program_header.size_in_memory()); - - auto tls_region = make(0, 4); - tls_region->write32(0, shadow_wrap_as_initialized(tcb_region->base() + program_header.size_in_memory())); - memset(tls_region->shadow_data(), 0x01, 4); - - mmu().add_region(move(tcb_region)); - mmu().set_tls_region(move(tls_region)); - return; - } }); - m_cpu.set_eip(m_elf->image().entry().get()); + auto entry_point = interpreter_image.entry().offset(interpreter_load_offset).get(); + m_cpu.set_eip(entry_point); - auto malloc_symbol = m_elf->find_demangled_function("malloc"); - auto free_symbol = m_elf->find_demangled_function("free"); - auto realloc_symbol = m_elf->find_demangled_function("realloc"); - auto malloc_size_symbol = m_elf->find_demangled_function("malloc_size"); + // executable_fd will be used by the loader + int executable_fd = open(m_executable_path.characters(), O_RDONLY); + if (executable_fd < 0) + return false; - m_malloc_symbol_start = malloc_symbol.value().value(); - m_malloc_symbol_end = m_malloc_symbol_start + malloc_symbol.value().size(); - m_free_symbol_start = free_symbol.value().value(); - m_free_symbol_end = m_free_symbol_start + free_symbol.value().size(); - m_realloc_symbol_start = realloc_symbol.value().value(); - m_realloc_symbol_end = m_realloc_symbol_start + realloc_symbol.value().size(); - m_malloc_size_symbol_start = malloc_size_symbol.value().value(); - m_malloc_size_symbol_end = m_malloc_size_symbol_start + malloc_size_symbol.value().size(); + auto aux_vector = generate_auxiliary_vector(interpreter_load_offset, entry_point, m_executable_path, executable_fd); + setup_stack(move(aux_vector)); - m_debug_info = make(m_elf); return true; } int Emulator::exec() { - X86::ELFSymbolProvider symbol_provider(*m_elf); + // X86::ELFSymbolProvider symbol_provider(*m_elf); + X86::ELFSymbolProvider* symbol_provider = nullptr; bool trace = false; @@ -182,7 +239,7 @@ int Emulator::exec() auto insn = X86::Instruction::from_stream(m_cpu, true, true); if (trace) - outln("{:p} \033[33;1m{}\033[0m", m_cpu.base_eip(), insn.to_string(m_cpu.base_eip(), &symbol_provider)); + outln("{:p} \033[33;1m{}\033[0m", m_cpu.base_eip(), insn.to_string(m_cpu.base_eip(), symbol_provider)); (m_cpu.*insn.handler())(insn); @@ -217,16 +274,58 @@ Vector Emulator::raw_backtrace() return backtrace; } +const MmapRegion* Emulator::find_text_region(FlatPtr address) +{ + const MmapRegion* matching_region = nullptr; + mmu().for_each_region([&](auto& region) { + if (!region.is_mmap()) + return IterationDecision::Continue; + const auto& mmap_region = static_cast(region); + if (!(mmap_region.is_executable() && address >= mmap_region.base() && address < mmap_region.base() + mmap_region.size())) + return IterationDecision::Continue; + matching_region = &mmap_region; + return IterationDecision::Break; + }); + return matching_region; +} + +String Emulator::create_backtrace_line(FlatPtr address) +{ + String minimal = String::format("=={%d}== %p", getpid(), address); + const auto* region = find_text_region(address); + if (!region) + return minimal; + auto separator_index = region->name().index_of(":"); + if (!separator_index.has_value()) + return minimal; + + String lib_name = region->name().substring(0, separator_index.value()); + String lib_path = lib_name; + if (region->name().contains(".so")) + lib_path = String::format("/usr/lib/%s", lib_path.characters()); + + auto mapped_file = make(lib_path); + if (!mapped_file->is_valid()) + return minimal; + + auto loader = ELF::Loader::create((const u8*)mapped_file->data(), mapped_file->size()); + String symbol = loader->symbolicate(address - region->base()); + + auto line_without_source_info = String::format("=={%d}== %p [%s]: %s", getpid(), address, lib_name.characters(), symbol.characters()); + auto debug_info = make(loader); + + auto source_position = debug_info->get_source_position(address - region->base()); + if (source_position.has_value()) + return String::format("=={%d}== %p [%s]: %s (\033[34;1m%s\033[0m:%u)", getpid(), address, lib_name.characters(), symbol.characters(), LexicalPath(source_position.value().file_path).basename().characters(), source_position.value().line_number); + else { + return line_without_source_info; + } +} + void Emulator::dump_backtrace(const Vector& backtrace) { for (auto& address : backtrace) { - u32 offset = 0; - String symbol = m_elf->symbolicate(address, &offset); - auto source_position = m_debug_info->get_source_position(address); - if (source_position.has_value()) - reportln("=={}== {:p} {} (\033[34;1m{}\033[0m:{})", getpid(), address, symbol, LexicalPath(source_position.value().file_path).basename(), source_position.value().line_number); - else - reportln("=={}== {:p} {} +{:x}", getpid(), address, symbol, offset); + reportln("{}", create_backtrace_line(address)); } } @@ -406,6 +505,8 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3) return virt$clock_nanosleep(arg1); case SC_readlink: return virt$readlink(arg1); + case SC_allocate_tls: + return virt$allocate_tls(arg1); default: reportln("\n=={}== \033[31;1mUnimplemented syscall: {}\033[0m, {:p}", getpid(), Syscall::to_string((Syscall::Function)function), function); dump_backtrace(); @@ -870,8 +971,6 @@ u32 Emulator::virt$mmap(u32 params_addr) Syscall::SC_mmap_params params; mmu().copy_from_vm(¶ms, params_addr, sizeof(params)); - ASSERT(params.addr == 0); - u32 final_size = round_up_to_power_of_two(params.size, PAGE_SIZE); u32 final_address = allocate_vm(final_size, params.alignment); if (params.addr != 0) { @@ -886,14 +985,18 @@ u32 Emulator::virt$mmap(u32 params_addr) if (params.flags & MAP_ANONYMOUS) mmu().add_region(MmapRegion::create_anonymous(final_address, final_size, params.prot)); else { - dbgln("chars: {:p}, len: {}", params.name.characters, params.name.length); String name_str; if (params.name.characters) { auto name = ByteBuffer::create_uninitialized(params.name.length); mmu().copy_from_vm(name.data(), (FlatPtr)params.name.characters, params.name.length); name_str = { name.data(), name.size() }; } - mmu().add_region(MmapRegion::create_file_backed(final_address, final_size, params.prot, params.flags, params.fd, params.offset, name_str)); + auto region = MmapRegion::create_file_backed(final_address, final_size, params.prot, params.flags, params.fd, params.offset, name_str); + if (region->name() == "libc.so: .text (Emulated)") { + bool rc = find_malloc_symbols(*region); + ASSERT(rc); + } + mmu().add_region(move(region)); } return final_address; @@ -1567,4 +1670,46 @@ int Emulator::virt$readlink(FlatPtr params_addr) return rc; } +u32 Emulator::virt$allocate_tls(size_t size) +{ + // TODO: Why is this needed? without this, the loader overflows the bounds of the TLS region. + constexpr size_t TLS_SIZE_HACK = 8; + auto tcb_region = make(0x20000000, size + TLS_SIZE_HACK); + bzero(tcb_region->data(), size); + memset(tcb_region->shadow_data(), 0x01, size); + + auto tls_region = make(0, 4); + tls_region->write32(0, shadow_wrap_as_initialized(tcb_region->base() + (u32)size)); + memset(tls_region->shadow_data(), 0x01, 4); + + u32 tls_base = tcb_region->base(); + mmu().add_region(move(tcb_region)); + mmu().set_tls_region(move(tls_region)); + return tls_base; +} + +bool Emulator::find_malloc_symbols(const MmapRegion& libc_text) +{ + auto mapped_file = make("/usr/lib/libc.so"); + if (!mapped_file->is_valid()) + return {}; + + ELF::Image image((const u8*)mapped_file->data(), mapped_file->size()); + auto malloc_symbol = image.find_demangled_function("malloc"); + auto free_symbol = image.find_demangled_function("free"); + auto realloc_symbol = image.find_demangled_function("realloc"); + auto malloc_size_symbol = image.find_demangled_function("malloc_size"); + if (!malloc_symbol.has_value() || !free_symbol.has_value() || !realloc_symbol.has_value() || !malloc_size_symbol.has_value()) + return false; + + m_malloc_symbol_start = malloc_symbol.value().value() + libc_text.base(); + m_malloc_symbol_end = m_malloc_symbol_start + malloc_symbol.value().size(); + m_free_symbol_start = free_symbol.value().value() + libc_text.base(); + m_free_symbol_end = m_free_symbol_start + free_symbol.value().size(); + m_realloc_symbol_start = realloc_symbol.value().value() + libc_text.base(); + m_realloc_symbol_end = m_realloc_symbol_start + realloc_symbol.value().size(); + m_malloc_size_symbol_start = malloc_size_symbol.value().value() + libc_text.base(); + m_malloc_size_symbol_end = m_malloc_size_symbol_start + malloc_size_symbol.value().size(); + return true; +} } diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index 764fb68bc1..8696ee4a32 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -32,6 +32,7 @@ #include "SoftMMU.h" #include #include +#include #include #include #include @@ -45,7 +46,7 @@ class Emulator { public: static Emulator& the(); - Emulator(const Vector& arguments, const Vector& environment, NonnullRefPtr); + Emulator(const String& executable_path, const Vector& arguments, const Vector& environment); bool load_elf(); void dump_backtrace(); @@ -60,19 +61,22 @@ public: MallocTracer* malloc_tracer() { return m_malloc_tracer; } bool is_in_malloc_or_free() const; + bool is_in_loader_code() const; void did_receive_signal(int signum) { m_pending_signals |= (1 << signum); } private: - NonnullRefPtr m_elf; - OwnPtr m_debug_info; + const String m_executable_path; + const Vector m_arguments; + const Vector m_environment; SoftMMU m_mmu; SoftCPU m_cpu; OwnPtr m_malloc_tracer; - void setup_stack(const Vector& arguments, const Vector& environment); + void setup_stack(Vector); + Vector generate_auxiliary_vector(FlatPtr load_base, FlatPtr entry_eip, String executable_path, int executable_fd) const; void register_signal_handlers(); void setup_signal_trampoline(); @@ -158,10 +162,14 @@ private: pid_t virt$setsid(); int virt$watch_file(FlatPtr, size_t); int virt$readlink(FlatPtr); + u32 virt$allocate_tls(size_t); FlatPtr allocate_vm(size_t size, size_t alignment); + bool find_malloc_symbols(const MmapRegion& libc_text); void dispatch_one_pending_signal(); + const MmapRegion* find_text_region(FlatPtr address); + String create_backtrace_line(FlatPtr address); bool m_shutdown { false }; int m_exit_status { 0 }; @@ -186,6 +194,8 @@ private: SignalHandlerInfo m_signal_handler[NSIG]; FlatPtr m_signal_trampoline { 0 }; + Optional m_loader_text_base; + Optional m_loader_text_size; }; ALWAYS_INLINE bool Emulator::is_in_malloc_or_free() const @@ -196,4 +206,11 @@ ALWAYS_INLINE bool Emulator::is_in_malloc_or_free() const || (m_cpu.base_eip() >= m_malloc_size_symbol_start && m_cpu.base_eip() < m_malloc_size_symbol_end); } +ALWAYS_INLINE bool Emulator::is_in_loader_code() const +{ + if (!m_loader_text_base.has_value() || !m_loader_text_size.has_value()) + return false; + return (m_cpu.base_eip() >= m_loader_text_base.value() && m_cpu.base_eip() < m_loader_text_base.value() + m_loader_text_size.value()); +} + } diff --git a/DevTools/UserspaceEmulator/MallocTracer.cpp b/DevTools/UserspaceEmulator/MallocTracer.cpp index 1a9b1d4077..98e9c934c7 100644 --- a/DevTools/UserspaceEmulator/MallocTracer.cpp +++ b/DevTools/UserspaceEmulator/MallocTracer.cpp @@ -58,6 +58,8 @@ inline void MallocTracer::for_each_mallocation(Callback callback) const void MallocTracer::target_did_malloc(Badge, FlatPtr address, size_t size) { + if (m_emulator.is_in_loader_code()) + return; auto* region = m_emulator.mmu().find_region({ 0x20, address }); ASSERT(region); ASSERT(region->is_mmap()); @@ -109,6 +111,7 @@ ALWAYS_INLINE size_t MallocRegionMetadata::chunk_index_for_address(FlatPtr addre return 0; } auto chunk_offset = address - (this->address + sizeof(ChunkedBlock)); + ASSERT(this->chunk_size); return chunk_offset / this->chunk_size; } @@ -116,6 +119,8 @@ void MallocTracer::target_did_free(Badge, FlatPtr address) { if (!address) return; + if (m_emulator.is_in_loader_code()) + return; if (auto* mallocation = find_mallocation(address)) { if (mallocation->freed) { @@ -136,6 +141,8 @@ void MallocTracer::target_did_free(Badge, FlatPtr address) void MallocTracer::target_did_realloc(Badge, FlatPtr address, size_t size) { + if (m_emulator.is_in_loader_code()) + return; auto* region = m_emulator.mmu().find_region({ 0x20, address }); ASSERT(region); ASSERT(region->is_mmap()); @@ -201,8 +208,13 @@ void MallocTracer::audit_read(const Region& region, FlatPtr address, size_t size if (!m_auditing_enabled) return; - if (m_emulator.is_in_malloc_or_free()) + if (m_emulator.is_in_malloc_or_free()) { return; + } + + if (m_emulator.is_in_loader_code()) { + return; + } auto* mallocation = find_mallocation(region, address); @@ -246,6 +258,10 @@ void MallocTracer::audit_write(const Region& region, FlatPtr address, size_t siz if (m_emulator.is_in_malloc_or_free()) return; + if (m_emulator.is_in_loader_code()) { + return; + } + auto* mallocation = find_mallocation(region, address); if (!mallocation) { reportln("\n=={}== \033[31;1mHeap buffer overflow\033[0m, invalid {}-byte write at address {:p}", getpid(), size, address); @@ -315,6 +331,8 @@ bool MallocTracer::is_reachable(const Mallocation& mallocation) const return IterationDecision::Continue; if (region.is_text()) return IterationDecision::Continue; + if (!region.is_readable()) + return IterationDecision::Continue; // Skip malloc blocks if (region.is_mmap() && static_cast(region).is_malloc_block()) return IterationDecision::Continue; diff --git a/DevTools/UserspaceEmulator/MmapRegion.cpp b/DevTools/UserspaceEmulator/MmapRegion.cpp index c0ce837c38..9e5eda4e56 100644 --- a/DevTools/UserspaceEmulator/MmapRegion.cpp +++ b/DevTools/UserspaceEmulator/MmapRegion.cpp @@ -44,7 +44,6 @@ NonnullOwnPtr MmapRegion::create_file_backed(u32 base, u32 size, u32 auto region = adopt_own(*new MmapRegion(base, size, prot)); region->m_file_backed = true; if (!name.is_empty()) { - dbgln("name is not empty"); name = String::format("%s (Emulated)", name.characters()); region->m_name = name; } diff --git a/DevTools/UserspaceEmulator/MmapRegion.h b/DevTools/UserspaceEmulator/MmapRegion.h index a94077fec7..51c2a8e370 100644 --- a/DevTools/UserspaceEmulator/MmapRegion.h +++ b/DevTools/UserspaceEmulator/MmapRegion.h @@ -61,6 +61,8 @@ public: MallocRegionMetadata* malloc_metadata() { return m_malloc_metadata; } void set_malloc_metadata(Badge, NonnullOwnPtr metadata) { m_malloc_metadata = move(metadata); } + const String& name() const { return m_name; } + private: MmapRegion(u32 base, u32 size, int prot); virtual bool is_mmap() const override { return true; } diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index cec716739b..280c38b35f 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -229,6 +229,13 @@ void SoftCPU::push_string(const StringView& string) m_emulator.mmu().write8({ 0x20, esp().value() + string.length() }, shadow_wrap_as_initialized((u8)'\0')); } +void SoftCPU::push_buffer(const u8* data, size_t size) +{ + set_esp({ esp().value() - size, esp().shadow() }); + warn_if_uninitialized(esp(), "push_buffer"); + m_emulator.mmu().copy_to_vm(esp().value(), data, size); +} + void SoftCPU::push32(ValueWithShadow value) { set_esp({ esp().value() - sizeof(u32), esp().shadow() }); diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h index 7a29cb30f4..89ece8976d 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.h +++ b/DevTools/UserspaceEmulator/SoftCPU.h @@ -93,6 +93,7 @@ public: ValueWithShadow pop16(); void push_string(const StringView&); + void push_buffer(const u8* data, size_t); u16 segment(X86::SegmentRegister seg) const { return m_segment[(int)seg]; } u16& segment(X86::SegmentRegister seg) { return m_segment[(int)seg]; } diff --git a/DevTools/UserspaceEmulator/main.cpp b/DevTools/UserspaceEmulator/main.cpp index 85b53753a0..ec6c320d94 100644 --- a/DevTools/UserspaceEmulator/main.cpp +++ b/DevTools/UserspaceEmulator/main.cpp @@ -50,14 +50,6 @@ int main(int argc, char** argv, char** env) auto executable_path = Core::find_executable_in_path(command[0]); - MappedFile mapped_file(executable_path); - if (!mapped_file.is_valid()) { - reportln("Unable to map {}", executable_path); - return 1; - } - - auto elf = ELF::Loader::create((const u8*)mapped_file.data(), mapped_file.size()); - Vector arguments; for (auto arg : command) { arguments.append(arg); @@ -69,7 +61,7 @@ int main(int argc, char** argv, char** env) } // FIXME: It might be nice to tear down the emulator properly. - auto& emulator = *new UserspaceEmulator::Emulator(arguments, environment, move(elf)); + auto& emulator = *new UserspaceEmulator::Emulator(executable_path, arguments, environment); if (!emulator.load_elf()) return 1; diff --git a/Userland/DynamicLoader/main.cpp b/Userland/DynamicLoader/main.cpp index c8a9904d62..ce40482591 100644 --- a/Userland/DynamicLoader/main.cpp +++ b/Userland/DynamicLoader/main.cpp @@ -254,6 +254,8 @@ static FlatPtr loader_main(auxv_t* auxvp) } } ASSERT(main_program_fd >= 0); + ASSERT(!main_program_name.is_null()); + dbgln("loading: {}", main_program_name); map_library(main_program_name, main_program_fd); map_dependencies(main_program_name);