windows-nt/Source/XPSP1/NT/sdktools/debuggers/imagehlp/mapdebug.c
2020-09-26 16:20:57 +08:00

1878 lines
53 KiB
C

#include <private.h>
#include <symbols.h>
#include "globals.h"
// forward reference
void
RetrievePdbInfo(
PIMGHLP_DEBUG_DATA pIDD,
CHAR const *szReference
);
BOOL
FindDebugInfoFileExCallback(
HANDLE FileHandle,
PSTR FileName,
PVOID CallerData
);
BOOL
FindExecutableImageExCallback(
HANDLE FileHandle,
PSTR FileName,
PVOID CallerData
);
BOOL
ProcessDebugInfo(
PIMGHLP_DEBUG_DATA pIDD,
DWORD datasrc
);
__inline
BOOL
ProcessImageDebugInfo(
PIMGHLP_DEBUG_DATA pIDD
)
{
return ProcessDebugInfo(pIDD, dsImage);
}
__inline
BOOL
ProcessInProcDebugInfo(
PIMGHLP_DEBUG_DATA pIDD
)
{
return ProcessDebugInfo(pIDD, dsInProc);
}
__inline
BOOL
ProcessDbgDebugInfo(
PIMGHLP_DEBUG_DATA pIDD
)
{
return ProcessDebugInfo(pIDD, dsDbg);
}
BOOL
ProcessCallerDataDebugInfo(
PIMGHLP_DEBUG_DATA pIDD
)
{
PMODLOAD_DATA mld = pIDD->mld;
PIMAGE_DEBUG_DIRECTORY dd;
PCHAR pCV;
DWORD cdd;
DWORD i;
if (!mld)
return FALSE;
if (!mld->ssize
|| !mld->size
|| !mld->data)
return FALSE;
if (mld->ssig != DBHHEADER_DEBUGDIRS)
return FALSE;
cdd = mld->size / sizeof(IMAGE_DEBUG_DIRECTORY);
dd = (PIMAGE_DEBUG_DIRECTORY)mld->data;
for (i = 0; i < cdd; i++, dd++) {
if (dd->Type != IMAGE_DEBUG_TYPE_CODEVIEW)
continue;
pCV = (PCHAR)mld->data + dd->PointerToRawData;
pIDD->fCvMapped = TRUE;
pIDD->pMappedCv = (PCHAR)pCV;
pIDD->cMappedCv = dd->SizeOfData;
pIDD->dsCV = dsCallerData;
pIDD->PdbSignature = 0;
pIDD->PdbAge = 0;
RetrievePdbInfo(pIDD, pIDD->ImageFilePath);
mdSet(pIDD->md, dd->Type, dsNone, dsCallerData);
break;
}
return TRUE;
}
// functions called by the MODULE_DATA array...
BOOL
mdfnOpenDbgFile(
PIMGHLP_DEBUG_DATA pIDD
)
{
dprint("mdfnOpenDbgFile()\n");
if (pIDD->DbgFileHandle)
return TRUE;
if (*pIDD->OriginalDbgFileName) {
pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
pIDD->OriginalDbgFileName,
pIDD->SymbolPath,
pIDD->DbgFilePath,
FindDebugInfoFileExCallback,
pIDD,
fdifRECURSIVE);
}
if (!pIDD->DbgFileHandle) {
pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
pIDD->ImageName,
pIDD->SymbolPath,
pIDD->DbgFilePath,
FindDebugInfoFileExCallback,
pIDD,
fdifRECURSIVE);
}
if (!pIDD->DbgFileHandle)
g.LastSymLoadError = SYMLOAD_DBGNOTFOUND;
// if we have a .dbg file. See what we can get from it.
if (pIDD->DbgFileHandle) {
ProcessDbgDebugInfo(pIDD);
}
return TRUE;
}
BOOL
mdfnGetExecutableImage(
PIMGHLP_DEBUG_DATA pIDD
)
{
dprint("mdfnGetExecutableImage()\n");
if (!*pIDD->ImageName)
return TRUE;
if (!pIDD->ImageFileHandle)
pIDD->ImageFileHandle = FindExecutableImageEx(pIDD->ImageName,
pIDD->SymbolPath,
pIDD->ImageFilePath,
FindExecutableImageExCallback,
pIDD);
if (pIDD->ImageFileHandle)
ProcessImageDebugInfo(pIDD);
return TRUE;
}
// this struct is used to initilaize the module data array for a new module
static MODULE_DATA gmd[NUM_MODULE_DATA_ENTRIES] =
{
{mdHeader, dsNone, dsNone, FALSE, NULL},
{mdSecHdrs, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_UNKNOWN, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_COFF, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_CODEVIEW, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_FPO, dsNone, dsNone, TRUE, mdfnGetExecutableImage},
{IMAGE_DEBUG_TYPE_MISC, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_EXCEPTION, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_FIXUP, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_OMAP_TO_SRC, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_OMAP_FROM_SRC, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_BORLAND, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_RESERVED10, dsNone, dsNone, FALSE, NULL},
{IMAGE_DEBUG_TYPE_CLSID, dsNone, dsNone, FALSE, NULL}
};
DWORD
mdSet(
PMODULE_DATA md,
DWORD id,
DWORD hint,
DWORD src
)
{
DWORD i;
for (i = 0; i < NUM_MODULE_DATA_ENTRIES; md++, i++) {
if (md->id == id) {
if (hint != dsNone)
md->hint = hint;
if (src != dsNone)
md->src = src;
return i;
}
}
return 0;
}
void
mdDump(
PMODULE_DATA md,
BOOL verbose
)
{
DWORD i;
static PCHAR idstr[] =
{
"mdHeader",
"mdSecHdrs",
"IMAGE_DEBUG_TYPE_UNKNOWN",
"IMAGE_DEBUG_TYPE_COFF",
"IMAGE_DEBUG_TYPE_CODEVIEW",
"IMAGE_DEBUG_TYPE_FPO",
"IMAGE_DEBUG_TYPE_MISC",
"IMAGE_DEBUG_TYPE_EXCEPTION",
"IMAGE_DEBUG_TYPE_FIXUP",
"IMAGE_DEBUG_TYPE_OMAP_TO_SRC",
"IMAGE_DEBUG_TYPE_OMAP_FROM_SRC",
"IMAGE_DEBUG_TYPE_BORLAND",
"IMAGE_DEBUG_TYPE_RESERVED10",
"IMAGE_DEBUG_TYPE_CLSID"
};
static PCHAR dsstr[] =
{
"dsNone",
"dsInProc",
"dsImage",
"dsDbg",
"dsPdb",
"dsDia"
};
for (i = 0; i < NUM_MODULE_DATA_ENTRIES; md++, i++) {
if (verbose | md->hint | md->src) {
dprint("MD:%30s hint=%s src=%s\n",
idstr[i],
dsstr[md->hint],
dsstr[md->src]);
}
}
dprint("\n");
}
BOOL
GetUnfoundData(
PIMGHLP_DEBUG_DATA pIDD
)
{
DWORD i;
PMODULE_DATA md;
for (md = pIDD->md, i = 0; i < NUM_MODULE_DATA_ENTRIES; md++, i++) {
if (!md->required)
continue;
if (md->hint == dsNone)
continue;
if (md->src != dsNone)
continue;
if (!md->fn)
continue;
if (!md->fn(pIDD))
return FALSE;
}
return TRUE;
}
BOOL
IsImageMachineType64(
DWORD MachineType
)
{
switch(MachineType) {
case IMAGE_FILE_MACHINE_AXP64:
case IMAGE_FILE_MACHINE_IA64:
case IMAGE_FILE_MACHINE_AMD64:
return TRUE;
default:
return FALSE;
}
}
ULONG
ReadImageData(
IN HANDLE hprocess,
IN ULONG64 ul,
IN ULONG64 addr,
OUT LPVOID buffer,
IN ULONG size
)
{
ULONG bytesread;
if (hprocess) {
ULONG64 base = ul;
BOOL rc;
rc = ReadInProcMemory(hprocess,
base + addr,
buffer,
size,
&bytesread);
if (!rc || (bytesread < (ULONG)size))
return 0;
} else {
PCHAR p = (PCHAR)ul + addr;
memcpy(buffer, p, size);
}
return size;
}
PVOID
MapItRO(
HANDLE FileHandle
)
{
PVOID MappedBase = NULL;
if (FileHandle) {
HANDLE MappingHandle = CreateFileMapping( FileHandle, NULL, PAGE_READONLY, 0, 0, NULL );
if (MappingHandle) {
MappedBase = MapViewOfFile( MappingHandle, FILE_MAP_READ, 0, 0, 0 );
CloseHandle(MappingHandle);
}
}
return MappedBase;
}
void
CloseSymbolServer(
VOID
)
{
if (!g.hSrv)
return;
if (g.fnSymbolServerClose)
g.fnSymbolServerClose();
FreeLibrary(g.hSrv);
g.hSrv = 0;
*g.szSrvName = 0;
g.szSrvParams = NULL;
g.fnSymbolServer = NULL;
g.fnSymbolServerClose = NULL;
g.fnSymbolServerSetOptions = NULL;
}
DWORD
ProcessSymbolServerError(
BOOL success,
LPCSTR params
)
{
DWORD rc;
if (success)
return NO_ERROR;
rc = GetLastError();
switch(rc)
{
case ERROR_FILE_NOT_FOUND: // obvious
case ERROR_MORE_DATA: // didn't pass any tokens
break;
case ERROR_INVALID_NAME:
CloseSymbolServer();
g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
evtprint(NULL, sevProblem, ERROR_INVALID_NAME, NULL, "SYMSRV: %s needs a downstream store.\n", params);
break;
case ERROR_FILE_INVALID:
evtprint(NULL, sevProblem, ERROR_FILE_INVALID, NULL, "SYMSRV: Compressed file needs a downstream store.\n");
break;
default:
dprint("symsrv error 0x%x\n", rc);
break;
}
return rc;
}
BOOL
GetFileFromSymbolServer(
IN LPCSTR ServerInfo,
IN LPCSTR FileName,
IN GUID *guid,
IN DWORD two,
IN DWORD three,
OUT LPSTR FilePath
)
{
BOOL rc;
CHAR *params;
LPCSTR fname;
// strip any path information from the filename
for (fname = FileName + strlen(FileName); fname > FileName; fname--) {
if (*fname == '\\') {
fname++;
break;
}
}
// initialize server, if needed
if (g.hSrv == (HINSTANCE)INVALID_HANDLE_VALUE)
return FALSE;
if (!g.hSrv) {
g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
strcpy(g.szSrvName, &ServerInfo[7]);
if (!*g.szSrvName)
return FALSE;
g.szSrvParams = strchr(g.szSrvName, '*');
if (!g.szSrvParams )
return FALSE;
*g.szSrvParams++ = '\0';
g.hSrv = LoadLibrary(g.szSrvName);
if (g.hSrv) {
g.fnSymbolServer = (PSYMBOLSERVERPROC)GetProcAddress(g.hSrv, "SymbolServer");
if (!g.fnSymbolServer) {
FreeLibrary(g.hSrv);
g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
}
g.fnSymbolServerClose = (PSYMBOLSERVERCLOSEPROC)GetProcAddress(g.hSrv, "SymbolServerClose");
g.fnSymbolServerSetOptions = (PSYMBOLSERVERSETOPTIONSPROC)GetProcAddress(g.hSrv, "SymbolServerSetOptions");
SetSymbolServerOptions(SSRVOPT_RESET, 0);
SetSymbolServerOptions(SSRVOPT_GUIDPTR, 1);
} else {
g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
}
}
// bail, if we have no valid server
if (g.hSrv == INVALID_HANDLE_VALUE) {
dprint("SymSrv load failure: %s\n", g.szSrvName);
return FALSE;
}
params = strchr(ServerInfo, '*');
if (!params)
return FALSE;
params = strchr(params+1, '*');
if (!params)
return FALSE;
SetCriticalErrorMode();
rc = g.fnSymbolServer(params+1, fname, guid, two, three, FilePath);
#ifdef GETRIDOFTHISASAP
if (!rc) {
SetSymbolServerOptions(SSRVOPT_RESET, 0);
SetSymbolServerOptions(SSRVOPT_OLDGUIDPTR, 1);
rc = g.fnSymbolServer(params+1, fname, guid, two, three, FilePath);
SetSymbolServerOptions(SSRVOPT_RESET, 0);
SetSymbolServerOptions(SSRVOPT_GUIDPTR, 1);
}
#endif
ResetCriticalErrorMode();
ProcessSymbolServerError(rc, params+1);
return rc;
}
BOOL
SymbolServerCallback(
UINT_PTR action,
ULONG64 data,
ULONG64 context
)
{
BOOL rc = TRUE;
char *sz;
switch (action) {
case SSRVACTION_TRACE:
sz = (char *)data;
eprint((char *)data);
break;
default:
// unsupported
rc = FALSE;
break;
}
return rc;
}
void
SetSymbolServerOptions(
ULONG_PTR options,
ULONG64 data
)
{
static ULONG_PTR ssopts = 0;
static ULONG64 ssdata = 0;
if (options != SSRVOPT_RESET) {
ssopts = options;
ssdata = data;
}
if (g.fnSymbolServerSetOptions)
g.fnSymbolServerSetOptions(ssopts, ssdata);
}
void
SetSymbolServerCallback(
BOOL state
)
{
if (state)
SetSymbolServerOptions(SSRVOPT_CALLBACK, (ULONG64)SymbolServerCallback);
else
SetSymbolServerOptions(0, 0);
}
BOOL
ProcessOldStyleCodeView(
PIMGHLP_DEBUG_DATA pIDD
)
{
OMFSignature *omfSig;
OMFDirHeader *omfDirHdr;
OMFDirEntry *omfDirEntry;
OMFSegMap *omfSegMap;
OMFSegMapDesc *omfSegMapDesc;
DWORD i, j, k, SectionSize;
DWORD SectionStart;
PIMAGE_SECTION_HEADER Section;
if (pIDD->cOmapFrom) {
// If there's omap, we need to generate the original section map
omfSig = (OMFSignature *)pIDD->pMappedCv;
omfDirHdr = (OMFDirHeader*) ((PCHAR)pIDD->pMappedCv + (DWORD)omfSig->filepos);
omfDirEntry = (OMFDirEntry*) ((PCHAR)omfDirHdr + sizeof(OMFDirHeader));
if (!omfDirHdr->cDir) {
pIDD->cOmapFrom = 0;
pIDD->cOmapTo = 0;
}
for (i=0; i<omfDirHdr->cDir; i++,omfDirEntry++) {
if (omfDirEntry->SubSection == sstSegMap) {
omfSegMap = (OMFSegMap*) ((PCHAR)pIDD->pMappedCv + omfDirEntry->lfo);
omfSegMapDesc = (OMFSegMapDesc*)&omfSegMap->rgDesc[0];
SectionStart = *(DWORD *)pIDD->pOmapFrom;
SectionSize = 0;
Section = (PIMAGE_SECTION_HEADER) MemAlloc(omfSegMap->cSeg * sizeof(IMAGE_SECTION_HEADER));
if (Section) {
for (j=0, k=0; j < omfSegMap->cSeg; j++) {
if (omfSegMapDesc[j].frame) {
// The linker sets the frame field to the actual section header number. Zero is
// used to track absolute symbols that don't exist in a real sections.
Section[k].VirtualAddress =
SectionStart =
SectionStart + ((SectionSize + (pIDD->ImageAlign-1)) & ~(pIDD->ImageAlign-1));
Section[k].Misc.VirtualSize =
SectionSize = omfSegMapDesc[j].cbSeg;
k++;
}
}
pIDD->pOriginalSections = Section;
pIDD->cOriginalSections = k;
}
}
}
}
return TRUE;
}
__inline
DWORD
IsDataInSection (PIMAGE_SECTION_HEADER Section,
PIMAGE_DATA_DIRECTORY Data
)
{
DWORD RealDataOffset;
if ((Data->VirtualAddress >= Section->VirtualAddress) &&
((Data->VirtualAddress + Data->Size) <= (Section->VirtualAddress + Section->SizeOfRawData))) {
RealDataOffset = (DWORD)(Data->VirtualAddress -
Section->VirtualAddress +
Section->PointerToRawData);
} else {
RealDataOffset = 0;
}
return RealDataOffset;
}
__inline
DWORD
SectionContains (
HANDLE hp,
PIMAGE_SECTION_HEADER pSH,
PIMAGE_DATA_DIRECTORY ddir
)
{
DWORD rva = 0;
if (!ddir->VirtualAddress)
return 0;
if (ddir->VirtualAddress >= pSH->VirtualAddress) {
if ((ddir->VirtualAddress + ddir->Size) <= (pSH->VirtualAddress + pSH->SizeOfRawData)) {
rva = ddir->VirtualAddress;
if (!hp)
rva = rva - pSH->VirtualAddress + pSH->PointerToRawData;
}
}
return rva;
}
void
RetrievePdbInfo(
PIMGHLP_DEBUG_DATA pIDD,
CHAR const *szReference
)
{
CHAR szRefDrive[_MAX_DRIVE];
CHAR szRefPath[_MAX_DIR];
PCVDD pcv = (PCVDD)pIDD->pMappedCv;
if (pIDD->PdbSignature)
return;
switch (pcv->dwSig)
{
case '01BN':
pIDD->PdbAge = pcv->nb10i.age;
pIDD->PdbSignature = pcv->nb10i.sig;
strcpy(pIDD->PdbFileName, pcv->nb10i.szPdb);
break;
case 'SDSR':
pIDD->PdbRSDS = TRUE;
pIDD->PdbAge = pcv->rsdsi.age;
memcpy(&pIDD->PdbGUID, &pcv->rsdsi.guidSig, sizeof(GUID));
strcpy(pIDD->PdbFileName, pcv->rsdsi.szPdb);
break;
default:
return;
}
// if there is a path in the CV record - use it
if ((g.SymOptions & SYMOPT_IGNORE_CVREC) == 0) {
_splitpath(szReference, szRefDrive, szRefPath, NULL, NULL);
_makepath(pIDD->PdbReferencePath, szRefDrive, szRefPath, NULL, NULL);
if (strlen(szRefPath) > 1) {
pIDD->PdbReferencePath[strlen(pIDD->PdbReferencePath)-1] = '\0';
return;
}
}
// if we have full path info for the image - use it
_splitpath(pIDD->ImageName, szRefDrive, szRefPath, NULL, NULL);
_makepath(pIDD->PdbReferencePath, szRefDrive, szRefPath, NULL, NULL);
if (strlen(szRefPath) > 1) {
pIDD->PdbReferencePath[strlen(pIDD->PdbReferencePath)-1] = '\0';
return;
}
// No path. Put on at least a dot "."
strcpy(pIDD->PdbReferencePath, ".");
}
BOOL
FakePdbName(
PIMGHLP_DEBUG_DATA pIDD
)
{
CHAR szName[_MAX_FNAME];
if (pIDD->PdbSignature) {
return FALSE;
}
if (!pIDD->ImageName)
return FALSE;
_splitpath(pIDD->ImageName, NULL, NULL, szName, NULL);
if (!*szName)
return FALSE;
strcpy(pIDD->PdbFileName, szName);
strcat(pIDD->PdbFileName, ".pdb");
return TRUE;
}
BOOL
FindDebugInfoFileExCallback(
HANDLE FileHandle,
PSTR FileName,
PVOID CallerData
)
{
PIMGHLP_DEBUG_DATA pIDD;
PIMAGE_SEPARATE_DEBUG_HEADER DbgHeader;
PVOID FileMap;
BOOL rc;
rc = TRUE;
if (!CallerData)
return TRUE;
pIDD = (PIMGHLP_DEBUG_DATA)CallerData;
FileMap = MapItRO(FileHandle);
if (!FileMap) {
return FALSE;
}
DbgHeader = (PIMAGE_SEPARATE_DEBUG_HEADER)FileMap;
// Only support .dbg files for X86 and Alpha (32 bit).
if ((DbgHeader->Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE) ||
((DbgHeader->Machine != IMAGE_FILE_MACHINE_I386) &&
(DbgHeader->Machine != IMAGE_FILE_MACHINE_ALPHA)))
{
rc = FALSE;
goto cleanup;
}
// ignore checksums, they are bogus
rc = (pIDD->TimeDateStamp == DbgHeader->TimeDateStamp) ? TRUE : FALSE;
cleanup:
if (FileMap)
UnmapViewOfFile(FileMap);
return rc;
}
BOOL
ProcessDebugInfo(
PIMGHLP_DEBUG_DATA pIDD,
DWORD datasrc
)
{
BOOL status;
ULONG cb;
IMAGE_DOS_HEADER dh;
IMAGE_NT_HEADERS32 nh32;
IMAGE_NT_HEADERS64 nh64;
PIMAGE_ROM_OPTIONAL_HEADER rom = NULL;
IMAGE_SEPARATE_DEBUG_HEADER sdh;
PIMAGE_FILE_HEADER fh;
PIMAGE_DEBUG_MISC md;
ULONG ddva;
ULONG shva;
ULONG nSections;
PIMAGE_SECTION_HEADER psh;
IMAGE_DEBUG_DIRECTORY dd;
PIMAGE_DATA_DIRECTORY datadir;
PCHAR pCV;
ULONG i;
int nDebugDirs = 0;
HANDLE hp;
ULONG64 base;
IMAGE_ROM_HEADERS ROMImage;
DWORD rva;
PCHAR filepath;
IMAGE_EXPORT_DIRECTORY expdir;
DWORD fsize;
BOOL rc;
USHORT filetype;
// setup pointers for grabing data
switch (datasrc) {
case dsInProc:
hp = pIDD->hProcess;
base = pIDD->InProcImageBase;
fsize = 0;
filepath = pIDD->ImageFilePath;
pIDD->PdbSrc = srcCVRec;
break;
case dsImage:
hp = NULL;
pIDD->ImageMap = MapItRO(pIDD->ImageFileHandle);
base = (ULONG64)pIDD->ImageMap;
fsize = GetFileSize(pIDD->ImageFileHandle, NULL);
filepath = pIDD->ImageFilePath;
pIDD->PdbSrc = srcImagePath;
break;
case dsDbg:
hp = NULL;
pIDD->DbgFileMap = MapItRO(pIDD->DbgFileHandle);
base = (ULONG64)pIDD->DbgFileMap;
fsize = GetFileSize(pIDD->DbgFileHandle, NULL);
filepath = pIDD->DbgFilePath;
pIDD->PdbSrc = srcDbgPath;
break;
default:
return FALSE;
}
// some initialization
pIDD->fNeedImage = FALSE;
rc = FALSE;
ddva = 0;
__try {
// test the file type
status = ReadImageData(hp, base, 0, &filetype, sizeof(filetype));
if (!status) {
g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
return FALSE;
}
pIDD->ImageType = datasrc;
if (filetype == IMAGE_SEPARATE_DEBUG_SIGNATURE)
goto dbg;
if (filetype == IMAGE_DOS_SIGNATURE)
{
// grab the dos header
status = ReadImageData(hp, base, 0, &dh, sizeof(dh));
if (!status) {
g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
return FALSE;
}
// grab the pe header
status = ReadImageData(hp, base, dh.e_lfanew, &nh32, sizeof(nh32));
if (!status) {
g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
return FALSE;
}
// read header info
if (nh32.Signature != IMAGE_NT_SIGNATURE) {
// if header is not NT sig, this is a ROM image
rom = (PIMAGE_ROM_OPTIONAL_HEADER)&nh32.OptionalHeader;
fh = &nh32.FileHeader;
shva = dh.e_lfanew + sizeof(DWORD) +
sizeof(IMAGE_FILE_HEADER) + fh->SizeOfOptionalHeader;
}
} else if (filetype == IMAGE_FILE_MACHINE_I386) {
// This is an X86 ROM image
status = ReadImageData(hp, base, 0, &nh32.FileHeader, sizeof(nh32.FileHeader)+sizeof(nh32.OptionalHeader));
if (!status)
return FALSE;
nh32.Signature = 'ROM ';
} else {
// This may be a ROM image
status = ReadImageData(hp, base, 0, &ROMImage, sizeof(ROMImage));
if (!status) {
g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
return FALSE;
}
if ((ROMImage.FileHeader.Machine == IMAGE_FILE_MACHINE_I386) ||
(ROMImage.FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA) ||
(ROMImage.FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA64))
{
rom = (PIMAGE_ROM_OPTIONAL_HEADER)&ROMImage.OptionalHeader;
fh = &ROMImage.FileHeader;
shva = sizeof(IMAGE_FILE_HEADER) + fh->SizeOfOptionalHeader;
} else {
return FALSE;
}
}
if (rom) {
if (rom->Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC) {
pIDD->fROM = TRUE;
pIDD->iohMagic = rom->Magic;
pIDD->ImageBaseFromImage = rom->BaseOfCode;
pIDD->SizeOfImage = rom->SizeOfCode;
pIDD->CheckSum = 0;
} else {
return FALSE;
}
} else {
// otherwise, get info from appropriate header type for 32 or 64 bit
if (IsImageMachineType64(nh32.FileHeader.Machine)) {
// Reread the header as a 64bit header.
status = ReadImageData(hp, base, dh.e_lfanew, &nh64, sizeof(nh64));
if (!status) {
g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
return FALSE;
}
fh = &nh64.FileHeader;
datadir = nh64.OptionalHeader.DataDirectory;
shva = dh.e_lfanew + sizeof(nh64);
pIDD->iohMagic = nh64.OptionalHeader.Magic;
pIDD->fPE64 = TRUE; // seems to be unused
if (datasrc == dsImage || datasrc == dsInProc) {
pIDD->ImageBaseFromImage = nh64.OptionalHeader.ImageBase;
pIDD->ImageAlign = nh64.OptionalHeader.SectionAlignment;
pIDD->CheckSum = nh64.OptionalHeader.CheckSum;
}
pIDD->SizeOfImage = nh64.OptionalHeader.SizeOfImage;
}
else {
fh = &nh32.FileHeader;
datadir = nh32.OptionalHeader.DataDirectory;
pIDD->iohMagic = nh32.OptionalHeader.Magic;
if (nh32.Signature == 'ROM ') {
shva = sizeof(nh32.FileHeader)+sizeof(nh32.OptionalHeader);
} else {
shva = dh.e_lfanew + sizeof(nh32);
}
if (datasrc == dsImage || datasrc == dsInProc) {
pIDD->ImageBaseFromImage = nh32.OptionalHeader.ImageBase;
pIDD->ImageAlign = nh32.OptionalHeader.SectionAlignment;
pIDD->CheckSum = nh32.OptionalHeader.CheckSum;
}
pIDD->SizeOfImage = nh32.OptionalHeader.SizeOfImage;
}
}
mdSet(pIDD->md, mdHeader, datasrc, datasrc);
// read the section headers
nSections = fh->NumberOfSections;
psh = (PIMAGE_SECTION_HEADER) MemAlloc(nSections * sizeof(IMAGE_SECTION_HEADER));
if (!psh)
goto debugdirs;
status = ReadImageData(hp, base, shva, psh, nSections * sizeof(IMAGE_SECTION_HEADER));
if (!status)
goto debugdirs;
// store off info to return struct
pIDD->pCurrentSections = psh;
pIDD->cCurrentSections = nSections;
pIDD->pImageSections = psh;
pIDD->cImageSections = nSections;
pIDD->Machine = fh->Machine;
pIDD->TimeDateStamp = fh->TimeDateStamp;
pIDD->Characteristics = fh->Characteristics;
mdSet(pIDD->md, mdSecHdrs, datasrc, datasrc);
// get information from the sections
for (i = 0; i < nSections; i++, psh++) {
DWORD offset;
if (pIDD->fROM &&
((fh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == 0) &&
(!strcmp((LPSTR)psh->Name, ".rdata")))
{
nDebugDirs = 1;
ddva = psh->VirtualAddress;
break;
}
if (offset = SectionContains(hp, psh, &datadir[IMAGE_DIRECTORY_ENTRY_EXPORT]))
{
pIDD->dsExports = datasrc;
pIDD->cExports = datadir[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
pIDD->oExports = offset;
ReadImageData(hp, base, offset, &pIDD->expdir, sizeof(pIDD->expdir));
}
if (offset = SectionContains(hp, psh, &datadir[IMAGE_DIRECTORY_ENTRY_DEBUG]))
{
ddva = offset;
nDebugDirs = datadir[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY);
}
}
goto debugdirs;
dbg:
// grab the dbg header
status = ReadImageData(hp, base, 0, &sdh, sizeof(sdh));
if (!status)
return FALSE;
// Only support .dbg files for X86 and Alpha (32 bit).
if ((sdh.Machine != IMAGE_FILE_MACHINE_I386)
&& (sdh.Machine != IMAGE_FILE_MACHINE_ALPHA))
{
UnmapViewOfFile(pIDD->DbgFileMap);
pIDD->DbgFileMap = 0;
return FALSE;
}
pIDD->ImageAlign = sdh.SectionAlignment;
pIDD->CheckSum = sdh.CheckSum;
pIDD->Machine = sdh.Machine;
pIDD->TimeDateStamp = sdh.TimeDateStamp;
pIDD->Characteristics = sdh.Characteristics;
if (!pIDD->ImageBaseFromImage) {
pIDD->ImageBaseFromImage = sdh.ImageBase;
}
if (!pIDD->SizeOfImage) {
pIDD->SizeOfImage = sdh.SizeOfImage;
}
nSections = sdh.NumberOfSections;
psh = (PIMAGE_SECTION_HEADER) MemAlloc(nSections * sizeof(IMAGE_SECTION_HEADER));
if (!psh)
goto debugdirs;
status = ReadImageData(hp,
base,
sizeof(IMAGE_SEPARATE_DEBUG_HEADER),
psh,
nSections * sizeof(IMAGE_SECTION_HEADER));
if (!status)
goto debugdirs;
pIDD->pCurrentSections = psh;
pIDD->cCurrentSections = nSections;
pIDD->pDbgSections = psh;
pIDD->cDbgSections = nSections;
// pIDD->ExportedNamesSize = sdh.ExportedNamesSize;
if (sdh.DebugDirectorySize) {
nDebugDirs = (int)(sdh.DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY));
ddva = sizeof(IMAGE_SEPARATE_DEBUG_HEADER)
+ (sdh.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))
+ sdh.ExportedNamesSize;
}
debugdirs:
rc = TRUE;
// copy the virtual addr of the debug directories over for MapDebugInformation
if (datasrc == dsImage) {
pIDD->ddva = ddva;
pIDD->cdd = nDebugDirs;
}
// read the debug directories
while (nDebugDirs) {
status = ReadImageData(hp, base, (ULONG_PTR)ddva, &dd, sizeof(dd));
if (!status)
break;
if (!dd.SizeOfData)
goto nextdebugdir;
// indicate that we found the debug directory
mdSet(pIDD->md, dd.Type, datasrc, dsNone);
// these debug directories are processed both in-proc and from file
switch (dd.Type)
{
case IMAGE_DEBUG_TYPE_CODEVIEW:
// get info on pdb file
if (hp && dd.AddressOfRawData) {
// in-proc image
if (!(pCV = (PCHAR)MemAlloc(dd.SizeOfData)))
break;
status = ReadImageData(hp, base, dd.AddressOfRawData, pCV, dd.SizeOfData);
if (!status) {
MemFree(pCV);
break;
}
} else {
// file-base image
if (dd.PointerToRawData >= fsize)
break;
pCV = (PCHAR)base + dd.PointerToRawData;
pIDD->fCvMapped = TRUE;
}
pIDD->pMappedCv = (PCHAR)pCV;
pIDD->cMappedCv = dd.SizeOfData;
pIDD->dsCV = datasrc;
RetrievePdbInfo(pIDD, filepath);
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
break;
case IMAGE_DEBUG_TYPE_MISC:
// on stripped files, find the dbg file
// on dbg file, find the original file name
if (dd.PointerToRawData < fsize) {
md = (PIMAGE_DEBUG_MISC)((PCHAR)base + dd.PointerToRawData);
if (md->DataType != IMAGE_DEBUG_MISC_EXENAME)
break;
if (datasrc == dsDbg) {
if (!*pIDD->OriginalImageFileName)
strncpy(pIDD->OriginalImageFileName, (LPSTR)md->Data, sizeof(pIDD->OriginalImageFileName));
break;
}
if (fh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
strncpy(pIDD->OriginalDbgFileName, (LPSTR)md->Data, sizeof(pIDD->OriginalDbgFileName));
} else {
strncpy(pIDD->OriginalImageFileName, (LPSTR)md->Data, sizeof(pIDD->OriginalImageFileName));
}
}
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
break;
case IMAGE_DEBUG_TYPE_COFF:
if (dd.PointerToRawData < fsize) {
// pIDD->fNeedImage = TRUE;
pIDD->pMappedCoff = (PCHAR)base + dd.PointerToRawData;
pIDD->cMappedCoff = dd.SizeOfData;
pIDD->fCoffMapped = TRUE;
pIDD->dsCoff = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
} else {
pIDD->fNeedImage = TRUE;
}
break;
#ifdef INPROC_SUPPORT
case IMAGE_DEBUG_TYPE_FPO:
if (dd.PointerToRawData < fsize) {
pIDD->pFpo = (PCHAR)base + dd.PointerToRawData;
pIDD->cFpo = dd.SizeOfData / SIZEOF_RFPO_DATA;
pIDD->fFpoMapped = TRUE;
pIDD->dsFPO = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
} else {
dprint("found fpo in-process\n");
}
break;
case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
if (dd.PointerToRawData < fsize) {
pIDD->pOmapTo = (PCHAR)base + dd.PointerToRawData;
pIDD->cOmapTo = dd.SizeOfData / sizeof(OMAP);
pIDD->fOmapToMapped = TRUE;
pIDD->dsOmapTo = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
} else {
dprint("found found omap-to in-process\n");
}
break;
case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
if (dd.PointerToRawData < fsize) {
pIDD->pOmapFrom = (PCHAR)base + dd.PointerToRawData;
pIDD->cOmapFrom = dd.SizeOfData / sizeof(OMAP);
pIDD->fOmapFromMapped = TRUE;
pIDD->dsOmapFrom = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
} else {
dprint("found omap-from in-process\n");
}
break;
#endif
}
// these debug directories are only processed for disk-based images
if (dd.PointerToRawData < fsize) {
switch (dd.Type)
{
case IMAGE_DEBUG_TYPE_FPO:
pIDD->pFpo = (PCHAR)base + dd.PointerToRawData;
pIDD->cFpo = dd.SizeOfData / SIZEOF_RFPO_DATA;
pIDD->fFpoMapped = TRUE;
pIDD->dsFPO = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
break;
case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
pIDD->pOmapTo = (POMAP)((PCHAR)base + dd.PointerToRawData);
pIDD->cOmapTo = dd.SizeOfData / sizeof(OMAP);
pIDD->fOmapToMapped = TRUE;
pIDD->dsOmapTo = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
break;
case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
pIDD->pOmapFrom = (POMAP)((PCHAR)base + dd.PointerToRawData);
pIDD->cOmapFrom = dd.SizeOfData / sizeof(OMAP);
pIDD->fOmapFromMapped = TRUE;
pIDD->dsOmapFrom = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
break;
case IMAGE_DEBUG_TYPE_EXCEPTION:
pIDD->dsExceptions = datasrc;
mdSet(pIDD->md, dd.Type, dsNone, datasrc);
break;
}
}
nextdebugdir:
ddva += sizeof(IMAGE_DEBUG_DIRECTORY);
nDebugDirs--;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
// We might have gotten enough information
// to be okay. So don't indicate error.
}
return rc;
}
BOOL
FigureOutImageName(
PIMGHLP_DEBUG_DATA pIDD
)
/*
We got here because we didn't get the image name passed in from the original call
to GetDebugData AND we were unable to find the MISC data with the name
Have to figure it out.
A couple of options here. First, if the DLL bit is set, try looking for Export
table. If found, IMAGE_EXPORT_DIRECTORY->Name is a rva pointer to the dll name.
If it's not found, see if there's a OriginalDbgFileName.
If so see if the format is <ext>\<filename>.dbg.
If there's more than one backslash or no backslash, punt and label it with a .dll
extension.
Otherwise a splitpath will do the trick.
If there's no DbgFilePath, see if there's a PDB name. The same rules apply there as
for .dbg files. Worst case, you s/b able to get the base name and just stick on a
If this all fails, label it as mod<base address>.
If the DLL bit is not set, assume an exe and tag it with that extension. The base name
can be retrieved from DbgFilePath, PdbFilePath, or use just APP.
*/
{
// Quick hack to get Dr. Watson going.
CHAR szName[_MAX_FNAME];
CHAR szExt[_MAX_FNAME];
if (pIDD->OriginalDbgFileName[0]) {
_splitpath(pIDD->OriginalDbgFileName, NULL, NULL, szName, NULL);
strcpy(pIDD->OriginalImageFileName, szName);
strcat(pIDD->OriginalImageFileName, pIDD->Characteristics & IMAGE_FILE_DLL ? ".dll" : ".exe");
} else if (pIDD->ImageName) {
_splitpath(pIDD->ImageName, NULL, NULL, szName, szExt);
strcpy(pIDD->OriginalImageFileName, szName);
if (*szExt) {
strcat(pIDD->OriginalImageFileName, szExt);
}
} else if (pIDD->PdbFileName[0]) {
_splitpath(pIDD->PdbFileName, NULL, NULL, szName, NULL);
strcpy(pIDD->OriginalImageFileName, szName);
strcat(pIDD->OriginalImageFileName, pIDD->Characteristics & IMAGE_FILE_DLL ? ".dll" : ".exe");
} else {
sprintf(pIDD->OriginalImageFileName, "MOD%p", pIDD->InProcImageBase);
}
return TRUE;
}
BOOL
FindExecutableImageExCallback(
HANDLE FileHandle,
PSTR FileName,
PVOID CallerData
)
{
PIMGHLP_DEBUG_DATA pIDD;
PIMAGE_FILE_HEADER FileHeader = NULL;
PVOID ImageMap = NULL;
BOOL rc;
if (!CallerData)
return TRUE;
pIDD = (PIMGHLP_DEBUG_DATA)CallerData;
if (!pIDD->TimeDateStamp)
return TRUE;
// Crack the image and let's see what we're working with
ImageMap = MapItRO(FileHandle);
if (!ImageMap)
return TRUE;
// Check the first word. We're either looking at a normal PE32/PE64 image, or it's
// a ROM image (no DOS stub) or it's a random file.
switch (*(PUSHORT)ImageMap) {
case IMAGE_FILE_MACHINE_I386:
// Must be an X86 ROM image (ie: ntldr)
FileHeader = &((PIMAGE_ROM_HEADERS)ImageMap)->FileHeader;
// Make sure
if (!(FileHeader->SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32) &&
pIDD->iohMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC))
{
FileHeader = NULL;
}
break;
case IMAGE_FILE_MACHINE_ALPHA:
case IMAGE_FILE_MACHINE_ALPHA64:
case IMAGE_FILE_MACHINE_IA64:
case IMAGE_FILE_MACHINE_AMD64:
// Should be an Alpha/IA64 ROM image (ie: osloader.exe)
FileHeader = &((PIMAGE_ROM_HEADERS)ImageMap)->FileHeader;
// Make sure
if (!(FileHeader->SizeOfOptionalHeader == sizeof(IMAGE_ROM_OPTIONAL_HEADER) &&
pIDD->iohMagic == IMAGE_ROM_OPTIONAL_HDR_MAGIC))
{
FileHeader = NULL;
}
break;
case IMAGE_DOS_SIGNATURE:
{
PIMAGE_NT_HEADERS NtHeaders = ImageNtHeader(ImageMap);
if (NtHeaders) {
FileHeader = &NtHeaders->FileHeader;
}
}
break;
default:
break;
}
// default return is a match
rc = TRUE;
// compare timestamps
if (FileHeader && FileHeader->TimeDateStamp != pIDD->TimeDateStamp)
rc = FALSE;
pIDD->ImageSrc = srcSearchPath;
// cleanup
if (ImageMap)
UnmapViewOfFile(ImageMap);
return rc;
}
BOOL
SymbolInfoFound(
PIMGHLP_DEBUG_DATA pIDD
)
{
OMFSignature *omfSig;
if (pIDD->dia)
return TRUE;
// look for embedded codeview
if (pIDD->pMappedCv) {
omfSig = (OMFSignature*) pIDD->pMappedCv;
if (*(DWORD *)(omfSig->Signature) == '80BN')
return TRUE;
if (*(DWORD *)(omfSig->Signature) == '90BN')
return TRUE;
if (*(DWORD *)(omfSig->Signature) == '11BN')
return TRUE;
}
// look for coff symbols
if (pIDD->pMappedCoff)
return TRUE;
// must be no debug info
return FALSE;
}
BOOL FileNameIsPdb(
PIMGHLP_DEBUG_DATA pIDD,
LPSTR FileName
)
{
CHAR drive[_MAX_DRIVE];
CHAR path[_MAX_DIR];
char ext[20];
_splitpath(FileName, drive, path, NULL, ext);
if (_strcmpi(ext, ".pdb"))
return FALSE;
strcpy(pIDD->PdbFileName, FileName);
_makepath(pIDD->PdbReferencePath, drive, path, NULL, NULL);
if (strlen(path) > 1) {
// Chop off trailing backslash.
pIDD->PdbReferencePath[strlen(pIDD->PdbReferencePath)-1] = '\0';
} else {
// No path. Put on at least a dot "."
strcpy(pIDD->PdbReferencePath, ".");
}
return TRUE;
}
PIMGHLP_DEBUG_DATA
GetDebugData(
HANDLE hProcess,
HANDLE FileHandle,
LPSTR FileName,
LPSTR SymbolPath,
ULONG64 ImageBase,
PMODLOAD_DATA mld,
ULONG dwFlags
)
/*
Given:
ImageFileHandle - Map the thing. The only time FileHandle s/b non-null
is if we're given an image handle. If this is not
true, ignore the handle.
!ImageFileHandle - Use the filename and search for first the image name,
then the .dbg file, and finally a .pdb file.
dwFlags: NO_PE64_IMAGES - Return failure if only image is PE64.
Used to implement MapDebugInformation()
*/
{
PIMGHLP_DEBUG_DATA pIDD;
// if (traceSubName(FileName)) // for setting debug breakpoints from DBGHELP_TOKEN
// dprint("debug(%s)\n", FileName);
// No File handle and no file name. Bail
if (!FileHandle && (!FileName || !*FileName)) {
return NULL;
}
SetLastError(NO_ERROR);
pIDD = InitDebugData();
if (!pIDD)
return NULL;
pIDD->flags = dwFlags;
__try {
// store off parameters
pIDD->InProcImageBase = ImageBase;
pIDD->hProcess = hProcess;
pIDD->mld = mld;
if (FileName && !FileNameIsPdb(pIDD, FileName))
lstrcpy(pIDD->ImageName, FileName);
if (SymbolPath) {
pIDD->SymbolPath = (PCHAR)MemAlloc(strlen(SymbolPath) + 1);
if (pIDD->SymbolPath) {
strcpy(pIDD->SymbolPath, SymbolPath);
}
}
// if we have a base pointer into process memory. See what we can get here.
if (pIDD->InProcImageBase) {
pIDD->fInProcHeader = ProcessInProcDebugInfo(pIDD);
if (pIDD->fInProcHeader)
pIDD->ImageSrc = srcMemory;
}
// find disk-based image
if (FileHandle) {
// if passed a handle, save it
if (!DuplicateHandle(
GetCurrentProcess(),
FileHandle,
GetCurrentProcess(),
&pIDD->ImageFileHandle,
GENERIC_READ,
FALSE,
DUPLICATE_SAME_ACCESS
))
{
return NULL;
}
pIDD->ImageSrc = srcHandle;
if (FileName) {
strcpy(pIDD->ImageFilePath, FileName);
}
} else if (!pIDD->fInProcHeader)
{
// otherwise use the file name to open the disk image
// only if we didn't have access to in-proc headers
pIDD->ImageFileHandle = FindExecutableImageEx(pIDD->ImageName,
SymbolPath,
pIDD->ImageFilePath,
FindExecutableImageExCallback,
pIDD);
}
// if we have a file handle. See what we can get here.
if (pIDD->ImageFileHandle) {
if (!pIDD->DbgFileHandle && !*pIDD->PdbFileName) {
ProcessImageDebugInfo(pIDD);
}
}
// get info from the caller's data struct
ProcessCallerDataDebugInfo(pIDD);
// search for pdb, if indicated or if we have found no image info, so far
pIDD->DbgFileHandle = 0;
if (!pIDD->Characteristics || (pIDD->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
if (*pIDD->OriginalDbgFileName) {
pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
pIDD->OriginalDbgFileName,
pIDD->SymbolPath,
pIDD->DbgFilePath,
FindDebugInfoFileExCallback,
pIDD,
fdifRECURSIVE);
}
if (!pIDD->DbgFileHandle) {
pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
pIDD->ImageName,
pIDD->SymbolPath,
pIDD->DbgFilePath,
FindDebugInfoFileExCallback,
pIDD,
fdifRECURSIVE);
}
if (!pIDD->DbgFileHandle)
g.LastSymLoadError = SYMLOAD_DBGNOTFOUND;
}
// if we have a .dbg file. See what we can get from it.
if (pIDD->DbgFileHandle) {
ProcessDbgDebugInfo(pIDD);
}
// make sure we can process omaps
if (!pIDD->ImageAlign)
pIDD->fNeedImage = TRUE;
// check one more time to see if information we have acquired
// indicates we need the image from disk.
if (FileName && *FileName && pIDD->fNeedImage) {
pIDD->ImageFileHandle = FindExecutableImageEx(FileName,
SymbolPath,
pIDD->ImageFilePath,
FindExecutableImageExCallback,
pIDD);
if (pIDD->ImageFileHandle) {
ProcessImageDebugInfo(pIDD);
}
}
// if there's a pdb. Pull what we can from there.
if (*pIDD->PdbFileName) {
diaOpenPdb(pIDD);
// otherwise, if old codeview, pull from there
} else if (pIDD->pMappedCv) {
ProcessOldStyleCodeView(pIDD);
// otherwise if we couldn't read from the image info, look for PDB anyway
} else if (!pIDD->ImageFileHandle && !pIDD->DbgFileHandle) {
if (FakePdbName(pIDD)) {
diaOpenPdb(pIDD);
}
}
// if all else fails, one more try for a dbg
if (!(pIDD->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
&& !pIDD->DbgFileHandle
&& !SymbolInfoFound(pIDD)
)
{
pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
(*pIDD->OriginalDbgFileName) ? pIDD->OriginalDbgFileName : pIDD->ImageName,
pIDD->SymbolPath,
pIDD->DbgFilePath,
FindDebugInfoFileExCallback,
pIDD,
fdifRECURSIVE);
// if we have a .dbg file. See what we can get from it.
if (pIDD->DbgFileHandle) {
ProcessDbgDebugInfo(pIDD);
}
}
if (!pIDD->OriginalImageFileName[0]) {
FigureOutImageName(pIDD);
}
GetUnfoundData(pIDD);
// mdDump(pIDD->md, FALSE);
} __except (EXCEPTION_EXECUTE_HANDLER) {
if (pIDD) {
ReleaseDebugData(pIDD, IMGHLP_FREE_ALL);
pIDD = NULL;
}
}
return pIDD;
}
PIMGHLP_DEBUG_DATA
InitDebugData(
VOID
)
{
PIMGHLP_DEBUG_DATA pIDD;
pIDD = (PIMGHLP_DEBUG_DATA)MemAlloc(sizeof(IMGHLP_DEBUG_DATA));
if (!pIDD) {
SetLastError(ERROR_OUTOFMEMORY);
g.LastSymLoadError = SYMLOAD_OUTOFMEMORY;
return NULL;
}
ZeroMemory(pIDD, sizeof(IMGHLP_DEBUG_DATA));
pIDD->md = (PMODULE_DATA)MemAlloc(sizeof(gmd));
if (!pIDD->md) {
SetLastError(ERROR_OUTOFMEMORY);
g.LastSymLoadError = SYMLOAD_OUTOFMEMORY;
MemFree(pIDD);
return NULL;
}
memcpy(pIDD->md, gmd, sizeof(gmd));
return pIDD;
}
void
ReleaseDebugData(
PIMGHLP_DEBUG_DATA pIDD,
DWORD dwFlags
)
{
if (!pIDD)
return;
if (pIDD->ImageMap) {
UnmapViewOfFile(pIDD->ImageMap);
}
if (pIDD->ImageFileHandle) {
CloseHandle(pIDD->ImageFileHandle);
}
if (pIDD->DbgFileMap) {
UnmapViewOfFile(pIDD->DbgFileMap);
}
if (pIDD->DbgFileHandle) {
CloseHandle(pIDD->DbgFileHandle);
}
if ((dwFlags & IMGHLP_FREE_FPO) &&
pIDD->pFpo &&
!pIDD->fFpoMapped
)
{
MemFree(pIDD->pFpo);
}
if ((dwFlags & IMGHLP_FREE_PDATA) &&
pIDD->pPData &&
!pIDD->fPDataMapped
)
{
MemFree(pIDD->pPData);
}
if ((dwFlags & IMGHLP_FREE_XDATA) &&
pIDD->pXData &&
!pIDD->fXDataMapped
)
{
MemFree(pIDD->pXData);
}
if ((dwFlags & IMGHLP_FREE_PDATA) &&
pIDD->pMappedCoff &&
!pIDD->fCoffMapped
)
{
MemFree(pIDD->pMappedCoff);
}
if ((dwFlags & IMGHLP_FREE_PDATA) &&
pIDD->pMappedCv &&
!pIDD->fCvMapped
)
{
MemFree(pIDD->pMappedCv);
}
if ((dwFlags & IMGHLP_FREE_OMAPT) &&
pIDD->pOmapTo &&
!pIDD->fOmapToMapped
)
{
MemFree(pIDD->pOmapTo);
}
if ((dwFlags & IMGHLP_FREE_OMAPF) &&
pIDD->pOmapFrom &&
!pIDD->fOmapFromMapped
)
{
MemFree(pIDD->pOmapFrom);
}
if ((dwFlags & IMGHLP_FREE_OSECT) &&
pIDD->pOriginalSections
)
{
MemFree(pIDD->pOriginalSections);
}
if ((dwFlags & IMGHLP_FREE_CSECT) &&
pIDD->pCurrentSections &&
!pIDD->fCurrentSectionsMapped
)
{
MemFree(pIDD->pCurrentSections);
}
if (pIDD->SymbolPath) {
MemFree(pIDD->SymbolPath);
}
MemFree(pIDD->md);
MemFree(pIDD);
return;
}
#ifdef MAP_DEBUG_TEST
#if 0
void
__cdecl
main(
int argc,
char *argv[]
)
{
CHAR szSymPath[4096];
PIMGHLP_DEBUG_DATA pDebugInfo;
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test1");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test1\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test2");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test2\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test3");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test3\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test4");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test4\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test5");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test5\\ntdll.dll", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test6");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test6\\ntdll.dll", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test7");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test7\\osloader.exe", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test8");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test8\\osloader.exe", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test9");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test9\\msvcrt.dll", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test10");
pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test10\\msvcrt.dll", szSymPath, 0x1000000, NULL, 0);
ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
}
#endif
#endif