📄 linuxacc.c
字号:
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 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 );
}
typedef void (*sighandler_t)(int);
static sighandler_t setsig( int sig, sighandler_t handler )
{
struct sigaction sa, old_sa;
sa.sa_flags = SA_RESTART;
sa.sa_handler = handler;
sigaction( sig, &sa, &old_sa );
return old_sa.sa_handler;
}
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 ) );
}
unsigned ReqRedirect_stdout( void )
{
redirect_stdout_ret *ret;
ret = GetOutPtr( 0 );
ret->err = 1;
return( sizeof( *ret ) );
}
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 );
}
unsigned ReqGet_message_text( void )
{
get_message_text_ret *ret;
char *err_txt;
ret = GetOutPtr( 0 );
err_txt = GetOutPtr( sizeof( *ret ) );
if( last_sig == -1 ) {
err_txt[0] = '\0';
} else if( last_sig > (sizeof( ExceptionMsgs ) / sizeof( char * ) - 1) ) {
strcpy( err_txt, TRP_EXC_unknown );
} else {
strcpy( err_txt, ExceptionMsgs[ last_sig ] );
last_sig = -1;
ret->flags = MSG_NEWLINE | MSG_ERROR;
}
return( sizeof( *ret ) + strlen( err_txt ) + 1 );
}
unsigned ReqAddr_info( void )
{
addr_info_req *acc;
addr_info_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ret->is_32 = TRUE;
return( sizeof( *ret ) );
}
trap_version TRAPENTRY TrapInit( char *parm, char *err, bool remote )
{
trap_version ver;
parm = parm;
remote = remote;
err[0] = '\0'; /* all ok */
ver.major = TRAP_MAJOR_VERSION;
ver.minor = TRAP_MINOR_VERSION;
ver.remote = FALSE;
OrigPGrp = getpgrp();
return( ver );
}
void TRAPENTRY TrapFini()
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -