993 lines
27 KiB
C
993 lines
27 KiB
C
/*++
|
|
|
|
|
|
Copyright 1996 - 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cv.c
|
|
|
|
Abstract:
|
|
|
|
This module handles the conversion activities requires for converting
|
|
COFF debug data to CODEVIEW debug data.
|
|
|
|
Author:
|
|
|
|
Wesley A. Witt (wesw) 19-April-1993
|
|
|
|
Environment:
|
|
|
|
Win32, User Mode
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <imagehlp.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "cv.h"
|
|
#define _SYMCVT_SOURCE_
|
|
#include "symcvt.h"
|
|
#include "cvcommon.h"
|
|
|
|
typedef struct tagOFFSETSORT {
|
|
DWORD dwOffset; // offset for the symbol
|
|
DWORD dwSection; // section number of the symbol
|
|
DATASYM32 *dataSym; // pointer to the symbol info
|
|
} OFFSETSORT;
|
|
|
|
|
|
#define n_name N.ShortName
|
|
#define n_zeroes N.Name.Short
|
|
#define n_nptr N.LongName[1]
|
|
#define n_offset N.Name.Long
|
|
|
|
static LPSTR GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s );
|
|
DWORD CreateModulesFromCoff( PPOINTERS p );
|
|
DWORD CreatePublicsFromCoff( PPOINTERS p );
|
|
DWORD CreateSegMapFromCoff( PPOINTERS p );
|
|
DWORD CreateSrcLinenumbers( PPOINTERS p );
|
|
|
|
|
|
|
|
LONG
|
|
GuardPageFilterFunction(
|
|
DWORD ec,
|
|
LPEXCEPTION_POINTERS lpep
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function catches all exceptions from the convertcofftocv function
|
|
and all that it calls. The purpose of this function is allocate memory
|
|
when it is necessary. This happens because the cofftocv conversion cannot
|
|
estimate the memory requirements before the conversion takes place. To
|
|
handle this properly space in the virtual address space is reserved, the
|
|
reservation amount is 10 times the image size. The first page is commited
|
|
and then the conversion is started. When an access violation occurs and the
|
|
page that is trying to be access has a protection of noaccess then the
|
|
page is committed. Any other exception is not handled.
|
|
|
|
Arguments:
|
|
|
|
ec - the ecxeption code (should be EXCEPTION_ACCESS_VIOLATION)
|
|
lpep - pointer to the exception record and context record
|
|
|
|
|
|
Return Value:
|
|
|
|
EXCEPTION_CONTINUE_EXECUTION - access violation handled
|
|
EXCEPTION_EXECUTE_HANDLER - unknown exception and is not handled
|
|
|
|
--*/
|
|
|
|
{
|
|
LPVOID vaddr;
|
|
SYSTEM_INFO si;
|
|
MEMORY_BASIC_INFORMATION mbi;
|
|
|
|
|
|
if (ec == EXCEPTION_ACCESS_VIOLATION) {
|
|
vaddr = (LPVOID)lpep->ExceptionRecord->ExceptionInformation[1];
|
|
VirtualQuery( vaddr, &mbi, sizeof(mbi) );
|
|
if (mbi.AllocationProtect == PAGE_NOACCESS) {
|
|
GetSystemInfo( &si );
|
|
VirtualAlloc( vaddr, si.dwPageSize, MEM_COMMIT, PAGE_READWRITE );
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
}
|
|
|
|
// return EXCEPTION_CONTINUE_SEARCH;
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ConvertCoffToCv( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the control function for the conversion of COFF to CODEVIEW
|
|
debug data. It calls individual functions for the conversion of
|
|
specific types of debug data.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE - conversion succeded
|
|
FALSE - conversion failed
|
|
|
|
--*/
|
|
|
|
{
|
|
SYSTEM_INFO si;
|
|
DWORD cbsize;
|
|
BOOL rval = TRUE;
|
|
|
|
|
|
GetSystemInfo( &si );
|
|
cbsize = max( p->iptrs.fsize * 10, si.dwPageSize * 10 );
|
|
|
|
//
|
|
// reserve all necessary pages
|
|
//
|
|
p->pCvCurr = p->pCvStart.ptr = VirtualAlloc( NULL, cbsize, MEM_RESERVE, PAGE_NOACCESS );
|
|
|
|
//
|
|
// commit the first pages
|
|
//
|
|
VirtualAlloc( p->pCvCurr, min( cbsize, 5 * si.dwPageSize), MEM_COMMIT, PAGE_READWRITE );
|
|
|
|
|
|
try {
|
|
|
|
CreateSignature( p );
|
|
CreateModulesFromCoff( p );
|
|
CreatePublicsFromCoff( p );
|
|
CreateSymbolHashTable( p );
|
|
CreateAddressSortTable( p );
|
|
CreateSegMapFromCoff( p );
|
|
// CreateSrcLinenumbers( p );
|
|
CreateDirectories( p );
|
|
|
|
} except ( GuardPageFilterFunction( GetExceptionCode(), GetExceptionInformation() )) {
|
|
|
|
VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
|
|
p->pCvStart.ptr = NULL;
|
|
rval = FALSE;
|
|
|
|
}
|
|
|
|
if (rval) {
|
|
p->pCvCurr = malloc( p->pCvStart.size );
|
|
CopyMemory( p->pCvCurr, p->pCvStart.ptr, p->pCvStart.size );
|
|
VirtualFree( p->pCvStart.ptr, cbsize, MEM_DECOMMIT );
|
|
p->pCvStart.ptr = p->pCvCurr;
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateModulesFromCoff( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the individual CV module records. There is one CV module
|
|
record for each .FILE record in the COFF debug data. This is true
|
|
even if the COFF size is zero.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of modules that were created.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i,j;
|
|
DWORD dwOff;
|
|
DWORD numaux;
|
|
DWORD nummods = 0;
|
|
char szSymName[256];
|
|
PIMAGE_SYMBOL Symbol;
|
|
PIMAGE_AUX_SYMBOL AuxSymbol;
|
|
OMFModule *m = NULL;
|
|
int cSeg = 0;
|
|
char * pb;
|
|
BOOLEAN rgfCode[500];
|
|
|
|
|
|
memset(rgfCode, 2, sizeof(rgfCode));
|
|
|
|
for (i=0,j=0, Symbol=p->iptrs.AllSymbols;
|
|
i<(int)p->iptrs.numberOfSymbols;
|
|
i+=numaux+1,Symbol+=numaux+1) {
|
|
|
|
numaux = Symbol->NumberOfAuxSymbols;
|
|
if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
|
|
j++;
|
|
}
|
|
|
|
}
|
|
|
|
p->pMi = (LPMODULEINFO) malloc( sizeof(MODULEINFO) * (j + 1) );
|
|
ZeroMemory( p->pMi, sizeof(MODULEINFO) * (j + 1) );
|
|
|
|
|
|
if (!j) {
|
|
//
|
|
// Handle the situation where there are not any .file records in the
|
|
// COFF symbol table. This can happen for ROM images. If this happens
|
|
// then we will fabricate a bogus module.
|
|
//
|
|
m = (OMFModule *) p->pCvCurr;
|
|
m->ovlNumber = 0;
|
|
m->iLib = 0;
|
|
m->Style[0] = 'C';
|
|
m->Style[1] = 'V';
|
|
|
|
for (i=0,j=0, dwOff=0; i<p->iptrs.numberOfSections; i++) {
|
|
if (p->iptrs.sectionHdrs[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) {
|
|
m->SegInfo[j].Seg = i + 1;
|
|
m->SegInfo[j].cbSeg = p->iptrs.sectionHdrs[i].SizeOfRawData;
|
|
m->SegInfo[j++].Off = dwOff;
|
|
}
|
|
dwOff += p->iptrs.sectionHdrs[i].SizeOfRawData;
|
|
}
|
|
|
|
m->cSeg = (unsigned short) j;
|
|
|
|
strcpy(szSymName,"foo.c");
|
|
pb = (char *) &m->SegInfo[j];
|
|
*pb = (char)strlen(szSymName);
|
|
memcpy(pb+1, szSymName, *pb);
|
|
|
|
p->pMi[0].name = _strdup(szSymName);
|
|
p->pMi[0].iMod = 1;
|
|
p->pMi[0].cb = 0;
|
|
p->pMi[0].SrcModule = 0;
|
|
|
|
m = NextMod(m);
|
|
p->modcnt = 1;
|
|
UpdatePtrs( p, &p->pCvModules, (LPVOID)m, 1 );
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
for (i=0, Symbol = p->iptrs.AllSymbols;
|
|
i < (int) p->iptrs.numberOfSymbols;
|
|
i += numaux + 1, Symbol += numaux + 1) {
|
|
|
|
//
|
|
// Get the number of aux symbol records for this symbol
|
|
//
|
|
numaux = Symbol->NumberOfAuxSymbols;
|
|
AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
|
|
|
|
if ((i == 0) && ((Symbol+numaux+1)->StorageClass != IMAGE_SYM_CLASS_FILE)) {
|
|
//
|
|
// we have a situation where the first '.file' record
|
|
// is missing. currently this only happens with the
|
|
// claxp compiler on alpha.
|
|
//
|
|
m = (OMFModule *) p->pCvCurr;
|
|
cSeg = 0;
|
|
m->ovlNumber = 0;
|
|
m->iLib = 0;
|
|
m->Style[0] = 'C';
|
|
m->Style[1] = 'V';
|
|
strcpy( szSymName, "fake.c" );
|
|
} else
|
|
|
|
//
|
|
// If this is a FILE record -- then we need to create a
|
|
// module item to correspond to this file record.
|
|
//
|
|
|
|
if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
|
|
if (m == NULL) {
|
|
m = (OMFModule *) p->pCvCurr;
|
|
} else {
|
|
//
|
|
// Clean up the last item, if we saw any
|
|
// section records then drop them in here
|
|
//
|
|
|
|
if (cSeg > 0) {
|
|
m->cSeg = (unsigned short) cSeg;
|
|
pb = (char *) &m->SegInfo[cSeg];
|
|
*pb = (char)strlen(szSymName);
|
|
memcpy(pb+1, szSymName, *pb);
|
|
|
|
p->pMi[nummods].name = _strdup(szSymName);
|
|
p->pMi[nummods].iMod = nummods + 1;
|
|
p->pMi[nummods].cb = 0;
|
|
p->pMi[nummods].SrcModule = 0;
|
|
|
|
m = NextMod(m);
|
|
nummods++;
|
|
}
|
|
}
|
|
|
|
cSeg = 0;
|
|
m->ovlNumber = 0;
|
|
m->iLib = 0;
|
|
m->Style[0] = 'C';
|
|
m->Style[1] = 'V';
|
|
|
|
/*
|
|
* Save off the file name to use when we have finished
|
|
* processing this module
|
|
*/
|
|
|
|
memcpy(szSymName, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
|
|
szSymName[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
|
|
|
|
}
|
|
/*
|
|
* We have found a "SECTION" record. Add the info to the
|
|
* module record
|
|
*/
|
|
else
|
|
if ((Symbol->SectionNumber & 0xffff) > 0xfff0) {
|
|
continue;
|
|
} else
|
|
if (Symbol->SectionNumber > sizeof(rgfCode)/sizeof(rgfCode[0])) {
|
|
return 0;
|
|
} else
|
|
if ((m != NULL) &&
|
|
(rgfCode[Symbol->SectionNumber] != 0) &&
|
|
(Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC) &&
|
|
((*Symbol->n_name == '.') ||
|
|
(Symbol->Type == IMAGE_SYM_TYPE_NULL)) &&
|
|
(Symbol->NumberOfAuxSymbols == 1) &&
|
|
(AuxSymbol->Section.Length != 0)) {
|
|
|
|
if (rgfCode[Symbol->SectionNumber] == 2) {
|
|
if ((p->iptrs.sectionHdrs[Symbol->SectionNumber - 1].
|
|
Characteristics & IMAGE_SCN_CNT_CODE) == 0) {
|
|
rgfCode[Symbol->SectionNumber] = 0;
|
|
continue;
|
|
}
|
|
rgfCode[Symbol->SectionNumber] = 1;
|
|
}
|
|
|
|
m->SegInfo[cSeg].Seg = Symbol->SectionNumber;
|
|
m->SegInfo[cSeg].cbSeg = AuxSymbol->Section.Length;
|
|
m->SegInfo[cSeg].Off = Symbol->Value -
|
|
p->iptrs.sectionHdrs[Symbol->SectionNumber-1].
|
|
VirtualAddress;
|
|
cSeg += 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Wrap up the last possible open module record
|
|
*/
|
|
|
|
if (m != NULL) {
|
|
if (cSeg > 0) {
|
|
m->cSeg = (unsigned short) cSeg;
|
|
pb = (char *) &m->SegInfo[cSeg];
|
|
*pb = (char)strlen(szSymName);
|
|
memcpy(pb+1, szSymName, *pb);
|
|
|
|
p->pMi[nummods].name = _strdup(szSymName);
|
|
p->pMi[nummods].iMod = nummods + 1;
|
|
p->pMi[nummods].cb = 0;
|
|
p->pMi[nummods].SrcModule = 0;
|
|
|
|
m = NextMod(m);
|
|
nummods++;
|
|
}
|
|
}
|
|
|
|
|
|
p->modcnt = nummods;
|
|
UpdatePtrs( p, &p->pCvModules, (LPVOID)m, nummods );
|
|
|
|
return nummods;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreatePublicsFromCoff( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the individual CV public symbol records. There is one CV
|
|
public record created for each COFF symbol that is marked as EXTERNAL
|
|
and has a section number greater than zero. The resulting CV publics
|
|
are sorted by section and offset.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of publics created.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
DWORD numaux;
|
|
DWORD numsyms = 0;
|
|
char szSymName[256];
|
|
PIMAGE_SYMBOL Symbol;
|
|
OMFSymHash *omfSymHash;
|
|
DATASYM32 *dataSym;
|
|
DATASYM32 *dataSym2;
|
|
|
|
omfSymHash = (OMFSymHash *) p->pCvCurr;
|
|
dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
|
|
|
|
for (i= 0, Symbol = p->iptrs.AllSymbols;
|
|
i < p->iptrs.numberOfSymbols;
|
|
i += numaux + 1, Symbol += numaux + 1) {
|
|
|
|
if ((Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) &&
|
|
(Symbol->SectionNumber > 0)) {
|
|
|
|
if (GetSymName( Symbol, p->iptrs.stringTable, szSymName )) {
|
|
dataSym->rectyp = S_PUB32;
|
|
dataSym->seg = Symbol->SectionNumber;
|
|
dataSym->off = Symbol->Value -
|
|
p->iptrs.sectionHdrs[Symbol->SectionNumber-1].VirtualAddress;
|
|
dataSym->typind = 0;
|
|
dataSym->name[0] = (char)strlen( szSymName );
|
|
strcpy( &dataSym->name[1], szSymName );
|
|
dataSym2 = NextSym32( dataSym );
|
|
dataSym->reclen = (USHORT) ((DWORD)dataSym2 - (DWORD)dataSym) - 2;
|
|
dataSym = dataSym2;
|
|
numsyms += 1;
|
|
}
|
|
}
|
|
numaux = Symbol->NumberOfAuxSymbols;
|
|
}
|
|
|
|
UpdatePtrs( p, &p->pCvPublics, (LPVOID)dataSym, numsyms );
|
|
|
|
omfSymHash->cbSymbol = p->pCvPublics.size - sizeof(OMFSymHash);
|
|
omfSymHash->symhash = 0;
|
|
omfSymHash->addrhash = 0;
|
|
omfSymHash->cbHSym = 0;
|
|
omfSymHash->cbHAddr = 0;
|
|
|
|
return numsyms;
|
|
} /* CreatePublisFromCoff() */
|
|
|
|
|
|
DWORD
|
|
CreateSrcLinenumbers(
|
|
PPOINTERS p
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the individual CV soure line number records.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of publics created.
|
|
|
|
--*/
|
|
|
|
{
|
|
typedef struct _SEGINFO {
|
|
DWORD start;
|
|
DWORD end;
|
|
DWORD cbLines;
|
|
DWORD ptrLines;
|
|
DWORD va;
|
|
DWORD num;
|
|
BOOL used;
|
|
} SEGINFO, *LPSEGINFO;
|
|
|
|
typedef struct _SRCINFO {
|
|
LPSEGINFO seg;
|
|
DWORD numSeg;
|
|
DWORD cbSeg;
|
|
CHAR name[MAX_PATH+1];
|
|
} SRCINFO, *LPSRCINFO;
|
|
|
|
typedef struct _SECTINFO {
|
|
DWORD va;
|
|
DWORD size;
|
|
DWORD ptrLines;
|
|
DWORD numLines;
|
|
} SECTINFO, *LPSECTINFO;
|
|
|
|
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD k;
|
|
DWORD l;
|
|
DWORD actual;
|
|
DWORD sidx;
|
|
DWORD NumSrcFiles;
|
|
DWORD SrcFileCnt;
|
|
DWORD numaux;
|
|
PIMAGE_SYMBOL Symbol;
|
|
PIMAGE_AUX_SYMBOL AuxSymbol;
|
|
BOOL first = TRUE;
|
|
OMFSourceModule *SrcModule;
|
|
OMFSourceFile *SrcFile;
|
|
OMFSourceLine *SrcLine;
|
|
LPBYTE lpb;
|
|
LPDWORD lpdw;
|
|
PUSHORT lps;
|
|
PUCHAR lpc;
|
|
PIMAGE_LINENUMBER pil, pilSave;
|
|
LPSRCINFO si;
|
|
LPSECTINFO sections;
|
|
|
|
|
|
//
|
|
// setup the section info structure
|
|
//
|
|
sections = (LPSECTINFO) malloc( sizeof(SECTINFO) * p->iptrs.numberOfSections );
|
|
for (i=0; i<(DWORD)p->iptrs.numberOfSections; i++) {
|
|
sections[i].va = p->iptrs.sectionHdrs[i].VirtualAddress;
|
|
sections[i].size = p->iptrs.sectionHdrs[i].SizeOfRawData;
|
|
sections[i].ptrLines = p->iptrs.sectionHdrs[i].PointerToLinenumbers;
|
|
sections[i].numLines = p->iptrs.sectionHdrs[i].NumberOfLinenumbers;
|
|
}
|
|
|
|
//
|
|
// count the number of source files that contibute linenumbers
|
|
//
|
|
SrcFileCnt = 100;
|
|
si = (LPSRCINFO) malloc( sizeof(SRCINFO) * SrcFileCnt );
|
|
ZeroMemory( si, sizeof(SRCINFO) * SrcFileCnt );
|
|
for (i=0, j=0, Symbol=p->iptrs.AllSymbols, NumSrcFiles=0;
|
|
i<(DWORD)p->iptrs.numberOfSymbols;
|
|
i+=(numaux+1), Symbol+=(numaux + 1)) {
|
|
|
|
numaux = Symbol->NumberOfAuxSymbols;
|
|
AuxSymbol = (PIMAGE_AUX_SYMBOL) (Symbol+1);
|
|
|
|
if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE) {
|
|
|
|
if (!first) {
|
|
si[NumSrcFiles].cbSeg = j;
|
|
NumSrcFiles++;
|
|
if (NumSrcFiles == SrcFileCnt) {
|
|
SrcFileCnt += 100;
|
|
si = (LPSRCINFO) realloc( si, sizeof(SRCINFO) * SrcFileCnt );
|
|
}
|
|
}
|
|
|
|
memcpy(si[NumSrcFiles].name, (char *)AuxSymbol, numaux*sizeof(IMAGE_AUX_SYMBOL));
|
|
si[NumSrcFiles].name[numaux*sizeof(IMAGE_AUX_SYMBOL)] = 0;
|
|
si[NumSrcFiles].numSeg = 100;
|
|
si[NumSrcFiles].seg = (LPSEGINFO) malloc( sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
|
|
ZeroMemory( si[NumSrcFiles].seg, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
|
|
first = FALSE;
|
|
j = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// we do not want to look for segment information until we
|
|
// have found a valid source file
|
|
//
|
|
if (first) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// check the symbol to see if it is a segment record
|
|
//
|
|
if (numaux && Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC &&
|
|
(*Symbol->n_name == '.' ||
|
|
((Symbol->Type & 0xf) == IMAGE_SYM_TYPE_NULL && AuxSymbol->Section.Length)) &&
|
|
AuxSymbol->Section.NumberOfLinenumbers > 0) {
|
|
|
|
//
|
|
// find the section that this symbol belongs to
|
|
//
|
|
for (k=0; k<(DWORD)p->iptrs.numberOfSections; k++) {
|
|
if (Symbol->Value >= sections[k].va &&
|
|
Symbol->Value < sections[k].va + sections[k].size) {
|
|
|
|
sidx = k;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (k != (DWORD)p->iptrs.numberOfSections &&
|
|
p->iptrs.sectionHdrs[k].NumberOfLinenumbers) {
|
|
|
|
pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + sections[sidx].ptrLines);
|
|
k = 0;
|
|
|
|
while( k < AuxSymbol->Section.NumberOfLinenumbers ) {
|
|
|
|
//
|
|
// count the linenumbers in this section or sub-section
|
|
//
|
|
for ( pilSave=pil,l=0;
|
|
k<AuxSymbol->Section.NumberOfLinenumbers;
|
|
k++,pilSave++,l++ ) {
|
|
|
|
if ((k != (DWORD)AuxSymbol->Section.NumberOfLinenumbers-1) &&
|
|
(pilSave->Linenumber > (pilSave+1)->Linenumber)) {
|
|
pilSave++;
|
|
l++;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// pil == beginning of the range
|
|
// pilSave == end of the range
|
|
//
|
|
|
|
si[NumSrcFiles].seg[j].start =
|
|
(pil->Type.VirtualAddress - sections[sidx].va);
|
|
|
|
if (sections[sidx].numLines == l) {
|
|
pilSave--;
|
|
si[NumSrcFiles].seg[j].end =
|
|
(pilSave->Type.VirtualAddress - sections[sidx].va) + 1;
|
|
// (Symbol->Value - sections[sidx].va) + 1;
|
|
} else {
|
|
si[NumSrcFiles].seg[j].end =
|
|
(pilSave->Type.VirtualAddress - sections[sidx].va) - 1;
|
|
// (Symbol->Value - sections[sidx].va) - 1;
|
|
}
|
|
|
|
si[NumSrcFiles].seg[j].ptrLines = sections[sidx].ptrLines;
|
|
si[NumSrcFiles].seg[j].cbLines = l;
|
|
si[NumSrcFiles].seg[j].va = sections[sidx].va;
|
|
si[NumSrcFiles].seg[j].num = sidx + 1;
|
|
si[NumSrcFiles].seg[j].used = FALSE;
|
|
|
|
sections[sidx].ptrLines += (l * sizeof(IMAGE_LINENUMBER));
|
|
sections[sidx].numLines -= l;
|
|
|
|
j++;
|
|
if (j == si[NumSrcFiles].numSeg) {
|
|
si[NumSrcFiles].numSeg += 100;
|
|
si[NumSrcFiles].seg = (LPSEGINFO) realloc( si[NumSrcFiles].seg, sizeof(SEGINFO) * si[NumSrcFiles].numSeg );
|
|
}
|
|
k++;
|
|
pil = pilSave;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lpb = (LPBYTE) p->pCvCurr;
|
|
|
|
//
|
|
// if there is nothing to do then bail out
|
|
//
|
|
if (!NumSrcFiles) {
|
|
UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, 0 );
|
|
return 0;
|
|
}
|
|
|
|
for (i=0,actual=0,l=0; i<NumSrcFiles; i++) {
|
|
|
|
if (si[i].cbSeg == 0) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// create the source module header
|
|
//
|
|
SrcModule = (OMFSourceModule*) lpb;
|
|
SrcModule->cFile = 1;
|
|
SrcModule->cSeg = (USHORT)si[i].cbSeg;
|
|
SrcModule->baseSrcFile[0] = 0;
|
|
|
|
//
|
|
// write the start/end pairs
|
|
//
|
|
lpdw = (LPDWORD) ((LPBYTE)SrcModule + sizeof(OMFSourceModule));
|
|
for (k=0; k<si[i].cbSeg; k++) {
|
|
*lpdw++ = si[i].seg[k].start;
|
|
*lpdw++ = si[i].seg[k].end;
|
|
}
|
|
|
|
//
|
|
// write the segment numbers
|
|
//
|
|
lps = (PUSHORT) lpdw;
|
|
for (k=0; k<si[i].cbSeg; k++) {
|
|
*lps++ = (USHORT)si[i].seg[k].num;
|
|
}
|
|
|
|
//
|
|
// align to a dword boundry
|
|
//
|
|
lps = (PUSHORT) ((LPBYTE)lps + align(lps));
|
|
|
|
//
|
|
// update the base pointer
|
|
//
|
|
SrcModule->baseSrcFile[0] = (DWORD) ((LPBYTE)lps - (LPBYTE)SrcModule);
|
|
|
|
//
|
|
// write the source file record
|
|
//
|
|
SrcFile = (OMFSourceFile*) lps;
|
|
SrcFile->cSeg = (USHORT)si[i].cbSeg;
|
|
SrcFile->reserved = 0;
|
|
|
|
for (k=0; k<si[i].cbSeg; k++) {
|
|
SrcFile->baseSrcLn[k] = 0;
|
|
}
|
|
|
|
//
|
|
// write the start/end pairs
|
|
//
|
|
lpdw = (LPDWORD) ((LPBYTE)SrcFile + 4 + (4 * si[i].cbSeg));
|
|
for (k=0; k<si[i].cbSeg; k++) {
|
|
*lpdw++ = si[i].seg[k].start;
|
|
*lpdw++ = si[i].seg[k].end;
|
|
}
|
|
|
|
//
|
|
// write the source file name
|
|
//
|
|
lpc = (PUCHAR) lpdw;
|
|
k = strlen(si[i].name);
|
|
*lpc++ = (UCHAR) k;
|
|
strcpy( lpc, si[i].name );
|
|
lpb = lpc + k;
|
|
|
|
//
|
|
// find the module info struct
|
|
//
|
|
for (; l<p->modcnt; l++) {
|
|
if (_stricmp(p->pMi[l].name,si[i].name)==0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
p->pMi[l].SrcModule = (DWORD) SrcModule;
|
|
|
|
//
|
|
// align to a dword boundry
|
|
//
|
|
lpb = (LPBYTE) (lpb + align(lpb));
|
|
|
|
//
|
|
// create the line number pairs
|
|
//
|
|
for (k=0; k<si[i].cbSeg; k++) {
|
|
|
|
//
|
|
// find the first line number that applies to this segment
|
|
//
|
|
pil = (PIMAGE_LINENUMBER) (p->iptrs.fptr + si[i].seg[k].ptrLines);
|
|
|
|
//
|
|
// update the base pointer
|
|
//
|
|
SrcFile->baseSrcLn[k] = (DWORD) (lpb - (LPBYTE)SrcModule);
|
|
|
|
//
|
|
// write the line numbers
|
|
//
|
|
SrcLine = (OMFSourceLine*) lpb;
|
|
SrcLine->Seg = (USHORT)si[i].seg[k].num;
|
|
SrcLine->cLnOff = (USHORT) si[i].seg[k].cbLines;
|
|
pilSave = pil;
|
|
lpdw = (LPDWORD) (lpb + 4);
|
|
for (j=0; j<SrcLine->cLnOff; j++) {
|
|
*lpdw++ = pil->Type.VirtualAddress - si[i].seg[k].va;
|
|
pil++;
|
|
}
|
|
lps = (PUSHORT) lpdw;
|
|
pil = pilSave;
|
|
for (j=0; j<SrcLine->cLnOff; j++) {
|
|
*lps++ = pil->Linenumber;
|
|
pil++;
|
|
}
|
|
|
|
//
|
|
// align to a dword boundry
|
|
//
|
|
lps = (PUSHORT) ((LPBYTE)lps + align(lps));
|
|
|
|
lpb = (LPBYTE) lps;
|
|
}
|
|
|
|
p->pMi[l].cb = (DWORD)lpb - (DWORD)SrcModule;
|
|
actual++;
|
|
|
|
}
|
|
|
|
UpdatePtrs( p, &p->pCvSrcModules, (LPVOID)lpb, actual );
|
|
|
|
//
|
|
// cleanup all allocated memory
|
|
//
|
|
|
|
free( sections );
|
|
|
|
for (i=0; i<SrcFileCnt; i++) {
|
|
if (si[i].seg) {
|
|
free( si[i].seg );
|
|
}
|
|
}
|
|
|
|
free( si );
|
|
|
|
return NumSrcFiles;
|
|
} /* CreateSrcLinenumbers() */
|
|
|
|
|
|
DWORD
|
|
CreateSegMapFromCoff( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the CV segment map. The segment map is used by debuggers
|
|
to aid in address lookups. One segment is created for each COFF
|
|
section in the image.
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of segments in the map.
|
|
|
|
--*/
|
|
|
|
{
|
|
int i;
|
|
SGM *sgm;
|
|
SGI *sgi;
|
|
PIMAGE_SECTION_HEADER sh;
|
|
|
|
|
|
sgm = (SGM *) p->pCvCurr;
|
|
sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
|
|
|
|
sgm->cSeg = (unsigned short) p->iptrs.numberOfSections;
|
|
sgm->cSegLog = (unsigned short) p->iptrs.numberOfSections;
|
|
|
|
sh = p->iptrs.sectionHdrs;
|
|
|
|
for (i=0; i<p->iptrs.numberOfSections; i++, sh++) {
|
|
sgi->sgf.fRead = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_READ) == IMAGE_SCN_MEM_READ;
|
|
sgi->sgf.fWrite = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_WRITE) == IMAGE_SCN_MEM_WRITE;
|
|
sgi->sgf.fExecute = (USHORT) (sh->Characteristics & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE;
|
|
sgi->sgf.f32Bit = 1;
|
|
sgi->sgf.fSel = 0;
|
|
sgi->sgf.fAbs = 0;
|
|
sgi->sgf.fGroup = 1;
|
|
sgi->iovl = 0;
|
|
sgi->igr = 0;
|
|
sgi->isgPhy = (USHORT) i + 1;
|
|
sgi->isegName = 0;
|
|
sgi->iclassName = 0;
|
|
sgi->doffseg = 0;
|
|
sgi->cbSeg = sh->SizeOfRawData;
|
|
sgi++;
|
|
}
|
|
|
|
UpdatePtrs( p, &p->pCvSegMap, (LPVOID)sgi, i );
|
|
|
|
return i;
|
|
}
|
|
|
|
|
|
LPSTR
|
|
GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Extracts the COFF symbol from the image symbol pointer and puts
|
|
the ascii text in the character pointer passed in.
|
|
|
|
|
|
Arguments:
|
|
|
|
Symbol - COFF Symbol Record
|
|
StringTable - COFF string table
|
|
s - buffer for the symbol string
|
|
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
|
|
if (Symbol->n_zeroes) {
|
|
for (i=0; i<8; i++) {
|
|
if ((Symbol->n_name[i]>0x1f) && (Symbol->n_name[i]<0x7f)) {
|
|
*s++ = Symbol->n_name[i];
|
|
}
|
|
}
|
|
*s = 0;
|
|
}
|
|
else {
|
|
if (StringTable[Symbol->n_offset] == '?') {
|
|
i = UnDecorateSymbolName( &StringTable[Symbol->n_offset],
|
|
s,
|
|
255,
|
|
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
|
|
);
|
|
if (!i) {
|
|
return NULL;
|
|
}
|
|
} else {
|
|
strcpy( s, &StringTable[Symbol->n_offset] );
|
|
}
|
|
}
|
|
|
|
return s;
|
|
}
|