📄 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 <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "stdnt.h"
#include "trperr.h"
#include "srvcdbg.h"
#define ERR_CODES
#include "dosmsgs.h"
#ifndef CREATE_SEPARATE_WOW_VDM
#define CREATE_SEPARATE_WOW_VDM 0x00000800 // new for NT 3.5 (daytona)
#endif
/*
* executeUntilStart - run program until start address hit
*/
static BOOL executeUntilStart( BOOL was_running )
{
HANDLE ph;
brkpnt_type old;
brkpnt_type brk = BRK_POINT;
LPVOID base;
DWORD bytes;
CONTEXT con;
thread_info *ti;
ph = DebugEvent.u.CreateProcessInfo.hProcess;
if( !was_running ) {
/*
* if we are not debugging an already running app, then we
* plant a breakpoint at the first instruction of our new app
*/
base = DebugEvent.u.CreateProcessInfo.lpStartAddress;
ReadProcessMemory( ph, ( LPVOID )base, ( LPVOID )&old, sizeof( old ),
( LPDWORD )&bytes );
WriteProcessMemory( ph, ( LPVOID )base, ( LPVOID )&brk, sizeof( brk ),
( LPDWORD )&bytes );
} else {
// a trick to make app execute long enough to hit a breakpoint
PostMessage( HWND_TOPMOST, WM_NULL, 0, 0 );
}
for( ;; ) {
/*
* if we encounter anything but a break point, then we are in
* trouble!
*/
if( DebugExecute( STATE_IGNORE_DEBUG_OUT | STATE_IGNORE_DEAD_THREAD,
NULL, FALSE ) & COND_BREAK ) {
ti = FindThread( DebugEvent.dwThreadId );
MyGetThreadContext( ti, &con );
if( was_running ) {
AdjustIP( &con, sizeof( brk ) );
MySetThreadContext( ti, &con );
return( TRUE );
}
if( StopForDLLs ) {
/*
* the user has asked us to stop before any DLL's run
* their startup code (";dll"), so we do.
*/
WriteProcessMemory( ph, ( LPVOID )base, ( LPVOID )&old,
sizeof( old ), ( LPDWORD )&bytes );
AdjustIP( &con, sizeof( brk ) );
MySetThreadContext( ti, &con );
return( TRUE );
}
if( ( AdjustIP( &con, 0 ) == ( DWORD ) base ) ) {
/*
* we stopped at the applications starting address,
* so we can offically declare that the app has loaded
*/
WriteProcessMemory( ph, ( LPVOID )base, ( LPVOID )&old,
sizeof( old ), ( LPDWORD )&bytes );
return( TRUE );
}
/*
* skip this breakpoint and continue
*/
AdjustIP( &con, sizeof( brk ) );
MySetThreadContext( ti, &con );
} else {
return( FALSE );
}
}
}
#ifdef WOW
/*
* addKERNEL - add the KERNEL module to the library load (WOW)
*/
static void addKERNEL( void )
{
#if 0
/*
* there are bugs in the way VDMDBG.DLL implements some of this
* stuff, so this is currently disabled
*/
MODULEENTRY me;
thread_info *ti;
IMAGE_NOTE im;
ti = FindThread( DebugeeTid );
me.dwSize = sizeof( MODULEENTRY );
if( pVDMModuleFirst( ProcessInfo.process_handle, ti->thread_handle,
&me, NULL, 0 ) ) {
do {
if( !memicmp( me.szModule, "KERNEL", 6 ) ) {
memcpy( &im.Module, &me.szModule, sizeof( me.szModule ) );
memcpy( &im.FileName, &me.szExePath, sizeof( me.szExePath ) );
AddLib( TRUE, &im );
break;
}
me.dwSize = sizeof( MODULEENTRY );
} while( pVDMModuleNext( ProcessInfo.process_handle, ti->thread_handle,
&me, NULL, 0 ) );
}
#else
IMAGE_NOTE im;
/*
* this is a giant kludge, but it works. Since KERNEL is already
* loaded in the WOW , we never get a DLL load notification, so
* we can't show any symbols. This fakes up the necessary information
*/
strcpy( im.Module, "KERNEL" );
GetSystemDirectory( im.FileName, sizeof( im.FileName ) );
strcat( im.FileName, "\\KRNL386.EXE" );
AddLib( TRUE, &im );
#endif
}
/*
* addAllWOWModules - add all modules as libraries. This is invoked if
* WOW was already running, since we will get no
* lib load notifications if it was.
*/
static void addAllWOWModules( void )
{
MODULEENTRY me;
thread_info *ti;
IMAGE_NOTE im;
ti = FindThread( DebugeeTid );
me.dwSize = sizeof( MODULEENTRY );
if( pVDMModuleFirst( ProcessInfo.process_handle, ti->thread_handle,
&me, NULL, 0 ) ) {
do {
if( !strcmp( me.szModule, WOWAppInfo.modname ) ) {
continue;
}
memcpy( &im.Module, &me.szModule, sizeof( me.szModule ) );
memcpy( &im.FileName, &me.szExePath, sizeof( me.szExePath ) );
AddLib( TRUE, &im );
me.dwSize = sizeof( MODULEENTRY );
} while( pVDMModuleNext( ProcessInfo.process_handle, ti->thread_handle,
&me, NULL, 0 ) );
}
}
/*
* executeUntilVDMStart - go until we hit our first VDM exception
*/
static BOOL executeUntilVDMStart( void )
{
int rc;
for( ;; ) {
rc = DebugExecute( STATE_WAIT_FOR_VDM_START, NULL, FALSE );
if( rc == COND_VDM_START ) {
return( TRUE );
}
return( FALSE );
}
}
/*
* EnumWOWProcessFunc - callback for each WOW process in the system
*/
static BOOL WINAPI EnumWOWProcessFunc( DWORD pid, DWORD attrib, LPARAM lparam )
{
if( attrib & WOW_SYSTEM ) {
*( DWORD * ) lparam = pid;
return( FALSE );
}
return( TRUE );
}
#else
static BOOL WINAPI EnumWOWProcessFunc( DWORD pid, DWORD attrib, LPARAM lparam )
{
(void)pid, (void)attrib; // Unused
*( DWORD *)lparam = 0;
return( FALSE );
}
#endif
/*
* AccLoadProg - create a new process for debugging
*/
unsigned ReqProg_load( void )
{
char *parm;
char *src;
char *dst;
char *endsrc;
char exe_name[PATH_MAX];
char ch;
BOOL rc;
int len;
CONTEXT con;
thread_info *ti;
HANDLE handle;
prog_load_req *acc;
prog_load_ret *ret;
header_info hi;
WORD stack;
WORD version;
DWORD pid;
DWORD pid_started;
DWORD cr_flags;
char *buff = NULL;
size_t nBuffRequired = 0;
char *dll_name;
char *service_name;
char *dll_destination;
char *service_parm;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
parm = GetInPtr( sizeof( *acc ) );
/*
* reset status variables
*/
LastExceptionCode = -1;
DebugString = NULL;
DebugeeEnded = FALSE;
RemoveAllThreads();
FreeLibList();
DidWaitForDebugEvent = FALSE;
DebugeePid = NULL;
DebugeeTid = NULL;
/*
* check if pid is specified
*/
ParseServiceStuff( parm, &dll_name, &service_name, &dll_destination,
&service_parm );
pid = 0;
src = parm;
/*
// Just to be really safe!
*/
nBuffRequired = GetTotalSize() + PATH_MAX + 16;
if( NULL == ( buff = malloc( nBuffRequired ) ) ) {
ret->err = ERROR_NOT_ENOUGH_MEMORY;
return( sizeof( *ret ) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -