mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:48:12 +00:00
UserspaceEmulator: Load the target executable ELF semi-properly :^)
This patch adds a basic ELF program loader to the UserspaceEmulator and creates MMU regions for each PT_LOAD header. (Note that we don't yet respect the R/W/X flags etc.) We also turn the SoftCPU into an X86::InstructionStream and give it an EIP register so we can actually execute code by fetching memory through our MMU abstraction.
This commit is contained in:
parent
0eab5659f8
commit
ae1d14bc7a
5 changed files with 68 additions and 22 deletions
|
@ -29,6 +29,7 @@
|
|||
#include <AK/LogStream.h>
|
||||
#include <Kernel/API/Syscall.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace UserspaceEmulator {
|
||||
|
@ -85,6 +86,8 @@ public:
|
|||
*reinterpret_cast<u32*>(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<SimpleRegion>(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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue