mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2528 lines
58 KiB
2528 lines
58 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
emdp2.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the some of the machine independent portions of the
|
|
execution model. The machine dependent portions are in other files.
|
|
|
|
Author:
|
|
|
|
Kent Forschmiedt (kentf) 10-23-92
|
|
|
|
Environment:
|
|
|
|
Win32 -- User
|
|
|
|
Notes:
|
|
|
|
The orginal source for this came from the CodeView group.
|
|
|
|
--*/
|
|
|
|
extern CRITICAL_SECTION csCache;
|
|
|
|
#ifdef OSDEBUG4
|
|
|
|
#define DECL_XOSD(n,s) {s,n},
|
|
static struct _EMERROR {
|
|
LPSTR lpsz;
|
|
XOSD xosd;
|
|
} EmErrors[] = {
|
|
#include "xosd.h"
|
|
};
|
|
const int nErrors = (sizeof(EmErrors)/sizeof(*EmErrors));
|
|
#undef DECL_XOSD
|
|
|
|
#else
|
|
|
|
#define DECL_STR(s,v) {s,v},
|
|
static struct _EMERROR {
|
|
LPSTR lpsz;
|
|
XOSD xosd;
|
|
} EmErrors[] = {
|
|
#include "emerror.h"
|
|
};
|
|
const int nErrors = (sizeof(EmErrors)/sizeof(*EmErrors));
|
|
#undef DECL_STR
|
|
|
|
#endif
|
|
|
|
|
|
LPSTR
|
|
EmError(
|
|
XOSD xosd
|
|
)
|
|
{
|
|
int i;
|
|
for (i = 0; i < nErrors; i++) {
|
|
if (EmErrors[i].xosd == xosd) {
|
|
return EmErrors[i].lpsz;
|
|
}
|
|
}
|
|
return EmErrors[0].lpsz;
|
|
}
|
|
|
|
|
|
|
|
XOSD
|
|
LoadFixups (
|
|
HPID hpid,
|
|
MODULELOAD UNALIGNED *lpmdl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called in response to a module load message. It
|
|
will cause information to be internally setup for doing fixups/
|
|
unfixups ...
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies a handle for the process
|
|
|
|
lpmdl - Supplies a pointer to a module load message from the DM
|
|
|
|
Return Value:
|
|
|
|
xosd Error code
|
|
|
|
--*/
|
|
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
HMDI hmdi;
|
|
MDI UNALIGNED * lpmdi;
|
|
LPCH lpchName;
|
|
HPRC hprc = HprcFromHpid( hpid );
|
|
HLLI llmdi = LlmdiFromHprc ( hprc );
|
|
LPPRC lpprc;
|
|
int cobj;
|
|
//DWORD fIsRemote;
|
|
//LPSTR p1;
|
|
|
|
|
|
hmdi = LLCreate ( llmdi );
|
|
if ( hmdi == 0 ) {
|
|
assert( "load dll cannot create llmdi" && FALSE );
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
lpmdi = (MDI UNALIGNED *)LLLock ( hmdi );
|
|
|
|
lpmdi->mte = lpmdl->mte;
|
|
lpmdi->lpBaseOfDll = (DWORD)lpmdl->lpBaseOfDll;
|
|
lpmdi->dwSizeOfDll = lpmdl->dwSizeOfDll;
|
|
lpmdi->StartingSegment = lpmdl->StartingSegment;
|
|
|
|
lpmdi->CSSel = lpmdl->CSSel;
|
|
lpmdi->DSSel = lpmdl->DSSel;
|
|
|
|
lpmdi->fRealMode = lpmdl->fRealMode;
|
|
lpmdi->fOffset32 = lpmdl->fOffset32;
|
|
lpmdi->fFlatMode = lpmdl->fFlatMode;
|
|
|
|
if (lpmdi->fFlatMode) {
|
|
lpprc = LLLock( hprc );
|
|
lpprc->selFlatCs = lpmdi->CSSel;
|
|
lpprc->selFlatDs = lpmdi->DSSel;
|
|
LLUnlock( hprc );
|
|
}
|
|
|
|
|
|
//
|
|
// cobj might be -1 or 0. If it is -1, the objdir load is
|
|
// deferred until we need it. If it is 0, later segloads
|
|
// will add sections one at a time.
|
|
//
|
|
|
|
cobj = lpmdi->cobj = lpmdl->cobj;
|
|
if (cobj == -1) {
|
|
cobj = 0;
|
|
}
|
|
|
|
lpmdi->rgobjd = NULL;
|
|
lpchName = ( (LPCH) &( lpmdl->rgobjd[cobj] ) );
|
|
|
|
lpmdi->lszName = MHAlloc ( strlen ( lpchName ) + 1 );
|
|
if ( lpmdi->lszName == NULL ) {
|
|
LLUnlock( hmdi );
|
|
assert( "load dll cannot dup mod name" && FALSE );
|
|
return xosdOutOfMemory;
|
|
}
|
|
strcpy ( lpmdi->lszName, lpchName );
|
|
|
|
if (cobj) {
|
|
lpmdi->rgobjd = (LPOBJD) MHAlloc ( sizeof(OBJD) * cobj);
|
|
if ( lpmdi->rgobjd == NULL ) {
|
|
LLUnlock( hmdi );
|
|
assert( "load cannot create rgobjd" && FALSE );
|
|
return xosdOutOfMemory;
|
|
}
|
|
memcpy( lpmdi->rgobjd, lpmdl->rgobjd, sizeof(OBJD) * cobj );
|
|
}
|
|
|
|
LLAdd ( llmdi, hmdi );
|
|
|
|
xosd = CallDB (
|
|
dbcModLoad,
|
|
hpid,
|
|
NULL,
|
|
CEXM_MDL_native,
|
|
(UINT) hmdi,
|
|
lpmdi->lszName
|
|
);
|
|
|
|
LLUnlock ( hmdi );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
UnLoadFixups (
|
|
HPID hpid,
|
|
HEMI hemi,
|
|
BOOL fSendAck
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called in response to a module unload message.
|
|
|
|
It returns the emi of the module being unloaded
|
|
|
|
Arguments:
|
|
|
|
hprc - Supplies a handle for the process
|
|
hemi - Supplies hemi (if Unload)
|
|
|
|
Return Value:
|
|
|
|
TRUE if deleted
|
|
|
|
--*/
|
|
|
|
{
|
|
HLLI hlli;
|
|
HMDI hmdi;
|
|
BYTE b = 1;
|
|
|
|
|
|
hlli = LlmdiFromHprc( HprcFromHpid ( hpid ));
|
|
hmdi = LLFind( hlli, 0, (LPVOID)&hemi, (LONG) emdiEMI);
|
|
|
|
if (hmdi != hmdiNull) {
|
|
LLDelete( hlli, hmdi );
|
|
}
|
|
|
|
/*
|
|
* Ack back to to DM
|
|
*/
|
|
|
|
if (fSendAck) {
|
|
CallTL ( tlfReply, hpid, 1, &b );
|
|
}
|
|
|
|
return hmdi != hmdiNull;
|
|
} /* UnLoadFixups() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**** ****
|
|
* *
|
|
* PURPOSE: *
|
|
* *
|
|
* INPUTS: *
|
|
* *
|
|
* OUTPUTS: *
|
|
* *
|
|
* IMPLEMENTATION: *
|
|
* *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
XOSD
|
|
CreateThreadStruct (
|
|
HPID hpid,
|
|
TID tid,
|
|
HTID *lphtid
|
|
)
|
|
{
|
|
HPRC hprc = HprcFromHpid ( hpid );
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
HTHD hthd = hthdNull;
|
|
LPTHD lpthd = NULL;
|
|
|
|
hthd = HthdFromTid ( hprc, tid );
|
|
assert(hthd == NULL);
|
|
if ( hthd == hthdNull ) {
|
|
|
|
hthd = LLCreate ( lpprc->llthd );
|
|
lpthd = LLLock ( hthd );
|
|
|
|
CallDB (
|
|
dbcoCreateThread,
|
|
hpid,
|
|
NULL,
|
|
CEXM_MDL_native,
|
|
sizeof ( HTID ),
|
|
(LPVOID)lphtid
|
|
);
|
|
|
|
lpthd->htid = *lphtid;
|
|
lpthd->hprc = hprc;
|
|
lpthd->tid = tid;
|
|
lpthd->drt = drtNonePresent;
|
|
lpthd->dwcbSpecial = lpprc->dmi.cbSpecialRegs;
|
|
if (lpthd->dwcbSpecial) {
|
|
lpthd->pvSpecial = malloc(lpthd->dwcbSpecial);
|
|
}
|
|
|
|
LLAdd ( lpprc->llthd, hthd );
|
|
}
|
|
else {
|
|
lpthd = LLLock ( hthd );
|
|
assert ( lpthd->fVirtual == TRUE );
|
|
*lphtid = lpthd->htid;
|
|
lpthd->fVirtual = FALSE;
|
|
lpthd->drt = drtNonePresent;
|
|
}
|
|
|
|
LLUnlock ( hthd );
|
|
LLUnlock ( hprc );
|
|
|
|
return xosdNone;
|
|
} /* CreateThreadStruct() */
|
|
|
|
|
|
VOID
|
|
SyncHprcWithDM(
|
|
HPID hpid
|
|
)
|
|
{
|
|
BYTE rgb[sizeof(DBB) + sizeof(EXCMD)];
|
|
LPDBB pdbb = (LPDBB) rgb;
|
|
LPEXCEPTION_CONTROL lpexc = &((LPEXCMD)(pdbb + 1))->exc;
|
|
LPEXCEPTION_DESCRIPTION lpexd = &((LPEXCMD)(pdbb + 1))->exd;
|
|
LPEXCEPTION_DESCRIPTION lpexdr;
|
|
HEXD hexd;
|
|
HPRC hprc;
|
|
HLLI llexc;
|
|
LONG lT;
|
|
|
|
hprc = HprcFromHpid(hpid);
|
|
if (!hprc) {
|
|
return;
|
|
}
|
|
llexc = ((LPPRC)LLLock(hprc))->llexc;
|
|
LLUnlock(hprc);
|
|
|
|
// force the DMINFO struct to get loaded
|
|
|
|
DebugMetric ( hpid, NULL, mtrcProcessorType, &lT );
|
|
|
|
|
|
// get exception info
|
|
|
|
pdbb->dmf = dmfGetExceptionState;
|
|
pdbb->hpid = hpid;
|
|
pdbb->htid = NULL;
|
|
*lpexc = exfFirst;
|
|
|
|
do {
|
|
|
|
CallTL(tlfRequest, hpid, sizeof(rgb), rgb);
|
|
if (LpDmMsg->xosdRet != xosdNone) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// add to local exception list
|
|
//
|
|
hexd = LLCreate( llexc );
|
|
LLAdd( llexc, hexd );
|
|
lpexdr = LLLock( hexd );
|
|
*lpexdr = *((LPEXCEPTION_DESCRIPTION)(LpDmMsg->rgb));
|
|
LLUnlock( hexd );
|
|
|
|
//
|
|
// ask for the next one
|
|
//
|
|
*lpexd = *((LPEXCEPTION_DESCRIPTION)(LpDmMsg->rgb));
|
|
*lpexc = exfNext;
|
|
|
|
} while (lpexd->dwExceptionCode != 0);
|
|
}
|
|
|
|
|
|
XOSD
|
|
CreateHprc (
|
|
HPID hpid
|
|
)
|
|
{
|
|
XOSD xosd = xosdNone;
|
|
HPRC hprc;
|
|
LPPRC lpprc;
|
|
|
|
hprc = LLCreate ( llprc );
|
|
|
|
if ( hprc == 0 ) {
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
LLAdd ( llprc, hprc );
|
|
|
|
lpprc = (LPPRC) LLLock ( hprc );
|
|
|
|
lpprc->stat = statDead;
|
|
lpprc->hpid = hpid;
|
|
lpprc->pid = (PID) 0;
|
|
lpprc->fDmiCache = 0;
|
|
|
|
GetAddrSeg ( lpprc->addrTaskData ) = 0;
|
|
GetAddrOff ( lpprc->addrTaskData ) = 0;
|
|
|
|
lpprc->cFPThread = 1;
|
|
|
|
lpprc->llthd = LLInit (
|
|
sizeof ( THD ),
|
|
llfNull,
|
|
TiDKill,
|
|
TDComp
|
|
);
|
|
|
|
if ( lpprc->llthd == 0 ) {
|
|
xosd = xosdOutOfMemory;
|
|
}
|
|
|
|
lpprc->llmdi = LLInit ( sizeof ( MDI ), llfNull, MDIKill, MDIComp );
|
|
|
|
if ( lpprc->llmdi == 0 ) {
|
|
xosd = xosdOutOfMemory;
|
|
}
|
|
|
|
lpprc->llexc = LLInit ( sizeof(EXCEPTION_DESCRIPTION),
|
|
llfNull,
|
|
NULL,
|
|
EXCComp );
|
|
if ( lpprc->llexc == 0 ) {
|
|
xosd = xosdOutOfMemory;
|
|
}
|
|
|
|
LLUnlock ( hprc );
|
|
|
|
return xosd;
|
|
}
|
|
|
|
VOID
|
|
DestroyHprc (
|
|
HPRC hprc
|
|
)
|
|
{
|
|
EnterCriticalSection(&csCache);
|
|
|
|
LLDelete ( llprc, hprc );
|
|
FlushPTCache();
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
}
|
|
|
|
VOID
|
|
DestroyHthd(
|
|
HTHD hthd
|
|
)
|
|
{
|
|
LPTHD lpthd;
|
|
HPRC hprc;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
lpthd = LLLock ( hthd );
|
|
hprc = lpthd->hprc;
|
|
LLUnlock ( hthd );
|
|
LLDelete ( LlthdFromHprc ( hprc ), hthd );
|
|
FlushPTCache();
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
}
|
|
|
|
void EMENTRY
|
|
PiDKill (
|
|
LPVOID lpv
|
|
)
|
|
{
|
|
LPPRC lpprc = (LPPRC) lpv;
|
|
LLDestroy ( lpprc->llthd );
|
|
LLDestroy ( lpprc->llmdi );
|
|
LLDestroy ( lpprc->llexc );
|
|
}
|
|
|
|
void EMENTRY
|
|
TiDKill (
|
|
LPVOID lpv
|
|
)
|
|
{
|
|
LPTHD lpthd = (LPTHD) lpv;
|
|
if (lpthd->pvSpecial) {
|
|
free(lpthd->pvSpecial);
|
|
}
|
|
}
|
|
|
|
void EMENTRY
|
|
MDIKill(
|
|
LPVOID lpv
|
|
)
|
|
{
|
|
LPMDI lpmdi = (LPMDI)lpv;
|
|
if (lpmdi->lszName) {
|
|
MHFree(lpmdi->lszName);
|
|
lpmdi->lszName = NULL;
|
|
}
|
|
if (lpmdi->rgobjd) {
|
|
MHFree(lpmdi->rgobjd);
|
|
lpmdi->rgobjd = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
int EMENTRY
|
|
PDComp (
|
|
LPVOID lpv1,
|
|
LPVOID lpv2,
|
|
LONG lParam
|
|
)
|
|
{
|
|
|
|
Unreferenced(lParam);
|
|
|
|
if ( ( (LPPRC) lpv1)->hpid == *( (LPHPID) lpv2 ) ) {
|
|
return fCmpEQ;
|
|
}
|
|
else {
|
|
return fCmpLT;
|
|
}
|
|
}
|
|
|
|
int EMENTRY
|
|
TDComp (
|
|
LPVOID lpv1,
|
|
LPVOID lpv2,
|
|
LONG lParam
|
|
)
|
|
{
|
|
|
|
Unreferenced(lParam);
|
|
|
|
if ( ( (LPTHD) lpv1)->htid == *( (LPHTID) lpv2 ) ) {
|
|
return fCmpEQ;
|
|
}
|
|
else {
|
|
return fCmpLT;
|
|
}
|
|
}
|
|
|
|
|
|
int EMENTRY
|
|
MDIComp (
|
|
LPVOID lpv1,
|
|
LPVOID lpv,
|
|
LONG lParam
|
|
)
|
|
{
|
|
LPMDI lpmdi = (LPMDI) lpv1;
|
|
CHAR fname[_MAX_FNAME];
|
|
CHAR ext[_MAX_EXT];
|
|
CHAR fn1[MAX_PATH];
|
|
CHAR fn2[MAX_PATH];
|
|
|
|
|
|
switch ( lParam ) {
|
|
|
|
case emdiName:
|
|
if ( !strchr(lpv,'|') ) {
|
|
char *p1,*p2;
|
|
p1 = lpmdi->lszName;
|
|
if ( *p1 == '|' ) {
|
|
p1++;
|
|
}
|
|
p2 = strchr(p1,'|');
|
|
if ( !p2 ) {
|
|
p2 = p1 + strlen(p1);
|
|
}
|
|
memcpy(fn2, p1, p2-p1);
|
|
fn2[p2-p1]='\0';
|
|
|
|
_splitpath( (LPSTR)lpv, NULL, NULL, fname, ext );
|
|
_makepath( fn1, NULL, NULL, fname, ext );
|
|
|
|
_splitpath( (LPSTR)fn2, NULL, NULL, fname, ext );
|
|
_makepath( fn2, NULL, NULL, fname, ext );
|
|
|
|
return _stricmp ( fn1, fn2 );
|
|
|
|
} else {
|
|
|
|
return _stricmp ( lpv, lpmdi->lszName );
|
|
|
|
}
|
|
|
|
case emdiEMI:
|
|
return !(lpmdi->hemi == *(( HEMI * ) lpv ) );
|
|
|
|
case emdiMTE:
|
|
return !(lpmdi->mte == *((LPWORD) lpv ));
|
|
|
|
case emdiBaseAddr:
|
|
return !(lpmdi->lpBaseOfDll == *((OFFSET *) lpv));
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
EXCComp(
|
|
LPVOID lpRec,
|
|
LPVOID lpVal,
|
|
LONG lParam
|
|
)
|
|
{
|
|
Unreferenced(lParam);
|
|
if ( ((LPEXCEPTION_DESCRIPTION)lpRec)->dwExceptionCode ==
|
|
*((LPDWORD)lpVal)) {
|
|
return fCmpEQ;
|
|
} else {
|
|
return fCmpLT;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
ConvertOmapFromSrc(
|
|
LPMDI lpmdi,
|
|
DWORD addr
|
|
)
|
|
{
|
|
DWORD rva;
|
|
DWORD comap;
|
|
LPOMAP pomapLow;
|
|
LPOMAP pomapHigh;
|
|
DWORD comapHalf;
|
|
LPOMAP pomapMid;
|
|
|
|
|
|
if (!lpmdi) {
|
|
return addr;
|
|
}
|
|
|
|
if ( lpmdi->lpgsi == NULL ) {
|
|
SHWantSymbols( (HEXE)lpmdi->hemi );
|
|
lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)lpmdi->hemi );
|
|
}
|
|
|
|
if ((!lpmdi->lpDebug) || (!lpmdi->lpDebug->lpOmapFrom)) {
|
|
return addr;
|
|
}
|
|
|
|
rva = addr - lpmdi->lpBaseOfDll;
|
|
|
|
comap = lpmdi->lpDebug->cOmapFrom;
|
|
pomapLow = lpmdi->lpDebug->lpOmapFrom;
|
|
pomapHigh = pomapLow + comap;
|
|
|
|
while (pomapLow < pomapHigh) {
|
|
|
|
comapHalf = comap / 2;
|
|
|
|
pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
|
|
|
|
if (rva == pomapMid->rva) {
|
|
return lpmdi->lpBaseOfDll + pomapMid->rvaTo;
|
|
}
|
|
|
|
if (rva < pomapMid->rva) {
|
|
pomapHigh = pomapMid;
|
|
comap = (comap & 1) ? comapHalf : (comapHalf - 1);
|
|
} else {
|
|
pomapLow = pomapMid + 1;
|
|
comap = comapHalf;
|
|
}
|
|
}
|
|
|
|
assert(pomapLow == pomapHigh);
|
|
|
|
//
|
|
// If no exact match, pomapLow points to the next higher address
|
|
//
|
|
if (pomapLow == lpmdi->lpDebug->lpOmapFrom) {
|
|
//
|
|
// This address was not found
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
if (pomapLow[-1].rvaTo == 0) {
|
|
//
|
|
// This address is not translated so just return the original
|
|
//
|
|
return addr;
|
|
}
|
|
|
|
//
|
|
// Return the closest address plus the bias
|
|
//
|
|
return lpmdi->lpBaseOfDll + pomapLow[-1].rvaTo + (rva - pomapLow[-1].rva);
|
|
}
|
|
|
|
|
|
DWORD
|
|
ConvertOmapToSrc(
|
|
LPMDI lpmdi,
|
|
DWORD addr
|
|
)
|
|
{
|
|
DWORD rva;
|
|
DWORD comap;
|
|
LPOMAP pomapLow;
|
|
LPOMAP pomapHigh;
|
|
DWORD comapHalf;
|
|
LPOMAP pomapMid;
|
|
INT i;
|
|
|
|
|
|
if (!lpmdi) {
|
|
return addr;
|
|
}
|
|
|
|
if ( lpmdi->lpgsi == NULL ) {
|
|
SHWantSymbols( (HEXE)lpmdi->hemi );
|
|
lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)lpmdi->hemi );
|
|
}
|
|
|
|
if ((!lpmdi->lpDebug) || (!lpmdi->lpDebug->lpOmapTo)) {
|
|
return addr;
|
|
}
|
|
|
|
rva = addr - lpmdi->lpBaseOfDll;
|
|
|
|
comap = lpmdi->lpDebug->cOmapTo;
|
|
pomapLow = lpmdi->lpDebug->lpOmapTo;
|
|
pomapHigh = pomapLow + comap;
|
|
|
|
while (pomapLow < pomapHigh) {
|
|
|
|
comapHalf = comap / 2;
|
|
|
|
pomapMid = pomapLow + ((comap & 1) ? comapHalf : (comapHalf - 1));
|
|
|
|
if (rva == pomapMid->rva) {
|
|
if (pomapMid->rvaTo == 0) {
|
|
//
|
|
// We are probably in the middle of a routine
|
|
//
|
|
i = -1;
|
|
while ((&pomapMid[i] != lpmdi->lpDebug->lpOmapTo) && pomapMid[i].rvaTo == 0) {
|
|
//
|
|
// Keep on looping back until the beginning
|
|
//
|
|
i--;
|
|
}
|
|
return lpmdi->lpBaseOfDll + pomapMid[i].rvaTo;
|
|
} else {
|
|
return lpmdi->lpBaseOfDll + pomapMid->rvaTo;
|
|
}
|
|
}
|
|
|
|
if (rva < pomapMid->rva) {
|
|
pomapHigh = pomapMid;
|
|
comap = (comap & 1) ? comapHalf : (comapHalf - 1);
|
|
} else {
|
|
pomapLow = pomapMid + 1;
|
|
comap = comapHalf;
|
|
}
|
|
}
|
|
|
|
assert(pomapLow == pomapHigh);
|
|
|
|
//
|
|
// If no exact match, pomapLow points to the next higher address
|
|
//
|
|
if (pomapLow == lpmdi->lpDebug->lpOmapTo) {
|
|
//
|
|
// This address was not found
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
if (pomapLow[-1].rvaTo == 0) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Return the new address plus the bias
|
|
//
|
|
return lpmdi->lpBaseOfDll + pomapLow[-1].rvaTo + (rva - pomapLow[-1].rva);
|
|
}
|
|
|
|
|
|
XOSD
|
|
FixupAddr (
|
|
HPID hpid,
|
|
LPADDR lpaddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to convert addresses between linker index (section
|
|
or segment relative) addresses and real addresses (segment:offset).
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process for context to convert
|
|
the address.
|
|
lpaddr - Pointer to address packet to be converted.
|
|
|
|
Return Value:
|
|
|
|
XOSD error code.
|
|
|
|
--*/
|
|
|
|
{
|
|
HMDI hmdi;
|
|
|
|
// Check to see if the address is already a segment:offset pair and return if it is.
|
|
|
|
if ( !ADDR_IS_LI(*lpaddr) ) {
|
|
return xosdNone;
|
|
}
|
|
|
|
// Now based on the emi field of the address (which uniquely defines the
|
|
// executable module in the symbol handler), get the conversion information.
|
|
|
|
assert( emiAddr( *lpaddr ) != 0 );
|
|
|
|
if ( (HPID)emiAddr ( *lpaddr ) == hpid ) {
|
|
|
|
ADDR_IS_LI(*lpaddr) = FALSE;
|
|
|
|
#if defined(TARGET_MIPS) || defined(TARGET_ALPHA) || defined(TARGET_PPC)
|
|
|
|
// The opposite of the code in UnFixupAddr -- Remove the 1 which was
|
|
// stuck in to make sure we did not think it was an absolute.
|
|
|
|
lpaddr->addr.seg = 0;
|
|
|
|
#endif // TARGET_MIPS || TARGET_ALPHA || TARGET_PPC
|
|
|
|
} else {
|
|
|
|
// Based on the symbol handler handle find our internal data structure
|
|
// for the dll.
|
|
|
|
hmdi = LLFind ( LlmdiFromHprc ( HprcFromHpid(hpid) ), 0,
|
|
(LPVOID)&emiAddr ( *lpaddr ), (LONG) emdiEMI );
|
|
|
|
if ( hmdi == 0 ) {
|
|
|
|
ADDR_IS_LI(*lpaddr) = FALSE;
|
|
|
|
} else {
|
|
|
|
LPMDI lpmdi = LLLock ( hmdi );
|
|
WORD wsel;
|
|
LPSGI lpsgi;
|
|
unsigned short seg;
|
|
|
|
// If we could not find an internal structure for the DLL
|
|
// then it must be some type of error.
|
|
|
|
if ( lpmdi == NULL ) {
|
|
return xosdUnknown;
|
|
}
|
|
|
|
if (lpmdi->cobj == -1) {
|
|
if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
|
|
return xosdUnknown;
|
|
}
|
|
}
|
|
|
|
// If the segment/selector is 0 then it must be an absolute symbol
|
|
// and we therefore don't need to do any conversion.
|
|
//
|
|
// If we could get no information describing the symbol information
|
|
// then we can't do any conversion.
|
|
|
|
if ( lpmdi->lpgsi == NULL ) {
|
|
LLUnlock( hmdi );
|
|
SHWantSymbols( (HEXE)(emiAddr( *lpaddr )) );
|
|
lpmdi = LLLock ( hmdi );
|
|
lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)(emiAddr( *lpaddr )) );
|
|
}
|
|
|
|
seg = GetAddrSeg( *lpaddr );
|
|
|
|
if ( seg > 0 ) {
|
|
if (lpmdi->lpgsi) {
|
|
|
|
// Get the linker index number for the segment number
|
|
// and assure that it is valid.
|
|
|
|
wsel = (WORD) (GetAddrSeg( *lpaddr ) - 1);
|
|
if ( wsel >= lpmdi->lpgsi->csgMax ) {
|
|
|
|
// Linker index is either not valid or not yet loaded
|
|
|
|
return xosdUnknown;
|
|
} else {
|
|
|
|
// We know which section it comes from. To compute the
|
|
// real offset we need to add the following items
|
|
// together.
|
|
//
|
|
// original offset GetAddrOff( *lpaddr )
|
|
// offset of index in section lpsgi->doffseg
|
|
// (this is the group offset)
|
|
// offset of section from base of rgobjd[physSeg-1].offset
|
|
// image
|
|
//
|
|
// The segment can just be loaded from the MAP. Notice
|
|
// that we will infact "lose" information in this
|
|
// conversion sometimes. Specifically a cs:data address
|
|
// after unfixup and fixup will come out ds:data. This
|
|
// is "expected" behavior.
|
|
|
|
lpsgi = &lpmdi->lpgsi->rgsgi[ wsel ];
|
|
|
|
if (lpmdi->rgobjd[(lpsgi->isgPhy-1)].wPad == 0) {
|
|
return xosdUnknown;
|
|
}
|
|
|
|
GetAddrOff ( *lpaddr ) += lpsgi->doffseg;
|
|
|
|
GetAddrOff( *lpaddr ) +=
|
|
(UOFFSET) (lpmdi->rgobjd[ (lpsgi->isgPhy - 1) ]. offset);
|
|
|
|
// Make sure we adjust to the original start (just in case the
|
|
// image was modified since the CV info was written).
|
|
//
|
|
// rgobjd contains the VA for each section start.
|
|
// lpSecStart contains the calculated RVA for the section start.
|
|
|
|
if (lpmdi->lpDebug->lpSecStart) {
|
|
GetAddrOff ( *lpaddr ) +=
|
|
lpmdi->lpDebug->lpSecStart[(lpsgi->isgPhy - 1)].Offset -
|
|
(lpmdi->rgobjd[(lpsgi->isgPhy - 1)].offset -
|
|
lpmdi->lpBaseOfDll);
|
|
}
|
|
seg = lpmdi->rgobjd[(lpsgi->isgPhy - 1)].wSel;
|
|
}
|
|
|
|
GetAddrSeg ( *lpaddr ) = seg;
|
|
}
|
|
}
|
|
|
|
// Set the bits describing the address
|
|
|
|
ADDR_IS_REAL(*lpaddr) = lpmdi->fRealMode;
|
|
ADDR_IS_OFF32(*lpaddr) = lpmdi->fOffset32;
|
|
ADDR_IS_FLAT(*lpaddr) = lpmdi->fFlatMode;
|
|
ADDR_IS_LI(*lpaddr) = FALSE;
|
|
|
|
if (lpmdi->lpDebug->lpOmapFrom) {
|
|
DWORD off = ConvertOmapFromSrc( lpmdi, lpaddr->addr.off );
|
|
if (off) {
|
|
lpaddr->addr.off = off;
|
|
}
|
|
}
|
|
|
|
// Now release the module description
|
|
|
|
LLUnlock ( hmdi );
|
|
}
|
|
}
|
|
|
|
return xosdNone;
|
|
} /* FixupAddr() */
|
|
|
|
|
|
XOSD
|
|
UnFixupAddr(
|
|
HPID hpid,
|
|
LPADDR lpaddr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to convert addresses from Real Physical addresses
|
|
to linker index addresses. Linker index addresses have an advantage
|
|
to the symbol handler in that we know which DLL the address is in.
|
|
|
|
The result of calling UnFixupAddr should be one of the following:
|
|
|
|
1. A true Linker Index address. In this case
|
|
emi == the HEXE (assigned by SH) for the DLL containning the address
|
|
seg == the Section number of the address
|
|
off == the offset in the Section
|
|
|
|
2. Address not in a dll. In this case
|
|
emi == the HPID of the current process
|
|
seg == the physical selector of the address
|
|
off == the offset in the physical selector
|
|
|
|
3. An error
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies the handle to the process the address is in
|
|
lpaddr - Supplies a pointer to the address to be converted. The
|
|
address is converted in place
|
|
|
|
Return Value:
|
|
|
|
XOSD error code
|
|
|
|
--*/
|
|
|
|
{
|
|
HPRC hprc;
|
|
LPPRC lpprc;
|
|
LDT_ENTRY ldt;
|
|
XOSD xosd;
|
|
|
|
// If the address already has the Linker Index bit set then there
|
|
// is no work for use to do.
|
|
|
|
if ( ADDR_IS_LI(*lpaddr) ) {
|
|
return xosdNone;
|
|
}
|
|
|
|
// If the EMI field in the address is not already filled in, then
|
|
// we will now fill it in.
|
|
|
|
if ( emiAddr ( *lpaddr ) == 0 ) {
|
|
SetEmi ( hpid, lpaddr );
|
|
}
|
|
|
|
// Get the internal Process Descriptor structure
|
|
|
|
hprc = HprcFromHpid(hpid);
|
|
|
|
// Is the EMI we got from the address equal to the process handle? if so then
|
|
// we cannot unfix the address and should just set the bits in the mode field.
|
|
|
|
if ( (HPID)emiAddr ( *lpaddr ) != hpid ) {
|
|
LPMDI lpmdi;
|
|
HMDI hmdi = LLFind (LlmdiFromHprc ( hprc ), 0,
|
|
(LPVOID)&emiAddr ( *lpaddr ), (LONG) emdiEMI);
|
|
WORD igsn;
|
|
LPSGI lpsgi;
|
|
unsigned long ulo;
|
|
USHORT seg;
|
|
ULONG iSeg;
|
|
|
|
if (hmdi == 0) {
|
|
|
|
// If we get here we are really messed up. We have a valid (?)
|
|
// emi field set in the ADDR packeet, it is not the process
|
|
// handle, but it does not correspond to a known emi in the
|
|
// current process. Therefore bail out as an error
|
|
|
|
return xosdUnknown;
|
|
}
|
|
|
|
lpmdi = LLLock ( hmdi );
|
|
if ( lpmdi == NULL ) {
|
|
return xosdUnknown;
|
|
}
|
|
|
|
if (lpmdi->cobj == -1) {
|
|
if (GetSectionObjectsFromDM( hpid, lpmdi ) != xosdNone) {
|
|
return xosdUnknown;
|
|
}
|
|
}
|
|
|
|
// Start out by using the "default" set of fields. These are based
|
|
// on what our best guess is for the executable module. This is based
|
|
// on what the DM told use when it loaded the exe.
|
|
|
|
ADDR_IS_REAL(*lpaddr) = lpmdi->fRealMode;
|
|
ADDR_IS_OFF32(*lpaddr) = lpmdi->fOffset32;
|
|
ADDR_IS_FLAT(*lpaddr) = lpmdi->fFlatMode;
|
|
|
|
// If there is not table describing the layout of segments in the exe, there
|
|
// is no debug information and there fore no need to continue process.
|
|
|
|
if ( lpmdi->lpgsi == NULL ) {
|
|
LLUnlock( hmdi );
|
|
SHWantSymbols( (HEXE)(emiAddr( *lpaddr )) );
|
|
lpmdi = LLLock ( hmdi );
|
|
lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)(emiAddr( *lpaddr )) );
|
|
}
|
|
|
|
if (lpmdi->lpDebug->lpOmapTo) {
|
|
DWORD off = ConvertOmapToSrc( lpmdi, lpaddr->addr.off );
|
|
if (off) {
|
|
lpaddr->addr.off = off;
|
|
}
|
|
}
|
|
|
|
if ( lpmdi->lpgsi == NULL ) {
|
|
LLUnlock( hmdi );
|
|
goto itsBogus;
|
|
}
|
|
|
|
lpsgi = lpmdi->lpgsi->rgsgi;
|
|
ulo = (unsigned long)GetAddrOff( *lpaddr );
|
|
seg = (unsigned short)GetAddrSeg( *lpaddr );
|
|
|
|
// First correct out the "segment" portion of the offset.
|
|
//
|
|
// For flat addresses this means that we locate which section
|
|
// number the address fell in and adjust back to that section
|
|
//
|
|
// For non-flat address this mains locate which segment number
|
|
// the selector matches
|
|
|
|
assert(lpmdi->cobj >= 0);
|
|
|
|
if (ADDR_IS_FLAT( *lpaddr )) {
|
|
|
|
// If there's a SecStart table use it (it should contain the section
|
|
// values the symbolic was built with).
|
|
if (lpmdi->lpDebug->lpSecStart) {
|
|
DWORD NewOff = ulo - lpmdi->lpBaseOfDll;
|
|
LPSECSTART SecStart = lpmdi->lpDebug->lpSecStart;
|
|
|
|
for ( iSeg=0; iSeg < lpmdi->cobj; iSeg++) {
|
|
if ((SecStart[iSeg].Offset <= NewOff) &&
|
|
NewOff < (SecStart[iSeg].Offset + SecStart[iSeg].Size)
|
|
) {
|
|
ulo = NewOff - SecStart[iSeg].Offset;
|
|
// ulo -=
|
|
// SecStart[iSeg].Offset -
|
|
// (lpmdi->rgobjd[iSeg].offset - lpmdi->lpBaseOfDll);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
// Then convert to a true rva so we can find it in the symbol tree.
|
|
|
|
for ( iSeg=0; iSeg < lpmdi->cobj; iSeg++) {
|
|
if ((lpmdi->rgobjd[ iSeg ].offset <= ulo) &&
|
|
(ulo < (OFFSET) (lpmdi->rgobjd[ iSeg ].offset +
|
|
lpmdi->rgobjd[ iSeg].cb))
|
|
) {
|
|
ulo -= lpmdi->rgobjd[ iSeg ].offset;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (iSeg=0; iSeg < lpmdi->cobj; iSeg++) {
|
|
if (lpmdi->rgobjd[iSeg].wSel == seg) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (iSeg == lpmdi->cobj) {
|
|
emiAddr( *lpaddr ) = (HEMI) hpid;
|
|
goto itsBogus;
|
|
}
|
|
|
|
iSeg += 1;
|
|
|
|
for( igsn=0; igsn < lpmdi->lpgsi->csgMax; igsn++, lpsgi++ ) {
|
|
|
|
if ( (ULONG)lpsgi->isgPhy == iSeg &&
|
|
lpsgi->doffseg <= ulo &&
|
|
ulo < lpsgi->doffseg + lpsgi->cbSeg ) {
|
|
|
|
GetAddrSeg( *lpaddr ) = (USHORT) (igsn + 1);
|
|
GetAddrOff( *lpaddr ) = ulo - lpsgi->doffseg;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (igsn == lpmdi->lpgsi->csgMax) {
|
|
LLUnlock ( hmdi );
|
|
emiAddr( *lpaddr ) = (HEMI) hpid;
|
|
goto itsBogus;
|
|
}
|
|
LLUnlock ( hmdi );
|
|
|
|
} else {
|
|
|
|
itsBogus:
|
|
if (ADDR_IS_REAL( *lpaddr )) {
|
|
ADDR_IS_FLAT( *lpaddr ) = FALSE;
|
|
ADDR_IS_OFF32( *lpaddr ) = FALSE;
|
|
} else {
|
|
|
|
// See if the segment matches the flat segment. If it does not
|
|
// then we must be in a non-flat segment.
|
|
|
|
lpprc = LLLock( hprc );
|
|
|
|
if ((lpaddr->addr.seg == 0) ||
|
|
(lpprc->dmi.fAlwaysFlat) ||
|
|
(lpaddr->addr.seg == lpprc->selFlatCs) ||
|
|
(lpaddr->addr.seg == lpprc->selFlatDs)) {
|
|
|
|
ADDR_IS_FLAT(*lpaddr) = TRUE;
|
|
ADDR_IS_OFF32(*lpaddr) = TRUE;
|
|
ADDR_IS_REAL(*lpaddr) = FALSE;
|
|
|
|
} else {
|
|
|
|
xosd = SendRequestX(dmfQuerySelector, hpid, NULL,
|
|
sizeof(SEGMENT), &GetAddrSeg(*lpaddr) );
|
|
|
|
if (xosd != xosdNone) {
|
|
LLUnlock(hprc);
|
|
return xosd;
|
|
}
|
|
|
|
memcpy( &ldt, LpDmMsg->rgb, sizeof(ldt));
|
|
|
|
ADDR_IS_FLAT(*lpaddr) = FALSE;
|
|
ADDR_IS_OFF32(*lpaddr) = (BYTE) ldt.HighWord.Bits.Default_Big;
|
|
ADDR_IS_REAL(*lpaddr) = FALSE;
|
|
}
|
|
LLUnlock( hprc );
|
|
}
|
|
|
|
#if !defined (TARGET_i386)
|
|
|
|
// This line is funny. We assume that all addresses
|
|
// which have a segment of 0 to be absolute symbols.
|
|
// We therefore set the segment to 1 just to make sure
|
|
// that it is not zero.
|
|
|
|
lpaddr->addr.seg = 1;
|
|
#endif // ! TARGET_i386
|
|
}
|
|
|
|
ADDR_IS_LI(*lpaddr) = TRUE;
|
|
return xosdNone;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
UpdateRegisters (
|
|
HPRC hprc,
|
|
HTHD hthd
|
|
)
|
|
{
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
|
|
SendRequest ( dmfReadReg, HpidFromHprc ( hprc ), HtidFromHthd ( hthd ) );
|
|
memcpy ( &lpthd->regs, LpDmMsg->rgb, sizeof ( lpthd->regs ) );
|
|
|
|
|
|
lpthd->drt = drtCntrlPresent | drtAllPresent;
|
|
|
|
LLUnlock ( hthd );
|
|
}
|
|
|
|
void
|
|
UpdateSpecialRegisters (
|
|
HPRC hprc,
|
|
HTHD hthd
|
|
)
|
|
{
|
|
#ifdef TARGET_i386
|
|
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
|
|
SendRequest ( dmfReadRegEx, HpidFromHprc ( hprc ), HtidFromHthd ( hthd ) );
|
|
|
|
if (lpthd->dwcbSpecial) {
|
|
//
|
|
// in kernel mode...
|
|
//
|
|
memcpy ( lpthd->pvSpecial, LpDmMsg->rgb, lpthd->dwcbSpecial );
|
|
lpthd->regs.Dr0 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr0;
|
|
lpthd->regs.Dr1 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr1;
|
|
lpthd->regs.Dr2 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr2;
|
|
lpthd->regs.Dr3 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr3;
|
|
lpthd->regs.Dr6 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr6;
|
|
lpthd->regs.Dr7 = ((PKSPECIAL_REGISTERS)(LpDmMsg->rgb))->KernelDr7;
|
|
} else {
|
|
//
|
|
// User mode
|
|
//
|
|
lpthd->regs.Dr0 = ((LPDWORD)(LpDmMsg->rgb))[0];
|
|
lpthd->regs.Dr1 = ((LPDWORD)(LpDmMsg->rgb))[1];
|
|
lpthd->regs.Dr2 = ((LPDWORD)(LpDmMsg->rgb))[2];
|
|
lpthd->regs.Dr3 = ((LPDWORD)(LpDmMsg->rgb))[3];
|
|
lpthd->regs.Dr6 = ((LPDWORD)(LpDmMsg->rgb))[4];
|
|
lpthd->regs.Dr7 = ((LPDWORD)(LpDmMsg->rgb))[5];
|
|
}
|
|
|
|
lpthd->drt &= ~drtSpecialDirty;
|
|
lpthd->drt |= drtSpecialPresent;
|
|
|
|
LLUnlock ( hthd );
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
XOSD
|
|
DoGetContext(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPVOID lpv
|
|
)
|
|
{
|
|
XOSD xosd = SendRequest ( dmfReadReg, hpid, htid );
|
|
if (xosd == xosdNone) {
|
|
memcpy ( *(LPVOID *)lpv, LpDmMsg->rgb, sizeof (CONTEXT) );
|
|
}
|
|
return xosd;
|
|
}
|
|
|
|
|
|
XOSD
|
|
DoSetContext(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPVOID lpv
|
|
)
|
|
{
|
|
return SendRequestX( dmfWriteReg, hpid, htid, sizeof(CONTEXT), lpv );
|
|
}
|
|
|
|
|
|
void
|
|
RegisterEmi (
|
|
HPID hpid,
|
|
LPREMI lpremi
|
|
)
|
|
{
|
|
HLLI llmdi;
|
|
HMDI hmdi;
|
|
LPMDI lpmdi;
|
|
LPSGI lpsgi;
|
|
LPSGI lpsgiMax;
|
|
USHORT usOvlMax = 0;
|
|
|
|
|
|
llmdi = LlmdiFromHprc( HprcFromHpid ( hpid ) );
|
|
assert( llmdi != 0 );
|
|
|
|
hmdi = LLFind( llmdi, 0, lpremi->lsz, (LONG)emdiName );
|
|
|
|
if (hmdi == 0) {
|
|
hmdi = LLFind( llmdi, 0, &lpremi->hemi, (LONG)emdiEMI );
|
|
}
|
|
|
|
assert( hmdi != 0 );
|
|
|
|
lpmdi = LLLock ( hmdi );
|
|
assert( lpmdi != NULL );
|
|
|
|
assert( lpremi->hemi != 0 );
|
|
|
|
lpmdi->hemi = lpremi->hemi;
|
|
|
|
#ifdef OSDEBUG4
|
|
lpmdi->lpDebug = (LPDEBUGDATA)SHGetDebugData( (HIND)(lpremi->hemi) );
|
|
|
|
// Get the GSN info table from the symbol handler
|
|
if ( lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HIND)(lpremi->hemi) ) )
|
|
#else
|
|
lpmdi->lpDebug = (LPDEBUGDATA)SHGetDebugData( (HEXE)(lpremi->hemi) );
|
|
|
|
// Get the GSN info table from the symbol handler
|
|
if ( lpmdi->lpgsi = (LPGSI)SHLpGSNGetTable( (HEXE)(lpremi->hemi) ) )
|
|
#endif
|
|
{
|
|
|
|
//
|
|
// If real mode, do some patch magic.
|
|
//
|
|
if ( lpmdi->fRealMode ) {
|
|
|
|
int i;
|
|
|
|
assert( lpmdi->cobj );
|
|
assert( lpmdi->rgobjd );
|
|
|
|
lpmdi->cobj = lpmdi->lpgsi->csgMax+1;
|
|
lpmdi->rgobjd = MHRealloc(lpmdi->rgobjd,
|
|
sizeof(OBJD)*lpmdi->cobj);
|
|
memset(lpmdi->rgobjd, 0, sizeof(OBJD)*(lpmdi->cobj));
|
|
|
|
lpsgi = lpmdi->lpgsi->rgsgi;
|
|
lpsgiMax = lpsgi + lpmdi->lpgsi->csgMax;
|
|
|
|
for( i=0; lpsgi < lpsgiMax; lpsgi++, i++ ) {
|
|
|
|
lpmdi->rgobjd[ i ].wSel = (WORD)(lpsgi->doffseg + lpmdi->StartingSegment);
|
|
lpmdi->rgobjd[ i ].wPad = 1;
|
|
lpmdi->rgobjd[ i ].cb = (DWORD) -1;
|
|
|
|
lpsgi->doffseg = 0;
|
|
|
|
}
|
|
}
|
|
|
|
// Determine if child is overlaid and, if so, how many overlays
|
|
lpsgi = lpmdi->lpgsi->rgsgi;
|
|
lpsgiMax = lpsgi + lpmdi->lpgsi->csgMax;
|
|
for( ; lpsgi < lpsgiMax; lpsgi++ ) {
|
|
|
|
// iovl == 0xFF is reserved, it means no overlay specified.
|
|
// we should ignore 0xFF in iovl. Linker uses it
|
|
// to (insert lots of hand-waving here) support COMDATS
|
|
if ( lpsgi->iovl < 0xFF ) { // [02]
|
|
usOvlMax = max( usOvlMax, lpsgi->iovl );
|
|
}
|
|
}
|
|
#ifndef TARGET32
|
|
// Setup the overlay table
|
|
if ( usOvlMax ) {
|
|
lpmdi->lpsel = MHRealloc( lpmdi->lpsel, sizeof( WORD ) * usOvlMax + 1 );
|
|
memset( &lpmdi->lpsel [ 1 ], 0, sizeof( WORD ) * usOvlMax );
|
|
}
|
|
#endif // !TARGET32
|
|
}
|
|
LLUnlock ( hmdi );
|
|
|
|
// purge the emi cache (get rid of old, now invalid hpid/emi pairs)
|
|
CleanCacheOfEmi();
|
|
}
|
|
|
|
|
|
void
|
|
UpdateProcess (
|
|
HPRC hprc
|
|
)
|
|
{
|
|
assert ( hprc != NULL );
|
|
EnterCriticalSection(&csCache);
|
|
|
|
{
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
|
|
FlushPTCache();
|
|
|
|
hprcCurr = hprc;
|
|
hpidCurr = lpprc->hpid;
|
|
pidCurr = lpprc->pid;
|
|
|
|
LLUnlock ( hprc );
|
|
}
|
|
LeaveCriticalSection(&csCache);
|
|
}
|
|
|
|
|
|
HEMI
|
|
HemiFromHmdi (
|
|
HMDI hmdi
|
|
)
|
|
{
|
|
LPMDI lpmdi = LLLock ( hmdi );
|
|
HEMI hemi = lpmdi->hemi;
|
|
|
|
LLUnlock ( hmdi );
|
|
return hemi;
|
|
}
|
|
|
|
|
|
void
|
|
FlushPTCache (
|
|
void
|
|
)
|
|
{
|
|
EnterCriticalSection(&csCache);
|
|
|
|
hprcCurr = NULL;
|
|
hpidCurr = NULL;
|
|
pidCurr = 0;
|
|
|
|
hthdCurr = NULL;
|
|
htidCurr = NULL;
|
|
tidCurr = 0;
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
}
|
|
|
|
|
|
HPRC
|
|
ValidHprcFromHpid(
|
|
HPID hpid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
only return an hprc if there is a real process for it.
|
|
the other version will return an hprc whose process has
|
|
not been created or has been destroyed.
|
|
|
|
Arguments:
|
|
|
|
hpid - Supplies hpid to look for in HPRC list.
|
|
|
|
Return Value:
|
|
|
|
An HPRC or NULL.
|
|
|
|
--*/
|
|
{
|
|
HPRC hprcT;
|
|
HPRC hprc = NULL;
|
|
LPPRC lpprc;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hpid == hpidCurr ) {
|
|
|
|
hprc = hprcCurr;
|
|
|
|
} else {
|
|
|
|
if ( hpid != NULL ) {
|
|
hprc = LLFind ( llprc, NULL, (LPVOID)&hpid, 0 );
|
|
}
|
|
|
|
if ( hprc != NULL ) {
|
|
lpprc = LLLock( hprcT = hprc );
|
|
if (lpprc->stat == statDead) {
|
|
hprc = NULL;
|
|
}
|
|
LLUnlock( hprcT );
|
|
}
|
|
if ( hprc != NULL ) {
|
|
UpdateProcess ( hprc );
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return hprc;
|
|
}
|
|
|
|
|
|
HPRC
|
|
HprcFromHpid (
|
|
HPID hpid
|
|
)
|
|
{
|
|
HPRC hprc = NULL;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hpid == hpidCurr ) {
|
|
|
|
hprc = hprcCurr;
|
|
|
|
} else {
|
|
|
|
if ( hpid != NULL ) {
|
|
hprc = LLFind ( llprc, NULL, (LPVOID)&hpid, 0 );
|
|
}
|
|
|
|
if ( hprc != NULL ) {
|
|
UpdateProcess ( hprc );
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return hprc;
|
|
}
|
|
|
|
|
|
HPRC
|
|
HprcFromPid (
|
|
PID pid
|
|
)
|
|
{
|
|
HPRC hprc;
|
|
BOOL fFound = FALSE;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( pid == pidCurr ) {
|
|
|
|
hprc = hprcCurr;
|
|
|
|
} else {
|
|
|
|
for ( hprc = LLNext ( llprc, 0 );
|
|
!fFound && hprc != 0;
|
|
hprc = LLNext ( llprc, hprc ) ) {
|
|
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
fFound = lpprc->pid == pid;
|
|
LLUnlock ( hprc );
|
|
}
|
|
|
|
if ( !fFound ) {
|
|
hprc = NULL;
|
|
} else {
|
|
UpdateProcess ( hprc );
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return hprc;
|
|
}
|
|
|
|
|
|
HPID
|
|
HpidFromHprc (
|
|
HPRC hprc
|
|
)
|
|
{
|
|
HPID hpid = NULL;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hprc == hprcCurr ) {
|
|
hpid = hpidCurr;
|
|
} else if ( hprc != NULL ) {
|
|
UpdateProcess ( hprc );
|
|
hpid = hpidCurr;
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return hpid;
|
|
}
|
|
|
|
|
|
PID
|
|
PidFromHprc (
|
|
HPRC hprc
|
|
)
|
|
{
|
|
PID pid = 0;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hprc == hprcCurr ) {
|
|
pid = pidCurr;
|
|
} else if ( hprc != NULL ) {
|
|
UpdateProcess ( hprc );
|
|
pid = pidCurr;
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return pid;
|
|
}
|
|
|
|
|
|
void
|
|
UpdateThread (
|
|
HTHD hthd
|
|
)
|
|
{
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hthd == NULL ) {
|
|
FlushPTCache();
|
|
} else {
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
|
|
UpdateProcess ( lpthd->hprc );
|
|
|
|
hthdCurr = hthd;
|
|
htidCurr = lpthd->htid;
|
|
tidCurr = lpthd->tid;
|
|
|
|
LLUnlock ( hthd );
|
|
}
|
|
LeaveCriticalSection(&csCache);
|
|
}
|
|
|
|
|
|
HTHD
|
|
HthdFromTid (
|
|
HPRC hprc,
|
|
TID tid
|
|
)
|
|
{
|
|
LPPRC lpprc;
|
|
HTHD hthd = NULL;
|
|
BOOL fFound = FALSE;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hprc == hprcCurr && tid == tidCurr ) {
|
|
hthd = hthdCurr;
|
|
} else {
|
|
lpprc = LLLock ( hprc );
|
|
|
|
for ( hthd = LLNext ( lpprc->llthd, 0 );
|
|
!fFound && hthd != 0;
|
|
hthd = LLNext ( lpprc->llthd, hthd ) ) {
|
|
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
fFound = lpthd->tid == tid;
|
|
|
|
LLUnlock ( hthd );
|
|
}
|
|
|
|
LLUnlock ( hprc );
|
|
|
|
if ( fFound ) {
|
|
UpdateThread ( hthd );
|
|
} else {
|
|
hthd = NULL;
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return hthd;
|
|
}
|
|
|
|
|
|
HTHD
|
|
HthdFromHtid (
|
|
HPRC hprc,
|
|
HTID htid
|
|
)
|
|
{
|
|
HTHD hthd = NULL;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hprc == hprcCurr && htid == htidCurr ) {
|
|
hthd = hthdCurr;
|
|
} else if ( hprc != NULL ) {
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
hthd = LLFind ( lpprc->llthd, NULL, (LPVOID)&htid, 0 );
|
|
LLUnlock ( hprc );
|
|
}
|
|
UpdateThread ( hthd );
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return hthd;
|
|
}
|
|
|
|
|
|
HTID
|
|
HtidFromHthd (
|
|
HTHD hthd
|
|
)
|
|
{
|
|
HTID htid = NULL;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hthd == hthdCurr ) {
|
|
htid = htidCurr;
|
|
} else if ( hthd != NULL ) {
|
|
UpdateThread ( hthd );
|
|
htid = htidCurr;
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return htid;
|
|
}
|
|
|
|
|
|
TID
|
|
TidFromHthd (
|
|
HTHD hthd
|
|
)
|
|
{
|
|
TID tid = 0;
|
|
|
|
EnterCriticalSection(&csCache);
|
|
|
|
if ( hthd == hthdCurr ) {
|
|
tid = tidCurr;
|
|
} else if ( hthd != NULL ) {
|
|
UpdateThread ( hthd );
|
|
tid = tidCurr;
|
|
}
|
|
|
|
LeaveCriticalSection(&csCache);
|
|
|
|
return tid;
|
|
}
|
|
|
|
|
|
|
|
HLLI LlthdFromHprc ( HPRC hprc ) {
|
|
HLLI llthd = 0;
|
|
|
|
if ( hprc != NULL ) {
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
llthd = lpprc->llthd;
|
|
LLUnlock ( hprc );
|
|
}
|
|
|
|
return llthd;
|
|
}
|
|
|
|
HLLI LlmdiFromHprc ( HPRC hprc ) {
|
|
HLLI llmdi = 0;
|
|
|
|
if ( hprc != NULL ) {
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
llmdi = lpprc->llmdi;
|
|
LLUnlock ( hprc );
|
|
}
|
|
|
|
return llmdi;
|
|
}
|
|
|
|
STAT StatFromHprc ( HPRC hprc ) {
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
STAT stat = lpprc->stat;
|
|
LLUnlock ( hprc );
|
|
return stat;
|
|
}
|
|
|
|
#ifndef OSDEBUG4
|
|
|
|
XOSD
|
|
GetPrompt(
|
|
HPID hpid,
|
|
HTID htid,
|
|
LPPROMPTMSG lppm
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sets the search path in the DM
|
|
|
|
Arguments:
|
|
|
|
hpid - process
|
|
htid - thread
|
|
Len - length of prompt buffer
|
|
Prompt - Path to search, PATH if null
|
|
|
|
|
|
Return Value:
|
|
|
|
xosd error code
|
|
|
|
--*/
|
|
|
|
{
|
|
XOSD xosd;
|
|
|
|
xosd = SendRequestX( dmfGetPrompt, hpid, htid,
|
|
lppm->len+sizeof(PROMPTMSG), lppm );
|
|
if (xosd == xosdNone) {
|
|
memcpy( lppm, LpDmMsg->rgb, lppm->len+sizeof(PROMPTMSG) );
|
|
}
|
|
return xosd;
|
|
}
|
|
#endif
|
|
|
|
//**************************************************************************
|
|
//
|
|
// global stack walking api support functions
|
|
//
|
|
// these are the callbacks used by imagehlp.dll
|
|
//
|
|
// there are custom callbacks in each of the emdpdev.c files
|
|
//
|
|
//**************************************************************************
|
|
|
|
HMDI
|
|
SwGetMdi(
|
|
HPID hpid,
|
|
DWORD Address
|
|
)
|
|
{
|
|
HLLI hlli = 0;
|
|
HMDI hmdi = 0;
|
|
LPMDI lpmdi = NULL;
|
|
|
|
|
|
hlli = LlmdiFromHprc( HprcFromHpid ( hpid ));
|
|
|
|
do {
|
|
|
|
hmdi = LLNext( hlli, hmdi );
|
|
if (hmdi) {
|
|
lpmdi = LLLock( hmdi );
|
|
if (lpmdi) {
|
|
//
|
|
// we have a pointer to a module so lets see if its the one...
|
|
//
|
|
if (Address >= lpmdi->lpBaseOfDll &&
|
|
Address < lpmdi->lpBaseOfDll+lpmdi->dwSizeOfDll ) {
|
|
|
|
LLUnlock( hmdi );
|
|
return hmdi;
|
|
|
|
}
|
|
LLUnlock( hmdi );
|
|
}
|
|
}
|
|
|
|
} while (hmdi);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SwGetModuleBase(
|
|
HPID hpid,
|
|
DWORD ReturnAddress
|
|
)
|
|
{
|
|
HLLI hlli = 0;
|
|
HMDI hmdi = 0;
|
|
LPMDI lpmdi = NULL;
|
|
|
|
|
|
hmdi = SwGetMdi( hpid, ReturnAddress );
|
|
if (!hmdi) {
|
|
return 0;
|
|
}
|
|
|
|
lpmdi = LLLock( hmdi );
|
|
if (lpmdi) {
|
|
LLUnlock( hmdi );
|
|
return lpmdi->lpBaseOfDll;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
XOSD
|
|
DebugPacket (
|
|
DBC dbc,
|
|
HPID hpid,
|
|
HTID htid,
|
|
DWORD wValue,
|
|
LPBYTE lpb
|
|
)
|
|
{
|
|
XOSD xosd = xosdContinue;
|
|
HPRC hprc = HprcFromHpid ( hpid );
|
|
HTHD hthd = HthdFromHtid ( hprc, htid );
|
|
LONG emdi;
|
|
LPTHD lpthd;
|
|
LPPRC lpprc;
|
|
|
|
if (hthd) {
|
|
lpthd = LLLock(hthd);
|
|
lpthd->drt = drtNonePresent;
|
|
LLUnlock(hthd);
|
|
}
|
|
|
|
|
|
/* Do any preprocessing on the packet before sending the notification
|
|
* on to the debugger. For example, the wValue and lValue might need
|
|
* some munging. Also, if the notification shouldn't be passed on to
|
|
* the debugger, then set xosd = xosdNone or some other value other
|
|
* than xosdContinue.
|
|
*/
|
|
|
|
switch ( dbc ) {
|
|
case dbceAssignPID:
|
|
{
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
|
|
assert ( wValue == sizeof ( PID ) );
|
|
lpprc->pid = *( (PID *) lpb );
|
|
lpprc->stat = statStarted;
|
|
LLUnlock ( hprc );
|
|
}
|
|
xosd = xosdNone;
|
|
break;
|
|
|
|
case dbcCreateThread:
|
|
|
|
if (!hprc) {
|
|
//
|
|
// happens during forced termination.
|
|
//
|
|
htid = 0;
|
|
CallTL ( tlfReply, hpid, sizeof ( HTID ), (LPVOID)&htid );
|
|
xosd = xosdUnknown;
|
|
|
|
} else {
|
|
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
|
|
assert ( wValue == sizeof ( TID ) );
|
|
xosd = CreateThreadStruct ( hpid, *( (TID *) lpb ), &htid );
|
|
|
|
CallTL ( tlfReply, hpid, sizeof ( HTID ), (LPVOID)&htid );
|
|
if ( xosd == xosdNone ) {
|
|
xosd = xosdContinue;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case dbcNewProc:
|
|
{
|
|
HPRC hprcT;
|
|
HPID hpidT;
|
|
LPPRC lpprc;
|
|
LPNPP lpnpp;
|
|
|
|
/*
|
|
* lpb points to an NPP (New Process Packet). The PID is
|
|
* the PID of the debuggee; fReallyNew indicates if this is
|
|
* really a new process or if it already existed but hasn't
|
|
* been seen before by OSDebug.
|
|
*/
|
|
|
|
assert ( wValue == sizeof(NPP) );
|
|
lpnpp = (LPNPP) lpb;
|
|
|
|
// See EMCallBackDB in od.c
|
|
|
|
CallDB ( dbcoNewProc, hpid, htid, CEXM_MDL_native,
|
|
sizeof ( HPID ), (LPVOID)&hpidT );
|
|
|
|
(void) CreateHprc ( hpidT );
|
|
|
|
hprcT = HprcFromHpid ( hpidT );
|
|
lpprc = LLLock ( hprcT );
|
|
lpprc->pid = lpnpp->pid;
|
|
lpprc->stat = statStarted;
|
|
LLUnlock ( hprcT );
|
|
|
|
CallTL ( tlfReply, hpid, sizeof ( HPID ), (LPVOID)&hpidT );
|
|
|
|
SyncHprcWithDM( hpidT );
|
|
|
|
wValue = (UINT)hpidT;
|
|
lpb = (LPBYTE) (LONG) lpnpp->fReallyNew;
|
|
if ( xosd == xosdNone ) {
|
|
xosd = xosdContinue;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case dbcThreadTerm:
|
|
|
|
if (!hprc) {
|
|
//
|
|
// happens during forced termination.
|
|
//
|
|
return xosdUnknown;
|
|
}
|
|
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
lpthd = LLLock(hthd);
|
|
lpthd->fRunning = FALSE;
|
|
LLUnlock(hthd);
|
|
|
|
case dbcProcTerm:
|
|
|
|
/*
|
|
* For both of these notifications, the incoming wValue is
|
|
* sizeof(ULONG), and lpb contains a ULONG which is the exit
|
|
* code of the process or thread. For the debugger, set
|
|
* wValue = 0 and lValue = exit code.
|
|
*/
|
|
|
|
assert ( wValue == sizeof(ULONG) );
|
|
wValue = 0;
|
|
lpb = (LPBYTE) (*(ULONG*)lpb);
|
|
break;
|
|
|
|
#ifdef OSDEBUG4
|
|
case dbcDeleteThread:
|
|
#else
|
|
case dbcThreadDestroy:
|
|
#endif
|
|
|
|
lpthd = LLLock(hthd);
|
|
lpthd->tid = (TID)-1;
|
|
LLUnlock(hthd);
|
|
|
|
assert ( wValue == sizeof(ULONG) );
|
|
wValue = 0;
|
|
lpb = (LPBYTE) (*(ULONG*)lpb);
|
|
break;
|
|
|
|
case dbcModLoad:
|
|
|
|
if (!hprc) {
|
|
//
|
|
// happens during forced termination.
|
|
//
|
|
return xosdUnknown;
|
|
}
|
|
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
if (hthd) {
|
|
lpthd = LLLock(hthd);
|
|
lpthd->fRunning = FALSE;
|
|
LLUnlock(hthd);
|
|
}
|
|
xosd = LoadFixups ( hpid, (LPMODULELOAD) lpb );
|
|
break;
|
|
|
|
case dbcModFree: /* Should use dbceModFree* */
|
|
assert(FALSE);
|
|
break;
|
|
|
|
case dbceModFree32:
|
|
emdi = emdiBaseAddr;
|
|
modFree:
|
|
{
|
|
HMDI hmdi;
|
|
LPMDI lpmdi;
|
|
HLLI llmdi;
|
|
|
|
llmdi = LlmdiFromHprc ( hprc );
|
|
assert( llmdi );
|
|
|
|
hmdi = LLFind( llmdi, 0, lpb, emdi);
|
|
assert( hmdi );
|
|
|
|
lpmdi = LLLock( hmdi );
|
|
lpb = (LPBYTE) lpmdi->hemi;
|
|
LLUnlock( hmdi );
|
|
|
|
dbc = dbcModFree;
|
|
}
|
|
break;
|
|
|
|
case dbceModFree16:
|
|
emdi = emdiMTE;
|
|
goto modFree;
|
|
break;
|
|
|
|
case dbcExecuteDone:
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
lpthd = LLLock(hthd);
|
|
lpthd->fRunning = FALSE;
|
|
LLUnlock(hthd);
|
|
break;
|
|
|
|
case dbcStep:
|
|
case dbcThreadBlocked:
|
|
case dbcSignal:
|
|
|
|
case dbcAsyncStop:
|
|
case dbcBpt:
|
|
case dbcCheckBpt:
|
|
case dbcEntryPoint:
|
|
case dbcLoadComplete:
|
|
{
|
|
LPBPR lpbpr = (LPBPR) lpb;
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
|
|
/*
|
|
* This assert should be re-enabled when all the DMs are
|
|
* fixed to send the proper packet back!!
|
|
*/
|
|
|
|
assert ( wValue == sizeof ( BPR ) );
|
|
|
|
PurgeCache ( );
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
lpthd->fRunning = FALSE;
|
|
|
|
|
|
#if defined(TARGET_i386)
|
|
lpthd->regs.SegCs = lpbpr->segCS;
|
|
lpthd->regs.SegSs = lpbpr->segSS;
|
|
lpthd->regs.Eip = lpbpr->offEIP;
|
|
lpthd->regs.Ebp = lpbpr->offEBP;
|
|
#elif defined(TARGET_MIPS)
|
|
lpthd->regs.XFir = lpbpr->offEIP;
|
|
lpthd->regs.XIntSp = lpbpr->offEBP;
|
|
#elif defined(TARGET_ALPHA)
|
|
lpthd->regs.Fir = lpbpr->offEIP;
|
|
lpthd->regs.IntSp = lpbpr->offEBP;
|
|
#elif defined(TARGET_PPC)
|
|
lpthd->regs.Iar = lpbpr->offEIP;
|
|
lpthd->regs.Gpr1 = lpbpr->offEBP;
|
|
#else
|
|
|
|
#error "unrecognized target CPU"
|
|
|
|
#endif
|
|
|
|
lpthd->fFlat = lpbpr->fFlat;
|
|
lpthd->fOff32 = lpbpr->fOff32;
|
|
lpthd->fReal = lpbpr->fReal;
|
|
|
|
lpthd->drt = drtCntrlPresent;
|
|
|
|
LLUnlock( hthd );
|
|
}
|
|
|
|
break;
|
|
|
|
case dbcException:
|
|
{
|
|
LPEPR lpepr = (LPEPR) lpb;
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
ADDR addr = {0};
|
|
|
|
PurgeCache ( );
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
lpthd->fRunning = FALSE;
|
|
|
|
|
|
#if defined(TARGET_i386)
|
|
lpthd->regs.SegCs = lpepr->bpr.segCS;
|
|
lpthd->regs.SegSs = lpepr->bpr.segSS;
|
|
lpthd->regs.Eip = lpepr->bpr.offEIP;
|
|
lpthd->regs.Ebp = lpepr->bpr.offEBP;
|
|
#elif defined(TARGET_MIPS)
|
|
lpthd->regs.XFir = lpepr->bpr.offEIP;
|
|
lpthd->regs.XIntSp = lpepr->bpr.offEBP;
|
|
#elif defined(TARGET_ALPHA)
|
|
lpthd->regs.Fir = lpepr->bpr.offEIP;
|
|
lpthd->regs.IntSp = lpepr->bpr.offEBP;
|
|
#elif defined(TARGET_PPC)
|
|
lpthd->regs.Iar = lpepr->bpr.offEIP;
|
|
lpthd->regs.Gpr1 = lpepr->bpr.offEBP;
|
|
#else
|
|
|
|
#error "unrecognized target CPU"
|
|
|
|
#endif
|
|
|
|
lpthd->fFlat = lpepr->bpr.fFlat;
|
|
lpthd->fOff32 = lpepr->bpr.fOff32;
|
|
lpthd->fReal = lpepr->bpr.fReal;
|
|
|
|
lpthd->drt = drtCntrlPresent;
|
|
|
|
LLUnlock( hthd );
|
|
}
|
|
break;
|
|
|
|
#if 0
|
|
|
|
// BUGBUG kentf review this... do we need to support it?
|
|
// if so, it should turn into a dbcInfoAvail and
|
|
// a breakpoint or something.
|
|
case dbcNtRip:
|
|
{
|
|
LPNT_RIP lprip = (LPNT_RIP) lpb;
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
ADDR addr = {0};
|
|
|
|
assert ( wValue == sizeof ( NT_RIP ) );
|
|
|
|
PurgeCache ( );
|
|
lpprc = LLLock(hprc);
|
|
lpprc->fRunning = FALSE;
|
|
LLUnlock(hprc);
|
|
lpthd->fRunning = FALSE;
|
|
|
|
|
|
#if defined(TARGET_i386)
|
|
lpthd->regs.SegCs = lprip->bpr.segCS;
|
|
lpthd->regs.SegSs = lprip->bpr.segSS;
|
|
lpthd->regs.Eip = lprip->bpr.offEIP;
|
|
lpthd->regs.Ebp = lprip->bpr.offEBP;
|
|
#elif defined(TARGET_MIPS)
|
|
lpthd->regs.XFir = lprip->bpr.offEIP;
|
|
lpthd->regs.XIntSp = lprip->bpr.offEBP;
|
|
#elif defined(TARGET_ALPHA)
|
|
lpthd->regs.Fir = lprip->bpr.offEIP;
|
|
lpthd->regs.IntSp = lprip->bpr.offEBP;
|
|
#elif defined(TARGET_PPC)
|
|
lpthd->regs.Iar = lprip->bpr.offEIP;
|
|
lpthd->regs.Gpr1 = lprip->bpr.offEBP;
|
|
#else
|
|
|
|
#error "unrecognized target CPU"
|
|
|
|
#endif
|
|
|
|
lpthd->fFlat = lprip->bpr.fFlat;
|
|
lpthd->fOff32 = lprip->bpr.fOff32;
|
|
lpthd->fReal = lprip->bpr.fReal;
|
|
|
|
lpthd->drt = drtCntrlPresent;
|
|
|
|
LLUnlock (hthd );
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case dbceCheckBpt:
|
|
assert(FALSE);
|
|
xosd = xosdNone;
|
|
break;
|
|
|
|
#if 0
|
|
|
|
// BUGBUG kentf yuck. what is this supposed to do?
|
|
|
|
case dbcError:
|
|
{
|
|
static char sz[500];
|
|
XOSD xosdErr = *( (XOSD *)lpb );
|
|
|
|
sprintf(sz,
|
|
"DMX32%04d: %s",
|
|
-(int)xosdErr,
|
|
EmError(xosdErr));
|
|
|
|
wValue = xosdErr;
|
|
lpb = sz;
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case dbceSegLoad:
|
|
{
|
|
SLI sli;
|
|
HMDI hmdi;
|
|
LPMDI lpmdi;
|
|
UINT i;
|
|
|
|
sli = *( (LPSLI) lpb );
|
|
|
|
hmdi = LLFind( LlmdiFromHprc( hprc ), 0, &sli.mte,
|
|
(LONG) emdiMTE);
|
|
|
|
assert( hmdi );
|
|
|
|
lpmdi = LLLock(hmdi );
|
|
|
|
if (sli.wSegNo >= lpmdi->cobj) {
|
|
i = lpmdi->cobj;
|
|
lpmdi->cobj = sli.wSegNo+1;
|
|
lpmdi->rgobjd = MHRealloc(lpmdi->rgobjd,
|
|
sizeof(OBJD)*lpmdi->cobj);
|
|
memset(&lpmdi->rgobjd[i], 0, sizeof(OBJD)*(lpmdi->cobj - i));
|
|
}
|
|
lpmdi->rgobjd[ sli.wSegNo ].wSel = sli.wSelector;
|
|
lpmdi->rgobjd[ sli.wSegNo ].wPad = 1;
|
|
lpmdi->rgobjd[ sli.wSegNo ].cb = (DWORD) -1;
|
|
|
|
LLUnlock( hmdi );
|
|
|
|
//
|
|
// Let the shell know that a new segment was loaded, so it
|
|
// can try to instantiate virtual BPs.
|
|
//
|
|
xosd=CallDB( dbcSegLoad, hpid, htid, CEXM_MDL_native, 0,
|
|
(LPVOID)sli.wSelector );
|
|
xosd=xosdNone;
|
|
|
|
}
|
|
break;
|
|
|
|
case dbceSegMove:
|
|
{
|
|
SLI sli;
|
|
HMDI hmdi;
|
|
LPMDI lpmdi;
|
|
|
|
sli = *( (LPSLI) lpb );
|
|
|
|
hmdi = LLFind( LlmdiFromHprc( hprc ), 0, &sli.mte,
|
|
(LONG) emdiMTE);
|
|
|
|
assert( hmdi );
|
|
|
|
lpmdi = LLLock(hmdi );
|
|
|
|
assert(sli.wSegNo > 0 );
|
|
if (sli.wSegNo < lpmdi->cobj) {
|
|
lpmdi->rgobjd[ sli.wSegNo - 1 ].wSel = sli.wSelector;
|
|
}
|
|
|
|
LLUnlock( hmdi );
|
|
}
|
|
break;
|
|
|
|
case dbcCanStep:
|
|
{
|
|
CANSTEP CanStep;
|
|
|
|
assert ( wValue == sizeof ( ADDR ) );
|
|
|
|
UnFixupAddr( hpid, (LPADDR) lpb);
|
|
|
|
xosd=CallDB(dbc,hpid,htid,CEXM_MDL_native,0,(LPVOID)lpb);
|
|
|
|
if ( xosd == xosdNone ) {
|
|
CanStep = *((CANSTEP*)lpb);
|
|
} else {
|
|
CanStep.Flags = CANSTEP_NO;
|
|
}
|
|
|
|
CallTL ( tlfReply, hpid, sizeof( CanStep ), &CanStep );
|
|
|
|
xosd = xosdNone;
|
|
}
|
|
break;
|
|
|
|
case dbceGetOffsetFromSymbol:
|
|
{
|
|
ADDR addr = {0};
|
|
if (SHGetPublicAddr(&addr, lpb)) {
|
|
FixupAddr(hpid, &addr);
|
|
}
|
|
CallTL( tlfReply, hpid, sizeof(addr.addr.off), (LPVOID)&addr.addr.off );
|
|
xosd = xosdNone;
|
|
}
|
|
break;
|
|
|
|
case dbceGetSymbolFromOffset:
|
|
{
|
|
LPSTR p;
|
|
ADDR addr;
|
|
LPDMSYM lpds;
|
|
STACKFRAME stk = {0};
|
|
LPSTR fname = SHAddrToPublicName( (LPADDR)lpb, &addr );
|
|
StackWalkSetup( hpid, htid, &stk );
|
|
if (fname) {
|
|
lpds = (LPDMSYM)malloc( sizeof(DMSYM) + strlen(fname) + 1);
|
|
strcpy(lpds->fname,fname);
|
|
free(fname);
|
|
} else {
|
|
lpds = (LPDMSYM)malloc( sizeof(DMSYM) + 32 );
|
|
sprintf( lpds->fname, "<unknown>0x%08x", GetAddrOff(*(LPADDR)lpb) );
|
|
}
|
|
lpds->AddrSym = addr;
|
|
lpds->Ra = stk.AddrReturn.Offset;
|
|
CallTL( tlfReply, hpid, sizeof(DMSYM) + strlen(lpds->fname) + 1 , (LPVOID)lpds );
|
|
free( lpds );
|
|
xosd = xosdNone;
|
|
}
|
|
break;
|
|
|
|
case dbceEnableCache:
|
|
EnableCache( hpid, htid, *(LPDWORD)lpb );
|
|
CallTL( tlfReply, hpid, 0, NULL );
|
|
xosd = xosdNone;
|
|
break;
|
|
|
|
case dbcLastAddr:
|
|
assert( wValue == sizeof( ADDR ) );
|
|
|
|
UnFixupAddr( hpid, (LPADDR) lpb );
|
|
|
|
xosd = CallDB(dbc, hpid, htid, CEXM_MDL_native, 0, (LPVOID) lpb);
|
|
|
|
if ( xosd == xosdNone ) {
|
|
FixupAddr( hpid, (LPADDR) lpb );
|
|
}
|
|
|
|
CallTL( tlfReply, hpid, sizeof(ADDR), lpb);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((xosd == xosdContinue) && (dbc < dbcMax) && (dbc != dbcModLoad)) {
|
|
xosd = CallDB ( dbc, hpid, htid, CEXM_MDL_native, wValue, (LPVOID)lpb );
|
|
}
|
|
|
|
switch ( dbc ) {
|
|
|
|
case dbcProcTerm:
|
|
{
|
|
LPPRC lpprc = LLLock ( hprc );
|
|
lpprc->stat = statDead;
|
|
LLUnlock ( hprc );
|
|
}
|
|
break;
|
|
|
|
case dbcThreadTerm:
|
|
{
|
|
LPTHD lpthd = LLLock ( hthd );
|
|
lpthd->fVirtual = TRUE;
|
|
LLUnlock ( hthd );
|
|
}
|
|
break;
|
|
|
|
case dbcDeleteProc:
|
|
break;
|
|
|
|
#ifdef OSDEBUG4
|
|
case dbcDeleteThread:
|
|
#else
|
|
case dbcThreadDestroy:
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return xosd;
|
|
} /* DebugPacket() */
|
|
|
|
XOSD
|
|
GetSectionObjectsFromDM(
|
|
HPID hpid,
|
|
LPMDI lpmdi
|
|
)
|
|
{
|
|
XOSD xosd;
|
|
xosd = SendRequestX( dmfGetSections,
|
|
hpid,
|
|
0,
|
|
sizeof(DWORD),
|
|
&lpmdi->lpBaseOfDll );
|
|
if (xosd != xosdNone) {
|
|
return xosd;
|
|
}
|
|
|
|
lpmdi->cobj = *(LPDWORD)LpDmMsg->rgb;
|
|
lpmdi->rgobjd = (LPOBJD) MHAlloc ( sizeof(OBJD) * lpmdi->cobj);
|
|
if ( lpmdi->rgobjd == NULL ) {
|
|
assert( "load cannot create rgobjd" && FALSE );
|
|
return xosdOutOfMemory;
|
|
}
|
|
|
|
memcpy( lpmdi->rgobjd,
|
|
LpDmMsg->rgb+sizeof(DWORD),
|
|
sizeof(OBJD) * lpmdi->cobj );
|
|
|
|
return xosdNone;
|
|
}
|