📄 linuxacc.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Main Linux specific debugger trap file OS access module.
*
****************************************************************************/
/* TODO:
* complete watchpoints
* combine global into a struct (like the QNX trap file) to make it a little
clearer what is global and what not.
* implement thread support
* implement corefile post-mortem support
*/
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include "trpimp.h"
#include "trperr.h"
#include "mad.h"
#include "madregs.h"
#include "exeelf.h"
#include "linuxcomm.h"
u_short flatCS;
u_short flatDS;
pid_t pid;
long orig_eax;
long last_eip;
static pid_t OrigPGrp;
static int attached;
static int last_sig;
static int at_end;
static struct r_debug rdebug; /* Copy of debuggee's r_debug (if present) */
static struct r_debug *dbg_rdebug; /* Ptr to r_debug in debuggee's space */
static int have_rdebug; /* Flag indicating valid r_debug */
static Elf32_Dyn *dbg_dyn; /* VA of debuggee's dynamic section (if present) */
static bp_t old_ld_bp;
unsigned ReqChecksum_mem( void )
{
char buf[256];
addr_off offv;
u_short length;
u_short size;
int i;
u_short amount;
u_long sum;
checksum_mem_req *acc;
checksum_mem_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
sum = 0;
if( pid != 0 ) {
length = acc->len;
offv = acc->in_addr.offset;
for( ;; ) {
if( length == 0 )
break;
size = (length > sizeof( buf )) ? sizeof( buf ) : length;
amount = ReadMem( pid, buf, offv, size );
for( i = amount; i != 0; --i )
sum += buf[ i - 1 ];
offv += amount;
length -= amount;
if( amount != size ) break;
}
}
ret->result = sum;
return( sizeof( *ret ) );
}
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 );
}
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 ) );
}
#if defined( MD_x86 )
static int GetFlatSegs( u_short *cs, u_short *ds )
{
user_regs_struct regs;
if( ptrace( PTRACE_GETREGS, pid, NULL, ®s ) == 0 ) {
*cs = regs.cs;
*ds = regs.ds;
return( TRUE );
}
return( FALSE );
}
#endif
static pid_t RunningProc( char *name, char **name_ret )
{
pid_t pidd;
char ch;
char *start;
start = name;
for( ;; ) {
ch = *name;
if( ch != ' ' && ch != '\t' ) break;
++name;
}
if( name_ret != NULL ) *name_ret = name;
pidd = 0;
for( ;; ) {
if( *name < '0' || *name > '9' ) break;
pidd = (pidd * 10) + (*name - '0');
++name;
}
if( *name != '\0') return( 0 );
return( pidd );
}
static int GetExeNameFromPid( pid_t pid, char *buffer, int max_len )
{
char procfile[24];
int len;
sprintf( procfile, "/proc/%d/exe", pid );
len = readlink( procfile, buffer, max_len );
if( len < 0 )
len = 0;
buffer[len] = '\0';
return( len );
}
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 );
}
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 ) );
}
unsigned ReqSet_break( void )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -