static unsigned DoAWrite( unsigned req, sys_handle hdl, void *ptr, unsigned len ) { mx_entry in[2]; mx_entry out[1]; union { file_write_req file; file_write_console_req con; } acc; file_write_ret ret; SUPP_FILE_SERVICE( acc.file, req ); if( req == REQ_FILE_WRITE_CONSOLE ) { in[0].len = sizeof( acc.con ); } else { acc.file.handle = hdl; CONV_LE_32( acc.file.handle ); in[0].len = sizeof( acc.file ); } in[0].ptr = &acc; in[1].ptr = ptr; in[1].len = len; out[0].ptr = &ret; out[0].len = sizeof( ret ); TrapAccess( 2, &in, 1, &out ); CONV_LE_32( ret.err ); CONV_LE_16( ret.len ); if( ret.err != 0 ) { StashErrCode( ret.err, OP_REMOTE ); return( ERR_RETURN ); } else { return( ret.len ); } }
unsigned long RemoteSeek( sys_handle hdl, unsigned long pos, unsigned method ) { file_seek_req acc; file_seek_ret ret; int locfile; if( SuppFileId == 0 ) return( 0 ); /* Seek on local copy too (if available) */ locfile = GetCachedHandle( hdl ); if( locfile != -1 ) { lseek( locfile, pos, method ); } SUPP_FILE_SERVICE( acc, REQ_FILE_SEEK ); acc.handle = hdl; /* Magic again! The seek mode mapped exactly to our definition! */ acc.mode = method; acc.pos = pos; CONV_LE_32( acc.handle ); CONV_LE_32( acc.pos ); TrapSimpAccess( sizeof( acc ), &acc, sizeof( ret ), &ret ); CONV_LE_32( ret.pos ); CONV_LE_32( ret.err ); if( ret.err != 0 ) { StashErrCode( ret.err, OP_REMOTE ); return( -1UL ); } else { return( ret.pos ); } }
static unsigned DoRead( sys_handle hdl, void *ptr, unsigned len ) { mx_entry in[1]; mx_entry out[2]; file_read_req acc; file_read_ret ret; unsigned got; SUPP_FILE_SERVICE( acc, REQ_FILE_READ ); acc.handle = hdl; acc.len = len; in[0].ptr = &acc; in[0].len = sizeof( acc ); out[0].ptr = &ret; out[0].len = sizeof( ret ); out[1].ptr = ptr; out[1].len = len; CONV_LE_32( acc.handle ); CONV_LE_16( acc.len ); got = TrapAccess( 1, &in, 2, &out ); CONV_LE_32( ret.err ); if( ret.err != 0 ) { StashErrCode( ret.err, OP_REMOTE ); return( ERR_RETURN ); } else { return( got - sizeof( ret ) ); } }
sys_handle RemoteOpen( char *name, open_access mode ) { mx_entry in[2]; mx_entry out[1]; file_open_req acc; file_open_ret ret; int locfile; if( SuppFileId == 0 ) return( NIL_SYS_HANDLE ); SUPP_FILE_SERVICE( acc, REQ_FILE_OPEN ); acc.mode = 0; if( mode & OP_READ ) acc.mode |= TF_READ; if( mode & OP_WRITE ) acc.mode |= TF_WRITE; if( mode & OP_CREATE ) { acc.mode |= TF_CREATE; if( mode & OP_EXEC ) acc.mode |= TF_EXEC; } in[0].ptr = &acc; in[0].len = sizeof( acc ); in[1].ptr = name; in[1].len = strlen( name ) + 1; out[0].ptr = &ret; out[0].len = sizeof( ret ); TrapAccess( 2, &in, 1, &out ); CONV_LE_32( ret.err ); CONV_LE_32( ret.handle ); if( ret.err != 0 ) { StashErrCode( ret.err, OP_REMOTE ); return( NIL_SYS_HANDLE ); } else { /* See if the file is available locally. If so, open it here as * well as on the remote machine. */ // TODO: check if remote file is the same! #ifdef LOGGING fprintf( logf, "Trying to open local copy of remote file (remote handle %d)\n", ret.handle ); fprintf( logf, "%s\n", name ); #endif if( (locfile = open(name, O_RDONLY | O_BINARY, 0 )) != -1 ) { if(AddCachedHandle( locfile, ret.handle ) != 0 ) close( locfile ); #ifdef LOGGING fprintf(logf, "Success\n", name); #endif } return( ret.handle ); } }
static void fix_rel_byte_order( elf_file_handle elf_file_hnd, Elf32_Rel *e_rel ) { // note that one of the branches will always get compiled out, // depending on host endianness if( elf_file_hnd->flags & ORL_FILE_FLAG_BIG_ENDIAN ) { CONV_BE_32( e_rel->r_offset ); CONV_BE_32( e_rel->r_info ); } else { CONV_LE_32( e_rel->r_offset ); CONV_LE_32( e_rel->r_info ); } }
trap_retval ReqFile_write( void ) { file_write_req *acc; file_write_ret *ret; acc = GetInPtr( 0 ); CONV_LE_32( acc->handle ); ret = GetOutPtr( 0 ); ret->len = DoWrite( acc->handle, GetInPtr( sizeof( *acc ) ), GetTotalSize() - sizeof( *acc ) ); ret->err = errno; CONV_LE_32( ret->err ); CONV_LE_16( ret->len ); return( sizeof( *ret ) ); }
static void fix_sym_byte_order( elf_file_handle elf_file_hnd, Elf32_Sym *e_sym ) { // note that one of the branches will always get compiled out, // depending on host endianness if( elf_file_hnd->flags & ORL_FILE_FLAG_BIG_ENDIAN ) { CONV_BE_32( e_sym->st_name ); CONV_BE_32( e_sym->st_value ); CONV_BE_32( e_sym->st_size ); CONV_BE_16( e_sym->st_shndx ); } else { CONV_LE_32( e_sym->st_name ); CONV_LE_32( e_sym->st_value ); CONV_LE_32( e_sym->st_size ); CONV_LE_16( e_sym->st_shndx ); } }
unsigned ReqFile_string_to_fullpath( void ) { file_string_to_fullpath_req *acc; file_string_to_fullpath_ret *ret; int exe; int len; char *name; char *fullname; pid_t pidd; pidd = 0; acc = GetInPtr( 0 ); name = GetInPtr( sizeof( *acc ) ); ret = GetOutPtr( 0 ); fullname = GetOutPtr( sizeof( *ret ) ); exe = ( acc->file_type == TF_TYPE_EXE ) ? TRUE : FALSE; if( exe ) { pidd = RunningProc( name, &name ); } if( pidd != 0 ) { len = GetExeNameFromPid( pidd, fullname, PATH_MAX ); } else { len = FindFilePath( exe, name, fullname ); } if( len == 0 ) { ret->err = ENOENT; /* File not found */ } else { ret->err = 0; } CONV_LE_32( ret->err ); return( sizeof( *ret ) + len + 1 ); }
trap_retval ReqFile_close( void ) { file_close_req *acc; file_close_ret *ret; acc = GetInPtr( 0 ); CONV_LE_32( acc->handle ); ret = GetOutPtr( 0 ); if( close( acc->handle ) != -1 ) { errno = 0; ret->err = 0; } else { ret->err = errno; } CONV_LE_32( ret->err ); return( sizeof( *ret ) ); }
unsigned MakeAsyncRun( bool single ) { async_go_req acc; async_go_ret ret; addr_ptr tmp; if( SuppAsyncId == 0 ) return( 0 ); acc.supp.core_req = REQ_PERFORM_SUPPLEMENTARY_SERVICE; acc.supp.id = SuppAsyncId; if( single ) acc.req = REQ_ASYNC_STEP; else acc.req = REQ_ASYNC_GO; OnAnotherThreadSimpAccess( sizeof( acc ), &acc, sizeof( ret ), &ret ); CONV_LE_16( ret.conditions ); if( ret.conditions & COND_RUNNING ) { ret.stack_pointer.offset = 0; ret.stack_pointer.segment = 0; ret.program_counter.offset = 0; ret.program_counter.segment = 0; } else { CONV_LE_32( ret.stack_pointer.offset ); CONV_LE_16( ret.stack_pointer.segment ); CONV_LE_32( ret.program_counter.offset ); CONV_LE_16( ret.program_counter.segment ); if( ret.conditions & COND_CONFIG ) { GetSysConfig(); CheckMADChange(); } DbgRegs->mad = SysConfig.mad; /* Use 'tmp' because of alignment problems */ tmp = ret.stack_pointer; MADRegSpecialSet( MSR_SP, &DbgRegs->mr, &tmp ); tmp = ret.program_counter; MADRegSpecialSet( MSR_IP, &DbgRegs->mr, &tmp ); if( ret.conditions & COND_THREAD ) { DbgRegs->tid = RemoteSetThread( 0 ); } } return( ret.conditions ); }
trap_retval ReqFile_seek( void ) { file_seek_req *acc; file_seek_ret *ret; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); ret->pos = lseek( acc->handle, acc->pos, acc->mode ); if( ret->pos != ((off_t)-1) ) { errno = 0; ret->err = 0; } else { ret->err = errno; } CONV_LE_32( ret->pos ); CONV_LE_32( ret->err ); return( sizeof( *ret ) ); }
unsigned_32 GetLInt( void ) /*************************/ { unsigned_32 dword; dword = *(unsigned_32 *)RecPtr; CONV_LE_32( dword ); RecPtr += 4; return( dword ); }
//NYI: The 'bool executable' should be changed to allow different file types unsigned RemoteStringToFullName( bool executable, char *name, char *res, unsigned res_len ) { mx_entry in[2]; mx_entry out[2]; file_string_to_fullpath_req acc; file_string_to_fullpath_ret ret; handle h; if( SuppFileId == 0 ) { h = LclStringToFullName( name, strlen( name ), res ); if( h == NIL_HANDLE ) return( 0 ); FileClose( h ); return( strlen( res ) ); } #ifdef __NT__ // check whether short filename is necessary switch( SysConfig.os ) { case OS_AUTOCAD: case OS_DOS: case OS_RATIONAL: case OS_PHARLAP: case OS_WINDOWS: // convert long file name to short "DOS" compatible form { char short_filename[MAX_PATH + 1] = ""; GetShortPathNameA( name, short_filename, MAX_PATH ); if( strlen( short_filename ) != 0 ) { strcpy( name, short_filename ); } } break; } #endif SUPP_FILE_SERVICE( acc, REQ_FILE_STRING_TO_FULLPATH ); acc.file_type = ( executable ? TF_TYPE_EXE : TF_TYPE_PRS ); in[0].ptr = &acc; in[0].len = sizeof( acc ); in[1].ptr = name; in[1].len = strlen( name ) + 1; out[0].ptr = &ret; out[0].len = sizeof( ret ); out[1].ptr = res; out[1].len = res_len; TrapAccess( 2, &in, 2, &out ); CONV_LE_32( ret.err ); if( ret.err != 0 ) { *res = NULLCHAR; return( 0 ); } else { return( strlen( res ) ); } }
/* * AccGetLibName - get lib name of current module */ trap_retval ReqGet_lib_name( void ) { get_lib_name_req *acc; get_lib_name_ret *ret; char *name; unsigned i; trap_elen ret_len; acc = GetInPtr( 0 ); CONV_LE_32( acc->mod_handle ); ret = GetOutPtr( 0 ); name = GetOutPtr( sizeof( *ret ) ); ret->mod_handle = 0; ret_len = sizeof( *ret ); for( i = 0; i < ModuleTop; ++i ) { if( moduleInfo[i].newly_unloaded ) { Out( "(newly unloaded) " ); ret->mod_handle = i; *name = '\0'; moduleInfo[i].newly_unloaded = false; ++ret_len; break; } else if( moduleInfo[i].newly_loaded ) { Out( "(newly loaded) " ); ret->mod_handle = i; strcpy( name, moduleInfo[i].filename ); moduleInfo[i].newly_loaded = false; ret_len += strlen( name ) + 1; break; } } Out( "ReqGet_lib_name: in handle " ); OutNum( acc->mod_handle ); Out( " out handle " ); OutNum( ret->mod_handle ); Out( "\n" ); CONV_LE_32( ret->mod_handle ); return( ret_len ); }
unsigned ReqRead_mem( void ) { read_mem_req *acc; unsigned len; acc = GetInPtr( 0 ); CONV_LE_32( acc->mem_addr.offset ); CONV_LE_16( acc->mem_addr.segment ); CONV_LE_16( acc->len ); len = ReadMem( pid, GetOutPtr( 0 ), acc->mem_addr.offset, acc->len ); return( len ); }
trap_retval ReqFile_write_console( void ) { file_write_console_ret *ret; ret = GetOutPtr( 0 ); ret->len = DoWrite( 2, GetInPtr( sizeof( file_write_console_req ) ), GetTotalSize() - sizeof( file_write_console_req ) ); ret->err = errno; CONV_LE_32( ret->err ); CONV_LE_16( ret->len ); return( sizeof( *ret ) ); }
trap_retval ReqFile_read( void ) { unsigned total; unsigned len; char *ptr; size_t curr; ssize_t rv; file_read_req *acc; file_read_ret *ret; acc = GetInPtr( 0 ); CONV_LE_32( acc->handle ); CONV_LE_16( acc->len ); ret = GetOutPtr( 0 ); ptr = GetOutPtr( sizeof( *ret ) ); len = acc->len; total = 0; for( ;; ) { if( len == 0 ) break; curr = len; if( curr > INT_MAX ) curr = INT_MAX; rv = read( acc->handle, ptr, curr ); if( rv < 0 ) { total = -1; break; } total += rv; if( rv != curr ) break; ptr += rv; len -= rv; } if( total == -1 ) { total = 0; } else { errno = 0; } ret->err = errno; CONV_LE_32( ret->err ); return( sizeof( *ret ) + total ); }
trap_retval ReqFile_erase( void ) { file_erase_ret *ret; ret = GetOutPtr( 0 ); if( unlink( (char *)GetInPtr( sizeof( file_erase_req ) ) ) != 0 ) { ret->err = errno; } else { errno = 0; ret->err = 0; } CONV_LE_32( ret->err ); return( sizeof( *ret ) ); }
unsigned RemoteClose( sys_handle hdl ) { file_close_req acc; file_close_ret ret; int locfile; if( SuppFileId == 0 ) return( 0 ); locfile = GetCachedHandle( hdl ); if( locfile != -1 ) { close( locfile ); DelCachedHandle( locfile ); #ifdef LOGGING fprintf( logf, "Closing remote file handle %d\n", hdl ); #endif } SUPP_FILE_SERVICE( acc, REQ_FILE_CLOSE ); acc.handle = hdl; CONV_LE_32( acc.handle ); TrapSimpAccess( sizeof( acc ), &acc, sizeof( ret ), &ret ); CONV_LE_32( ret.err ); return( StashErrCode( ret.err, OP_REMOTE ) ); }
unsigned ReqWrite_mem( void ) { write_mem_req *acc; write_mem_ret *ret; unsigned len; acc = GetInPtr( 0 ); CONV_LE_32( acc->mem_addr.offset ); CONV_LE_16( acc->mem_addr.segment ); ret = GetOutPtr( 0 ); len = GetTotalSize() - sizeof( *acc ); ret->len = WriteMem( pid, GetInPtr( sizeof( *acc ) ), acc->mem_addr.offset, len ); CONV_LE_16( ret->len ); return( sizeof( *ret ) ); }
unsigned ReqClear_break( void ) { clear_break_req *acc; bp_t opcode; acc = GetInPtr( 0 ); CONV_LE_32( acc->break_addr.offset ); CONV_LE_16( acc->break_addr.segment ); opcode = acc->old; WriteMem( pid, &opcode, acc->break_addr.offset, sizeof( opcode ) ); Out( "ReqClear_break at " ); OutNum( acc->break_addr.offset ); Out( " (setting to " ); OutNum( opcode ); Out( ")\n" ); return( 0 ); }
static unsigned_32 GetOffset( void ) /**********************************/ { if( isMS386 ) { unsigned_32 dword; dword = *(unsigned_32 *)RecPtr; CONV_LE_32( dword ); RecPtr += 4; return( dword ); } else { unsigned_16 word; word = *(unsigned_16 *)RecPtr; CONV_LE_16( word ); RecPtr += 2; return( word ); } }
unsigned RemoteErase( char *name ) { mx_entry in[2]; mx_entry out[1]; file_erase_req acc; file_erase_ret ret; if( SuppFileId == 0 ) return( 0 ); SUPP_FILE_SERVICE( acc, REQ_FILE_ERASE ); in[0].ptr = &acc; in[0].len = sizeof( acc ); in[1].ptr = name; in[1].len = strlen( name ) + 1; out[0].ptr = &ret; out[0].len = sizeof( ret ); TrapAccess( 2, &in, 1, &out ); CONV_LE_32( ret.err ); return( StashErrCode( ret.err, OP_REMOTE ) ); }
long RemoteFork( char *cmd, unsigned len ) { mx_entry in[2]; mx_entry out[1]; file_run_cmd_req acc; file_run_cmd_ret ret; if( SuppFileId == 0 ) return( 0 ); SUPP_FILE_SERVICE( acc, REQ_FILE_RUN_CMD ); acc.chk_size = CheckSize; in[0].ptr = &acc; in[0].len = sizeof( acc ); in[1].ptr = cmd; in[1].len = len; out[0].ptr = &ret; out[0].len = sizeof( ret ); TrapAccess( 2, &in, 1, &out ); CONV_LE_32( ret.err ); return( StashErrCode( ret.err, OP_REMOTE ) ); }
unsigned ReqSet_break( void ) { set_break_req *acc; set_break_ret *ret; bp_t opcode; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); CONV_LE_32( acc->break_addr.offset ); CONV_LE_16( acc->break_addr.segment ); ReadMem( pid, &opcode, acc->break_addr.offset, sizeof( opcode ) ); ret->old = opcode; opcode = BRK_POINT; WriteMem( pid, &opcode, acc->break_addr.offset, sizeof( opcode ) ); Out( "ReqSet_break at " ); OutNum( acc->break_addr.offset ); Out( " (was " ); OutNum( ret->old ); Out( ")\n" ); return( sizeof( *ret ) ); }
unsigned ReqProg_kill( void ) { prog_kill_ret *ret; if( pid != 0 && !at_end ) { if( attached ) { ptrace( PTRACE_DETACH, pid, NULL, NULL ); attached = FALSE; } else { int status; ptrace( PTRACE_KILL, pid, NULL, NULL ); waitpid( pid, &status, 0 ); } } DelProcess(); at_end = FALSE; pid = 0; ret = GetOutPtr( 0 ); ret->err = 0; CONV_LE_32( ret->err ); return( sizeof( *ret ) ); }
void WriteLittleEndian32( unsigned_32 num ) { CONV_LE_32( num ); WriteNew( &num, sizeof( num ) ); }
unsigned ReqProg_load( void ) { char **args; char *parms; char *parm_start; int i; char exe_name[PATH_MAX]; char *name; pid_t save_pgrp; prog_load_req *acc; prog_load_ret *ret; unsigned len; int status; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); last_sig = -1; have_rdebug = FALSE; dbg_dyn = NULL; at_end = FALSE; parms = (char *)GetInPtr( sizeof( *acc ) ); parm_start = parms; len = GetTotalSize() - sizeof( *acc ); if( acc->true_argv ) { i = 1; for( ;; ) { if( len == 0 ) break; if( *parms == '\0' ) { i++; } ++parms; --len; } args = alloca( i * sizeof( *args ) ); parms = parm_start; len = GetTotalSize() - sizeof( *acc ); i = 1; for( ;; ) { if( len == 0 ) break; if( *parms == '\0' ) { args[i++] = parms + 1; } ++parms; --len; } args[i - 1] = NULL; } else { while( *parms != '\0' ) { ++parms; --len; } ++parms; --len; i = SplitParms( parms, NULL, len ); args = alloca( (i + 2) * sizeof( *args ) ); args[SplitParms( parms, &args[1], len ) + 1] = NULL; } args[0] = parm_start; attached = TRUE; pid = RunningProc( args[0], &name ); if( pid == 0 || ptrace( PTRACE_ATTACH, pid, NULL, NULL ) == -1 ) { attached = FALSE; args[0] = name; if( FindFilePath( TRUE, args[0], exe_name ) == 0 ) { exe_name[0] = '\0'; } save_pgrp = getpgrp(); setpgid( 0, OrigPGrp ); pid = fork(); if( pid == -1 ) return( 0 ); if( pid == 0 ) { if( ptrace( PTRACE_TRACEME, 0, NULL, NULL ) < 0 ) { exit( 1 ); } execve( exe_name, (const char **)args, (const char **)dbg_environ ); exit( 1 ); /* failsafe */ } setpgid( 0, save_pgrp ); } else if( pid ) { GetExeNameFromPid( pid, exe_name, PATH_MAX ); } ret->flags = 0; ret->mod_handle = 0; if( (pid != -1) && (pid != 0) ) { int status; ret->task_id = pid; ret->flags |= LD_FLAG_IS_PROT | LD_FLAG_IS_32; /* wait until it hits _start (upon execve) or gives us a SIGSTOP (if attached) */ if( waitpid( pid, &status, 0 ) < 0 ) goto fail; if( !WIFSTOPPED( status ) ) goto fail; if( attached ) { ret->flags |= LD_FLAG_IS_STARTED; if( WSTOPSIG( status ) != SIGSTOP ) goto fail; } else { if( WSTOPSIG( status ) != SIGTRAP ) goto fail; } #if defined( MD_x86 ) if( !GetFlatSegs( &flatCS, &flatDS ) ) goto fail; #endif dbg_dyn = GetDebuggeeDynSection( exe_name ); AddProcess(); errno = 0; } ret->err = errno; if( ret->err != 0 ) { pid = 0; } CONV_LE_32( ret->err ); CONV_LE_32( ret->task_id ); CONV_LE_32( ret->mod_handle ); return( sizeof( *ret ) ); fail: if( pid != 0 && pid != -1 ) { if( attached ) { ptrace( PTRACE_DETACH, pid, NULL, NULL ); attached = FALSE; } else { ptrace( PTRACE_KILL, pid, NULL, NULL ); waitpid( pid, &status, 0 ); } } pid = 0; CONV_LE_32( ret->err ); CONV_LE_32( ret->task_id ); CONV_LE_32( ret->mod_handle ); return( 0 ); }
static unsigned ProgRun( int step ) { static int ptrace_sig = 0; static int ld_state = 0; user_regs_struct regs; int status; prog_go_ret *ret; void (*old)(int); int debug_continue; if( pid == 0 ) return( 0 ); ret = GetOutPtr( 0 ); if( at_end ) { ptrace_sig = 0; ret->conditions = COND_TERMINATE; goto end; } /* we only want child-generated SIGINTs now */ do { old = setsig( SIGINT, SIG_IGN ); if( step ) { Out( "PTRACE_SINGLESTEP\n" ); if( ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)ptrace_sig ) == -1 ) perror( "PTRACE_SINGLESTEP" ); } else { Out( "PTRACE_CONT\n" ); if( ptrace( PTRACE_CONT, pid, NULL, (void *)ptrace_sig ) == -1 ) perror( "PTRACE_CONT" ); } waitpid( pid, &status, 0 ); setsig( SIGINT, old ); #if defined( MD_x86 ) ptrace( PTRACE_GETREGS, pid, NULL, ®s ); #elif defined( MD_ppc ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_NIP, NULL ); regs.esp = ptrace( PTRACE_PEEKUSER, pid, REGSIZE * PT_R1, NULL ); #elif defined( MD_mips ) regs.eip = ptrace( PTRACE_PEEKUSER, pid, (void *)PC, NULL ); regs.esp = ptrace( PTRACE_PEEKUSER, pid, (void *)29, NULL ); #endif Out( " eip " ); OutNum( regs.eip ); Out( "\n" ); debug_continue = FALSE; if( WIFSTOPPED( status ) ) { switch( ( ptrace_sig = WSTOPSIG( status ) ) ) { case SIGSEGV: case SIGILL: case SIGFPE: case SIGABRT: case SIGBUS: case SIGQUIT: case SIGSYS: last_sig = ptrace_sig; ret->conditions = COND_EXCEPTION; ptrace_sig = 0; break; case SIGINT: ret->conditions = COND_USER; ptrace_sig = 0; break; case SIGTRAP: ret->conditions = step ? COND_TRACE : COND_BREAK; Out( "sigtrap\n" ); ptrace_sig = 0; break; default: /* For signals that we do not wish to handle, we need * to continue the debuggee until we get a signal * that we need to handle */ Out( "Unknown signal " ); OutNum( ptrace_sig ); Out( "\n" ); debug_continue = TRUE; break; } } else if( WIFEXITED( status ) ) { Out( "WIFEXITED\n" ); at_end = TRUE; ret->conditions = COND_TERMINATE; ptrace_sig = 0; goto end; } } while( debug_continue ); if( ret->conditions == COND_BREAK ) { #if defined( MD_x86 ) if( regs.eip == rdebug.r_brk + sizeof( old_ld_bp ) ) { #elif defined( MD_ppc ) || defined( MD_mips ) if( regs.eip == rdebug.r_brk ) { #endif int psig = 0; void (*oldsig)(int); bp_t opcode = BRK_POINT; /* The dynamic linker breakpoint was hit, meaning that * libraries are being loaded or unloaded. This gets a bit * tricky because we must restore the original code that was * at the breakpoint and execute it, but we still want to * keep the breakpoint. */ WriteMem( pid, &old_ld_bp, rdebug.r_brk, sizeof( old_ld_bp ) ); ReadMem( pid, &rdebug, (addr48_off)dbg_rdebug, sizeof( rdebug ) ); Out( "ld breakpoint hit, state is " ); switch( rdebug.r_state ) { case RT_ADD: Out( "RT_ADD\n" ); ld_state = RT_ADD; AddOneLib( rdebug.r_map ); break; case RT_DELETE: Out( "RT_DELETE\n" ); ld_state = RT_DELETE; break; case RT_CONSISTENT: Out( "RT_CONSISTENT\n" ); if( ld_state == RT_DELETE ) DelOneLib( rdebug.r_map ); ld_state = RT_CONSISTENT; break; default: Out( "error!\n" ); break; } regs.orig_eax = -1; #if defined( MD_x86 ) regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif oldsig = setsig( SIGINT, SIG_IGN ); ptrace( PTRACE_SINGLESTEP, pid, NULL, (void *)psig ); waitpid( pid, &status, 0 ); setsig( SIGINT, oldsig ); WriteMem( pid, &opcode, rdebug.r_brk, sizeof( old_ld_bp ) ); ret->conditions = COND_LIBRARIES; } else { #if defined( MD_x86 ) Out( "decrease eip(sigtrap)\n" ); regs.orig_eax = -1; regs.eip--; ptrace( PTRACE_SETREGS, pid, NULL, ®s ); #endif } } orig_eax = regs.orig_eax; last_eip = regs.eip; ret->program_counter.offset = regs.eip; ret->program_counter.segment = regs.cs; ret->stack_pointer.offset = regs.esp; ret->stack_pointer.segment = regs.ss; ret->conditions |= COND_CONFIG; /* If debuggee has dynamic section, try getting the r_debug struct * every time the debuggee stops. The r_debug data may not be available * immediately after the debuggee process loads. */ if( !have_rdebug && (dbg_dyn != NULL) ) { if( Get_ld_info( pid, dbg_dyn, &rdebug, &dbg_rdebug ) ) { bp_t opcode; AddInitialLibs( rdebug.r_map ); have_rdebug = TRUE; ret->conditions |= COND_LIBRARIES; /* Set a breakpoint in dynamic linker. That way we can be * informed on dynamic library load/unload events. */ ReadMem( pid, &old_ld_bp, rdebug.r_brk, sizeof( old_ld_bp ) ); Out( "Setting ld breakpoint at " ); OutNum( rdebug.r_brk ); Out( " old opcode was " ); OutNum( old_ld_bp ); Out( "\n" ); opcode = BRK_POINT; WriteMem( pid, &opcode, rdebug.r_brk, sizeof( opcode ) ); } } end: CONV_LE_32( ret->stack_pointer.offset ); CONV_LE_16( ret->stack_pointer.segment ); CONV_LE_32( ret->program_counter.offset ); CONV_LE_16( ret->program_counter.segment ); CONV_LE_16( ret->conditions ); return( sizeof( *ret ) ); } unsigned ReqProg_step( void ) { return( ProgRun( TRUE ) ); } unsigned ReqProg_go( void ) { return( ProgRun( FALSE ) ); } unsigned ReqRedirect_stdin( void ) { redirect_stdin_ret *ret; ret = GetOutPtr( 0 ); ret->err = 1; return( sizeof( *ret ) ); }
/* * AccMapAddr - map address in image from link-time virtual address to * actual linear address as loaded in memory. For executables, this will * in effect return the address unchanged (image base 0x08048100 equals * linear 0x08048100), for shared libs this will typically add the offset * from zero (link time VA) to actual load base. */ trap_retval ReqMap_addr( void ) { map_addr_req *acc; map_addr_ret *ret; unsigned long val; lib_load_info *lli; // Note: Info about the process address space is stored in the user register // for GDB, so we can use that to find out what we need to convert these // values in here... acc = GetInPtr( 0 ); CONV_LE_32( acc->in_addr.offset ); CONV_LE_16( acc->in_addr.segment ); CONV_LE_32( acc->mod_handle ); ret = GetOutPtr( 0 ); ret->lo_bound = 0; ret->hi_bound = ~(addr_off)0; errno = 0; if( (val = ptrace( PTRACE_PEEKUSER, pid, (void *)(offsetof( user_struct, start_code )), 0 )) == -1 ) { if( errno ) { Out( "ReqMap_addr: first PTRACE_PEEKUSER failed!\n" ); val = 0; } } #ifdef __MIPS__ // Hack for MIPS - the above call seems to be failing but isn't returning // an error; it's possible that the call just isn't valid. val = 0; #endif ret->out_addr.offset = acc->in_addr.offset + val; if( acc->mod_handle > ModuleTop ) { Out( "ReqMap_addr: Invalid handle passed!\n" ); return( sizeof( *ret ) ); } else { lli = &moduleInfo[acc->mod_handle]; } Out( "ReqMap_addr: addr " ); OutNum( acc->in_addr.segment ); Out( ":" ); OutNum( acc->in_addr.offset ); Out( " in module " ); OutNum( acc->mod_handle ); if( acc->in_addr.segment == MAP_FLAT_DATA_SELECTOR || acc->in_addr.segment == flatDS ) { if( (val = ptrace( PTRACE_PEEKUSER, pid, (void *)offsetof( user_struct, u_tsize ), 0 )) == -1 ) { if( errno ) { Out( "ReqMap_addr: second PTRACE_PEEKUSER failed!\n" ); val = 0; } } ret->out_addr.offset += val; ret->out_addr.segment = flatDS; } else { ret->out_addr.segment = flatCS; } ret->out_addr.offset += lli->offset; Out( " to " ); OutNum( ret->out_addr.offset ); Out( "\n" ); CONV_LE_32( ret->out_addr.offset ); CONV_LE_16( ret->out_addr.segment ); CONV_LE_32( ret->lo_bound ); CONV_LE_32( ret->hi_bound ); return( sizeof( *ret ) ); }