mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:02:43 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									3d42b85969
								
							
						
					
					
						commit
						27c1690504
					
				
					 3 changed files with 28 additions and 18 deletions
				
			
		|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling