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.
284 lines
8.1 KiB
284 lines
8.1 KiB
/*
|
|
Copyright 1999 Microsoft Corporation
|
|
|
|
Neptune data collection server
|
|
|
|
Walter Smith (wsmith)
|
|
|
|
Matches Symbols with The Corresponding Binary
|
|
|
|
*/
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
#include <dbghelp.h>
|
|
#include <symres.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <shlwapi.h>
|
|
#include <sys\stat.h>
|
|
#include <string.h>
|
|
#undef UNICODE
|
|
#include <strsafe.h>
|
|
|
|
#ifndef DIMA
|
|
#define DIMAT(Array, EltType) (sizeof(Array) / sizeof(EltType))
|
|
#define DIMA(Array) DIMAT(Array, (Array)[0])
|
|
#endif
|
|
|
|
void
|
|
UndecorateSymbol(
|
|
LPTSTR szSymbol // [in] [out] function name undecorated in place
|
|
)
|
|
{
|
|
char szTemp[MAX_PATH];
|
|
PIMAGEHLP_SYMBOL pihsym;
|
|
DWORD dwSize;
|
|
|
|
dwSize = sizeof(IMAGEHLP_SYMBOL)+MAX_PATH;
|
|
pihsym = (IMAGEHLP_SYMBOL *) malloc(dwSize);
|
|
pihsym->SizeOfStruct = dwSize;
|
|
pihsym->Address = 0;
|
|
pihsym->Flags = 0;
|
|
pihsym->MaxNameLength = MAX_PATH;
|
|
wcstombs(pihsym->Name,szSymbol, lstrlen(szSymbol));
|
|
SymUnDName(pihsym,szTemp,MAX_PATH);
|
|
mbstowcs(szSymbol,szTemp, strlen(szTemp));
|
|
}
|
|
|
|
// select file from list of open files, or open and add to list
|
|
// maintain files in usage order, least recently used at end of list
|
|
OPENFILE* // pointer to open file info
|
|
SymbolResolver::GetFile(
|
|
LPWSTR szwModule // [in] name of file
|
|
)
|
|
{
|
|
OPENFILE* pFile = NULL;
|
|
MAPDEF map;
|
|
DWORD dwCread;
|
|
WCHAR wszBuffer[MAX_PATH];
|
|
|
|
StringCchCopyW(wszBuffer, DIMA(wszBuffer), szwModule);
|
|
PathRemoveExtension(wszBuffer);
|
|
PathAddExtension(wszBuffer, L".sym");
|
|
|
|
pFile = new OPENFILE;
|
|
// open SYM file
|
|
pFile->hfFile = CreateFileW(wszBuffer,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (pFile->hfFile == INVALID_HANDLE_VALUE) return NULL;
|
|
// copy filename and version into pFile node
|
|
StringCchCopyW(pFile->szwName, DIMA(pFile->szwName), szwModule);
|
|
|
|
// read map definition
|
|
ReadFile(pFile->hfFile, &map, sizeof(MAPDEF)-1, &dwCread, NULL);
|
|
|
|
if (dwCread != sizeof(MAPDEF)-1)
|
|
{
|
|
if (pFile->hfFile)
|
|
CloseHandle(pFile->hfFile);
|
|
if (pFile)
|
|
delete pFile;
|
|
throw E_FAIL;
|
|
}
|
|
|
|
pFile->ulFirstSeg = map.md_spseg*16;
|
|
pFile->nSeg = map.md_cseg;
|
|
pFile->psCurSymDefPtrs = NULL;
|
|
|
|
return pFile;
|
|
}
|
|
|
|
|
|
// parse sym file to resolve address
|
|
// read segment defintion for dwSection
|
|
ULONG // return offset of segment definition, 0 if failed
|
|
SymbolResolver::GetSegDef(OPENFILE* pFile, // [in] pointer to open file info
|
|
DWORD dwSection, // [in] section number
|
|
SEGDEF* pSeg) // [out] pointer to segment definition
|
|
{
|
|
ULONG ulCurSeg = pFile->ulFirstSeg;
|
|
int iSectionIndex = 0;
|
|
DWORD dwCread;
|
|
|
|
// step through segments
|
|
while (iSectionIndex < pFile->nSeg)
|
|
{
|
|
// go to segment beginning
|
|
if (SetFilePointer(pFile->hfFile, ulCurSeg, NULL, FILE_BEGIN) == 0xFFFFFFFF)
|
|
{
|
|
ulCurSeg = 0;
|
|
break;
|
|
}
|
|
|
|
// read seg defn
|
|
if (!ReadFile(pFile->hfFile, pSeg, sizeof(SEGDEF)-1, &dwCread, NULL))
|
|
{
|
|
ulCurSeg = 0;
|
|
break;
|
|
}
|
|
|
|
iSectionIndex++;
|
|
if (iSectionIndex == (int)dwSection) // gotcha
|
|
{
|
|
break;
|
|
}
|
|
|
|
// go to next segment definition
|
|
ulCurSeg = pSeg->gd_spsegnext*16;
|
|
}
|
|
|
|
// found our section and it's non-empty?
|
|
if (iSectionIndex != (int)dwSection || !pSeg->gd_csym) // no
|
|
{
|
|
ulCurSeg = 0;
|
|
}
|
|
|
|
return ulCurSeg;
|
|
}
|
|
|
|
// parse sym file to resolve address
|
|
bool
|
|
SymbolResolver::GetNameFromAddr(
|
|
LPWSTR szwModule, // [in] name of symbol file
|
|
DWORD dwSection, // [in] section part of address to resolve
|
|
DWORD dwOffsetToRva, // [in] Section base
|
|
UINT_PTR uRva, // [in] offset part of address to resolve
|
|
LPWSTR wszFuncName // [out] resolved function name,
|
|
)
|
|
{
|
|
SEGDEF seg;
|
|
DWORD dwSymAddr;
|
|
TCHAR sztFuncName[MAX_NAME+1];
|
|
int i;
|
|
int nNameLen;
|
|
DWORD dwCread;
|
|
int nToRead;
|
|
unsigned char cName;
|
|
ULONG ulCurSeg;
|
|
ULONG ulSymNameOffset = 0;
|
|
HANDLE hfFile;
|
|
OPENFILE* pFile = NULL;
|
|
DWORD dwArrayOffset;
|
|
DWORD dwSymOffset;
|
|
bool fResult = false;
|
|
|
|
// get file from open list, or open file
|
|
pFile = GetFile(szwModule);
|
|
|
|
if (!pFile)
|
|
return false;
|
|
|
|
if ((ulCurSeg = GetSegDef(pFile, dwSection, &seg)) == 0)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
BYTE* pSymDefPtrs;
|
|
|
|
// big symbols?
|
|
if (seg.gd_type & MSF_BIGSYMDEF)
|
|
{
|
|
dwArrayOffset = seg.gd_psymoff * 16;
|
|
pSymDefPtrs = (BYTE*)(new BYTE[seg.gd_csym*3]);
|
|
}
|
|
else
|
|
{
|
|
dwArrayOffset = seg.gd_psymoff;
|
|
pSymDefPtrs = (BYTE*)(new BYTE[seg.gd_csym*2]);
|
|
}
|
|
hfFile = pFile->hfFile;
|
|
|
|
SetFilePointer(hfFile, ulCurSeg + dwArrayOffset, NULL, FILE_BEGIN);
|
|
|
|
// read symbol definition pointers array
|
|
ReadFile(hfFile, pSymDefPtrs, seg.gd_csym * ((seg.gd_type & MSF_BIGSYMDEF)?3:2), &dwCread, NULL);
|
|
|
|
pFile->psCurSymDefPtrs = pSymDefPtrs;
|
|
|
|
// save this section
|
|
pFile->dwCurSection = dwSection;
|
|
|
|
// read symbols
|
|
|
|
for (i = 0; i < seg.gd_csym; i++)
|
|
{
|
|
// go to offset of sym defintion
|
|
if (seg.gd_type & MSF_BIGSYMDEF)
|
|
{
|
|
dwSymOffset = pFile->psCurSymDefPtrs[i*3+0]
|
|
+ pFile->psCurSymDefPtrs[i*3+1]*256
|
|
+ pFile->psCurSymDefPtrs[i*3+2]*65536;
|
|
}
|
|
else
|
|
{
|
|
dwSymOffset = pFile->psCurSymDefPtrs[i*2+0]
|
|
+ pFile->psCurSymDefPtrs[i*2+1]*256;
|
|
}
|
|
|
|
SetFilePointer(hfFile, ulCurSeg + dwSymOffset, NULL, FILE_BEGIN);
|
|
|
|
// read symbol address DWORD
|
|
ReadFile(hfFile,&dwSymAddr,sizeof(DWORD),&dwCread,NULL);
|
|
|
|
// symbol address is 1 word or two?
|
|
nToRead = sizeof(SHORT) + ((seg.gd_type & MSF_32BITSYMS) * sizeof(SHORT));
|
|
|
|
// calculate offset of symbol name
|
|
ulSymNameOffset = ulCurSeg + dwSymOffset + nToRead;
|
|
|
|
// use just lower word of address if 16-bit symbol
|
|
if (!(seg.gd_type & MSF_32BITSYMS))
|
|
{
|
|
dwSymAddr = dwSymAddr & 0x0000FFFF;
|
|
}
|
|
dwSymAddr += dwOffsetToRva;
|
|
|
|
if (dwSymAddr > uRva ) break;
|
|
if (dwSymAddr == uRva )
|
|
{
|
|
// do we have our function?
|
|
// if current address is greater than offset, then since we are
|
|
// traversing in the increasing order of addresses, the previous
|
|
// symbol must be our quarry
|
|
|
|
SetFilePointer(hfFile, ulSymNameOffset, NULL, FILE_BEGIN);
|
|
|
|
// read length of name
|
|
ReadFile(hfFile,&cName,sizeof(TCHAR),&dwCread,NULL);
|
|
|
|
nNameLen = (int) cName;
|
|
|
|
// read symbol name
|
|
ReadFile(hfFile,sztFuncName,nNameLen,&dwCread,NULL);
|
|
|
|
sztFuncName[nNameLen/2 - (nNameLen+1)%2] = TCHAR('\0');
|
|
|
|
UndecorateSymbol(sztFuncName);
|
|
|
|
StrCpyNW(wszFuncName, sztFuncName, MAX_NAME);
|
|
fResult = true;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (pFile->hfFile)
|
|
CloseHandle(pFile->hfFile);
|
|
|
|
if (pFile->psCurSymDefPtrs)
|
|
delete pFile->psCurSymDefPtrs;
|
|
|
|
if (pFile)
|
|
delete pFile;
|
|
|
|
return fResult;
|
|
}
|
|
|