From 2682c125e0f87b5f4f4701e2a83d3dfee7cfee8e Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 7 Jun 2018 13:03:36 +0900 Subject: [PATCH] More real ELF loading and brk handling; more tests pass. --- plat/linux68k/emu/sim.c | 121 ++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 41 deletions(-) diff --git a/plat/linux68k/emu/sim.c b/plat/linux68k/emu/sim.c index 64757607c..2e084828f 100755 --- a/plat/linux68k/emu/sim.c +++ b/plat/linux68k/emu/sim.c @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #include @@ -13,12 +15,11 @@ void disassemble_program(); #define RAM_BASE 0x08000000 #define RAM_TOP 0x08100000 +#define BRK_TOP (RAM_TOP - 0x1000) + #define INIT_SP RAM_TOP #define INIT_PC 0x08000054 -#define BRK_BOTTOM (RAM_BASE + 0x20000) -#define BRK_TOP (RAM_TOP - 0x1000) - /* Read/write macros */ #define READ_BYTE(BASE, ADDR) (BASE)[ADDR] #define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | \ @@ -40,23 +41,24 @@ void disassemble_program(); static void exit_error(char* fmt, ...); static void emulated_syscall(void); -unsigned int cpu_read_byte(unsigned int address); -unsigned int cpu_read_word(unsigned int address); -unsigned int cpu_read_long(unsigned int address); -void cpu_write_byte(unsigned int address, unsigned int value); -void cpu_write_word(unsigned int address, unsigned int value); -void cpu_write_long(unsigned int address, unsigned int value); +uint32_t cpu_read_byte(uint32_t address); +uint32_t cpu_read_word(uint32_t address); +uint32_t cpu_read_long(uint32_t address); +void cpu_write_byte(uint32_t address, uint32_t value); +void cpu_write_word(uint32_t address, uint32_t value); +void cpu_write_long(uint32_t address, uint32_t value); unsigned char g_ram[RAM_TOP - RAM_BASE]; -unsigned int brkpos = BRK_BOTTOM; - +uint32_t brkbase = RAM_BASE; +uint32_t brkpos = RAM_BASE; +uint32_t entrypoint = RAM_BASE; /* Exit with an error message. Use printf syntax. */ void exit_error(char* fmt, ...) { static int guard_val = 0; char buff[100]; - unsigned int pc; + uint32_t pc; va_list args; if(guard_val) @@ -75,71 +77,78 @@ void exit_error(char* fmt, ...) exit(EXIT_FAILURE); } -static inline unsigned int transform_address(unsigned int address) +static inline uint32_t transform_address(uint32_t address) { - unsigned int i = (address & ADDRESS_MASK) - RAM_BASE; - if (i >= (unsigned int)(RAM_TOP - RAM_BASE)) + uint32_t i = (address & ADDRESS_MASK) - RAM_BASE; + if (i >= (uint32_t)(RAM_TOP - RAM_BASE)) exit_error("Attempted to read from RAM address %08x", address); return i; } -unsigned int cpu_read_long(unsigned int address) +uint32_t cpu_read_long(uint32_t address) { switch (address) { case 0x00: return INIT_SP; - case 0x04: return INIT_PC; + case 0x04: return entrypoint; case 0x80: emulated_syscall(); return 0x10000; case 0x10000: return 0x4e734e73; /* rte; rte */ case 0x10004: return 0; - default: return READ_LONG(g_ram, transform_address(address)); + default: + { + uint32_t value = READ_LONG(g_ram, transform_address(address)); + #if 0 + printf("read %08x from %08x\n", value, address); + #endif + return value; + } } } -unsigned int cpu_read_word(unsigned int address) +uint32_t cpu_read_word(uint32_t address) { - unsigned int l = cpu_read_long(address & ~3); + uint32_t l = cpu_read_long(address & ~3); l >>= 16 - (address & 2)*8; return l & 0xffff; } -unsigned int cpu_read_byte(unsigned int address) +uint32_t cpu_read_byte(uint32_t address) { - unsigned int l = cpu_read_long(address & ~3); + uint32_t l = cpu_read_long(address & ~3); l >>= 24 - (address & 3)*8; return l & 0xff; } -unsigned int cpu_read_word_dasm(unsigned int address) +uint32_t cpu_read_word_dasm(uint32_t address) { return cpu_read_word(address); } -unsigned int cpu_read_long_dasm(unsigned int address) +uint32_t cpu_read_long_dasm(uint32_t address) { return cpu_read_long(address); } /* Write data to RAM or a device */ -void cpu_write_byte(unsigned int address, unsigned int value) +void cpu_write_byte(uint32_t address, uint32_t value) { WRITE_BYTE(g_ram, transform_address(address), value); } -void cpu_write_word(unsigned int address, unsigned int value) +void cpu_write_word(uint32_t address, uint32_t value) { WRITE_WORD(g_ram, transform_address(address), value); } -void cpu_write_long(unsigned int address, unsigned int value) +void cpu_write_long(uint32_t address, uint32_t value) { WRITE_LONG(g_ram, transform_address(address), value); } /* Disassembler */ -void make_hex(char* buff, unsigned int pc, unsigned int length) +void make_hex(char* buff, uint32_t pc, uint32_t length) { char* ptr = buff; @@ -155,8 +164,8 @@ void make_hex(char* buff, unsigned int pc, unsigned int length) void disassemble_program() { - unsigned int pc; - unsigned int instr_size; + uint32_t pc; + uint32_t instr_size; char buff[100]; char buff2[100]; @@ -174,7 +183,7 @@ void disassemble_program() void cpu_instr_callback() { - unsigned int pc = m68k_get_reg(NULL, M68K_REG_PC); + uint32_t pc = m68k_get_reg(NULL, M68K_REG_PC); if (pc == 0xc) exit_error("address exception"); @@ -183,7 +192,7 @@ void cpu_instr_callback() #if 0 static char buff[100]; static char buff2[100]; - static unsigned int instr_size; + static uint32_t instr_size; instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68020); make_hex(buff2, pc, instr_size); @@ -220,19 +229,19 @@ static void emulated_syscall(void) case 4: /* write */ { - unsigned int fd = m68k_get_reg(NULL, M68K_REG_D1); - unsigned int ptr = m68k_get_reg(NULL, M68K_REG_D2); - unsigned int len = m68k_get_reg(NULL, M68K_REG_D3); + uint32_t fd = m68k_get_reg(NULL, M68K_REG_D1); + uint32_t ptr = m68k_get_reg(NULL, M68K_REG_D2); + uint32_t len = m68k_get_reg(NULL, M68K_REG_D3); m68k_set_reg(M68K_REG_D0, write(fd, g_ram + transform_address(ptr), len)); break; } case 45: /* brk */ { - unsigned int newpos = m68k_get_reg(NULL, M68K_REG_D1); + uint32_t newpos = m68k_get_reg(NULL, M68K_REG_D1); if (newpos == 0) m68k_set_reg(M68K_REG_D0, brkpos); - else if ((newpos < BRK_BOTTOM) || (newpos >= BRK_TOP)) + else if ((newpos < brkbase) || (newpos >= BRK_TOP)) m68k_set_reg(M68K_REG_D0, -ENOMEM); else { @@ -251,6 +260,37 @@ static void emulated_syscall(void) } } +static void load_program(FILE* fd) +{ + fseek(fd, 0, SEEK_SET); + if (fread(g_ram, 1, 0x34, fd) != 0x34) + exit_error("couldn't read ELF header"); + + uint32_t phoff = READ_LONG(g_ram, 0x1c); + uint16_t phentsize = READ_WORD(g_ram, 0x2a); + uint16_t phnum = READ_WORD(g_ram, 0x2c); + entrypoint = READ_LONG(g_ram, 0x18); + if ((phentsize != 0x20) || (phnum != 1)) + exit_error("unsupported ELF file"); + + fseek(fd, phoff, SEEK_SET); + if (fread(g_ram, 1, phentsize, fd) != phentsize) + exit_error("couldn't read program header"); + + uint32_t offset = READ_LONG(g_ram, 0x04); + uint32_t vaddr = READ_LONG(g_ram, 0x08); + uint32_t filesz = READ_LONG(g_ram, 0x10); + uint32_t memsz = READ_LONG(g_ram, 0x14); + brkbase = brkpos = vaddr + memsz; + + uint32_t vaddroffset = transform_address(vaddr); + transform_address(vaddr + memsz); /* bounds check */ + memset(g_ram+vaddroffset, 0, memsz); + fseek(fd, offset, SEEK_SET); + if (fread(g_ram+vaddroffset, 1, filesz, fd) != filesz) + exit_error("couldn't read program data"); +} + /* The main loop */ int main(int argc, char* argv[]) { @@ -265,8 +305,7 @@ int main(int argc, char* argv[]) if((fhandle = fopen(argv[1], "rb")) == NULL) exit_error("Unable to open %s", argv[1]); - if(fread(g_ram, 1, RAM_TOP - RAM_BASE, fhandle) <= 0) - exit_error("Error reading %s", argv[1]); + load_program(fhandle); // disassemble_program(); @@ -287,9 +326,9 @@ int main(int argc, char* argv[]) */ { - unsigned int sp = INIT_SP; + uint32_t sp = INIT_SP; cpu_write_long(sp -= 4, 0); - unsigned int envp = sp; + uint32_t envp = sp; cpu_write_long(sp -= 4, envp); cpu_write_long(sp -= 4, 0); unsigned long argv = sp;