summaryrefslogtreecommitdiff
path: root/crenshaw
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2018-08-12 21:55:28 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2018-08-12 21:55:28 +0200
commite2a3a2b217e8dcc1e3f4ec67c00a7a98d07fa698 (patch)
treee9b44b9e2fbc8e53c743165561ebb76f9a5d4c1f /crenshaw
parent8a4cfc2e63cc21328dbffd11d1a0455d806d48ef (diff)
downloadcompilertests-e2a3a2b217e8dcc1e3f4ec67c00a7a98d07fa698.tar.gz
compilertests-e2a3a2b217e8dcc1e3f4ec67c00a7a98d07fa698.tar.bz2
crenshaw: small emulator for testing with capstone and unicorn
Diffstat (limited to 'crenshaw')
-rw-r--r--crenshaw/README22
-rwxr-xr-xcrenshaw/build.sh11
-rw-r--r--crenshaw/emul.c173
-rw-r--r--crenshaw/main.pas13
-rw-r--r--crenshaw/test.prog1
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
-