📄 os2v2acc.c
字号:
{
mad_registers *mr;
mr = GetInPtr( sizeof( write_regs_req ) );
if( Pid != 0 ) {
WriteCPU( &mr->x86.cpu );
WriteRegs( &Buff );
Buff.Cmd = DBG_C_WriteCoRegs;
Buff.Buffer = (ULONG)&mr->x86.fpu;
Buff.Value = DBG_CO_387; /* for 2.0: DBG_CO_387 */
Buff.Len = DBG_LEN_387; /* for 2.0: buffer size */
Buff.Index = 0; /* for 2.0: must be zero */
CallDosDebug( &Buff );
WriteXMMRegs( &mr->x86.xmm );
}
return( 0 );
}
unsigned ReqGet_lib_name( void )
{
get_lib_name_req *acc;
get_lib_name_ret *ret;
char *name;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
if( acc->handle != 0 ) {
CurrModHandle = acc->handle + 1;
}
if( CurrModHandle >= NumModHandles ) {
ret->handle = 0;
return( sizeof( *ret ) );
}
name = GetOutPtr( sizeof( *ret ) );
Buff.Value = ModHandles[CurrModHandle];
DosQueryModuleName( ModHandles[CurrModHandle], 128, name );
ret->handle = CurrModHandle;
return( sizeof( *ret ) + strlen( name ) + 1 );
}
static USHORT GetEXEFlags( char *name )
{
HFILE hdl;
USHORT type;
ULONG new_head;
USHORT exeflags;
if( !FindNewHeader( name, &hdl, &new_head, &type ) ) {
return( 0 );
}
if( type == EXE_NE ) {
SeekRead( hdl, new_head + 0x0c, &exeflags, sizeof( exeflags ) );
} else if( type == EXE_LE || type == EXE_LX ) {
SeekRead( hdl, new_head + 0x10, &exeflags, sizeof( exeflags ) );
} else {
exeflags = 0;
}
DosClose( hdl );
exeflags &= 0x0700;
return( exeflags );
} /* GetEXEFlags */
static bool FindLinearStartAddress( ULONG *pLin, char *name )
{
bool rc;
HFILE hdl;
USHORT type;
ULONG new_head;
ULONG objnum;
USHORT sobjn;
ULONG eip;
USHORT ip;
if( !FindNewHeader( name, &hdl, &new_head, &type ) ) {
return( FALSE );
}
for( ;; ) {
rc = FALSE;
if( type == EXE_NE ) {
if( !SeekRead( hdl, new_head + 0x14, &ip, sizeof( ip ) ) ) {
break;
}
eip = ip;
if( !SeekRead( hdl, new_head + 0x16, &sobjn, sizeof( sobjn ) ) ) {
break;
}
objnum = sobjn;
Is32Bit = FALSE;
} else if( type == EXE_LE || type == EXE_LX ) {
if( !SeekRead( hdl, new_head + 0x1c, &eip, sizeof( eip ) ) ) {
break;
}
if( !SeekRead( hdl, new_head + 0x18, &objnum, sizeof( objnum ) ) ) {
break;
}
Is32Bit = TRUE;
} else {
break;
}
Buff.Cmd = DBG_C_NumToAddr;
Buff.Value = objnum;
Buff.MTE = ModHandles[0];
CallDosDebug( &Buff );
if( Buff.Cmd != DBG_N_Success ) {
break;
}
*pLin = eip + Buff.Addr;
Buff.MTE = ModHandles[0];
rc = TRUE;
break;
}
DosClose( hdl );
return( rc );
} /* FindLinearStartAddress */
static BOOL ExecuteUntilLinearAddressHit( ULONG lin )
{
byte breakpnt = 0xCC;
BOOL rc = TRUE;
ReadLinear( &saved_splice_bp, lin, sizeof( byte ) );
WriteLinear( &breakpnt, lin, sizeof( byte ) );
splice_bp_set = TRUE;
splice_bp_lin_addr = lin;
do {
ExceptNum = 0;
DebugExecute( &Buff, DBG_C_Go, TRUE );
if( ExceptNum == 0 ) {
rc = TRUE; // DLL loaded
/* Breaking on DLL load means that this routine does not
* necessarily stop when the linear address is truly hit;
* this seemingly strange behaviour is desirable if we
* want to debug startup code of DLLs (and we do) - we have
* to stop program execution before DLLs are all loaded!
*/
break;
}
if( ExceptNum != XCPT_BREAKPOINT ) {
rc = FALSE;
break;
}
} while( ExceptLinear != lin );
return( rc );
}
void AppSession( void )
{
if( !IsPMDebugger() )
DosSelectSession( SID );
}
void DebugSession( void )
{
if( !IsPMDebugger() )
DosSelectSession( 0 );
}
static unsigned StartProcess( const char *exe_name, char *parms )
{
STARTDATA start;
PTIB ptib;
PPIB ppib;
char appname[CCHMAXPATH];
unsigned rc;
start.Length = offsetof( STARTDATA, IconFile ); /* default for the rest */
start.Related = 1;
start.FgBg = !Remote;
start.TraceOpt = 1;
strcpy( appname, TRP_The_WATCOM_Debugger );
strcat( appname, ": " );
strcat( appname, exe_name );
start.PgmTitle = (PSZ)appname;
start.PgmName = UtilBuff;
start.PgmInputs = parms;
start.TermQ = 0;
/* We need to inherit from parent to get open file handles etc. */
start.InheritOpt = SSF_INHERTOPT_PARENT;
/* We want debugger's (debugger's parent really) environment */
DosGetInfoBlocks( &ptib, &ppib );
start.Environment = ppib->pib_pchenv;
rc = 0;
if( GetEXEFlags( UtilBuff ) == EXE_IS_PM ) {
if( TypeProcess == SSF_TYPE_WINDOWABLEVIO ) {
rc = ERROR_NOT_IN_WINDOW;
} else {
start.SessionType = SSF_TYPE_PM;
if( !IsPMDebugger() )
StartPMHelp();
}
} else if( TypeProcess == PT_WINDOWABLEVIO || TypeProcess == PT_PM ) {
start.SessionType = SSF_TYPE_WINDOWABLEVIO;
} else if( TypeProcess == PT_FULLSCREEN ) {
start.SessionType = SSF_TYPE_FULLSCREEN;
}
if( rc == 0 ) {
rc = DosStartSession( (void *)&start, &SID, &Pid );
}
if( rc == ERROR_SMG_START_IN_BACKGROUND ) {
rc = 0;
}
return( rc );
}
unsigned ReqProg_load( void )
{
char *parms;
char *end;
char *src;
char *prog;
char *endsrc;
char exe_name[CCHMAXPATH];
ULONG startLinear;
prog_load_ret *ret;
int attach_pid;
LastMTE = 0;
ExceptNum = -1;
ret = GetOutPtr(0);
AtEnd = FALSE;
TaskFS = 0;
attach_pid = -1;
src = prog = GetInPtr( sizeof( prog_load_req ) );
// See if a PID was specified; if so, we will be attaching to
// an existing process, not loading a new one. The PID may
// be specified either as "#<hex pid>" or "<decimal pid>".
if( *src == '#' ) {
src++;
attach_pid = strtoul( src, &endsrc, 16 );
if( attach_pid == 0 )
attach_pid = -1;
// strcpy( buff, endsrc );
} else {
while( *src ) {
if( !isdigit( *src ) ) {
break;
}
src++;
}
if( *src == 0 && src != prog ) {
attach_pid = atoi( prog );
}
}
/* If PID was not specified, start the debuggee process */
if( attach_pid == -1 ) {
isAttached = FALSE;
if( FindFilePath( prog, exe_name, OS2ExtList ) != 0 ) {
exe_name[0] = '\0';
}
parms = AddDriveAndPath( exe_name, UtilBuff );
while( *prog != '\0' )
++prog;
++prog;
end = (char *)GetInPtr( GetTotalSize() - 1 ) + 1;
MergeArgvArray( prog, parms, end - prog );
ret->err = StartProcess( exe_name, parms );
} else {
isAttached = TRUE;
Buff.Addr = 0; // Sever connection
Buff.Pid = attach_pid;
Buff.Tid = 0;
Buff.Cmd = DBG_C_Attach;
Buff.Value = DBG_L_386;
CallDosDebug( &Buff );
if( Buff.Cmd == DBG_N_Success ) {
Pid = attach_pid;
ret->err = 0;
} else {
ret->err = Buff.Value;
}
}
if( ret->err != 0 ) {
Pid = 0;
/* may need to do this
ret->task_id = Pid;
ret->thread = 1;
ret->flags = LD_FLAG_IS_PROT;
*/
} else {
ret->task_id = Pid;
ret->flags = LD_FLAG_IS_PROT;
if( !isAttached ) {
Buff.Pid = Pid;
Buff.Tid = 0;
Buff.Cmd = DBG_C_Connect;
Buff.Value = DBG_L_386;
CallDosDebug( &Buff );
}
else {
ret->flags |= LD_FLAG_IS_STARTED;
// TODO: figure out if 32-bit process
Is32Bit = TRUE;
}
Buff.Pid = Pid;
Buff.Tid = 1;
if( !isAttached ) {
DebugExecute( &Buff, DBG_C_Stop, FALSE );
if( Buff.Cmd != DBG_N_Success ) {
ret->err = 14; /* can't load */
return( sizeof( *ret ) );
}
}
ReadRegs( &Buff );
CanExecTask = FALSE;
splice_bp_set = FALSE;
splice_bp_lin_addr = 0;
if( isAttached ) {
} else {
if( FindLinearStartAddress( &startLinear, UtilBuff ) ) {
CanExecTask = ExecuteUntilLinearAddressHit( startLinear );
ReadRegs( &Buff );
}
}
/* Splice our helper DLL into debuggee's context */
if( CanExecTask ) {
uDB_t save;
save.Pid = Pid;
save.Tid = 1;
ReadRegs( &save );
if( !CausePgmToLoadHelperDLL( startLinear ) ) {
CanExecTask = FALSE;
// Note - the breakpoint is still set; we'll likely hit
// it later
} else {
// Remove breakpoint
WriteLinear( &saved_splice_bp, startLinear, sizeof( byte ) );
splice_bp_set = FALSE;
splice_bp_lin_addr = 0;
}
WriteRegs( &save );
}
Buff.Pid = Pid;
Buff.Tid = 1;
ReadRegs( &Buff );
TaskFS = Buff.FS;
}
if( Is32Bit ) {
ret->flags |= LD_FLAG_IS_32;
}
ret->flags |= LD_FLAG_HAVE_RUNTIME_DLLS;
ret->mod_handle = 0;
CurrModHandle = 1;
return( sizeof( *ret ) );
}
unsigned ReqProg_kill( void )
{
prog_kill_ret *ret;
ret = GetOutPtr( 0 );
SaveStdIn = NIL_DOS_HANDLE;
SaveStdOut = NIL_DOS_HANDLE;
if( Pid != 0 ) {
if( isAttached )
Buff.Cmd = DBG_C_Detach;
else
Buff.Cmd = DBG_C_Term;
Buff.Pid = Pid;
CallDosDebug( &Buff );
}
NumModHandles = 0;
CurrModHandle = 1;
Pid = 0;
ret->err = 0;
DosSleep( 100 ); // Without this, it seems that restarts happen too fast
// and we end up running a 2nd instance of a dead task
// or some such sillyness. I don't really know, but
// this DosSleep avoids problems when restarting a PM app
// ( ... Yes, this is a Hail Mary ... )
StopPMHelp();
return( sizeof( *ret ) );
}
unsigned ReqSet_break( void )
{
byte ch;
set_break_req *acc;
set_break_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ReadBuffer( &ch, acc->break_addr.segment, acc->break_addr.offset, sizeof( byte ) );
ret->old = ch;
ch = 0xCC;
WriteBuffer( &ch, acc->break_addr.segment, acc->break_addr.offset, sizeof( byte ) );
return( sizeof( *ret ) );
}
unsigned ReqClear_break( void )
{
clear_break_req *acc;
byte ch;
acc = GetInPtr( 0 );
ch = acc->old;
WriteBuffer( &ch, acc->break_addr.segment, acc->break_addr.offset, sizeof( byte ) );
return( 0 );
}
unsigned ReqSet_watch( void )
{
set_watch_req *acc;
set_watch_ret *ret;
dword buff;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ret->err = 1;
if( WatchCount < MAX_WP ) { // nyi - artificial limit (32 should be lots)
WatchPoints[WatchCount].addr.segment = acc->watch_addr.segment;
WatchPoints[WatchCount].addr.offset = acc->watch_addr.offset;
WatchPoints[WatchCount].len = acc->size;
ReadBuffer( (char *)&buff, acc->watch_addr.segment,
acc->watch_addr.offset, sizeof( dword ) );
WatchPoints[WatchCount].value = buff;
DebugRegsNeeded += (acc->watch_addr.offset & (acc->size - 1)) ? 2 : 1;
ret->err = 0;
++WatchCount;
}
ret->multiplier = 50000;
if( ret->err == 0 && DebugRegsNeeded <= 4 ) {
ret->multiplier |= USING_DEBUG_REG;
}
return( sizeof( *ret ) );
}
unsigned ReqClear_watch( void )
{
clear_watch_req *acc;
watch *dst;
watch *src;
int i;
acc = GetInPtr( 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -