📄 accload.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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <ctype.h>
#include <dos.h>
#include "wdebug.h"
#include "stdwin.h"
#include "winacc.h"
#include "getcsip.h"
#define SIG_OFF 0
#define SIG_SIZE 4
#define TINY_ERROR(x) ((signed long)x < 0)
const unsigned short __based(__segname("_CONST")) win386sig[] = { 0xDEAD,0xBEEF };
const unsigned short __based(__segname("_CONST")) win386sig2[] = { 0xBEEF,0xDEAD };
BOOL WasStarted;
typedef struct {
WORD mustbe2;
WORD cmdshow;
} word_struct;
typedef struct
{
WORD wEnvSeg;
LPSTR lpCmdLine;
word_struct *cmdshow;
DWORD reserved;
} lm_parms;
/*
* AccLoadProg
*
* To load a app, we do the following:
*
* Case 1: debugging an existing task
* - Find its current CS:IP.
* - Plant a breakpoint at the current CS:IP
*
* Case 2: starting a task from scratch
* - Look up the start address from the .EXE
* - WinExec the app
* - Wait for the STARTASK notification for the app
* - Plant a breakpoint at its start address
*
* - Wait for the app to hit the breakpoint
* - Check if the app is a 32-bit app (look for "DEADBEEF" in code seg).
* If it is a 32-bit app:
* - Flip the "DEADBEEF" to "BEEFDEAD". If the extender see's the
* "BEEFDEAD", it executes a breakpoint right before it jumps to
* the 32-bit code
* - Let the app run until a breakpoint is hit
* - Trace one instruction. This leaves you at the first instruction
* of the 32-bit code
*/
unsigned ReqProg_load( void )
{
char exe_name[_MAX_PATH];
char drive[_MAX_DRIVE],directory[_MAX_DIR];
char buff[256];
lm_parms loadp;
word_struct cmdshow;
char *parm;
char *src;
char *dst;
char ch;
unsigned a,b;
private_msg pmsg;
char sig[sizeof(DWORD)];
HTASK tid;
DWORD csip;
prog_load_req *acc;
prog_load_ret *ret;
char *end;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ret->flags = LD_FLAG_IS_PROT | LD_FLAG_HAVE_RUNTIME_DLLS;
parm = GetInPtr( sizeof( *acc ) );
/*
* reset flags
*/
OutPos = 0;
WasStarted = FALSE;
LoadingDebugee = TRUE;
Debugging32BitApp = FALSE;
AddAllCurrentModules();
/*
* check for task id
*/
tid = 0;
src = parm;
if( *src == '#' ) {
src++;
tid = (HTASK)strtol( src, NULL, 16 );
} else {
while( *src != 0 ) {
if( !isdigit( *src ) ) {
break;
}
src++;
}
if( *src == 0 && src != parm ) {
tid = (HTASK)atoi( parm );
}
}
if( tid != 0 ) {
csip = GetRealCSIP( tid, &DebugeeModule );
if( csip == 0 ) {
tid = 0;
} else {
DebugeeTask = tid;
StopNewTask.loc.segment = FP_SEG( (LPVOID) csip );
StopNewTask.loc.offset = FP_OFF( (LPVOID) csip );
ReadMem( StopNewTask.loc.segment, StopNewTask.loc.offset,
&StopNewTask.value, 1 );
ch = 0xcc;
WriteMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &ch, 1 );
}
} else {
tid = 0;
}
/*
* get the file to execute
*/
if( tid == 0 ) {
if( TINY_ERROR( FindFilePath( parm, exe_name, ExtensionList ) ) ) {
exe_name[0] = 0;
} else {
_splitpath( exe_name, drive, directory, NULL, NULL );
a = tolower( drive[0] ) - 'a' + 1;
_dos_setdrive( a, &b );
directory[ strlen( directory ) - 1 ] = 0;
chdir( directory );
}
/*
* get the parm list
*/
src = parm;
while( *src != 0 )
++src;
++src;
end = GetInPtr( GetTotalSize() - 1 );
dst = &buff[1];
for( ;; ) {
if( src > end )
break;
ch = *src;
if( ch == 0 )
ch = ' ';
*dst = ch;
++dst;
++src;
}
if( dst > &buff[1] )
--dst;
*dst = '\0';
buff[0] = dst-buff-1;
/*
* get starting point in task
*/
if( !GetStartAddress( exe_name, &StopNewTask.loc ) ) {
Out((OUT_ERR,"Could not get starting address"));
ret->err = WINERR_NOSTART;
LoadingDebugee = FALSE;
return( sizeof( *ret ) );
}
StopNewTask.segment_number = StopNewTask.loc.segment;
Out((OUT_LOAD,"Loading %s, cs:ip = %04x:%04lx", exe_name, StopNewTask.loc.segment,
StopNewTask.loc.offset ));
/*
* load the task
*/
loadp.cmdshow = &cmdshow;
loadp.wEnvSeg = 0;
loadp.lpCmdLine = (LPSTR) buff;
loadp.cmdshow->mustbe2 = 2;
loadp.cmdshow->cmdshow = SW_NORMAL;
loadp.reserved = 0L;
DebuggerState = LOADING_DEBUGEE;
DebugeeInstance = LoadModule( exe_name, (LPVOID) &loadp );
if( (UINT)DebugeeInstance < 32 ) {
Out((OUT_ERR,"Debugee did not load %d", DebugeeInstance));
ret->err = WINERR_NOLOAD;
LoadingDebugee = FALSE;
return( sizeof( *ret ) );
}
DebuggerWaitForMessage( WAITING_FOR_TASK_LOAD, NULL, RESTART_APP );
}
AddDebugeeModule();
pmsg = DebuggerWaitForMessage( WAITING_FOR_BREAKPOINT, DebugeeTask, RESTART_APP );
if( pmsg == START_BP_HIT ) {
ret->err = 0;
ret->task_id = (unsigned_32)DebugeeTask;
/*
* look for 32-bit windows application
*/
ReadMem( IntResult.CS, SIG_OFF, sig, sizeof( DWORD ) );
if( !StopOnExtender && (!memcmp( sig, win386sig, 4 ) ||
!memcmp( sig, win386sig2, 4 )) ) {
Out((OUT_LOAD,"Is Win32App" ));
Debugging32BitApp = TRUE;
/*
* make sure that WDEBUG.386 is installed
*/
if( !WDebug386 ) {
ret->err = WINERR_NODEBUG32; /* Can't debug 32 bit app */
LoadingDebugee = FALSE;
return( sizeof( *ret ) );
}
ret->flags |= LD_FLAG_IS_32;
if( tid == 0 ) {
WriteMem( IntResult.CS, SIG_OFF, win386sig2, sizeof( DWORD ) );
pmsg = DebuggerWaitForMessage( GOING_TO_32BIT_START,
DebugeeTask, RESTART_APP );
if( pmsg == FAULT_HIT && IntResult.InterruptNumber == INT_3 ) {
IntResult.EIP++;
SingleStepMode();
pmsg = DebuggerWaitForMessage( GOING_TO_32BIT_START,
DebugeeTask, RESTART_APP );
if( pmsg != FAULT_HIT || IntResult.InterruptNumber != INT_1 ) {
Out((OUT_ERR,"Expected INT_1 not found"));
ret->err = WINERR_NOINT1;
}
} else {
Out((OUT_ERR,"Expected INT_3 not found"));
ret->err = WINERR_NOINT3;
}
}
}
if( tid != 0 ) {
ret->flags |= LD_FLAG_IS_STARTED;
WasStarted = TRUE;
}
} else {
Out((OUT_ERR,"Starting breakpoint not found, pmsg=%d", pmsg ));
ret->err = WINERR_STARTNOTFOUND;
}
#if 0
if( DebugeeTask != NULL ) {
InitASynchHook();
}
#endif
LoadingDebugee = FALSE;
CurrentModule = 1;
ret->mod_handle = 0;
return( sizeof( *ret ) );
}
/*
* ReqProg_kill
*
* If it was a task that we attached to (WasStarted), all we do is
* forgive the last interrupt, and then exit
*
* If it was a task we started, we TerminateApp it, and then wait for
* the task ended notification. Note: Task ended isn't quite good enough,
* since the module isn't unloaded. However, you may never get the module
* unloaded notification, if you are debugging the 2nd, 3rd etc instance
* of an app, since the module is loaded more than once. BUT, a NEW command
* from the debugger ends up restarting the app "too fast" - the module isn't
* deleted yet, and so it ends up running a second instance, even if you
* really don't have a first instance. This is the reason for that half
* second pause - to allow Windows to get on with the unloading of the module,
* if it is going to. Ack.
*/
unsigned ReqProg_kill( void )
{
prog_kill_ret *ret;
ret = GetOutPtr( 0 );
ret->err = 0;
Out((OUT_LOAD,"KILL: DebugeeTask=%04x, WasStarted=%d",
DebugeeTask, WasStarted ));
if( DebugeeTask != NULL ) {
IntResult.EFlags &= ~TRACE_BIT;
if( WasStarted ) {
Out((OUT_LOAD,"Doing Release Debugee"));
DebuggerWaitForMessage( RELEASE_DEBUGEE, DebugeeTask, RESTART_APP );
} else {
TerminateApp( DebugeeTask, NO_UAE_BOX );
DebuggerWaitForMessage( KILLING_DEBUGEE, NULL, -1 );
Out((OUT_LOAD,"Task Terminated(not current)"));
{
DWORD a;
a = GetTickCount();
while( GetTickCount() < a + 500 ) {
Yield();
}
}
}
#if 0
FiniASynchHook();
#endif
}
ExitSoftMode();
if( WDebug386 ) {
if( WasInt32 ) {
WasInt32 = FALSE;
DoneWithInterrupt( NULL );
}
}
DebugeeTask = NULL;
ModuleTop = 0;
CurrentModule = 1;
FaultHandlerEntered = FALSE;
PendingTrap = FALSE;
SaveStdIn = NIL_HANDLE;
SaveStdOut = NIL_HANDLE;
Debugging32BitApp = FALSE;
return( sizeof( *ret ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -