Windows NT 4.0 source code leak
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

/*++
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;
}