Ver código fonte

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.
Andreas Kling 5 anos atrás
pai
commit
27c1690504

+ 13 - 9
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::Loader> elf)
+Emulator::Emulator(const Vector<String>& arguments, NonnullRefPtr<ELF::Loader> 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<String>& arguments)
 {
     auto stack_region = make<SimpleRegion>(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<u32> 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);

+ 2 - 4
DevTools/UserspaceEmulator/Emulator.h

@@ -37,7 +37,7 @@ namespace UserspaceEmulator {
 
 class Emulator {
 public:
-    Emulator(const String& executable_path, NonnullRefPtr<ELF::Loader>);
+    Emulator(const Vector<String>& arguments, NonnullRefPtr<ELF::Loader>);
 
     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<String>& 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;
 };
 
 }

+ 13 - 5
DevTools/UserspaceEmulator/main.cpp

@@ -30,14 +30,17 @@
 #include <AK/MappedFile.h>
 #include <LibCore/ArgsParser.h>
 #include <LibELF/Loader.h>
+#include <getopt.h>
 
 int main(int argc, char** argv)
 {
-    const char* executable_path = nullptr;
+    if (argc == 1) {
+        out() << "usage: UserspaceEmulator <command>";
+        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<String> arguments;
+    for (int i = 1; i < argc; ++i) {
+        arguments.append(argv[i]);
+    }
+
+    UserspaceEmulator::Emulator emulator(arguments, move(elf));
     if (!emulator.load_elf())
         return 1;