Windows2000/private/windbg64/windbg/apisupp.c
2020-09-30 17:12:32 +02:00

2451 lines
69 KiB
C

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
apisupp.c
Abstract:
This file contains the set of routines which preform the interfacing
between the debugger dlls and the shell exe.
Author:
Jim Schaad (jimsch)
Environment:
Win32 - User
--*/
/*** INCLUDES *********/
#include "precomp.h"
#pragma hdrstop
extern ULONG ulPseudo[];
extern char in386mode;
extern LPSHF Lpshf;
extern CXF CxfIp;
char is_assign;
LPTD LptdFuncEval = NULL;
BOOL EstablishConnection(LPSTR);
BOOL SYSetProfileString(LPCSTR szName, LPCSTR szValue);
BOOL SYGetProfileString(LPCSTR szName, LPSTR szValue, ULONG cbValue,
ULONG * pcbRet);
// these are used only by Symbol serve routines
// GetSymbolFileFromServer
// CloseSymbolServer
HINSTANCE ghSrv = 0;
CHAR gszSrvName[_MAX_PATH * 2];
LPSTR gszSrvParams = NULL;
PSYMBOLSERVERPROC gfnSymbolServer = NULL;
PSYMBOLSERVERCLOSEPROC gfnSymbolServerClose = NULL;
char *
__cdecl
t_itoa(
int a,
char * b,
int c
)
{
return _itoa(a, b, c);
}
char * _cdecl t_ultoa(ulong a, char * b, int c)
{
return _ultoa(a, b, c);
}
int
__cdecl
d_sprintf(
char * a,
const char * b,
...
)
{
char rgch[100];
int returnvalue;
va_list va_arg;
va_start(va_arg, b);
strcpy(rgch, b);
returnvalue = vsprintf(a, (char *) rgch, va_arg) ;
va_end(va_arg);
return returnvalue;
} /* d_sprintf() */
int
__cdecl
d_eprintf(
const char * a,
char * b,
char * c,
int d
)
{
char rgch1[100];
char rgch2[100];
char rgch3[100];
char rgch4[100];
strcpy(rgch1, a);
strcpy(rgch2, b);
strcpy(rgch3, c);
sprintf(rgch4, rgch1, rgch2, rgch3, d);
DebugBreak();
return( strlen(rgch4) );
} /* d_eprintf() */
TCHAR OutQ[10*2048]={0}; // Max 10 dprintfs in queue
ULONG indx=0;
void
DPRINTF(
LPSTR fmt,
...
) {
TCHAR *buff= &OutQ[indx*2048];
va_list args;
DWORD cb;
va_start(args, fmt);
indx = (indx + 1) % 10;
cb = _vsnprintf(buff, 2047, fmt, args);
buff[cb] = '\0';
PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, TRUE, (LPARAM)buff );
va_end(args);
}
// Symbol server stuff
void
CloseSymbolServer(
VOID
)
{
if (!ghSrv)
return;
if (gfnSymbolServerClose)
gfnSymbolServerClose();
FreeLibrary(ghSrv);
ghSrv = 0;
*gszSrvName = 0;
gszSrvParams = NULL;
gfnSymbolServer = NULL;
gfnSymbolServerClose = NULL;
}
BOOL
GetSymbolFileFromServer(
IN LPCSTR ServerInfo,
IN LPCSTR FileName,
IN DWORD num1,
IN DWORD num2,
IN DWORD num3,
OUT LPSTR FilePath
)
{
// initialize server, if needed
if (!ghSrv) {
ghSrv = (HINSTANCE) INVALID_HANDLE_VALUE;
strcpy(gszSrvName, &ServerInfo[7]);
if (!*gszSrvName)
return FALSE;
// BUGBUG: gszSrvParams is no longer needed because it is
// now implemented in the local variable, 'params'
// Still, we need to zero out this location to get gszSrvName.
gszSrvParams = (PCHAR) strchr((PUCHAR) gszSrvName, '*');
if (!gszSrvParams )
return FALSE;
*gszSrvParams++ = '\0';
ghSrv = LoadLibrary(gszSrvName);
if (ghSrv) {
gfnSymbolServer = (PSYMBOLSERVERPROC)GetProcAddress(ghSrv, "SymbolServer");
if (!gfnSymbolServer) {
FreeLibrary(ghSrv);
ghSrv = (HINSTANCE) INVALID_HANDLE_VALUE;
}
gfnSymbolServerClose = (PSYMBOLSERVERCLOSEPROC)GetProcAddress(ghSrv, "SymbolServerClose");
} else {
ghSrv = (HINSTANCE) INVALID_HANDLE_VALUE;
}
}
// bail, if we have no valid server
if (ghSrv == INVALID_HANDLE_VALUE)
return FALSE;
strcpy(gszSrvName, &ServerInfo[7]);
gszSrvParams = (PCHAR) strchr((PUCHAR) gszSrvName, '*');
*gszSrvParams++ = '\0';
return gfnSymbolServer(gszSrvParams, FileName, num1, num2, num3, FilePath);
}
int
OSDAPI
LBQuit(
DWORD ui
)
{
return 0;
} /* LBQuit() */
int
OSDAPI
AssertOut(
LPSTR lszMsg,
LPSTR lszFile,
DWORD iln
)
{
ShowAssert(lszMsg, iln, lszFile);
return TRUE;
} /* AssertOut() */
VOID
DLoadedSymbols(
SHE she,
LSZ pszPath
)
{
HEXE emi;
LPSTR pszErrText;
LPSTR pszModName;
DWORD dwLen;
emi = SHGethExeFromName((char *)pszPath);
Assert(emi != 0);
ModListModLoad( SHGetExeName( emi ), she );
if (she != sheSuppressSyms && g_contWorkspace_WkSp.m_bVerbose) {
pszErrText = SHLszGetErrorText(she);
if (she == sheNoSymbols) {
pszModName = SHGetExeName( emi );
} else {
pszModName = SHGetSymFName( emi );
}
if (NULL == pszModName || 0 == strlen(pszModName)) {
// Let's at least print something out.
Assert(!"A function maimed the name of the module. Ignorable error.");
pszModName = pszPath;
}
dwLen = 32;
if (pszErrText) {
dwLen += strlen(pszErrText);
}
dwLen += strlen(pszModName);
LPSTR pszBuf = (LPSTR) malloc( dwLen );
Assert(pszBuf);
sprintf( pszBuf, "Module Load: %s (%s)\r\n", pszModName, pszErrText ? pszErrText : "" );
PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, TRUE, (LPARAM)pszBuf );
}
return;
}
BOOL
SYGetDefaultShe(
LSZ pszModuleName,
SHE *pShe
)
/*++
Description:
This is a callback for the back end to determine whether symbols
should be loaded at startup or defered until needed.
Arguments:
pszModuleName - if NULL we are getting the default symbol loading behavior
If not NULL, then the front end is being queryed as to whether the
symbol loading behavior is different than the default behavior.
This is not a hack but the design of the debugger. Previously,
all module loading behavior could be specified by the user, but
this was causing some serious problems since users could never
really figure out what or why some symbols were loaded at specific
times.
pShe - Indicates when the symbols should be loaded:
sheNone - Load symbols for this module at startup
sheDefer - Defer symbols loading until the module is needed.
sheSuppress - Suppress symbol loading for this module.
Returns:
TRUE - success
FALSE - failure
--*/
{
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
if ( pszModuleName ) {
// Load these symbols at startup because the kernel debugger needs them.
_tsplitpath( pszModuleName, NULL, NULL, szFName, szExt );
if ( !_tcsicmp( szFName, _T("nt") ) ||
( !_tcsicmp( szFName, _T("hal") ) && !_tcsicmp( szExt, _T(".dll") ) )
) {
*pShe = sheNone; // sheNone - means load at startup
return TRUE;
}
}
return ModListGetDefaultShe( pszModuleName, pShe );
}
void
LBLog(
LSZ lsz
)
{
OutputDebugString(lsz);
return;
} /* LBLog() */
PVOID
MHAlloc(
size_t cb
)
{
return malloc(cb);
} /* MHAlloc() */
PVOID
MHAllocHuge(
LONG l,
UINT ui
)
{
return MHAlloc(l * ui );
} /* MHAllocHuge() */
PVOID
MHRealloc(
PVOID lpv,
size_t cb
)
{
return realloc(lpv, cb);
} /* MHRealloc() */
LPTSTR
MHStrdup(
LPCTSTR p
)
{
return _tcsdup(p);
}
void
MHFree(
PVOID lpv
)
{
free(lpv);
} /* MHFree() */
DWORD
OSDAPI
DHGetNumber(
LPSTR String,
LPLONG Result
)
/*++
Routine Description:
Evaluate an expression, returning a long.
Arguments:
lpv - supplies pointer to the string to convert to a number.
result - returns the value of the expression as a long
Returns:
the error code returned by CPGetCastNbr
--*/
{
return (DWORD) CPGetCastNbr ( String,
T_LONG,
radix,
fCaseSensitive,
&CxfIp,
(LPSTR) Result,
NULL,
g_contWorkspace_WkSp.m_bMasmEval
);
}
HDEP
MMAllocHmem(
size_t cb
)
{
return (HDEP) calloc(1, cb);
} /* MMAllocHmem() */
HDEP
MMReallocHmem(
HDEP hmem,
size_t cb
)
{
LPBYTE p = (LPBYTE)hmem;
size_t s = p ? _msize(p) : 0;
if (cb > s) {
p = (LPBYTE) realloc(p, cb);
if (p) {
ZeroMemory(p+s, cb-s);
}
}
return (HDEP)p;
} /* MMReallocHmem() */
VOID
MMFreeHmem(
HDEP hmem
)
{
free((LPVOID)hmem);
} /* MMFreeHmem() */
LPVOID
MMLpvLockMb(
HDEP hmem
)
{
return (LPVOID)hmem;
} /* MMLpvLockMb() */
void
MMbUnlockMb(
HDEP hmem
)
{
return;
} /* MMbUnlockMb() */
HANDLE
SYOpen(
LSZ lsz
)
{
DWORD dwShareAttributes;
EstablishConnection(lsz);
if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
dwShareAttributes = (FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE);
} else {
dwShareAttributes = (FILE_SHARE_READ | FILE_SHARE_WRITE);
}
return CreateFile(lsz,
GENERIC_READ,
dwShareAttributes,
NULL,
OPEN_EXISTING,
0,
NULL);
} /* SYOpen() */
VOID
SYClose(
HANDLE hFile
)
{
CloseHandle((HANDLE) hFile);
return;
} /* SYClose() */
UINT
SYRead(
HANDLE hFile,
LPB pch,
UINT cb
)
{
DWORD dwBytesRead;
ReadFile(hFile, pch, cb, &dwBytesRead, NULL);
return (dwBytesRead);
} /* SYRead() */
long
SYLseek(
HANDLE hFile,
LONG cbOff,
UINT iOrigin
)
{
return SetFilePointer(hFile, cbOff, NULL, iOrigin);
} /* SYLseek() */
long
SYTell(
HANDLE hFile
)
{
return SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
} /* SYTell() */
static LPSTR LpBaseDir = NULL;
VOID
SetFindExeBaseName(
LPSTR lpName
)
{
LPSTR p;
if (LpBaseDir) {
free(LpBaseDir);
LpBaseDir = 0;
}
if (lpName) {
// search from tail for '\\'
if ( p = strrchr(lpName, '\\') ) {
if (p == lpName || (p == (lpName + 2) && lpName[1] == ':')) {
if (!IsDBCSLeadByte(*lpName))
p += 1;
}
} else if ( lpName[0] != '\0' && lpName[1] == ':' ) {
if (!IsDBCSLeadByte(*lpName))
p = lpName + 2;
}
if (p) {
LpBaseDir = (LPSTR) malloc((size_t)(p - lpName) + 1);
Assert(LpBaseDir);
strncpy(LpBaseDir, lpName, (size_t)(p - lpName));
LpBaseDir[p-lpName] = '\0';
}
}
}
BOOL
IsExistingConnection(
LPSTR RemoteName
)
{
DWORD rc;
HANDLE hEnum;
DWORD Entries;
NETRESOURCE *nrr = NULL;
DWORD cb;
DWORD i;
DWORD ss;
BOOL rval = FALSE;
rc = WNetOpenEnum( RESOURCE_CONNECTED, RESOURCETYPE_ANY, 0, NULL, &hEnum );
if (rc != NO_ERROR) {
return FALSE;
}
ss = 0;
cb = 64 * 1024;
nrr = (NETRESOURCE *) calloc( cb, sizeof(char));
Assert(nrr);
while( TRUE ) {
Entries = (DWORD)-1;
rc = WNetEnumResource( hEnum, &Entries, nrr, &cb );
if (rc == ERROR_NO_MORE_ITEMS) {
break;
} else if (rc == ERROR_MORE_DATA) {
cb += 16;
nrr = (NETRESOURCE *) realloc( nrr, cb );
Assert(nrr);
ZeroMemory( nrr, cb );
continue;
} else if (rc != NO_ERROR) {
break;
}
for (i=0; i<Entries; i++) {
if (_stricmp( nrr[i].lpRemoteName, RemoteName ) == 0) {
rval = TRUE;
break;
}
}
}
free( nrr );
WNetCloseEnum( hEnum );
return rval;
}
BOOL
EstablishConnection(
LPSTR FileName
)
{
NETRESOURCE nr;
DWORD rc;
DWORD i;
LPSTR RemoteName;
LPSTR p;
if ((FileName[0] != '\\') || (FileName[1] != '\\')) {
return FALSE;
}
p = (LPSTR) strchr( (LPBYTE) &FileName[2], '\\' );
if (!p) {
// malformed name
return FALSE;
}
p = (LPSTR) strchr( (LPBYTE) p+1, '\\' );
if (!p) {
p = &FileName[strlen(FileName)];
}
i = (DWORD)(p - FileName);
RemoteName = (LPSTR) malloc( i + 4 );
Assert(RemoteName);
strncpy( RemoteName, FileName, i );
RemoteName[i] = 0;
if (IsExistingConnection( RemoteName )) {
free( RemoteName );
return TRUE;
}
nr.dwScope = 0;
nr.dwType = RESOURCETYPE_DISK;
nr.dwDisplayType = 0;
nr.dwUsage = 0;
nr.lpLocalName = NULL;
nr.lpRemoteName = RemoteName;
nr.lpComment = NULL;
nr.lpProvider = NULL;
rc = WNetAddConnection2( &nr, NULL, NULL, 0 );
if (rc != NO_ERROR) {
free( RemoteName );
return FALSE;
}
free( RemoteName );
return TRUE;
}
void
DeleteSymFileLoadErrList(
SYM_FILE_LOAD_ERR * const pListHead
)
{
Assert(pListHead);
PSYM_FILE_LOAD_ERR pCur = pListHead;
do {
if (pCur->hSymFile) {
CloseHandle(pCur->hSymFile);
pCur->hSymFile = NULL;
}
if (pCur->pszExtendedSHE) {
free(pCur->pszExtendedSHE);
pCur->pszExtendedSHE = NULL;
}
if (pCur->pszSHE) {
free(pCur->pszSHE);
pCur->pszSHE = NULL;
}
if (pListHead != pCur) {
RemoveEntryList( (PLIST_ENTRY) pCur );
free(pCur);
}
pCur = pListHead->Flink;
} while ( !IsListEmpty( (PLIST_ENTRY) pListHead ) );
}
BOOL
CALLBACK
FindDebugFileCallback(
HANDLE hFileHandle,
LPSTR pszFileName,
PVOID pvCallerData
)
/*++
Routine Description:
Arguments:
FileHandle - Handle to a symbol file
FileName - path to the symbol file
CallerData - Validation data....
--*/
{
Assert(hFileHandle);
Assert(pszFileName);
Assert(pvCallerData);
SHE sheTmp;
PFIND_SYM_FILE pFindSymFileData = (PFIND_SYM_FILE) pvCallerData;
SYM_FILE_LOAD_ERR TmpLoadErr = {0};
Assert(_tcslen(pszFileName) < sizeof(TmpLoadErr.szSymFilePath) / sizeof(TCHAR));
// Make sure that the head of the list has been initialized.
Assert(pFindSymFileData->LoadErr.Flink);
Assert(pFindSymFileData->LoadErr.Blink);
Assert(pFindSymFileData->pfnValidateExe);
// Copy data into the TmpLoadErr struct
_tcscpy(TmpLoadErr.szSymFilePath, pszFileName);
TmpLoadErr.hSymFile = NULL;
TmpLoadErr.she = pFindSymFileData->pfnValidateExe( hFileHandle,
pFindSymFileData->pVldChk);
// Use a temp value for the switch so we don't have to use a goto, or some uglier
// hack. We don't want to modify 'TmpLoadErr.she' because we need to preserve the
// actual sym handler error.
sheTmp = TmpLoadErr.she;
// Ignore checksum errors for NTDLL.DLL and KERNEL32.DLL
if (sheBadChecksum == sheTmp) {
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
_splitpath(pFindSymFileData->szImageFilePath, NULL, NULL, szFName, szExt);
if ( !_tcsicmp(szExt, ".dll") ) {
// We have a dll. Is it ntdll or kernel32?
if ( !_tcsicmp(szFName, "ntdll") || !_tcsicmp(szFName, "kernel32") ) {
// Lie, and say that there were no errors loading either one of these
sheTmp = sheNone;
}
}
}
switch ( sheTmp ) {
default:
// Since we are returning FALSE, DbgHelp will close the handle to this file,
// and we need to keep it open, so let's duplicate the file handle
Dbg(DuplicateHandle(GetCurrentProcess(),
hFileHandle,
GetCurrentProcess(),
&TmpLoadErr.hSymFile,
0,
TRUE,
DUPLICATE_SAME_ACCESS
));
// Append all of the symbol files that were examined, and any load errors
if (sheBadChecksum == TmpLoadErr.she) {
// extended error text associated with this error.
TmpLoadErr.pszExtendedSHE = WKSP_DynaLoadStringWithArgs(g_hInst,
DBG_Checksum_Mismatch,
pFindSymFileData->pVldChk->SymCheckSum,
pFindSymFileData->pVldChk->ImgCheckSum
);
} else if (sheBadTimeStamp == TmpLoadErr.she) {
// extended error text associated with this error.
TmpLoadErr.pszExtendedSHE = WKSP_DynaLoadStringWithArgs(g_hInst,
DBG_Timestamp_Mismatch,
pFindSymFileData->pVldChk->SymTimeDateStamp,
pFindSymFileData->pVldChk->ImgTimeDateStamp
);
}
TmpLoadErr.pszSHE = _strdup(SHLszGetErrorText(TmpLoadErr.she));
// Do we need to create a new list entry?
if (!pFindSymFileData->LoadErr.hSymFile) {
// The list head hasn't been used, use it now.
pFindSymFileData->LoadErr = TmpLoadErr;
InitializeListHead((PLIST_ENTRY) &pFindSymFileData->LoadErr);
} else {
// The list head has been used, create a new entry.
PSYM_FILE_LOAD_ERR pLoadErr = (PSYM_FILE_LOAD_ERR)
malloc( sizeof(SYM_FILE_LOAD_ERR) );
*pLoadErr = TmpLoadErr;
InsertTailList((PLIST_ENTRY) &pFindSymFileData->LoadErr, (PLIST_ENTRY) pLoadErr);
}
// File did not contain symbolic info, keep searching.
pFindSymFileData->bFound = FALSE;
return FALSE; // keep searching
case sheNoSymbols:
// File did not contain symbolic info, keep searching. If it doesn't have any symbolic
// info, don't list, it won't do us any good anyways.
pFindSymFileData->bFound = FALSE;
// Let DbgHelp close the file handle
return FALSE; // keep searching
case sheNone:
// We found the correct symbols. We can stop searching.
// Now we have to delete the entire list of previously
// tested symbols.
pFindSymFileData->bFound = TRUE;
// If we return TRUE, DbgHelp will not close the file handle
TmpLoadErr.hSymFile = hFileHandle;
// Iinform the user of any error codes.
if (sheBadChecksum == TmpLoadErr.she) {
// extended error text associated with this error.
TmpLoadErr.pszExtendedSHE = WKSP_DynaLoadStringWithArgs(g_hInst,
DBG_Checksum_Mismatch,
pFindSymFileData->pVldChk->SymCheckSum,
pFindSymFileData->pVldChk->ImgCheckSum
);
} else if (sheBadTimeStamp == TmpLoadErr.she) {
// extended error text associated with this error.
TmpLoadErr.pszExtendedSHE = WKSP_DynaLoadStringWithArgs(g_hInst,
DBG_Timestamp_Mismatch,
pFindSymFileData->pVldChk->SymTimeDateStamp,
pFindSymFileData->pVldChk->ImgTimeDateStamp
);
}
TmpLoadErr.pszSHE = _strdup(SHLszGetErrorText(TmpLoadErr.she));
// Delete the entire list.
DeleteSymFileLoadErrList(&pFindSymFileData->LoadErr);
// The copy the symbol data.
pFindSymFileData->LoadErr = TmpLoadErr;
InitializeListHead( (PLIST_ENTRY) &pFindSymFileData->LoadErr );
return TRUE; // Stop searching
}
}
BOOL
SYIgnoreAllSymbolErrors(
VOID
)
{
return g_contWorkspace_WkSp.m_bIgnoreAllSymbolErrors;
}
LPSTR
ExpandPath(
LPSTR lpPath
)
{
LPSTR p, newpath, p1, p2, p3;
CHAR envvar[MAX_PATH];
CHAR envstr[MAX_PATH];
ULONG i, PathMax;
if (!lpPath) {
return(NULL);
}
p = lpPath;
PathMax = strlen(lpPath) + MAX_PATH + 1;
p2 = newpath = (LPSTR) MHAlloc( PathMax );
if (!newpath) {
return(NULL);
}
while( p && *p) {
if (*p == '%') {
i = 0;
p++;
while (p && *p && *p != '%') {
envvar[i++] = *p++;
}
p++;
envvar[i] = '\0';
p1 = envstr;
*p1 = 0;
GetEnvironmentVariable( envvar, p1, MAX_PATH );
while (p1 && *p1) {
*p2++ = *p1++;
if (p2 >= newpath + PathMax) {
PathMax += MAX_PATH;
p3 = (PTSTR) MHRealloc(newpath, PathMax);
if (!p3) {
MHFree(newpath);
return(NULL);
} else {
p2 = p3 + (p2 - newpath);
newpath = p3;
}
}
}
}
*p2++ = *p++;
if (p2 >= newpath + PathMax) {
PathMax += MAX_PATH;
p3 = (PTSTR) MHRealloc(newpath, PathMax);
if (!p3) {
MHFree(newpath);
return(NULL);
} else {
p2 = p3 + (p2 - newpath);
newpath = p3;
}
}
}
*p2 = '\0';
return newpath;
}
HANDLE
FindExecutableImageEx2(
LPSTR FileName,
LPSTR SymbolPath,
LPSTR ImageFilePath,
PFIND_EXE_FILE_CALLBACK Callback,
PVOID CallerData
)
{
PTSTR Start;
PTSTR End;
HANDLE FileHandle = NULL;
TCHAR DirectoryPath[ MAX_PATH ];
PTSTR NewSymbolPath = NULL;
FIND_SYM_FILE *pFileData;
CHAR Drive[_MAX_DRIVE], Dir[_MAX_DIR], SubDirPart[_MAX_DIR], FilePart[_MAX_FNAME], Ext[_MAX_EXT];
BOOL symsrv=TRUE;
__try {
__try {
_splitpath(FileName, Drive, Dir, FilePart, Ext);
NewSymbolPath = ExpandPath(SymbolPath);
if (GetFullPathName( FileName, MAX_PATH, ImageFilePath, &Start )) {
//DPRINTF(NULL, "FindExecutableImageEx-> Looking for %s... ", ImageFilePath);
FileHandle = CreateFile( ImageFilePath,
GENERIC_READ,
OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? (FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE) : (FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL,
OPEN_EXISTING,
0,
NULL
);
if (FileHandle != INVALID_HANDLE_VALUE) {
if (Callback) {
if (!Callback(FileHandle, ImageFilePath, CallerData)) {
//EPRINTF(NULL, "mismatched timestamp\n");
CloseHandle(FileHandle);
FileHandle = INVALID_HANDLE_VALUE;
}
}
if (FileHandle != INVALID_HANDLE_VALUE) {
//EPRINTF(NULL, "OK\n");
MHFree( NewSymbolPath );
return FileHandle;
}
} else {
//EPRINTF(NULL, "no file\n");
}
}
Start = NewSymbolPath;
while (Start && *Start != '\0') {
if (End = _tcschr( Start, ';' )) {
int Len = (int)(End - Start);
Len = min(Len, sizeof(DirectoryPath)-1);
strncpy( DirectoryPath, Start, Len );
DirectoryPath[ Len ] = '\0';
End += 1;
} else {
strcpy( (PCHAR) DirectoryPath, Start );
}
if (!_strnicmp(DirectoryPath, "SYMSRV*", 7)) {
TCHAR FilePath[_MAX_PATH];
// DPRINTF("FindExecutableImageEx-> Searching %s for %s \r\n", DirectoryPath, FileName);
*ImageFilePath = 0;
pFileData = (FIND_SYM_FILE *)CallerData;
if (symsrv && pFileData) {
ULONG ImageSize=pFileData->pVldChk->ImgSize;
// DPRINTF("TS %x, Sz %x ... \r\n", pFileData->pVldChk->ImgTimeDateStamp, pFileData->pVldChk->ImgSize);
strcpy(FilePath, FilePart);
strcat(FilePath, ".dbg");
GetSymbolFileFromServer(DirectoryPath,
FilePath,
pFileData->pVldChk->ImgTimeDateStamp,
pFileData->pVldChk->ImgSize,
0,
ImageFilePath);
symsrv = FALSE;
// DPRINTF("FindExecutableImageEx-> Opening %s... \r\n", ImageFilePath);
if (ImageFilePath[0]) {
// DPRINTF("found \n");
goto found;
}
}
// goto next;
} else if (SearchTreeForFile( (PCHAR) DirectoryPath, FileName, ImageFilePath )) {
//DPRINTF(NULL, "FindExecutableImageEx-> Searching %s for %s... ", DirectoryPath, FileName);
//EPRINTF(NULL, "found\n");
//DPRINTF(NULL, "FindExecutableImageEx-> Opening %s... ", ImageFilePath);
found:
pFileData = (FIND_SYM_FILE *)CallerData;
if (symsrv && pFileData) {
// DPRINTF("TS %x, Sz %x ... \r\n", pFileData->pVldChk->ImgTimeDateStamp, pFileData->pVldChk->ImgSize);
}
FileHandle = CreateFile( ImageFilePath,
GENERIC_READ,
OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? (FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE) : (FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL,
OPEN_EXISTING,
0,
NULL
);
if (FileHandle != INVALID_HANDLE_VALUE) {
if (Callback) {
if (!Callback(FileHandle, ImageFilePath, CallerData)) {
//EPRINTF(NULL, "mismatched timestamp\n");
CloseHandle(FileHandle);
FileHandle = INVALID_HANDLE_VALUE;
}
}
if (FileHandle != INVALID_HANDLE_VALUE) {
//EPRINTF(NULL, "OK\n");
MHFree( NewSymbolPath );
return FileHandle;
}
} else {
//EPRINTF(NULL, "no file\n");
}
} else {
//EPRINTF(NULL, "no file\n");
}
//next:
Start = End;
symsrv = TRUE;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_PARAMETER);
}
ImageFilePath[0] = '\0';
} __except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_PARAMETER);
}
if (FileHandle) {
CloseHandle(FileHandle);
}
if (NewSymbolPath) {
MHFree( NewSymbolPath );
}
return NULL;
}
HANDLE
SYFindExeFile(
PTSTR pszFile,
PTSTR pszFound,
UINT cchFound,
PVLDCHK pVldChk,
PFNVALIDATEEXE pfnValidateExe,
SHE *pSheLoadError
)
/*++
Arguments:
pszFile - Image file we want to find symbols for.
pszFound - Path to the symbol file that will be used for
the image.
cchFound - Size of pszFound
pVldChk - Data used by the validation function to
match the image against the symbol file.
pfnValidateExe - Validation function. Uses the validation data
to match the image with its respective symbol
file
pSheLoadError - Any load error that was found while trying
to match the symbol file to the image.
Returns
Success - File handle to the open symbol file.
Failure - (-1)
--*/
{
Assert(pfnValidateExe);
Assert(pszFile);
Assert(pszFound);
Assert(cchFound);
PTSTR pzSearchPath = NULL;
TCHAR szFname[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFileName[MAX_PATH];
SHE she;
TCHAR rgch[MAX_PATH];
TCHAR szBuf[MAX_PATH];
DWORD len;
DWORD cSP;
HANDLE rVal = INVALID_HANDLE_VALUE; // Not found
FIND_SYM_FILE FindSymFileData = {0};
SYM_FILE_LOAD_ERR TmpLoadErr = {0};
PSYM_FILE_LOAD_ERR pCurLoadErr = NULL;
// Initialize
InitializeListHead( (PLIST_ENTRY) &FindSymFileData.LoadErr );
if (!pszFile || !*pszFile) {
rVal = INVALID_HANDLE_VALUE;
goto finished_searching;
}
if (*pszFile == '#') {
pszFile += 3;
}
_tsplitpath( pszFile, szDrive, szDir, szFname, szExt);
sprintf( szFileName, "%s%s", szFname, szExt );
cSP = ModListGetSearchPath(NULL, 0) + strlen(szDrive) + strlen(szDir) + 2;
if (!cSP) {
pzSearchPath = _strdup("");
} else {
pzSearchPath = (LPSTR) malloc(cSP);
Assert(pzSearchPath);
sprintf( pzSearchPath, "%s%s", szDrive, szDir );
len = strlen(pzSearchPath);
if (len) {
pzSearchPath[len++] = ';';
pzSearchPath[len] = 0;
}
ModListGetSearchPath( &pzSearchPath[len], cSP-len );
len = strlen(pzSearchPath);
Assert(len < cSP);
if (*pzSearchPath && pzSearchPath[len-1] == ';') {
// Kill the trailing semi-colon
pzSearchPath[len-1] = 0;
}
}
FindSymFileData.pfnValidateExe = pfnValidateExe;
FindSymFileData.pVldChk = pVldChk;
_tcscpy(FindSymFileData.szImageFilePath, szFileName);
sprintf( szFileName, "%s%s", szFname, szExt );
// Does the image contain debug info?
FindExecutableImageEx(szFileName,
pzSearchPath,
rgch,
FindDebugFileCallback,
&FindSymFileData
);
if (FindSymFileData.bFound) {
// The image contains debug info
goto done_found;
}
// The image didn't contain debug info, search the sym path
FindDebugInfoFileEx(szFileName,
pzSearchPath,
rgch,
FindDebugFileCallback,
&FindSymFileData
);
if (!FindSymFileData.bFound) {
FindExecutableImageEx2(szFileName,
pzSearchPath,
rgch,
FindDebugFileCallback,
&FindSymFileData
);
}
finished_searching:
if (!FindSymFileData.bFound) {
// None of the symbols on the search path are valid
if (g_contWorkspace_WkSp.m_bIgnoreAllSymbolErrors) {
// Don't prompt the user.
// Load the first symbol with one of the following ignorable errors:
// sheBadChecksum, sheBadTimeStamp, sheCouldntReadImageHeader
pCurLoadErr = &FindSymFileData.LoadErr;
do {
if (sheBadChecksum == pCurLoadErr->she
|| sheBadTimeStamp == pCurLoadErr->she
|| sheCouldntReadImageHeader == pCurLoadErr->she) {
// Store the sym file we picked.
TmpLoadErr = *pCurLoadErr;
// Zero these values out so they don't get freed/closed.
pCurLoadErr->hSymFile = NULL;
pCurLoadErr->pszExtendedSHE = NULL;
pCurLoadErr->pszSHE = NULL;
// Free the list
DeleteSymFileLoadErrList(&FindSymFileData.LoadErr);
// Place the data in the list head
FindSymFileData.LoadErr = TmpLoadErr;
FindSymFileData.bFound = TRUE;
goto done_found;
}
pCurLoadErr = pCurLoadErr->Flink;
} while (&FindSymFileData.LoadErr != pCurLoadErr);
// We didn't find any sym file with an ignorable load error.
rVal = INVALID_HANDLE_VALUE;
// Free the list
DeleteSymFileLoadErrList(&FindSymFileData.LoadErr);
} else {
if (!g_contWorkspace_WkSp.m_bBrowseForSymsOnSymLoadErrors) {
// User doesn't want to be bothered with browsing
rVal = INVALID_HANDLE_VALUE;
// Free the list
DeleteSymFileLoadErrList(&FindSymFileData.LoadErr);
} else {
INT_PTR nRes = ExeBrowseBadSym(&FindSymFileData);
if (IDCANCEL == nRes) {
// User didn't select or specify file
rVal = INVALID_HANDLE_VALUE;
FindSymFileData.bFound = FALSE;
// Free the list
DeleteSymFileLoadErrList(&FindSymFileData.LoadErr);
} else if (IDC_BUT_LOAD == nRes || IDC_BUT_BROWSE == nRes) {
// Make sure it has been initialized
Assert(OsVersionInfo.dwOSVersionInfoSize);
// At this point all we have is the file name. And it is stored in
// FindSymFileData.LoadErr.szSymFilePath
// Free the list
DeleteSymFileLoadErrList(&FindSymFileData.LoadErr);
// Now open the file
FindSymFileData.LoadErr.hSymFile =
SYOpen(FindSymFileData.LoadErr.szSymFilePath);
if (INVALID_HANDLE_VALUE == FindSymFileData.LoadErr.hSymFile) {
// Couldn't open the symbol file.
FindSymFileData.LoadErr.she = sheFileOpen;
FindSymFileData.bFound = FALSE;
} else {
_tsplitpath(FindSymFileData.LoadErr.szSymFilePath,
NULL,
NULL,
NULL,
szExt
);
if ( !_tcsicmp(".pdb", szExt) ) {
// Ignore trying to validate PDB files. Just mark them
// as being ok. The function that called this one will
// correctly validate the PDB.
FindSymFileData.LoadErr.she = sheNone;
} else {
// User wants us to try another file
// Valid sym file?
FindDebugFileCallback(FindSymFileData.LoadErr.hSymFile,
FindSymFileData.LoadErr.szSymFilePath,
&FindSymFileData
);
}
// Just to humor the user, we're going to load this file
// regardless of any errors.
FindSymFileData.bFound = TRUE;
}
} else {
Assert(0);
}
}
}
}
done_found:
// DPRINTF("Mod %s : TS %x, Sz %x ... \r\n", pszFile, FindSymFileData.pVldChk->ImgTimeDateStamp, FindSymFileData.pVldChk->ImgSize);
if (FindSymFileData.bFound) {
PTSTR msgBuf = (PTSTR) malloc( MAX_VAR_MSG_TXT * sizeof(TCHAR) );
// DPRINTF("found ");
sprintf( msgBuf,
"%s for %s (%s%s%s)\n",
FindSymFileData.LoadErr.szSymFilePath,
pszFile,
FindSymFileData.LoadErr.pszSHE ? FindSymFileData.LoadErr.pszSHE : "",
// Add a space between the error msg and the extended info
FindSymFileData.LoadErr.pszExtendedSHE ? " " : "",
FindSymFileData.LoadErr.pszExtendedSHE ? FindSymFileData.LoadErr.pszExtendedSHE : ""
);
PostMessage( Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, TRUE, (LPARAM)msgBuf );
rVal = FindSymFileData.LoadErr.hSymFile;
strncpy(pszFound, FindSymFileData.LoadErr.szSymFilePath, cchFound -1);
pszFound[cchFound -1] = NULL;
}
if (pSheLoadError) {
*pSheLoadError = FindSymFileData.LoadErr.she;
}
if (pzSearchPath) {
free(pzSearchPath);
}
// Zero these values out so they don't get freed/closed.
FindSymFileData.LoadErr.hSymFile = NULL;
// Free the list
DeleteSymFileLoadErrList(&FindSymFileData.LoadErr);
return rVal;
}
XOSD
SYUnFixupAddr(
LPADDR lpaddr
)
{
if (LppdCur == NULL) {
return xosdNone;
}
return OSDUnFixupAddr(LppdCur->hpid, NULL, lpaddr);
}
XOSD
SYFixupAddr(
LPADDR paddr
)
{
if (LppdCur == NULL) {
return xosdNone;
}
return OSDFixupAddr(LppdCur->hpid, NULL, paddr);
}
XOSD
SYSanitizeAddr(
LPADDR paddr
)
{
XOSD xosd;
emiAddr(*paddr) = 0;
if ((xosd = SYUnFixupAddr(paddr)) != xosdNone) {
return xosd;
}
return SYFixupAddr(paddr);
}
UINT SYProcessor(VOID)
{
long l = 0;
Assert(LppdCur);
OSDGetDebugMetric ( LppdCur->hpid, 0, mtrcProcessorType, &l );
return (int) l;
} /* SYProcessor() */
void
SYSetEmi (
HPID hpid,
HTID htid,
LPADDR lpaddr
)
{
Assert ( ! ADDR_IS_LI ( *lpaddr ) );
OSDSetEmi(hpid, htid, lpaddr);
return;
} /* SYSetEmi() */
BOOL
SYGetAddr(
HFRAME hframe,
LPADDR lpaddr,
ADR addrType
)
{
if ((LppdCur == NULL) || (hframe == NULL)) {
return FALSE;
}
return OSDGetAddr ( LppdCur->hpid, (HTID) hframe, addrType,
lpaddr) == xosdNone;
} /* SYGetAddr() */
XOSD
SYGetMemInfo(
LPMEMINFO lpmi
)
{
return OSDGetMemoryInformation(LppdCur->hpid, NULL, lpmi);
}
UINT
WINAPI
DHGetDebuggeeBytes(
ADDR addr,
UINT cb,
void * lpb
)
{
int terrno = errno;
XOSD xosd;
DWORD cbT;
if ((LppdCur == NULL) || (LptdCur == NULL)) { //Sanity check
return 0;
}
if ( ADDR_IS_LI ( addr ) ) {
OSDFixupAddr (LppdCur->hpid, LptdCur->htid, &addr );
}
if (OSDReadMemory(LppdCur->hpid, LptdCur->htid, &addr, lpb, cb, &cbT)
!= xosdNone) {
cbT = 0;
}
errno = terrno;
return cbT;
} /* DHGetDebuggeeBytes() */
/*** DHSetDebuggeeBytes
** Synopsis:
** uint = DHSetDebuggeeBytes(addr, cb, lpb)
** Entry:
** addr - address to write the bytes at
** cb - count of bytes to be written
** lpb - pointer to buffer of bytes to be written
** Returns:
** count of bytes actually written if positive otherwise an
** XOSD error code.
** Description:
** This function will write bytes into the debuggees memory space.
** To do this it uses OSDebug functions
*/
UINT
WINAPI
DHSetDebuggeeBytes(
ADDR addr,
UINT cb,
void * lpb
)
{
int terrno = errno;
DWORD cbT = 0;
XOSD xosd;
if ((LppdCur == NULL) || (LptdCur == NULL)) { //Sanity check
return cbT;
}
if ( ADDR_IS_LI ( addr ) ) {
SYFixupAddr ( &addr );
}
xosd = OSDWriteMemory(LppdCur->hpid, LptdCur->htid, &addr, lpb, cb, &cbT);
errno = terrno;
if (xosd == xosdNone) {
return cbT;
} else {
return 0;
}
} /* DHSetDebuggeeBytes() */
/*** DHGetReg
** Synopsis:
** pshreg = DHGetReg(pshreg, pcxt, pframe)
** Entry:
** pshreg The register structure. The member hReg must contain
** the handle to the register to get.
** pCxt The context packet to use.
** Returns:
** pshreg if successful, NULL if the call could not be completed.
** Description:
** Currently the 8087 registers are not implemented. In the future
** only ST0 will be implemented.
*/
PSHREG
DHGetReg(
PSHREG pShreg,
PCXT pCxt,
HFRAME hFrame
)
{
HPID hpid;
HTID htid;
if (pShreg->hReg >= CV_REG_PSEUDO1 && pShreg->hReg <= CV_REG_PSEUDO9) {
pShreg->Byte4 = ulPseudo[pShreg->hReg - CV_REG_PSEUDO1];
return pShreg;
} else if (LppdCur && LptdCur) {
if (hFrame) {
hpid = LppdCur->hpid;
htid = (HTID) hFrame;
} else {
hpid = LppdCur->hpid;
htid = LptdCur->htid;
}
if (OSDReadRegister( hpid,
htid,
pShreg->hReg,
&pShreg->Byte1 ) == xosdNone) {
return ( pShreg );
} else {
return NULL;
}
} else {
return NULL;
}
} /* DHGetReg() */
/*** DHSetReg
** Synopsis:
** pshreg = DHSetReg( pReg, pCxt, pframe )
** Entry:
** pReg - Register description to be read
** pCxt - context to use reading the register
** pframe
** Returns:
** pointer to register description
** Description:
*/
PSHREG
DHSetReg (
PSHREG pReg,
PCXT pCxt,
HFRAME hFrame
)
{
HPID hpid;
HTID htid;
Unreferenced( pCxt );
if (pReg->hReg >= CV_REG_PSEUDO1 && pReg->hReg <= CV_REG_PSEUDO9) {
ulPseudo[pReg->hReg - CV_REG_PSEUDO1] = pReg->Byte4;
return ( pReg );
}
if ( LppdCur && LptdCur ) {
if (hFrame) {
hpid = LppdCur->hpid;
htid = (HTID) hFrame;
} else {
hpid = LppdCur->hpid;
htid = LptdCur->htid;
}
if (OSDWriteRegister(hpid, htid, pReg->hReg, (void *) &pReg->Byte1 )
== xosdNone) {
return ( pReg );
} else {
return NULL;
}
} else {
return NULL;
}
} /* DHSetReg() */
BOOL
DHSetupExecute(
LPHDEP lphdep
)
/*++
Routine Description:
This function is called from the expression evaluator to setup things
up for a function evaluation call. This request is passed on to the
execution model.
Arguments:
lphdep - Supples a pointer to where a handle is returned
Return Value:
TRUE if something fails
--*/
{
if (LptdCur == NULL) {
return xosdUnknown;
}
LptdCur->fInFuncEval = TRUE;
LptdFuncEval = LptdCur;
return OSDSetupExecute( LppdCur->hpid, LptdCur->htid, lphdep ) != xosdNone;
} /* DHSetupExecute() */
BOOL
DHStartExecute(
HDEP hdep,
LPADDR lpaddr,
BOOL fIgnoreEvents,
SHCALL shcall
)
/*++
Routine Description:
This function is called when the expression evaluator starts
the debugging running a function evaluation. It must be preceded
by a call to DHSetupExecute.
Arguments:
hdep - Supplies the handle to the Execute Function object
lpaddr - Supplies the address to start execution at
fIgnoreEvents - Supplies
fFarRet - Supplies TRUE if a return should be executed
Return Value:
TRUE if something fails
--*/
{
XOSD xosd;
MSG msg;
BOOL fTmp;
if (!LptdFuncEval) {
return 1;
}
xosd = OSDStartExecute(LptdFuncEval->lppd->hpid, hdep, lpaddr,
fIgnoreEvents, shcall == SHFar);
if (xosd != xosdNone) {
return 1;
}
fTmp = SetAutoRunSuppress(TRUE);
while (GetMessage(&msg, NULL, 0, 0)) {
ProcessQCQPMessage(&msg);
if (!LptdFuncEval) {
xosd = 1;
break;
}
if ((msg.message == DBG_REFRESH) &&
(msg.wParam == dbcExecuteDone)) {
xosd = (XOSD) msg.lParam;
break;
}
}
SetAutoRunSuppress(fTmp);
return xosd != xosdNone;
} /* DHStartExecute() */
BOOL
DHCleanUpExecute(
HDEP hdep
)
/*++
Routine Description:
This function is used to clean up after doing a function evalution.
Arguments:
hdep - Supplies the handle to the function evaluation object
Return Value:
TRUE if something fails
--*/
{
if (!LptdFuncEval) {
return TRUE;
}
LptdFuncEval->fInFuncEval = FALSE;
return (OSDCleanUpExecute( LptdFuncEval->lppd->hpid, hdep ) != xosdNone);
} /* DHCleanUpExecute() */
// kcarlos
// BUGBUG
// dead code
/*
LSZ
FullPath(
LSZ lszBuf,
LSZ lszRel,
UINT cbBuf
)
{
char szBuf[500];
char szRel[500];
char * szRet;
strcpy( szRel, lszRel );
if ( szRet = _fullpath( (char *) szBuf, szRel, (size_t)cbBuf ) ) {
strcpy( lszBuf, szBuf );
}
return (LSZ)szRet;
}
*/
// kcarlos
// BUGBUG
// dead code
/*
void
MakePath(
LSZ lszPath,
LSZ lszDrive,
LSZ lszDir,
LSZ lszFName,
LSZ lszExt
)
{
char szPath[500];
char szDrive[256];
char szDir[256];
char szFName[256];
char szExt[256];
strcpy( szDrive, lszDrive );
strcpy( szDir, lszDir );
strcpy( szFName, lszFName );
strcpy( szExt, lszExt );
_makepath( szPath, szDrive, szDir, szFName, szExt );
strcpy( lszPath, szPath );
}
*/
// kcarlos
// BUGBUG
// dead code
/*
UINT
__cdecl
OurSprintf(
LSZ lszBuf,
LSZ lszFmt,
...
)
{
va_list val;
WORD wRet;
char szBuf[256];
char szFmt[256];
strcpy( szFmt, lszFmt );
va_start( val, lszFmt );
wRet = (WORD)vsprintf( szBuf, szFmt, val );
va_end( val );
strcpy( lszBuf, szBuf );
return wRet;
}
*/
// kcarlos
// BUGBUG
// dead code
/*
void
SearchEnv(
LSZ lszFile,
LSZ lszVar,
LSZ lszPath
)
{
char szFile[ 256 ];
char szVar[ 256 ];
char szPath[ 256 ];
strcpy( szFile, lszFile );
strcpy( szVar, lszVar );
_searchenv( szFile, szVar, szPath );
strcpy( lszPath, szPath );
}
*/
// kcarlos
// BUGBUG
// dead code
/*
void
SplitPath(
LSZ lsz1,
LSZ lsz2,
LSZ lsz3,
LSZ lsz4,
LSZ lsz5
)
{
#define _MAX_CVPATH 255
#define _MAX_CVDRIVE 3
#define _MAX_CVDIR 255
#define _MAX_CVFNAME 255
#define _MAX_CVEXT 255
char sz1[ _MAX_CVPATH ];
char sz2[ _MAX_CVDRIVE ];
char sz3[ _MAX_CVDIR ];
char sz4[ _MAX_CVFNAME];
char sz5[ _MAX_CVEXT];
strcpy( sz1, lsz1 );
_splitpath( sz1, sz2, sz3, sz4, sz5 );
if (lsz2 != NULL) strcpy( lsz2, sz2 );
if (lsz3 != NULL) strcpy( lsz3, sz3 );
if (lsz4 != NULL) strcpy( lsz4, sz4 );
if (lsz5 != NULL) strcpy( lsz5, sz5 );
return;
}
*/
LPSTR
FormatSymbol(
HSYM hsym,
PCXT lpcxt
)
{
HDEP hstr;
char szContext[512];
char szStr[512];
char szUndecStr[256];
EEFormatCXTFromPCXT( lpcxt, &hstr, g_contWorkspace_WkSp.m_bShortContext );
if (g_contWorkspace_WkSp.m_bShortContext) {
strcpy( szContext, (LPSTR)MMLpvLockMb(hstr) );
// We check this after the fact to avoid any side affects
// in calling MMLpvLockMb twice.
Assert(strlen(szContext) < sizeof(szContext));
} else {
BPShortenContext( (LPSTR)MMLpvLockMb(hstr), szContext );
}
MMbUnlockMb(hstr);
EEFreeStr(hstr);
FormatHSym(hsym, lpcxt, szStr);
if (*szStr == '?') {
if (UnDecorateSymbolName( szStr,
szUndecStr,
sizeof(szUndecStr),
UNDNAME_COMPLETE |
UNDNAME_NO_LEADING_UNDERSCORES |
UNDNAME_NO_MS_KEYWORDS |
UNDNAME_NO_FUNCTION_RETURNS |
UNDNAME_NO_ALLOCATION_MODEL |
UNDNAME_NO_ALLOCATION_LANGUAGE |
UNDNAME_NO_MS_THISTYPE |
UNDNAME_NO_CV_THISTYPE |
UNDNAME_NO_THISTYPE |
UNDNAME_NO_ACCESS_SPECIFIERS |
UNDNAME_NO_THROW_SIGNATURES |
UNDNAME_NO_MEMBER_TYPE |
UNDNAME_NO_RETURN_UDT_MODEL |
UNDNAME_NO_ARGUMENTS |
UNDNAME_NO_SPECIAL_SYMS |
UNDNAME_NAME_ONLY
)) {
strcat(szContext,szUndecStr);
}
} else {
strcat(szContext,szStr);
}
return _strdup(szContext);
}
BOOL
GetNearestSymbolInfo(
LPADDR addr,
LPNEARESTSYM lpnsym
)
{
ADDR addr1 = {0};
HDEP hsyml;
PHSL_HEAD lphsymhead;
PHSL_LIST lphsyml;
UINT n;
DWORDLONG dwOff;
DWORDLONG dwOffP;
DWORDLONG dwOffN;
DWORDLONG dwAddrP;
DWORDLONG dwAddrN;
EESTATUS eest;
HEXE hexe;
ZeroMemory(&lpnsym->cxt, sizeof(CXT));
SYUnFixupAddr(addr);
SHSetCxt(addr, &lpnsym->cxt);
hexe = (HEXE)emiAddr(*addr);
if ( hexe && (HPID)hexe != LppdCur->hpid ) {
SHWantSymbols(hexe);
}
hsyml = 0;
eest = EEGetHSYMList(&hsyml, &lpnsym->cxt, HSYMR_public, NULL, TRUE);
if (eest != EENOERROR) {
return FALSE;
}
lphsymhead = (PHSL_HEAD) MMLpvLockMb ( hsyml );
lphsyml = (PHSL_LIST)(lphsymhead + 1);
dwOffP = _UI64_MAX;
dwOffN = _UI64_MAX;
dwAddrP = _UI64_MAX;
dwAddrN = _UI64_MAX;
SYFixupAddr(addr);
addr1 = *addr;
for ( n = 0; n < (UINT)lphsyml->symbolcnt; n++ ) {
if (SHAddrFromHsym(&addr1, lphsyml->hSym[n])) {
SYFixupAddr(&addr1);
if (GetAddrSeg(addr1) != GetAddrSeg(*addr)) {
continue;
}
if (GetAddrOff(addr1) <= GetAddrOff(*addr)) {
dwOff = GetAddrOff(*addr) - GetAddrOff(addr1);
if (dwOff < dwOffP) {
dwOffP = dwOff;
dwAddrP = GetAddrOff(addr1);
lpnsym->hsymP = lphsyml->hSym[n];
lpnsym->addrP = addr1;
}
} else {
dwOff = GetAddrOff(addr1) - GetAddrOff(*addr);
if (dwOff < dwOffN) {
dwOffN = dwOff;
dwAddrN = GetAddrOff(addr1);
lpnsym->hsymN = lphsyml->hSym[n];
lpnsym->addrN = addr1;
}
}
}
}
MMbUnlockMb(hsyml);
MMFreeHmem(hsyml);
return TRUE;
}
LPSTR
GetNearestSymbolFromAddr(
LPADDR lpaddr,
LPADDR lpAddrRet
)
{
NEARESTSYM nsym;
ZeroMemory( &nsym, sizeof(nsym) );
if (!GetNearestSymbolInfo( lpaddr, &nsym )) {
return NULL;
}
if (!nsym.hsymP) {
return NULL;
}
*lpAddrRet = nsym.addrP;
SYFixupAddr(lpAddrRet);
return FormatSymbol( nsym.hsymP, &nsym.cxt );
}
BOOL
GetUnicodeStrings(
VOID
)
{
return g_contWorkspace_WkSp.m_bUnicodeIsDefault;
}
/*
** Set up the structures needed for OSDebug
** dbf - This structure contains a set of callback routines
** to be used by the OSDebug modules to get certian
** services
*/
DBF Dbf = {
MHAlloc, /* MHAlloc */
MHRealloc, /* MHRealloc */
MHFree, /* MHFree */
//(HLLI (WINAPI *)( UINT, LLF, LPFNKILLNODE, LPFNFCMPNODE ))
(LPLLINIT) LLPlliInit, /* LLInit */
//(HLLE (WINAPI *)( HLLI ))
(LPLLCREATE) LLPlleCreate, /* LLCreate */
//(VOID (WINAPI *)( HLLI, HLLE ))
(LPLLADD) LLAddPlleToLl, /* LLAdd */
//(VOID (WINAPI *)( HLLI, HLLE, DWORD ))
(LPLLINSERT) LLInsertPlleInLl, /* LLInsert */
//(BOOL (WINAPI *)( HLLI, HLLE ))
(LPLLDELETE) LLFDeletePlleFromLl, /* LLDelete */
//(HLLE (WINAPI *)( HLLI, HLLE ))
(LPLLNEXT) LLPlleFindNext, /* LLNext */
//(LONG (WINAPI *)( HLLI ))
(LPLLDESTROY) LLChlleDestroyLl, /* LLDestroy */
//(HLLE (WINAPI *)( HLLI, HLLE, LPV, DWORD ))
(LPLLFIND) LLPlleFindLpv, /* LLFind */
(LPLLSIZE) LLChlleInLl, /* LLSize */
//(LPVOID (WINAPI *)( HLLE ))
(LPLLLOCK) LLLpvFromPlle, /* LLLock */
//(VOID (WINAPI *)( HLLE ))
(LPLLUNLOCK) LLUnlockPlle, /* LLUnlock */
//(HLLE (WINAPI *)( HLLI ))
(LPLLLAST) LLPlleGetLast, /* LLLast */
//(VOID (WINAPI *)( HLLI, HLLE ))
(LPLLADDHEAD) LLPlleAddToHeadOfLI, /* LLAddHead */
//(BOOL (WINAPI *)( HLLI, HLLE ))
(LPLLREMOVE) LLFRemovePlleFromLl, /* LLRemove */
AssertOut, /* LBAssert */
LBQuit, /* LBQuit */
NULL, /* SHGetSymbol (1)*/
NULL, /* SHGetPublicAddr (1)*/
NULL, /* SHAddrToPublicName */
NULL, /* SHGetDebugData */
// NULL, /* SHLocateSymbolFile */
NULL, /* SHLpGSNGetTable (see FLoadEmTl)*/
NULL, /* SHWantSymbols */
DHGetNumber, /* DHGetNumber */
NULL, /* GetTargetProcessor */
// NULL, /* GetSet */
/* End of structure */
};
KNF Knf = {
sizeof(KNF),
MHAlloc, /* MHAlloc */
MHRealloc, /* MHRealloc */
MHFree, /* MHFree */
MHAllocHuge, /* MHAllocHuge */
MHFree, /* MHFreeHuge */
MMAllocHmem, /* MMAllocHmem */
MMFreeHmem, /* MMFreeHmem */
MMLpvLockMb, /* MMLock */
MMbUnlockMb, /* MMUnlock */
//(HLLI (WINAPI *)( DWORD, LLF, LPFNKILLNODE, LPFNFCMPNODE ))
(LPLLINIT) LLPlliInit, /* LLInit */
//(HLLE (WINAPI *)( HLLI ))
(LPLLCREATE) LLPlleCreate, /* LLCreate */
//(VOID (WINAPI *)( HLLI, HLLE ))
(LPLLADD) LLAddPlleToLl, /* LLAdd */
//(VOID (WINAPI *)( HLLI, HLLE ))
(LPLLADDHEAD) LLPlleAddToHeadOfLI, /* LLAddHead */
//(VOID (WINAPI *)( HLLI, HLLE, DWORD ))
(LPLLINSERT) LLInsertPlleInLl, /* LLInsert */
//(BOOL (WINAPI *)( HLLI, HLLE ))
(LPLLDELETE) LLFDeletePlleFromLl, /* LLDelete */
//(BOOL (WINAPI *)( HLLI, HLLE ))
(LPLLREMOVE) LLFRemovePlleFromLl, /* LLRemove */
//(LONG (WINAPI *)( HLLI ))
(LPLLDESTROY) LLChlleDestroyLl, /* LLDestroy */
//(HLLE (WINAPI *)( HLLI, HLLE ))
(LPLLNEXT) LLPlleFindNext, /* LLNext */
//(HLLE (WINAPI *)( HLLI, HLLE, LPV, DWORD ))
(LPLLFIND) LLPlleFindLpv, /* LLFind */
//(HLLE (WINAPI *)( HLLI ))
(LPLLLAST) LLPlleGetLast, /* LLLast */
//(DWORD (WINAPI *)( HLLI ))
(LPLLSIZE) LLChlleInLl, /* LLSize */
//(LPVOID (WINAPI *)( HLLE ))
(LPLLLOCK) LLLpvFromPlle, /* LLLock */
//(VOID (WINAPI *)( HLLE ))
(LPLLUNLOCK) LLUnlockPlle, /* LLUnlock */
//(BOOL (WINAPI *)(LPCH, LPCH, DWORD))
AssertOut, /* LPPrintf */
//(BOOL (WINAPI *)(DWORD))
LBQuit, /* LPQuit */
SYOpen, /* SYOpen */
SYClose, /* SYClose */
SYRead, /* SYRead */
SYLseek, /* SYSeek */
SYFixupAddr, /* SYFixupAddr */
SYUnFixupAddr, /* SYUnFixupAddr */
SYProcessor, /* SYProcessor */
//NULL,
// SYFIsOverlayLoaded, /* SYFIsOverlayLoaded */
// SearchEnv, /* searchenv */
// OurSprintf, /* sprintf */
// SplitPath, /* splitpath */
// FullPath, /* fullpath */
// MakePath, /* makepath */
// OurStat, /* stat */
// LBLog, /* LBLog */
SYTell, /* SYTell */
SYFindExeFile, /* SYFindExeFile */
GetSymbolFileFromServer, /* GetSymbolFileFromServer */
SYIgnoreAllSymbolErrors, /* SYIgnoreAllSymbolErrors */
DLoadedSymbols, /* LoadedSymbols */
SYGetDefaultShe, /* SYGetDefaultShe */
NULL, // SYFindDebugInfoFile
NULL, // GetRegistryRoot
SYSetProfileString, // SetProfileString
SYGetProfileString, // GetProfileString
}; /* End of structure */
CRF Crf = {
NULL, /* int */
t_ultoa, /* ultoa */
t_itoa, /* _itoa */
NULL, /* ltoa */
d_eprintf, /* eprintf */
d_sprintf /* sprintf */
}; /* End of structure */
CVF Cvf = {
MHAlloc, /* MHlpvAlloc */
MHFree, /* MHFreeLpv */
NULL, /* SHGetNextExe (1) */
NULL, /* SHHEXEFromHMOD (1)*/
NULL, /* SHGetNextMod (1)*/
NULL, /* SHGetCXTFromHMOD (1)*/
NULL, /* SHGetCXTFromHEXE (1)*/
NULL, /* SHSetCXT (1)*/
NULL, /* SHSetCXTMod (1)*/
NULL, /* SHFindNameInGlobal (1)*/
NULL, /* SHFindNameInContext (1)*/
NULL, /* SHGoToParent (1)*/
NULL, /* SHHSYMFromCXT */
NULL, /* SHNextHsym (1)*/
CLGetFuncCXF, /* SHGetFuncCXF */
NULL, /* SHGetModName */
NULL, /* SHGetExeName */
NULL, /* SHGetModNameFromHexe */
NULL, /* SHGetSymFName */
NULL, /* SHGethExeFromName (1)*/
NULL, /* SHGethExeFromModuleName (1)*/
NULL, /* SHGetNearestHSYM (1)*/
NULL, /* SHIsInProlog (1)*/
NULL, /* SHIsADDRInCXT */
NULL, /* SHModelFromAddr (1)*/
NULL, /* SHFindSLink32 */
NULL, /* SLLineFromAddr */
NULL, /* SLFLineToAddr (1)*/
NULL, /* SLNameFromHsf */
NULL, /* SLHmdsFromHsf */
NULL, /* SLHsfFromPcxt (1)*/
NULL, /* SLHsfFromFile (1)*/
NULL, /* PHGetNearestHSYM */
NULL, /* PHFindNameInPublics (1)*/
NULL, /* THGetTypeFromIndex (1)*/
NULL, /* THGetNextType */
MMAllocHmem, /* MHMemAllocate */
MMReallocHmem, /* MHMemReAlloc */
MMFreeHmem, /* MHMemFree */
MMLpvLockMb, /* MHMemLock */
MMbUnlockMb, /* MHMemUnLock */
NULL, /* MHIsMemLocked */
NULL, /* MHOmfLock */
NULL, /* MHOmfUnlock */
NULL, /* DHExecProc */
DHGetDebuggeeBytes, /* DHGetDebuggeeBytes */
DHSetDebuggeeBytes, /* DHPutDebuggeeBytes */
DHGetReg, /* DHGetReg */
DHSetReg, /* DHSetReg */
NULL, /* DHSaveReg */
NULL, /* DHRestoreReg */
&in386mode, /* in386mode */
&is_assign, /* is_assign */
//(int (OSDAPI *)( UINT ))
LBQuit, /* quit */
NULL, /* pArrayDefault ??? */
NULL, /* pSHCompareRE */
SYFixupAddr, /* SHFixupAddr */
SYUnFixupAddr, /* pSHUnFixupAddr */
NULL, /* pCVfnCmp */
NULL, /* pCVtdCmp */
NULL, /* pCVcsCmp */
//(int (OSDAPI *)( LPSTR, LPSTR, UINT))
AssertOut, /* assert */
DHSetupExecute, /* DHSetupExecute */
DHCleanUpExecute, /* DHCleanUpExecute */
DHStartExecute, /* DHStartExecute */
NULL, /* SHFindNameInTypes */
NULL, /* SYProcessor */
NULL, /* THAreTypesEqual */
NULL, /* GetTargetProcessor */
GetUnicodeStrings, /* GetUnicodeStrings */
SYGetAddr, /* pSYGetAddr */
NULL, /* pSYSetAddr */
SYGetMemInfo, /* pSYGetMemInfo */
NULL, /* SHWantSymbols */
}; /* End of structure */
LPSHF Lpshf;
/*** CopyShToEe
** Synopsis:
** void = CopyShToEe()
** Entry:
** none
** Returns:
** Nothing
** Description:
** Copy function pointers from the Symbol handler API to the
** Expression evaluator API
*/
void CopyShToEe()
{
Cvf.pSHGetNextExe = Lpshf->pSHGetNextExe;
Cvf.pSHHexeFromHmod = Lpshf->pSHHexeFromHmod;
Cvf.pSHGetNextMod = Lpshf->pSHGetNextMod;
Cvf.pSHGetCxtFromHmod = Lpshf->pSHGetCxtFromHmod;
Cvf.pSHGetCxtFromHexe = Lpshf->pSHGetCxtFromHexe;
Cvf.pSHSetCxt = Lpshf->pSHSetCxt;
Cvf.pSHFindNameInGlobal = Lpshf->pSHFindNameInGlobal;
Cvf.pSHFindNameInContext = Lpshf->pSHFindNameInContext;
Cvf.pSHGoToParent = Lpshf->pSHGoToParent;
Cvf.pSHNextHsym = Lpshf->pSHNextHsym;
Cvf.pSHGethExeFromName = Lpshf->pSHGethExeFromName;
Cvf.pSHGethExeFromModuleName = Lpshf->pSHGethExeFromModuleName;
Cvf.pSHGetNearestHsym = Lpshf->pSHGetNearestHsym;
Cvf.pSHIsInProlog = Lpshf->pSHIsInProlog;
Cvf.pSHModelFromAddr = Lpshf->pSHModelFromAddr;
Cvf.pSLFLineToAddr = Lpshf->pSLFLineToAddr;
Cvf.pSLHsfFromPcxt = Lpshf->pSLHsfFromPcxt;
Cvf.pSLHsfFromFile = Lpshf->pSLHsfFromFile;
Cvf.pPHFindNameInPublics = Lpshf->pPHFindNameInPublics;
Cvf.pTHGetTypeFromIndex = Lpshf->pTHGetTypeFromIndex;
Cvf.pSHCompareRE = Lpshf->pSHCompareRE;
Cvf.pSHGetExeName = Lpshf->pSHGetExeName;
Cvf.pSHGetModNameFromHexe = Lpshf->pSHGetModNameFromHexe;
Cvf.pSHGetSymFName = Lpshf->pSHGetSymFName;
Cvf.pSLNameFromHsf = Lpshf->pSLNameFromHsf;
Cvf.pSHWantSymbols = Lpshf->pSHWantSymbols;
Cvf.pTHAreTypesEqual = Lpshf->pTHAreTypesEqual;
Cvf.pSHFindNameInTypes = Lpshf->pSHFindNameInTypes;
Cvf.pSHSetCxtMod = Lpshf->pSHSetCxtMod;
Dbf.lpfnSHGetSymbol = Lpshf->pSHGetSymbol;
Dbf.lpfnSHGetPublicAddr = Lpshf->pSHGetPublicAddr;
Dbf.lpfnSHLpGSNGetTable = Lpshf->pSHLpGSNGetTable;
Dbf.lpfnSHGetDebugData = Lpshf->pSHGetDebugData;
// Dbf.lpfnSHFindSymbol = Lpshf->pSHFindSymbol;
Dbf.lpfnSHAddrToPublicName = GetNearestSymbolFromAddr;
Dbf.lpfnSHWantSymbols = Lpshf->pSHWantSymbols;
// Dbf.lpfnSHLocateSymbolFile = Lpshf->pSHLocateSymbolFile;
return;
} /* CopyShToEe() */