diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index 624c6768e3..8918bb6e69 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include namespace UserspaceEmulator { @@ -85,6 +86,8 @@ public: *reinterpret_cast(m_data + offset) = value; } + u8* data() { return m_data; } + private: u8* m_data { nullptr }; }; @@ -107,12 +110,26 @@ void Emulator::setup_stack() m_cpu.push32(0); } -int Emulator::exec(X86::SimpleInstructionStream& stream, u32 base) +bool Emulator::load_elf(const ELF::Loader& elf) +{ + elf.image().for_each_program_header([&](const ELF::Image::ProgramHeader& program_header) { + if (program_header.type() != PT_LOAD) + return; + auto region = make(program_header.vaddr().get(), program_header.size_in_memory()); + memcpy(region->data(), program_header.raw_data(), program_header.size_in_image()); + mmu().add_region(move(region)); + }); + + m_cpu.set_eip(elf.image().entry().get()); + return true; +} + +int Emulator::exec() { - size_t offset = 0; while (!m_shutdown) { - auto insn = X86::Instruction::from_stream(stream, true, true); - out() << "\033[33;1m" << insn.to_string(base + offset) << "\033[0m"; + auto base_eip = m_cpu.eip(); + auto insn = X86::Instruction::from_stream(m_cpu, true, true); + out() << "\033[33;1m" << insn.to_string(base_eip) << "\033[0m"; // FIXME: Remove this hack once it's no longer needed :^) if (insn.mnemonic() == "RET") @@ -120,8 +137,6 @@ int Emulator::exec(X86::SimpleInstructionStream& stream, u32 base) (m_cpu.*insn.handler())(insn); m_cpu.dump(); - - offset += insn.length(); } return m_exit_status; } diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index 12a571c1c7..69bda5a5c2 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -29,6 +29,7 @@ #include "SoftCPU.h" #include "SoftMMU.h" #include +#include #include #include @@ -38,7 +39,9 @@ class Emulator { public: Emulator(); - int exec(X86::SimpleInstructionStream&, u32 base); + bool load_elf(const ELF::Loader&); + + int exec(); u32 virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3); SoftMMU& mmu() { return m_mmu; } diff --git a/DevTools/UserspaceEmulator/SoftCPU.cpp b/DevTools/UserspaceEmulator/SoftCPU.cpp index 0969b279f5..f122dfe40a 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -78,9 +78,30 @@ void SoftCPU::dump() const printf("o=%u s=%u z=%u a=%u p=%u c=%u\n", of(), sf(), zf(), af(), pf(), cf()); } +u8 SoftCPU::read8() +{ + auto value = read_memory8({ cs(), eip() }); + m_eip += 1; + return value; +} + +u16 SoftCPU::read16() +{ + auto value = read_memory16({ cs(), eip() }); + m_eip += 2; + return value; +} + +u32 SoftCPU::read32() +{ + auto value = read_memory32({ cs(), eip() }); + m_eip += 4; + return value; +} + u8 SoftCPU::read_memory8(X86::LogicalAddress address) { - ASSERT(address.selector() == 0x20); + ASSERT(address.selector() == 0x18 || address.selector() == 0x20); auto value = m_emulator.mmu().read8(address.offset()); printf("\033[36;1mread_memory8: @%08x -> %02x\033[0m\n", address.offset(), value); return value; @@ -88,7 +109,7 @@ u8 SoftCPU::read_memory8(X86::LogicalAddress address) u16 SoftCPU::read_memory16(X86::LogicalAddress address) { - ASSERT(address.selector() == 0x20); + ASSERT(address.selector() == 0x18 || address.selector() == 0x20); auto value = m_emulator.mmu().read16(address.offset()); printf("\033[36;1mread_memory16: @%08x -> %04x\033[0m\n", address.offset(), value); return value; @@ -96,7 +117,7 @@ u16 SoftCPU::read_memory16(X86::LogicalAddress address) u32 SoftCPU::read_memory32(X86::LogicalAddress address) { - ASSERT(address.selector() == 0x20); + ASSERT(address.selector() == 0x18 || address.selector() == 0x20); auto value = m_emulator.mmu().read32(address.offset()); printf("\033[36;1mread_memory32: @%08x -> %08x\033[0m\n", address.offset(), value); return value; diff --git a/DevTools/UserspaceEmulator/SoftCPU.h b/DevTools/UserspaceEmulator/SoftCPU.h index dd322ccd60..bd95158add 100644 --- a/DevTools/UserspaceEmulator/SoftCPU.h +++ b/DevTools/UserspaceEmulator/SoftCPU.h @@ -48,11 +48,16 @@ union PartAddressableRegister { }; }; -class SoftCPU final : public X86::Interpreter { +class SoftCPU final + : public X86::Interpreter + , public X86::InstructionStream { public: explicit SoftCPU(Emulator&); void dump() const; + u32 eip() const { return m_eip; } + void set_eip(u32 eip) { m_eip = eip; } + struct Flags { enum Flag { CF = 0x0001, @@ -274,6 +279,13 @@ public: } private: + // ^X86::InstructionStream + virtual bool can_read() override { return false; } + virtual u8 read8() override; + virtual u16 read16() override; + virtual u32 read32() override; + + // ^X86::Interpreter virtual void AAA(const X86::Instruction&) override; virtual void AAD(const X86::Instruction&) override; virtual void AAM(const X86::Instruction&) override; @@ -779,6 +791,8 @@ private: PartAddressableRegister m_gpr[8]; u16 m_segment[8] { 0 }; u32 m_eflags { 0 }; + + u32 m_eip { 0 }; }; } diff --git a/DevTools/UserspaceEmulator/main.cpp b/DevTools/UserspaceEmulator/main.cpp index 5b844fc839..9266dbd817 100644 --- a/DevTools/UserspaceEmulator/main.cpp +++ b/DevTools/UserspaceEmulator/main.cpp @@ -30,7 +30,6 @@ #include #include #include -#include int main(int argc, char** argv) { @@ -48,15 +47,9 @@ int main(int argc, char** argv) auto elf = ELF::Loader::create((const u8*)mapped_file.data(), mapped_file.size()); - auto _start_symbol = elf->find_demangled_function("_start"); - if (!_start_symbol.has_value()) { - warn() << "Could not find '_start' symbol in executable"; - return 1; - } - - auto main_code = _start_symbol.value().raw_data(); - X86::SimpleInstructionStream stream((const u8*)main_code.characters_without_null_termination(), main_code.length()); - UserspaceEmulator::Emulator emulator; - return emulator.exec(stream, _start_symbol.value().value()); + if (!emulator.load_elf(*elf)) + return 1; + + return emulator.exec(); }