summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-09-24 19:07:11 +0000
committerAndreas Baumann <mail@andreasbaumann.cc>2021-09-24 19:07:11 +0000
commit728d58d5cbea121faf26699bca726db2530ae71a (patch)
tree040f87f438ce86b768f2c1b372be70bfb5c40452
parenta595e1f3e9ec47bdc0c9a8a0d7c764516e29e00b (diff)
downloadcompilertests-728d58d5cbea121faf26699bca726db2530ae71a.tar.gz
compilertests-728d58d5cbea121faf26699bca726db2530ae71a.tar.bz2
emul: added INT 0x80 hook for syscall 4 (write) for printint
-rw-r--r--ecomp-c/emul.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/ecomp-c/emul.c b/ecomp-c/emul.c
index f97e787..c1d819f 100644
--- a/ecomp-c/emul.c
+++ b/ecomp-c/emul.c
@@ -105,6 +105,58 @@ static int compute_p( int size )
return p;
}
+static void handle_interrupts( uc_engine *uc, uint32_t interrupt, void *user_data )
+{
+ uint32_t eax, ebx, ecx, edx;
+ bool trace = *((bool *)user_data);
+
+ if( trace ) {
+ printf( "INT %x\n", interrupt );
+ dump_regs( uc );
+ }
+
+ if( interrupt != 0x80 ) {
+ return;
+ }
+
+ uc_reg_read( uc, UC_X86_REG_EAX, &eax );
+ switch( eax ) {
+ case 4: // SYSCALL_WRITE
+ {
+ unsigned char buffer[256];
+ size_t size;
+ uc_err uerr;
+
+ uc_reg_read( uc, UC_X86_REG_EBX, &ebx );
+ if( ebx != 1 ) {
+ fprintf( stderr, "ERROR: failed to call SYSCALL_WRITE on non-stdout (not implemented)\n" );
+ return;
+ }
+
+ uc_reg_read( uc, UC_X86_REG_ECX, &ecx );
+ uc_reg_read( uc, UC_X86_REG_EDX, &edx );
+ size = sizeof( buffer ) - 1;
+ if( edx < sizeof( buffer ) - 1 ) {
+ size = edx;
+ }
+
+ uerr = uc_mem_read( uc, ecx, buffer, size );
+ buffer[size] = '\0';
+ if( uerr != UC_ERR_OK ) {
+ fprintf( stderr, "ERROR: failed to call uc_mem_read( ) in int x080 syscall 4 (SYSCALL_WRITE): %s\n", uc_strerror( uerr ) );
+ dump_regs( uc );
+ exit( EXIT_FAILURE );
+ }
+
+ printf( "%*s", size, buffer );
+ }
+ break;
+
+ default:
+ fprintf( stderr, "WARN: unknown syscall %0x, EAX: %d\n", interrupt, eax );
+ }
+}
+
int main( int argc, char *argv[] )
{
uc_engine *uc;
@@ -355,6 +407,16 @@ int main( int argc, char *argv[] )
if( trace ) {
printf( "Single step execution:\n" );
}
+
+ // hook for emulating syscalls (int 0x80 on the host)
+ uc_hook hook;
+ uerr = uc_hook_add( uc, &hook, UC_HOOK_INTR, handle_interrupts, (void *)&trace, 1, 0 );
+ if( uerr != UC_ERR_OK ) {
+ fprintf( stderr, "ERROR: failed to call uc_hook_add( handle_interrupts ): %s\n", uc_strerror( uerr ) );
+ cs_close( &cs );
+ uc_close( uc );
+ exit( EXIT_FAILURE );
+ }
while( !terminate ) {
@@ -393,7 +455,7 @@ int main( int argc, char *argv[] )
printf( "%s %s\n", instrs[n].mnemonic, instrs[n].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 ) );