756 lines
21 KiB
C
756 lines
21 KiB
C
/*++
|
|
|
|
Revision History:
|
|
|
|
2-Feb-95 a-robw (Bob Watson)
|
|
Made changes for windows95 compatibility:
|
|
Replaced KdPrint & DbgPrint functions with CapDbgPrint
|
|
"ifdef'd" the calls to the secondary symbol searches with
|
|
the _SECOND_CHANCE_LOOKUP macro
|
|
Replaced Module Scanning logic with functions supported by
|
|
PSAPI.DLL
|
|
|
|
10-Feb-95 a-robw (Bob Watson)
|
|
minor bug fixes
|
|
|
|
--*/
|
|
|
|
#include "cap.h"
|
|
|
|
/********************** G e t F u n c t i o n N a m e **********************
|
|
*
|
|
* GetFunctionName (ulFuncAddr, ulProfBlkOff, pulSymAddress) -
|
|
* This routine is called to find the function name associated
|
|
* with the specifed address.
|
|
*
|
|
* ENTRY ulFuncAddr - address within the function
|
|
* ulProfBlkOff - offset of first prof block of module list
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN pointer to the function name
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
/**************** cache test *************/
|
|
DWORD is_code_calls = 0;
|
|
DWORD is_code_cache_hits = 0;
|
|
DWORD is_code_tests = 0;
|
|
|
|
PTCHAR GetFunctionName (ULONG ulFuncAddr,
|
|
ULONG ulProfBlkOff,
|
|
ULONG * pulSymAddress)
|
|
{
|
|
PSYMINFO psyminfo;
|
|
int iCount; // 061693 Add
|
|
DWORD sigword;
|
|
int fAccessViolation = 0;
|
|
|
|
PIMAGEHLP_SYMBOL pImHelpSym;
|
|
IMAGEHLP_MODULE ImHelpModule;
|
|
DWORD dwSymbDisp;
|
|
PPROFBLK pProfBlk;
|
|
PTCHAR ptchSymbName;
|
|
TCHAR atchOutName[MAXNAMELENGTH];
|
|
TCHAR atchUnDName[MAXNAMELENGTH];
|
|
|
|
#if defined(MIPS) || defined(ALPHA) || defined(_PPC_)
|
|
ULONG ulOffsetFromTopRoutine;
|
|
PATCHCODE *pPatchStub;
|
|
#endif
|
|
|
|
#ifdef ALPHA
|
|
// BUGBUG
|
|
// Does this really need to be UNALIGNED ? These are instructions after all.
|
|
//
|
|
PULONG UNALIGNED pulAddr;
|
|
#elif defined(_PPC_)
|
|
PULONG pulAddr;
|
|
#endif
|
|
|
|
if (fLoadLibraryOn)
|
|
{
|
|
if (ulFuncAddr == (ULONG)CAP_LoadLibraryA)
|
|
{
|
|
strcpy((PCHAR)atchFuncName, "KERNel32.DLL:LoadLibraryA");
|
|
if (pulSymAddress)
|
|
{
|
|
*pulSymAddress = (ULONG)loadlibAaddr;
|
|
}
|
|
return(atchFuncName);
|
|
}
|
|
else if (ulFuncAddr == (ULONG)CAP_LoadLibraryExA)
|
|
{
|
|
strcpy((PCHAR)atchFuncName, "KERNel32.DLL:LoadLibraryExA");
|
|
if (pulSymAddress)
|
|
{
|
|
*pulSymAddress = (ULONG)loadlibExAaddr;
|
|
}
|
|
return(atchFuncName);
|
|
}
|
|
#ifndef _CHICAGO_
|
|
else if (ulFuncAddr == (ULONG)CAP_LoadLibraryW)
|
|
{
|
|
strcpy((PCHAR)atchFuncName, "KERNel32.DLL:LoadLibraryW");
|
|
if (pulSymAddress)
|
|
{
|
|
*pulSymAddress = (ULONG)loadlibWaddr;
|
|
}
|
|
return(atchFuncName);
|
|
}
|
|
else if (ulFuncAddr == (ULONG)CAP_LoadLibraryExW)
|
|
{
|
|
strcpy((PCHAR)atchFuncName, "KERNel32.DLL:LoadLibraryExW");
|
|
if (pulSymAddress)
|
|
{
|
|
*pulSymAddress = (ULONG)loadlibExWaddr;
|
|
}
|
|
return(atchFuncName);
|
|
}
|
|
#endif // !_CHICAGO_
|
|
}
|
|
|
|
INFOPrint(("CAP: Looking up symbol for addr [%08lx]\n", ulFuncAddr));
|
|
try // EXCEPT - to handle access violation exception.
|
|
{ // Access violation might happen while trying to use other processes
|
|
// profile blocks..
|
|
//
|
|
// XXX davidfie -- Why is this here? Can the server side processing cause faults
|
|
// other than stub checking? I don't think so but I'll leave this here for
|
|
// further investigation.
|
|
|
|
#ifdef i386
|
|
try // If this was a server side address we will probably fault here
|
|
{
|
|
sigword = *(PDWORD)(ulFuncAddr + 7);
|
|
}
|
|
//
|
|
// + : transfer control to the handler (EXCEPTION_EXECUTE_HANDLER)
|
|
// 0 : continue search (EXCEPTION_CONTINUE_SEARCH)
|
|
// - : dismiss exception & continue (EXCEPTION_CONTINUE_EXECUTION)
|
|
//
|
|
except (1)
|
|
{
|
|
fAccessViolation = 1;
|
|
}
|
|
// If this is a stub, find out the real address
|
|
if (!fAccessViolation && (sigword == STUB_SIGNATURE))
|
|
{
|
|
// If it is a stub we won't fault because this process must have created it
|
|
// and not the server side.
|
|
ulFuncAddr = (ULONG) (*(PDWORD)(ulFuncAddr + 1));
|
|
}
|
|
else
|
|
{
|
|
// if not a stub adjust address to start of function
|
|
ulFuncAddr = ulFuncAddr - 5;
|
|
}
|
|
|
|
#elif MIPS
|
|
|
|
#ifdef MIPS_VC40_INTERFACE
|
|
// Check for stub signature at end of stub patch
|
|
if (*((PULONG)ulFuncAddr + 5) == STUB_SIGNATURE)
|
|
{
|
|
// extract real function address from stub
|
|
pPatchStub = (PPATCHCODE)(ulFuncAddr - 5 * INST_SIZE);
|
|
ulFuncAddr = (pPatchStub->Lui_t0 << 16);
|
|
ulFuncAddr |= (pPatchStub->Ori_t0 & 0x0000ffff);
|
|
}
|
|
else
|
|
{
|
|
// Normal function - subtract offset of penter call
|
|
ulFuncAddr = ulFuncAddr - 12;
|
|
}
|
|
#else
|
|
//
|
|
// Compute the real address of the function since the penter
|
|
// stub is not located at the beginning of the code as in x86
|
|
//
|
|
ulOffsetFromTopRoutine = *((PULONG) (ulFuncAddr - INST_SIZE));
|
|
ulOffsetFromTopRoutine &= 0x000ff00;
|
|
ulOffsetFromTopRoutine >>= 8;
|
|
ulFuncAddr = ulFuncAddr - ulOffsetFromTopRoutine;
|
|
|
|
// We have to distinguish between a stub and a regular function
|
|
// since a stub has a different setup than a regular function.
|
|
|
|
if (*( (PULONG) ulFuncAddr - 1 +
|
|
(sizeof(PATCHCODE) / INST_SIZE) ) == STUB_SIGNATURE)
|
|
{
|
|
// These are the stubs we made up for Dll Patching
|
|
pPatchStub = (PPATCHCODE) ulFuncAddr;
|
|
ulFuncAddr = (pPatchStub->Lui_t0 << 16);
|
|
ulFuncAddr |= (pPatchStub->Ori_t0 & 0x0000ffff);
|
|
}
|
|
#endif // MIPS_VC40_INTERFACE
|
|
|
|
#elif ALPHA // endif MIPS
|
|
//
|
|
// Compute the real address of the function since the penter
|
|
// stub is not located at the beginning of the code as in x86
|
|
//
|
|
ulFuncAddr = ulFuncAddr - INST_SIZE;
|
|
|
|
// We have to distinguish between a stub and a regular function
|
|
// since a stub has a different setup than a regular function.
|
|
pulAddr = (PULONG UNALIGNED) ulFuncAddr;
|
|
if (*(pulAddr) == 0x681b4000 &&
|
|
(*(pulAddr + 1) == 0xa41e0000) &&
|
|
(*(pulAddr + 7) == STUB_SIGNATURE) )
|
|
{
|
|
// get the address that we will go after the penter function
|
|
ulFuncAddr = *(pulAddr + 3) & 0x0000ffff;
|
|
if (*(pulAddr + 4) & 0x00008000)
|
|
{
|
|
// fix the address since we have to add one when
|
|
// we created our stub code
|
|
ulFuncAddr -= 1;
|
|
}
|
|
ulFuncAddr = ulFuncAddr << 16;
|
|
ulFuncAddr |= *(pulAddr + 4) & 0x0000ffff;
|
|
}
|
|
#elif defined(_PPC_) // ifdef ALPHA
|
|
|
|
//
|
|
// Compute the real address of the function since the penter
|
|
// stub is not located at the beginning of the code as in x86
|
|
//
|
|
// The RealFuncAddr recorded should be instruction following
|
|
// bl ..__penter instruction which is 12 bytes past entry pt.
|
|
|
|
ulFuncAddr = ulFuncAddr - 12;
|
|
|
|
// We have to distinguish between a stub and a regular function
|
|
// since a stub has a different setup than a regular function.
|
|
pulAddr = (PULONG UNALIGNED) ulFuncAddr;
|
|
if (*(pulAddr) == 0x7D6903A6 &&
|
|
(*(pulAddr + 1) == 0x7C0802A6) &&
|
|
(*(pulAddr + 2) == 0x4E800421) &&
|
|
(*(pulAddr + 10) == STUB_SIGNATURE) )
|
|
{
|
|
// get the address that we will go after the penter function
|
|
ulFuncAddr = *(pulAddr + 4) & 0x0000ffff;
|
|
ulFuncAddr = ulFuncAddr << 16;
|
|
ulFuncAddr |= *(pulAddr + 5) & 0x0000ffff;
|
|
}
|
|
#endif
|
|
|
|
// Locate module that contains the address
|
|
while (ulProfBlkOff != 0)
|
|
{
|
|
pProfBlk = MKPPROFBLK(ulProfBlkOff);
|
|
|
|
if ( (ulFuncAddr >= (ULONG)pProfBlk->CodeStart) &&
|
|
(ulFuncAddr < ((ULONG)pProfBlk->CodeStart +
|
|
(ULONG)pProfBlk->CodeLength)) )
|
|
break;
|
|
|
|
ulProfBlkOff = pProfBlk->ulNxtBlk;
|
|
}
|
|
|
|
// if module found
|
|
if (ulProfBlkOff != 0)
|
|
{
|
|
// Start name with module name
|
|
iCount = sprintf (atchFuncName,"%s:",pProfBlk->atchImageName);
|
|
|
|
// Now locate the symbol itself
|
|
psyminfo = SymBSearch (ulFuncAddr,
|
|
MKPSYMBLK(pProfBlk->ulSym),
|
|
pProfBlk->iSymCnt);
|
|
|
|
// if symbol found at or below our address
|
|
if (psyminfo && ulFuncAddr >= psyminfo->ulAddr)
|
|
{
|
|
// append symbol name, undecorated if requested
|
|
/* if (fUndecorateName) */
|
|
/* { */
|
|
/* UnDecorateSymbolName(MKPSYMBOL(psyminfo->ulSymOff), &atchFuncName[iCount], */
|
|
/* MAXNAMELENGTH - iCount - 10, UNDNAME_NO_MS_KEYWORDS); */
|
|
/* } */
|
|
/* else */
|
|
{
|
|
strcpy(&atchFuncName[iCount], MKPSYMBOL(psyminfo->ulSymOff));
|
|
}
|
|
|
|
// if not exact match, append displacement
|
|
if (ulFuncAddr > psyminfo->ulAddr)
|
|
sprintf(atchFuncName + strlen(atchFuncName),"+0x%x",
|
|
ulFuncAddr - psyminfo->ulAddr);
|
|
}
|
|
else
|
|
{
|
|
// if no symbol, just append address
|
|
sprintf(&atchFuncName[iCount],"0x%08x", ulFuncAddr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if unknown module, return ????:address
|
|
sprintf(atchFuncName,"???:0x%08x",ulFuncAddr);
|
|
}
|
|
|
|
if (pulSymAddress)
|
|
*pulSymAddress = ulFuncAddr;
|
|
}
|
|
//
|
|
// + : transfer control to the handler (EXCEPTION_EXECUTE_HANDLER)
|
|
// 0 : continue search (EXCEPTION_CONTINUE_SEARCH)
|
|
// - : dismiss exception & continue (EXCEPTION_CONTINUE_EXECUTION)
|
|
//
|
|
except ( AccessXcptFilter (GetExceptionCode(),
|
|
GetExceptionInformation(),
|
|
PAGE_SIZE) )
|
|
{
|
|
//
|
|
// Should never get here since filter never returns
|
|
// EXCEPTION_EXECUTE_HANDLER.
|
|
//
|
|
CapDbgPrint ("CAP: GetFunctionname() - *LOGIC ERROR* - "
|
|
"Inside the EXCEPT: (xcpt=0x%lx)\n", GetExceptionCode());
|
|
}
|
|
|
|
return (atchFuncName);
|
|
|
|
} /* GetFunctionName () */
|
|
|
|
/************************** G e t S e c t i o n L i s t F r o m A d d r e s s *****************************
|
|
*
|
|
* GetSectionListFromAddress (pulAddress)
|
|
* This routine finds the section array for the module based on an
|
|
* address in the module.
|
|
*
|
|
* ENTRY pulAddress - an address in a module
|
|
*
|
|
* EXIT cNumberOfSections - The number of sections in the array.
|
|
* ppvCalleBase - The base of the module the address is in.
|
|
*
|
|
* RETURN a pointer to the begining of the array of sections for the module
|
|
* or NULL
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* The address isn't checked for validity so a stack or heap address would
|
|
* have an unknown effect.
|
|
*
|
|
*/
|
|
|
|
PIMAGE_SECTION_HEADER
|
|
GetSectionListFromAddress(
|
|
IN PULONG pulAddress,
|
|
OUT int *cNumberOfSections,
|
|
OUT PVOID *ppvCalleeImageBase
|
|
)
|
|
{
|
|
PLIST_ENTRY Next;
|
|
PIMAGE_NT_HEADERS pImageNtHeader;
|
|
PIMAGE_SECTION_HEADER pSections;
|
|
HANDLE hThisProcess;
|
|
HMODULE hImageModule;
|
|
MODULEINFO miData;
|
|
DWORD dwReqdSize;
|
|
DWORD dwModuleIndex;
|
|
DWORD dwLastModule;
|
|
HMODULE *hmTemp;
|
|
|
|
static HMODULE *hmArray = NULL;
|
|
static DWORD dwArraySize;
|
|
|
|
//
|
|
// Get image base from address by chaining down the
|
|
// loader table (stolen from DoDllInitializations) and
|
|
// and looking for an image which contains the thunked
|
|
// address
|
|
//
|
|
|
|
*ppvCalleeImageBase = NULL;
|
|
|
|
hThisProcess = GetCurrentCapProcess();
|
|
hImageModule = GetModuleHandle(NULL);
|
|
|
|
|
|
// If first time, get array for 100 modules
|
|
if (hmArray == NULL)
|
|
{
|
|
dwArraySize = 100 * sizeof(HMODULE);
|
|
hmArray = (HMODULE * ) GlobalAlloc (GPTR, dwArraySize);
|
|
|
|
if (hmArray == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
// get module List
|
|
while (1)
|
|
{
|
|
dwReqdSize = 0;
|
|
|
|
// Get list of loaded modules
|
|
EnumProcessModules (
|
|
hThisProcess,
|
|
hmArray,
|
|
dwArraySize,
|
|
&dwReqdSize);
|
|
|
|
// if buffer was big enough, we can continue
|
|
if (dwReqdSize <= dwArraySize)
|
|
break;
|
|
|
|
// realloc to the required size
|
|
hmTemp = (HMODULE * )GlobalReAlloc(hmArray, dwReqdSize, 0);
|
|
|
|
if (hmTemp != NULL)
|
|
{
|
|
hmArray = hmTemp;
|
|
dwArraySize = dwReqdSize;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
dwLastModule = dwReqdSize / sizeof(HMODULE);
|
|
|
|
// get processes exe module handle;
|
|
// walk module list to see which module contatins the desired address
|
|
|
|
for (dwModuleIndex = 0; dwModuleIndex < dwLastModule; dwModuleIndex++) {
|
|
|
|
GetModuleInformation (
|
|
hThisProcess,
|
|
hmArray[dwModuleIndex],
|
|
&miData,
|
|
sizeof(MODULEINFO));
|
|
|
|
if ((pulAddress > (PULONG)miData.lpBaseOfDll) &&
|
|
(pulAddress < (PULONG)((ULONG)miData.lpBaseOfDll +
|
|
miData.SizeOfImage))) {
|
|
*ppvCalleeImageBase = miData.lpBaseOfDll;
|
|
break;
|
|
}
|
|
|
|
} /* end for each module in image */
|
|
|
|
if (*ppvCalleeImageBase == NULL)
|
|
return(NULL);
|
|
//
|
|
// Get sectionlist from image base
|
|
//
|
|
pImageNtHeader = ImageNtHeader (*ppvCalleeImageBase);
|
|
if (pImageNtHeader == NULL)
|
|
return(NULL);
|
|
|
|
*cNumberOfSections = pImageNtHeader->FileHeader.NumberOfSections;
|
|
|
|
return(IMAGE_FIRST_SECTION(pImageNtHeader));
|
|
}
|
|
|
|
/************************** I s C o d e A d d r e s s *****************************
|
|
*
|
|
* IsCodeAddress(pulAddress, pSection, pvImageBase)
|
|
* This routine finds the section array for the module based on an
|
|
* address in the module.
|
|
*
|
|
* ENTRY pulAddress - an address in a module
|
|
* pSection - a section array in which to look for the address
|
|
* cNumberOfSections - the number of sections in the section array
|
|
* pvImageBase - the base of the image in which the address is located
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN TRUE - if the pointer is in a code section or if it's
|
|
not in any section which indicates its a forwarder.
|
|
* FALSE - otherwize
|
|
*
|
|
* WARNING:
|
|
* If data imports are forwarded this code will break. The way
|
|
* to fix would be to call GetSectionListFromAddress() with the
|
|
* forwarded address and the recursively call IsCodeAddress().
|
|
* There aren't any known forwarded data instances so.....
|
|
*
|
|
* COMMENT:
|
|
* On PPC, pulAddress may be indirect to executable code, via
|
|
* a pointer to a function descriptor. This may need a revisit
|
|
* if function descriptors are moved out of .reldata.
|
|
*
|
|
*/
|
|
BOOL
|
|
IsCodeAddress(
|
|
IN PULONG pulAddress,
|
|
IN PIMAGE_SECTION_HEADER pSection,
|
|
IN int cNumberOfSections,
|
|
IN PVOID pvImageBase
|
|
)
|
|
{
|
|
int i;
|
|
static last_match = 1;
|
|
|
|
if (pSection == NULL) return FALSE; // no section == no code address
|
|
|
|
for ( i=0 ; i < cNumberOfSections ; i++, pSection++)
|
|
{
|
|
ULONG SectionAddress =(ULONG)pvImageBase + pSection->VirtualAddress;
|
|
is_code_tests++;
|
|
#ifndef _PPC_
|
|
if (((ULONG)pulAddress >= SectionAddress) &&
|
|
((ULONG)pulAddress < (SectionAddress + pSection->Misc.VirtualSize)))
|
|
#else
|
|
if (((ULONG)*pulAddress >= SectionAddress) &&
|
|
((ULONG)*pulAddress < (SectionAddress + pSection->Misc.VirtualSize)))
|
|
#endif
|
|
{
|
|
if (i == last_match) is_code_cache_hits++;
|
|
is_code_calls++;
|
|
last_match = i;
|
|
|
|
if (pSection->Characteristics & IMAGE_SCN_CNT_CODE)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
}
|
|
OutputCapDebugString("CAP: IsCodeAddress() found forwarded import assuming it"
|
|
" is code and not data\n");
|
|
return(TRUE); // this must be a forwarder
|
|
// so we'll assume it's code
|
|
}
|
|
|
|
|
|
/************************** G e t C o d e S e c t i o n T a b l e *****************************
|
|
*
|
|
* GetCodeSectionTable(pImageDbgInfo, *CNumberOfSections)
|
|
* This routine builds an array which can be used to see if a section
|
|
* of an object is a code section.
|
|
*
|
|
* ENTRY pvImageBase - the base of the image in which the address is located
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN NULL - if it can't build the array
|
|
* otherwize - the array
|
|
*
|
|
* COMMENT:
|
|
*
|
|
*/
|
|
PBOOL
|
|
GetCodeSectionTable(
|
|
IN PIMAGE_DEBUG_INFORMATION pImageDbgInfo,
|
|
OUT int *cNumberOfSections
|
|
)
|
|
{
|
|
int i;
|
|
PIMAGE_SECTION_HEADER pSection;
|
|
PBOOL CodeSection;
|
|
|
|
*cNumberOfSections = pImageDbgInfo->NumberOfSections;
|
|
pSection = pImageDbgInfo->Sections;
|
|
|
|
CodeSection = LocalAlloc(LMEM_ZEROINIT, *cNumberOfSections*sizeof(BOOL));
|
|
if (CodeSection != NULL)
|
|
{
|
|
for ( i=0 ; i < *cNumberOfSections ; i++, pSection++)
|
|
{
|
|
if (pSection->Characteristics & IMAGE_SCN_CNT_CODE)
|
|
CodeSection[i] = TRUE;
|
|
}
|
|
}
|
|
return(CodeSection);
|
|
}
|
|
|
|
|
|
/******************* S e t S y m b o l S e a r c h P a t h ******************
|
|
*
|
|
* SetSymbolSearchPath ()
|
|
* Return complete search path for symbols files (.dbg)
|
|
*
|
|
* ENTRY -none-
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETURN -none-
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* "lpSymbolSearchPath" global LPSTR variable will point to the
|
|
* search path.
|
|
*/
|
|
#define FilePathLen 256
|
|
|
|
void SetSymbolSearchPath (void)
|
|
{
|
|
CHAR SymPath[FilePathLen];
|
|
CHAR AltSymPath[FilePathLen];
|
|
CHAR SysRootPath[FilePathLen];
|
|
LPSTR lpSymPathEnv=SymPath;
|
|
LPSTR lpAltSymPathEnv=AltSymPath;
|
|
LPSTR lpSystemRootEnv=SysRootPath;
|
|
ULONG cbSymPath;
|
|
DWORD dw;
|
|
HANDLE hMemoryHandle;
|
|
|
|
|
|
SymPath[0] = AltSymPath[0] = SysRootPath[0] = '\0';
|
|
|
|
cbSymPath = 18;
|
|
if (GetEnvironmentVariable("_NT_SYMBOL_PATH", SymPath, sizeof(SymPath)))
|
|
{
|
|
cbSymPath += strlen(lpSymPathEnv) + 1;
|
|
}
|
|
|
|
if (GetEnvironmentVariable("_NT_ALT_SYMBOL_PATH", AltSymPath, sizeof(AltSymPath)))
|
|
{
|
|
cbSymPath += strlen(lpAltSymPathEnv) + 1;
|
|
}
|
|
|
|
if (GetEnvironmentVariable("SystemRoot", SysRootPath, sizeof(SysRootPath)))
|
|
{
|
|
cbSymPath += strlen(lpSystemRootEnv) + 1;
|
|
}
|
|
|
|
hMemoryHandle = GlobalAlloc (GHND, cbSymPath+1);
|
|
if (!hMemoryHandle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lpSymbolSearchPath = GlobalLock (hMemoryHandle);
|
|
if (!lpSymbolSearchPath)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (*lpAltSymPathEnv)
|
|
{
|
|
dw = GetFileAttributes(lpAltSymPathEnv);
|
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
strcat(lpSymbolSearchPath,lpAltSymPathEnv);
|
|
strcat(lpSymbolSearchPath,";");
|
|
}
|
|
}
|
|
if (*lpSymPathEnv)
|
|
{
|
|
dw = GetFileAttributes(lpSymPathEnv);
|
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
strcat(lpSymbolSearchPath,lpSymPathEnv);
|
|
strcat(lpSymbolSearchPath,";");
|
|
}
|
|
}
|
|
if (*lpSystemRootEnv)
|
|
{
|
|
dw = GetFileAttributes(lpSystemRootEnv);
|
|
if ( dw != 0xffffffff && dw & FILE_ATTRIBUTE_DIRECTORY )
|
|
{
|
|
strcat(lpSymbolSearchPath,lpSystemRootEnv);
|
|
strcat(lpSymbolSearchPath,";");
|
|
}
|
|
}
|
|
|
|
strcat(lpSymbolSearchPath,".;");
|
|
|
|
} /* SetSymbolSearchPath () */
|
|
|
|
|
|
/************************ S y m B C o m p a r e ******************************
|
|
*
|
|
* SymBCompare(PDWORD pdwVal1, PSYMINFO val2)
|
|
*
|
|
* Compare values for Binary search
|
|
*
|
|
*
|
|
* ENTRY: pdwVal1 - value to be comapred against
|
|
* val2 - structure address to be comapred against
|
|
*
|
|
* EXIT: -none-
|
|
*
|
|
* RETUEN: -1 if val1 < val2
|
|
* 1 if val1 > val2
|
|
* 0 if val1 == val2
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
int SymBCompare (PDWORD pdwVal1, PSYMINFO val2)
|
|
{
|
|
return (*pdwVal1 < val2->ulAddr ? -1:
|
|
*pdwVal1 == val2->ulAddr ?
|
|
0 : 1);
|
|
|
|
} /* SymBCompare () */
|
|
|
|
|
|
/*********************** S y m B S e a r c h *******************************
|
|
*
|
|
* SymBSearch(DWORD dwAddr, SYMINFO syminfoCur[], INT n)
|
|
*
|
|
* Binary search function for finding a match in the SYMINFO array
|
|
*
|
|
*
|
|
* ENTRY: dwAddr - Address of calling function
|
|
* syminfoCur[] - Pointer to SYMINFO containg value to match
|
|
* with dwAddr
|
|
* n - Number of elements in SYMINFO array
|
|
*
|
|
* EXIT -none-
|
|
*
|
|
* RETUEN: PSYMINFO Pointer to matching or nearest SYMINFO
|
|
*
|
|
* WARNING:
|
|
* -none-
|
|
*
|
|
* COMMENT:
|
|
* -none-
|
|
*
|
|
*/
|
|
|
|
PSYMINFO SymBSearch (DWORD dwAddr, SYMINFO syminfoCur[], INT n)
|
|
{
|
|
int i;
|
|
ULONG ulHigh = n;
|
|
ULONG ulLow = 0;
|
|
ULONG ulMid;
|
|
|
|
if (n==0)
|
|
return NULL;
|
|
|
|
while (ulLow < ulHigh)
|
|
{
|
|
ulMid = ulHigh - (ulHigh - ulLow) / 2;
|
|
if ((i = SymBCompare(&dwAddr, &syminfoCur[ulMid])) < 0)
|
|
{
|
|
ulHigh = ulMid - 1;
|
|
}
|
|
else if (i > 0)
|
|
{
|
|
ulLow = ulMid;
|
|
}
|
|
else
|
|
{
|
|
return (&syminfoCur[ulMid]);
|
|
}
|
|
|
|
}
|
|
|
|
return &syminfoCur[ulLow];
|
|
|
|
} /* SymBSearch () */
|
|
|