diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2018-08-12 21:55:28 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2018-08-12 21:55:28 +0200 |
commit | e2a3a2b217e8dcc1e3f4ec67c00a7a98d07fa698 (patch) | |
tree | e9b44b9e2fbc8e53c743165561ebb76f9a5d4c1f /crenshaw | |
parent | 8a4cfc2e63cc21328dbffd11d1a0455d806d48ef (diff) | |
download | compilertests-e2a3a2b217e8dcc1e3f4ec67c00a7a98d07fa698.tar.gz compilertests-e2a3a2b217e8dcc1e3f4ec67c00a7a98d07fa698.tar.bz2 |
crenshaw: small emulator for testing with capstone and unicorn
Diffstat (limited to 'crenshaw')
-rw-r--r-- | crenshaw/README | 22 | ||||
-rwxr-xr-x | crenshaw/build.sh | 11 | ||||
-rw-r--r-- | crenshaw/emul.c | 173 | ||||
-rw-r--r-- | crenshaw/main.pas | 13 | ||||
-rw-r--r-- | crenshaw/test.prog | 1 |
5 files changed, 205 insertions, 15 deletions
diff --git a/crenshaw/README b/crenshaw/README index f95033f..56b01f6 100644 --- a/crenshaw/README +++ b/crenshaw/README @@ -1,15 +1,23 @@ debugging -#gdb ./test -#(gdb) set disassemble-next-line on -#(gdb) display $eax -#(gdb) display $ebx -#(gdb) start -#(gdb) si -#(gdb) info registers +set disassemble-next-line on +display $eax +display $ebx +display $ecx +info registers +start +si + +run in emulator (also for unit testing) + +gcc -Wall -std=c99 -o emul emul.c -lunicorn -pthread links https://en.wikibooks.org/wiki/68000_Assembly https://en.wikipedia.org/wiki/X86_instruction_listings file:///media/sd/compilertests/doc/Intel 80x86 Assembly Language OpCodes.html#div + +https://github.com/Rewzilla/asemu.git +http://www.unicorn-engine.org/ +http://www.capstone-engine.org/ diff --git a/crenshaw/build.sh b/crenshaw/build.sh index 5ef9938..5373e01 100755 --- a/crenshaw/build.sh +++ b/crenshaw/build.sh @@ -1,7 +1,10 @@ fpc main.pas ./main < test.prog > test.asm -nasm -f elf32 test.asm -gcc -m32 -march=i486 -ffreestanding -o test test.o -objcopy -O binary --only-section=.text test test.bin +nasm -o test.bin -f bin test.asm +#nasm -f elf32 test.asm +#gcc -m32 -march=i486 -ffreestanding -o test test.o +#objcopy -O binary --only-section=.text test test.bin ndisasm -b32 test.bin -./test +gcc -g -Wall -std=c99 -o emul emul.c -lunicorn -lcapstone -pthread +./emul test.bin +#./test diff --git a/crenshaw/emul.c b/crenshaw/emul.c new file mode 100644 index 0000000..2cdc04c --- /dev/null +++ b/crenshaw/emul.c @@ -0,0 +1,173 @@ +#include <unicorn/unicorn.h> +#include <capstone/capstone.h> + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <stdbool.h> + +#define PAGE_SIZE 4 * 1024 * 1024 +#define CODE_START 0x1000000 +#define CODE_SIZE PAGE_SIZE +#define STACK_SIZE PAGE_SIZE +#define STACK_START CODE_START + CODE_SIZE + STACK_SIZE + +#define EIP_START CODE_ADDRESS +#define ESP_START STACK_START +#define EBP_START ESP_START + +static void dump_regs( uc_engine *uc ) +{ + int eip; + int esp; + int eax; + int ebx; + int ecx; + + uc_reg_read( uc, UC_X86_REG_EIP, &eip ); + uc_reg_read( uc, UC_X86_REG_ESP, &esp ); + uc_reg_read( uc, UC_X86_REG_EAX, &eax ); + uc_reg_read( uc, UC_X86_REG_EBX, &ebx ); + uc_reg_read( uc, UC_X86_REG_ECX, &ecx ); + + printf( "--\n" ); + printf( "EIP: %08x\n", eip ); + printf( "ESP: %08x\n", esp ); + printf( "EAX: %08x\n", eax ); + printf( "EBX: %08x\n", ebx ); + printf( "ECX: %08x\n", ecx ); +} + +int main( int argc, char *argv[] ) +{ + uc_engine *uc; + uc_err uerr; + char *code; + size_t code_size; + size_t file_size; + FILE *f; + int res; + csh cs; + cs_err cerr; + + uerr = uc_open( UC_ARCH_X86, UC_MODE_32, &uc ); + if( uerr != UC_ERR_OK ) { + fprintf( stderr, "ERROR: failed to call uc_open( ): %s\n", uc_strerror( uerr ) ); + exit( EXIT_FAILURE ); + } + + cerr = cs_open( CS_ARCH_X86, CS_MODE_32, &cs ); + if( cerr != CS_ERR_OK ) { + uc_close( uc ); + fprintf( stderr, "ERROR: failed to call uc_open( ): %s\n", uc_strerror( uerr ) ); + exit( EXIT_FAILURE ); + } + + uerr = uc_mem_map( uc, CODE_START, CODE_SIZE, UC_PROT_ALL ); + if( uerr != UC_ERR_OK ) { + fprintf( stderr, "ERROR: failed to call uc_mem_map( ) for code memory: %s\n", uc_strerror( uerr ) ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + uerr = uc_mem_map( uc, STACK_START - STACK_SIZE, STACK_SIZE, UC_PROT_ALL ); + if( uerr != UC_ERR_OK ) { + fprintf( stderr, "ERROR: failed to call uc_mem_map( ) for stack memory: %s\n", uc_strerror( uerr ) ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + f = fopen( argv[1], "r" ); + if( f == NULL ) { + fprintf( stderr, "ERROR: unable to read file '%s': %s\n", argv[1], strerror( errno ) ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + res = fseek( f, 0, SEEK_END ); + if( res != 0 ) { + fprintf( stderr, "ERROR: unable to seek to end of file '%s': %s\n", argv[1], strerror( errno ) ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + file_size = ftell( f ); + code = (char *)malloc( file_size ); + if( code == NULL ) { + fprintf( stderr, "ERROR: out of memory\n" ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + fseek( f, 0, SEEK_SET ); + if( res != 0 ) { + fprintf( stderr, "ERROR: unable to seek to start of file '%s': %s\n", argv[1], strerror( errno ) ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + code_size = fread( code, 1, file_size, f ); + if( code_size != file_size ) { + fprintf( stderr, "ERROR: could not read complete code file, read only %d bytes instead of %d bytes\n", + code_size, file_size ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + printf( "Read %d bytes of code..\n", code_size ); + + uerr = uc_mem_write( uc, CODE_START, code, code_size ); + if( uerr != UC_ERR_OK ) { + fprintf( stderr, "ERROR: failed to call uc_mem_write( ): %s\n", uc_strerror( uerr ) ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + int addr = CODE_START; + int esp = STACK_START; + uc_reg_write( uc, UC_X86_REG_ESP, &esp ); + + uint64_t address = CODE_START; + cs_insn *instr = cs_malloc( cs ); + bool terminate = false; + + while( !terminate ) { + + if( !cs_disasm_iter( cs, (const uint8_t **)&code, &code_size, &address, instr ) ) { + fprintf( stderr, "ERROR: failed to call cs_disasm_iter( ): %s\n", cs_strerror( cs_errno( cs ) ) ); + cs_close( &cs ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + printf( "0x%08x:\t%s\t\t%s\n", + (uint32_t)instr->address, instr->mnemonic, instr->op_str ); + + uerr = uc_emu_start( uc, addr, CODE_START + CODE_SIZE, 0, 1 ); + if( uerr != UC_ERR_OK ) { + fprintf( stderr, "ERROR: failed to call uc_emu_start( ): %s\n", uc_strerror( uerr ) ); + cs_close( &cs ); + uc_close( uc ); + exit( EXIT_FAILURE ); + } + + int eip; + uc_reg_read( uc, UC_X86_REG_EIP, &eip ); + addr = eip; + address = eip; + + dump_regs( uc ); + + if( strcmp( instr->mnemonic, "hlt" ) == 0 ) { + terminate = true; + } + } + + cs_free( instr ); + cs_close( &cs ); + uc_close( uc ); + + exit( EXIT_SUCCESS ); +} + diff --git a/crenshaw/main.pas b/crenshaw/main.pas index 04a3624..dd49dd1 100644 --- a/crenshaw/main.pas +++ b/crenshaw/main.pas @@ -97,8 +97,9 @@ procedure Divide; begin Match('/'); Factor; - EmitLn('pop ebx'); - EmitLn('div ebx'); + EmitLn('mov ecx,eax'); + EmitLn('pop eax'); + EmitLn('div ecx'); end; procedure Term; @@ -129,6 +130,7 @@ begin; Term; EmitLn('pop ebx'); EmitLn('sub eax, ebx'); + EmitLn('neg eax'); end; procedure Expression; @@ -153,17 +155,22 @@ end; procedure Prologue; begin WriteLn('[bits 32]'); - WriteLn('section .text'); + WriteLn('org 0x1000000'); +{ WriteLn('section .text'); WriteLn('global main'); EmitLabel('main'); EmitLn('push ebp'); EmitLn('mov ebp, esp'); +} end; procedure Epilogue; begin + EmitLn('hlt'); +{ EmitLn('leave'); EmitLn('ret'); +} end; begin diff --git a/crenshaw/test.prog b/crenshaw/test.prog index a1d75c4..c208a59 100644 --- a/crenshaw/test.prog +++ b/crenshaw/test.prog @@ -1,2 +1 @@ (4+4)*3/2-3 - |