accmap.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 372 行
C
372 行
/****************************************************************************
*
* 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!
*
****************************************************************************/
#ifdef __WINDOWS__
#pragma library("toolhelp.lib");
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <ctype.h>
#include <dos.h>
#include "stdwin.h"
#include "winacc.h"
#include "ismod32.h"
#define MAX_MODULE 256
int ModuleTop=0;
int CurrentModule = 0;
static int mod32Top;
static HMODULE moduleIDs[ MAX_MODULE ];
static HMODULE modules32[ MAX_MODULE ];
static BOOL moduleIsDLL[ MAX_MODULE ];
/*
* AddAllCurrentModules - add all currently running modules to
* the module list
*/
void AddAllCurrentModules( void )
{
MODULEENTRY me;
me.dwSize = sizeof( MODULEENTRY );
if( !ModuleFirst( &me ) ) return;
do {
if( me.hModule != DebugeeModule ) {
AddModuleLoaded( me.hModule, FALSE );
}
me.dwSize = sizeof( MODULEENTRY );
} while( ModuleNext( &me ) );
} /* AddAllCurrentModules */
/*
* try32:
*
* see if a module is a Win386 app. If it is, then we add it to a list
* of 32-bit apps, so that we can give the segment aliases for them later.
*/
static void try32( HANDLE mod )
{
DWORD off;
WORD ds;
WORD cs;
if( CheckIsModuleWin32App( mod, &ds, &cs, &off ) ) {
modules32[ mod32Top ] = mod;
mod32Top++;
}
} /* try32 */
/*
* HasSegAliases - report if any modules are Win386 maps
*/
BOOL HasSegAliases( void )
{
return( (mod32Top > 0) );
} /* HasSegAliases */
/*
* AddDebugeeModule - put debugee module in table first, since thats what
* the debugger expects.
*/
void AddDebugeeModule( void )
{
int i;
for( i = ModuleTop; i > 0; i-- ) {
moduleIDs[i] = moduleIDs[i-1];
}
ModuleTop++;
Out((OUT_MAP,"AddDebugeeModule - ModuleTop=%d",ModuleTop));
moduleIDs[0] = DebugeeModule;
moduleIsDLL[0] = FALSE;
try32( DebugeeModule );
} /* AddDebugeeModule */
/*
* AddModuleLoaded - add a loaded module (dll or task) to the list
*/
void AddModuleLoaded( HANDLE mod, BOOL is_dll )
{
int i;
if( ModuleTop >= MAX_MODULE ) {
return;
}
if( ModuleTop == 0 ) {
Out((OUT_MAP,"AddModuleLoaded ModuleTop=%d mod=%d dll=%d",ModuleTop,mod,is_dll));
}
for( i=0;i<ModuleTop;i++ ) {
if( moduleIDs[i] == mod ) {
Out((OUT_MAP,"Already there"));
return;
}
}
try32( mod );
moduleIsDLL[ ModuleTop ] = is_dll;
moduleIDs[ ModuleTop ] = mod;
ModuleTop++;
} /* AddModuleLoaded */
/*
* AccGetLibName - get lib name of current module
*/
unsigned ReqGet_lib_name( void )
{
MODULEENTRY me;
get_lib_name_req *acc;
get_lib_name_ret *ret;
char *name;
acc = GetInPtr(0);
ret = GetOutPtr(0);
name = GetOutPtr( sizeof( *ret ) );
name[0] = '\0';
ret->handle = 0;
if( acc->handle != 0 ) {
CurrentModule = acc->handle + 1;
}
Out(( OUT_MAP,"acc->handle = %ld", acc->handle ));
if( CurrentModule >= ModuleTop ) {
Out(( OUT_MAP,"Past end of list" ));
return( sizeof( *ret ) + 1 );
}
me.dwSize = sizeof( me );
Out(( OUT_MAP,"ModuleTop=%d CurrentModule=%d id=%d", ModuleTop, CurrentModule, moduleIDs[ CurrentModule ] ));
if( ModuleFindHandle( &me, moduleIDs[ CurrentModule ] ) ) {
strcpy( name, me.szExePath );
}
ret->handle = CurrentModule;
Out(( OUT_MAP,"handle=%ld, name=\"%s\"", ret->handle, name ));
return( sizeof( *ret ) + strlen( name ) + 1 );
}
/*
* accessSegment:
*
* Access a segment to cause the windows loader to load it. We find
* the segment by looking through the module entry (which is a lot like
* an NE header, except that where segment numbers would be, the selector
* value is). We then have the app we are debugging execute an instruction that
* references the seqment in question.
*/
static void accessSegment( GLOBALHANDLE gh, WORD segment )
{
WORD i;
WORD sel;
WORD offset;
ReadMem( (WORD)gh, 0x22, &offset, sizeof( offset ) );
i = 0;
while( i < segment ) {
ReadMem( (WORD)gh, offset+8, &sel, sizeof( sel ) );
offset += 10;
i++;
}
SegmentToAccess = sel;
DebuggerWaitForMessage( RUNNING_DEBUGEE, TaskAtFault, ACCESS_SEGMENT );
} /* accessSegment */
/*
* horkyFindSegment:
*
* runs and tries to find a segment. It does this by finding the module
* entry in the global heap for this task. The module entry is a lot like
* an NE header, except that instead of segment numbers, it has the selector
* values themselves. We pass the module entry to accessSegment, who looks
* up the selector and causes it to load.
*
* The reason: load on call segments are not identified by toolhelp,
* so mapaddrs for those segments would fail without this putrid code.
* As well, the segments themselves are not always loaded (loadoncall
* segments), so if you were to look at the memory there, you would see
* nothing.
*
* Special note: this only works for the task that you are debugging.
* Windows knows what the current task is, and when you access a not present
* segment, it tries to load the segment based on the current task. Thus,
* you cannot try to have the debugee fault in a segment belonging to some
* other task. Why DLL's work at all (since they are not a "task") is beyond
* me.
*/
static BOOL horkyFindSegment( int module, WORD segment )
{
static GLOBALENTRY ge;
static HMODULE lastmodid;
HMODULE modid;
modid = moduleIDs[ module ];
if( !moduleIsDLL[ module ] ) {
return( FALSE );
}
if( lastmodid == modid ) {
accessSegment( ge.hBlock, segment );
return( TRUE );
}
lastmodid = modid;
ge.dwSize = sizeof( ge );
if( !GlobalFirst( &ge, GLOBAL_ALL ) ) {
lastmodid = NULL;
return( FALSE );
}
do {
if( ge.hOwner == modid && ge.wType == GT_MODULE ) {
accessSegment( ge.hBlock, segment );
return( TRUE );
}
ge.dwSize = sizeof( ge );
} while( GlobalNext( &ge, GLOBAL_ALL ) );
lastmodid = NULL;
return( FALSE );
} /* horkyFindSegment */
/*
* ReqMap_addr
*
* Access request to map a segment number to a selector.
* Possibilites:
* 1) We are mapping segments for a 32-bit extended app. In this case,
* we return the segment:offset returned by CheckIsModuleWin32App
* 2) We are mapping a segment for a 16-bit app that is NOT a load
* on call segment. In this case, GlobalEntryModule works and
* we return the value we obtain from it
* 3) We are mapping a segment for a 16-bit app that IS a load
* on call segment. In this case, GlobalEntryModule FAILS (stupid
* f*cking Windows) and so we have to go find it ourselves using
* horkyFindSegment. Once horkyFindSegment is done, GlobalEntryModule
* will give the right answer, and we return the value we obtain from it.
*/
unsigned ReqMap_addr( void )
{
GLOBALENTRY ge;
LPVOID ptr;
WORD sel;
WORD cs,ds;
DWORD off;
int module;
addr_seg in_seg;
map_addr_req *acc;
map_addr_ret *ret;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ret->out_addr = acc->in_addr;
ret->lo_bound = 0;
ret->hi_bound = ~(addr48_off)0;
module = acc->handle;
in_seg = acc->in_addr.segment;
if( CheckIsModuleWin32App( moduleIDs[ module ], &ds, &cs, &off ) ) {
Out((OUT_MAP,"is 32 bit module"));
if( in_seg == MAP_FLAT_DATA_SELECTOR ) {
ret->out_addr.segment = ds;
} else {
ret->out_addr.segment = cs;
}
ret->out_addr.offset = off;
} else {
switch( in_seg ) {
case MAP_FLAT_CODE_SELECTOR:
case MAP_FLAT_DATA_SELECTOR:
in_seg = 1;
break;
}
ge.dwSize = sizeof( ge );
if( !GlobalEntryModule( &ge, moduleIDs[ module ], in_seg ) ) {
if( horkyFindSegment( module, in_seg ) ) {
if( !GlobalEntryModule( &ge, moduleIDs[ module ], in_seg ) ) {
Out((OUT_MAP,"GlobalEntry 2nd time failed" ));
return( sizeof( *ret ) );
}
} else {
Out(( OUT_MAP,"Well I'll be! horkyFindSegment failed" ));
return( sizeof( *ret ) );
}
}
ptr = GlobalLock( ge.hBlock );
GlobalUnlock( ge.hBlock );
sel = FP_SEG( ptr );
if( sel == NULL ) {
sel = (WORD)ge.hBlock + 1;
}
ret->out_addr.segment = sel;
ret->out_addr.offset = 0;
}
ret->out_addr.offset += acc->in_addr.offset;
if( module == 0 ) {
Out(( OUT_MAP,"in=%4.4x:%8.8lx out=%4.4x:%8.8lx", acc->in_addr.segment, acc->in_addr.offset, ret->out_addr.segment, ret->out_addr.offset ));
}
return( sizeof( *ret ) );
}
/*
* ReqGet_next_alias
*
* Get next alias, for 32-bit extender apps only
* We maintain a list of all apps that are 32-bit, and return the
* aliases for each of them.
*/
unsigned ReqGet_next_alias( void )
{
get_next_alias_req *acc;
get_next_alias_ret *ret;
WORD ds,cs;
DWORD off;
acc = GetInPtr( 0 );
ret = GetOutPtr( 0 );
ret->seg = 0;
ret->alias = 0;
if( mod32Top > 0 ) {
mod32Top--;
CheckIsModuleWin32App( modules32[ mod32Top ], &ds, &cs, &off );
ret->seg = cs;
ret->alias = ds;
}
return( sizeof( *ret ) );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?