From 27c1690504bbac0e2b26148889dd2aea241828d2 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 13 Jul 2020 11:22:50 +0200 Subject: [PATCH] UserspaceEmulator: Pass arguments through to emulated process Ultimately we'll want to support passing some options to the emulator as well, but for now just pass all arguments (except argv[0] of course) through to the emulated process. This is still not perfect, but slightly better than what we had before. --- DevTools/UserspaceEmulator/Emulator.cpp | 22 +++++++++++++--------- DevTools/UserspaceEmulator/Emulator.h | 6 ++---- DevTools/UserspaceEmulator/main.cpp | 18 +++++++++++++----- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index 4ac805a5ee..626f0a6631 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -44,33 +44,37 @@ namespace UserspaceEmulator { static constexpr u32 stack_location = 0x10000000; static constexpr size_t stack_size = 64 * KB; -Emulator::Emulator(const String& executable_path, NonnullRefPtr elf) +Emulator::Emulator(const Vector& arguments, NonnullRefPtr elf) : m_elf(move(elf)) , m_cpu(*this) - , m_executable_path(executable_path) { - setup_stack(); + setup_stack(arguments); } -void Emulator::setup_stack() +void Emulator::setup_stack(const Vector& arguments) { auto stack_region = make(stack_location, stack_size); m_mmu.add_region(move(stack_region)); m_cpu.set_esp(stack_location + stack_size); - m_cpu.push_string(LexicalPath(m_executable_path).basename()); - u32 argv0 = m_cpu.esp(); + Vector argv_entries; + + for (auto& argument : arguments) { + m_cpu.push_string(argument.characters()); + argv_entries.append(m_cpu.esp()); + } m_cpu.push32(0); // char** envp = { nullptr } u32 envp = m_cpu.esp(); - m_cpu.push32(0); // char** argv = { argv0, nullptr } - m_cpu.push32(argv0); + m_cpu.push32(0); // char** argv = { argv_entries..., nullptr } + for (ssize_t i = argv_entries.size() - 1; i >= 0; --i) + m_cpu.push32(argv_entries[i]); u32 argv = m_cpu.esp(); m_cpu.push32(0); // (alignment) - u32 argc = 1; + u32 argc = argv_entries.size(); m_cpu.push32(envp); m_cpu.push32(argv); m_cpu.push32(argc); diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index 695cd0ee11..463d851dbd 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -37,7 +37,7 @@ namespace UserspaceEmulator { class Emulator { public: - Emulator(const String& executable_path, NonnullRefPtr); + Emulator(const Vector& arguments, NonnullRefPtr); bool load_elf(); void dump_backtrace(); @@ -53,7 +53,7 @@ private: SoftMMU m_mmu; SoftCPU m_cpu; - void setup_stack(); + void setup_stack(const Vector& arguments); u32 virt$mmap(u32); u32 virt$gettid(); @@ -77,8 +77,6 @@ private: bool m_shutdown { false }; int m_exit_status { 0 }; - - String m_executable_path; }; } diff --git a/DevTools/UserspaceEmulator/main.cpp b/DevTools/UserspaceEmulator/main.cpp index cb272c6d0b..58549e7f66 100644 --- a/DevTools/UserspaceEmulator/main.cpp +++ b/DevTools/UserspaceEmulator/main.cpp @@ -30,14 +30,17 @@ #include #include #include +#include int main(int argc, char** argv) { - const char* executable_path = nullptr; + if (argc == 1) { + out() << "usage: UserspaceEmulator "; + return 0; + } - Core::ArgsParser args_parser; - args_parser.add_positional_argument(executable_path, "Executable path", "executable"); - args_parser.parse(argc, argv); + // FIXME: Allow specifying any command in $PATH instead of requiring a full executable path. + const char* executable_path = argv[1]; MappedFile mapped_file(executable_path); if (!mapped_file.is_valid()) { @@ -47,7 +50,12 @@ int main(int argc, char** argv) auto elf = ELF::Loader::create((const u8*)mapped_file.data(), mapped_file.size()); - UserspaceEmulator::Emulator emulator(executable_path, move(elf)); + Vector arguments; + for (int i = 1; i < argc; ++i) { + arguments.append(argv[i]); + } + + UserspaceEmulator::Emulator emulator(arguments, move(elf)); if (!emulator.load_elf()) return 1;