mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +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 u32 stack_location = 0x10000000; | ||||||
| static constexpr size_t stack_size = 64 * KB; | 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_elf(move(elf)) | ||||||
|     , m_cpu(*this) |     , 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); |     auto stack_region = make<SimpleRegion>(stack_location, stack_size); | ||||||
|     m_mmu.add_region(move(stack_region)); |     m_mmu.add_region(move(stack_region)); | ||||||
|     m_cpu.set_esp(stack_location + stack_size); |     m_cpu.set_esp(stack_location + stack_size); | ||||||
| 
 | 
 | ||||||
|     m_cpu.push_string(LexicalPath(m_executable_path).basename()); |     Vector<u32> argv_entries; | ||||||
|     u32 argv0 = m_cpu.esp(); | 
 | ||||||
|  |     for (auto& argument : arguments) { | ||||||
|  |         m_cpu.push_string(argument.characters()); | ||||||
|  |         argv_entries.append(m_cpu.esp()); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     m_cpu.push32(0); // char** envp = { nullptr }
 |     m_cpu.push32(0); // char** envp = { nullptr }
 | ||||||
|     u32 envp = m_cpu.esp(); |     u32 envp = m_cpu.esp(); | ||||||
| 
 | 
 | ||||||
|     m_cpu.push32(0); // char** argv = { argv0, nullptr }
 |     m_cpu.push32(0); // char** argv = { argv_entries..., nullptr }
 | ||||||
|     m_cpu.push32(argv0); |     for (ssize_t i = argv_entries.size() - 1; i >= 0; --i) | ||||||
|  |         m_cpu.push32(argv_entries[i]); | ||||||
|     u32 argv = m_cpu.esp(); |     u32 argv = m_cpu.esp(); | ||||||
| 
 | 
 | ||||||
|     m_cpu.push32(0); // (alignment)
 |     m_cpu.push32(0); // (alignment)
 | ||||||
| 
 | 
 | ||||||
|     u32 argc = 1; |     u32 argc = argv_entries.size(); | ||||||
|     m_cpu.push32(envp); |     m_cpu.push32(envp); | ||||||
|     m_cpu.push32(argv); |     m_cpu.push32(argv); | ||||||
|     m_cpu.push32(argc); |     m_cpu.push32(argc); | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ namespace UserspaceEmulator { | ||||||
| 
 | 
 | ||||||
| class Emulator { | class Emulator { | ||||||
| public: | public: | ||||||
|     Emulator(const String& executable_path, NonnullRefPtr<ELF::Loader>); |     Emulator(const Vector<String>& arguments, NonnullRefPtr<ELF::Loader>); | ||||||
| 
 | 
 | ||||||
|     bool load_elf(); |     bool load_elf(); | ||||||
|     void dump_backtrace(); |     void dump_backtrace(); | ||||||
|  | @ -53,7 +53,7 @@ private: | ||||||
|     SoftMMU m_mmu; |     SoftMMU m_mmu; | ||||||
|     SoftCPU m_cpu; |     SoftCPU m_cpu; | ||||||
| 
 | 
 | ||||||
|     void setup_stack(); |     void setup_stack(const Vector<String>& arguments); | ||||||
| 
 | 
 | ||||||
|     u32 virt$mmap(u32); |     u32 virt$mmap(u32); | ||||||
|     u32 virt$gettid(); |     u32 virt$gettid(); | ||||||
|  | @ -77,8 +77,6 @@ private: | ||||||
| 
 | 
 | ||||||
|     bool m_shutdown { false }; |     bool m_shutdown { false }; | ||||||
|     int m_exit_status { 0 }; |     int m_exit_status { 0 }; | ||||||
| 
 |  | ||||||
|     String m_executable_path; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,14 +30,17 @@ | ||||||
| #include <AK/MappedFile.h> | #include <AK/MappedFile.h> | ||||||
| #include <LibCore/ArgsParser.h> | #include <LibCore/ArgsParser.h> | ||||||
| #include <LibELF/Loader.h> | #include <LibELF/Loader.h> | ||||||
|  | #include <getopt.h> | ||||||
| 
 | 
 | ||||||
| int main(int argc, char** argv) | int main(int argc, char** argv) | ||||||
| { | { | ||||||
|     const char* executable_path = nullptr; |     if (argc == 1) { | ||||||
|  |         out() << "usage: UserspaceEmulator <command>"; | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     Core::ArgsParser args_parser; |     // FIXME: Allow specifying any command in $PATH instead of requiring a full executable path.
 | ||||||
|     args_parser.add_positional_argument(executable_path, "Executable path", "executable"); |     const char* executable_path = argv[1]; | ||||||
|     args_parser.parse(argc, argv); |  | ||||||
| 
 | 
 | ||||||
|     MappedFile mapped_file(executable_path); |     MappedFile mapped_file(executable_path); | ||||||
|     if (!mapped_file.is_valid()) { |     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()); |     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()) |     if (!emulator.load_elf()) | ||||||
|         return 1; |         return 1; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling