1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:27:35 +00:00

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.
This commit is contained in:
Itamar 2020-11-23 20:00:35 +02:00 committed by Andreas Kling
parent 28cda567c1
commit 72ca45e300
9 changed files with 247 additions and 64 deletions

View file

@ -32,6 +32,7 @@
#include "SoftMMU.h"
#include <AK/Types.h>
#include <LibDebug/DebugInfo.h>
#include <LibELF/AuxiliaryVector.h>
#include <LibELF/Loader.h>
#include <LibX86/Instruction.h>
#include <signal.h>
@ -45,7 +46,7 @@ class Emulator {
public:
static Emulator& the();
Emulator(const Vector<String>& arguments, const Vector<String>& environment, NonnullRefPtr<ELF::Loader>);
Emulator(const String& executable_path, const Vector<String>& arguments, const Vector<String>& 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<ELF::Loader> m_elf;
OwnPtr<Debug::DebugInfo> m_debug_info;
const String m_executable_path;
const Vector<String> m_arguments;
const Vector<String> m_environment;
SoftMMU m_mmu;
SoftCPU m_cpu;
OwnPtr<MallocTracer> m_malloc_tracer;
void setup_stack(const Vector<String>& arguments, const Vector<String>& environment);
void setup_stack(Vector<AuxiliaryValue>);
Vector<AuxiliaryValue> 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<FlatPtr> m_loader_text_base;
Optional<size_t> 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());
}
}