mirror of https://github.com/lianthony/NT4.0
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.
1032 lines
24 KiB
1032 lines
24 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1992 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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "cv.h"
|
|
#include "symcvt.h"
|
|
|
|
typedef struct tagSYMHASH {
|
|
DWORD dwHashVal; // hash value for the symbol
|
|
DWORD dwHashBucket; // hash bucket number
|
|
DATASYM32 *dataSym; // pointer to the symbol info
|
|
} SYMHASH;
|
|
|
|
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 VOID GetSymName( PIMAGE_SYMBOL Symbol, PUCHAR StringTable, char *s );
|
|
static USHORT GetSegIndex( PPOINTERS p, DWORD n );
|
|
static VOID UpdatePtrs( PPOINTERS p, PPTRINFO pi, LPVOID lpv, DWORD count );
|
|
static DWORD CreateDirectorys( PPOINTERS p );
|
|
static DWORD CreateModuleDirectoryEntrys( PPOINTERS p );
|
|
static DWORD CreatePublicDirectoryEntrys( PPOINTERS p );
|
|
static DWORD CreateSegMapDirectoryEntrys( PPOINTERS p );
|
|
static DWORD CreateSignature( PPOINTERS p );
|
|
static DWORD CreateModules( PPOINTERS p );
|
|
static DWORD CreatePublics( PPOINTERS p );
|
|
static DWORD CreateSegMap( PPOINTERS p );
|
|
static DWORD CreateSymbolHashTable( PPOINTERS p );
|
|
static DWORD CreateAddressSortTable( PPOINTERS p );
|
|
static DWORD HashASymbol( char *szSym );
|
|
|
|
static int __cdecl SymbolCompare( const void *arg1, const void *arg2 );
|
|
static int __cdecl SymHashCompare( const void *arg1, const void *arg2 );
|
|
static int __cdecl OffsetSortCompare( const void *arg1, const void *arg2 );
|
|
|
|
|
|
|
|
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 (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE - conversion succeded
|
|
FALSE - conversion failed
|
|
|
|
--*/
|
|
|
|
{
|
|
p->pCvCurr = p->pCvStart.ptr = malloc( p->iptrs.fsize );
|
|
if (p->pCvStart.ptr == NULL) {
|
|
return FALSE;
|
|
}
|
|
memset( p->pCvStart.ptr, 0, p->iptrs.fsize );
|
|
|
|
CreateSignature( p );
|
|
CreateModules( p );
|
|
CreatePublics( p );
|
|
CreateSymbolHashTable( p );
|
|
CreateAddressSortTable( p );
|
|
CreateSegMap( p );
|
|
CreateDirectorys( p );
|
|
|
|
p->pCvStart.ptr = realloc( p->pCvStart.ptr, p->pCvStart.size );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateSignature( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the CODEVIEW signature record. Currently this converter only
|
|
generates NB08 data (MS C/C++ 7.0).
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
number of records generates, this is always 1.
|
|
|
|
--*/
|
|
|
|
{
|
|
OMFSignature *omfSig;
|
|
|
|
omfSig = (OMFSignature *) p->pCvCurr;
|
|
strcpy( omfSig->Signature, "NB08" );
|
|
omfSig->filepos = 0;
|
|
p->pCvStart.size += sizeof(OMFSignature);
|
|
p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFSignature);
|
|
return 1;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateDirectorys( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the control function for the generation of the CV directories.
|
|
It calls individual functions for the generation of specific types of
|
|
debug directories.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
the number of directories created.
|
|
|
|
--*/
|
|
|
|
{
|
|
OMFDirHeader *omfDir = (OMFDirHeader *)p->pCvCurr;
|
|
OMFSignature *omfSig = (OMFSignature *)p->pCvStart.ptr;
|
|
OMFDirEntry *omfDirEntry = NULL;
|
|
|
|
omfSig->filepos = (DWORD)p->pCvCurr - (DWORD)p->pCvStart.ptr;
|
|
|
|
omfDir->cbDirHeader = sizeof(OMFDirHeader);
|
|
omfDir->cbDirEntry = sizeof(OMFDirEntry);
|
|
omfDir->cDir = 0;
|
|
omfDir->lfoNextDir = 0;
|
|
omfDir->flags = 0;
|
|
|
|
p->pCvStart.size += sizeof(OMFDirHeader);
|
|
p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirHeader);
|
|
|
|
omfDir->cDir += CreateModuleDirectoryEntrys( p );
|
|
omfDir->cDir += CreatePublicDirectoryEntrys( p );
|
|
omfDir->cDir += CreateSegMapDirectoryEntrys( p );
|
|
|
|
return omfDir->cDir;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateModuleDirectoryEntrys( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates directory entries for each module in the image.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
the number of directory entries created.
|
|
|
|
--*/
|
|
|
|
{
|
|
OMFDirEntry *omfDirEntry = NULL;
|
|
OMFModule *m = NULL;
|
|
OMFModule *mNext = NULL;
|
|
DWORD i = 0;
|
|
DWORD mSize = 0;
|
|
DWORD lfo = (DWORD)p->pCvModules.ptr - (DWORD)p->pCvStart.ptr;
|
|
|
|
|
|
m = (OMFModule *) p->pCvModules.ptr;
|
|
for (i=0; i<p->pCvModules.count; i++) {
|
|
mNext = NextMod( m );
|
|
|
|
omfDirEntry = (OMFDirEntry *) p->pCvCurr;
|
|
|
|
mSize = (DWORD)mNext - (DWORD)m;
|
|
omfDirEntry->SubSection = sstModule;
|
|
omfDirEntry->iMod = (USHORT) i + 1;
|
|
omfDirEntry->lfo = lfo;
|
|
omfDirEntry->cb = mSize;
|
|
|
|
lfo += mSize;
|
|
|
|
p->pCvStart.size += sizeof(OMFDirEntry);
|
|
p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
|
|
|
|
m = mNext;
|
|
}
|
|
|
|
return p->pCvModules.count;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreatePublicDirectoryEntrys( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the directory entry for the global publics.
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
the number of directory entries created, always 1.
|
|
|
|
--*/
|
|
|
|
{
|
|
OMFDirEntry *omfDirEntry = (OMFDirEntry *) p->pCvCurr;
|
|
|
|
omfDirEntry->SubSection = sstGlobalPub;
|
|
omfDirEntry->iMod = 0xffff;
|
|
omfDirEntry->lfo = (DWORD)p->pCvPublics.ptr - (DWORD)p->pCvStart.ptr;
|
|
omfDirEntry->cb = p->pCvPublics.size;
|
|
|
|
p->pCvStart.size += sizeof(OMFDirEntry);
|
|
p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateSegMapDirectoryEntrys( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates the directory entry for the segment map.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
the number of directory entries created, always 1.
|
|
|
|
--*/
|
|
|
|
{
|
|
OMFDirEntry *omfDirEntry = (OMFDirEntry *) p->pCvCurr;
|
|
|
|
omfDirEntry->SubSection = sstSegMap;
|
|
omfDirEntry->iMod = 0xffff;
|
|
omfDirEntry->lfo = (DWORD)p->pCvSegMap.ptr - (DWORD)p->pCvStart.ptr;
|
|
omfDirEntry->cb = p->pCvSegMap.size;
|
|
|
|
p->pCvStart.size += sizeof(OMFDirEntry);
|
|
p->pCvCurr = (PUCHAR) p->pCvCurr + sizeof(OMFDirEntry);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateModules( 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 (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of modules that were created.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN fModule;
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD numaux;
|
|
DWORD nummods = 0;
|
|
char szSymName[256];
|
|
PIMAGE_SYMBOL NextSymbol;
|
|
PIMAGE_SYMBOL Symbol;
|
|
PIMAGE_AUX_SYMBOL AuxSymbol;
|
|
OMFModule *m;
|
|
OMFModule *mNext;
|
|
|
|
m = (OMFModule *) p->pCvCurr;
|
|
|
|
NextSymbol = p->iptrs.AllSymbols;
|
|
for (i= 0; i < p->iptrs.fileHdr->NumberOfSymbols; i++) {
|
|
Symbol = NextSymbol++;
|
|
GetSymName( Symbol, p->iptrs.stringTable, szSymName );
|
|
if (Symbol->StorageClass == IMAGE_SYM_CLASS_FILE ) {
|
|
m->ovlNumber = 0;
|
|
m->iLib = 0;
|
|
m->cSeg = 1;
|
|
m->Style[0] = 'C';
|
|
m->Style[1] = 'V';
|
|
m->SegInfo[0].Seg = 0;
|
|
m->SegInfo[0].pad = 0;
|
|
m->SegInfo[0].Off = 0;
|
|
m->SegInfo[0].cbSeg = 0;
|
|
fModule = TRUE;
|
|
}
|
|
else
|
|
if (fModule && Symbol->StorageClass == IMAGE_SYM_CLASS_STATIC &&
|
|
strcmp(szSymName,".text") == 0 ) {
|
|
m->SegInfo[0].cbSeg = Symbol->Value;
|
|
m->SegInfo[0].Off = Symbol->Value -
|
|
p->iptrs.sectionHdrs[Symbol->SectionNumber-1].VirtualAddress;
|
|
m->SegInfo[0].Seg = Symbol->SectionNumber;
|
|
m = NextMod( m );
|
|
nummods++;
|
|
fModule = FALSE;
|
|
}
|
|
if (numaux = Symbol->NumberOfAuxSymbols) {
|
|
for (j=numaux; j; --j) {
|
|
AuxSymbol = (PIMAGE_AUX_SYMBOL) NextSymbol;
|
|
NextSymbol++;
|
|
++i;
|
|
if (fModule && j==numaux) {
|
|
m->Name[0] = strlen( AuxSymbol->File.Name );
|
|
strcpy( &m->Name[1], AuxSymbol->File.Name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// walk the list of modules and fixup the cbSeg values.
|
|
m = (OMFModule *) p->pCvCurr;
|
|
for (i=0; i<nummods; i++) {
|
|
mNext = NextMod( m );
|
|
m->SegInfo[0].cbSeg = mNext->SegInfo[0].cbSeg - m->SegInfo[0].cbSeg;
|
|
if (m->SegInfo[0].cbSeg == 0) {
|
|
m->SegInfo[0].cbSeg =
|
|
m->SegInfo[0].Off =
|
|
m->SegInfo[0].Seg = 0;
|
|
}
|
|
m = mNext;
|
|
}
|
|
|
|
UpdatePtrs( p, &p->pCvModules, (LPVOID)m, nummods );
|
|
|
|
return nummods;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreatePublics( 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 (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of publics created.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD numaux;
|
|
DWORD numsyms = 0;
|
|
char szSymName[256];
|
|
PIMAGE_SYMBOL NextSymbol;
|
|
PIMAGE_SYMBOL Symbol;
|
|
PIMAGE_AUX_SYMBOL AuxSymbol;
|
|
OMFSymHash *omfSymHash;
|
|
DATASYM32 *dataSym;
|
|
DATASYM32 *dataSym2;
|
|
PIMAGE_SYMBOL *sortArray, *sortArrayStart;
|
|
|
|
|
|
|
|
omfSymHash = (OMFSymHash *) p->pCvCurr;
|
|
dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
|
|
|
|
sortArrayStart =
|
|
sortArray = (PIMAGE_SYMBOL *) malloc( p->iptrs.fileHdr->NumberOfSymbols * sizeof(PIMAGE_SYMBOL) );
|
|
if (sortArray == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
NextSymbol = p->iptrs.AllSymbols;
|
|
for (i= 0; i < p->iptrs.fileHdr->NumberOfSymbols; i++) {
|
|
Symbol = NextSymbol++;
|
|
GetSymName( Symbol, p->iptrs.stringTable, szSymName );
|
|
if (Symbol->StorageClass == IMAGE_SYM_CLASS_EXTERNAL && Symbol->SectionNumber > 0) {
|
|
*sortArray = Symbol;
|
|
sortArray++;
|
|
numsyms++;
|
|
}
|
|
if (numaux = Symbol->NumberOfAuxSymbols) {
|
|
for (j=numaux; j; --j) {
|
|
AuxSymbol = (PIMAGE_AUX_SYMBOL) NextSymbol;
|
|
NextSymbol++;
|
|
++i;
|
|
}
|
|
}
|
|
}
|
|
|
|
qsort( (void*)sortArrayStart, numsyms, sizeof(PIMAGE_SYMBOL), SymbolCompare );
|
|
|
|
for (i=0,sortArray=sortArrayStart; i < numsyms; i++) {
|
|
Symbol = *sortArray++;
|
|
GetSymName( Symbol, p->iptrs.stringTable, szSymName );
|
|
dataSym->rectyp = S_PUB32;
|
|
dataSym->off = Symbol->Value -
|
|
p->iptrs.sectionHdrs[Symbol->SectionNumber-1].VirtualAddress;
|
|
dataSym->seg = Symbol->SectionNumber;
|
|
dataSym->typind = 0;
|
|
dataSym->name[0] = strlen( szSymName );
|
|
strcpy( &dataSym->name[1], szSymName );
|
|
dataSym2 = NextSym( dataSym );
|
|
dataSym->reclen = (USHORT) ((DWORD)dataSym2 - (DWORD)dataSym) - 2;
|
|
dataSym = dataSym2;
|
|
}
|
|
|
|
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;
|
|
|
|
free ( sortArrayStart );
|
|
|
|
return numsyms;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateSymbolHashTable( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Creates the CV symbol hash table. This hash table is used
|
|
primarily by debuggers to access symbols in a quick manner.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of buckets is the hash table.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD numsyms;
|
|
DWORD numbuckets;
|
|
OMFSymHash *omfSymHash;
|
|
DATASYM32 *dataSymStart;
|
|
DATASYM32 *dataSym;
|
|
LPVOID pHashData;
|
|
USHORT *pCHash;
|
|
DWORD *pHashTable;
|
|
USHORT *pBucketCounts;
|
|
DWORD *pChainTable;
|
|
DWORD dwBucketCount;
|
|
SYMHASH *symHashStart;
|
|
SYMHASH *symHash;
|
|
|
|
|
|
numsyms = p->pCvPublics.count;
|
|
numbuckets = (numsyms + 9) / 10;
|
|
|
|
symHashStart =
|
|
symHash = (SYMHASH *) malloc( numsyms * sizeof(SYMHASH) );
|
|
|
|
if (symHashStart == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
memset( symHashStart, 0, numsyms * sizeof(SYMHASH) );
|
|
|
|
pHashData = (LPVOID) p->pCvCurr;
|
|
pCHash = (USHORT *) pHashData;
|
|
pHashTable = (DWORD *) ((DWORD)pHashData + sizeof(DWORD));
|
|
pBucketCounts = (USHORT *) ((DWORD)pHashTable + (sizeof(DWORD) * numbuckets));
|
|
pChainTable = (DWORD *) ((DWORD)pBucketCounts + ((sizeof(USHORT) * numbuckets)));
|
|
|
|
omfSymHash = (OMFSymHash *) p->pCvPublics.ptr;
|
|
dataSymStart =
|
|
dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
|
|
|
|
*pCHash = (USHORT)numbuckets;
|
|
|
|
/*
|
|
* cruise thru the symbols and calculate the hash values
|
|
* and the hash bucket numbers; save the info away for later use
|
|
*/
|
|
for (i=0; i<numsyms; i++) {
|
|
symHash->dwHashVal = HashASymbol( dataSym->name );
|
|
symHash->dwHashBucket = symHash->dwHashVal % numbuckets;
|
|
symHash->dataSym = dataSym;
|
|
symHash++;
|
|
dataSym = NextSym( dataSym );
|
|
}
|
|
|
|
qsort( (void*)symHashStart, numsyms, sizeof(SYMHASH), SymHashCompare );
|
|
|
|
j = (DWORD) (DWORD)pChainTable - (DWORD)pHashData;
|
|
for (i=0; i<numbuckets; i++,pHashTable++) {
|
|
*pHashTable = (DWORD) j + (i * 4);
|
|
}
|
|
|
|
for (i=0; i<numbuckets; i++,pBucketCounts++) {
|
|
dwBucketCount = 0;
|
|
for (j=0,symHash=symHashStart; j<numsyms; j++,symHash++) {
|
|
if (symHash->dwHashBucket == i) {
|
|
dwBucketCount++;
|
|
}
|
|
}
|
|
*pBucketCounts = (USHORT)dwBucketCount;
|
|
}
|
|
|
|
dataSymStart = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash);
|
|
for (i=0,symHash=symHashStart; i<numsyms; i++,symHash++,pChainTable++) {
|
|
*pChainTable = (DWORD) (DWORD)symHash->dataSym - (DWORD)dataSymStart;
|
|
}
|
|
|
|
UpdatePtrs( p, &p->pCvSymHash, (LPVOID)pChainTable, numsyms );
|
|
|
|
omfSymHash->symhash = 6;
|
|
omfSymHash->cbHSym = p->pCvSymHash.size;
|
|
|
|
free( symHashStart );
|
|
|
|
return numbuckets;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CreateAddressSortTable( PPOINTERS p )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Creates the CV address sort table. This hash table is used
|
|
primarily by debuggers to access symbols in a quick manner when
|
|
all you have is an address.
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of sections in the table.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
DWORD j;
|
|
DWORD numsyms = p->pCvPublics.count;
|
|
DWORD numsections;
|
|
OMFSymHash *omfSymHash;
|
|
DATASYM32 *dataSymStart;
|
|
DATASYM32 *dataSym;
|
|
LPVOID pAddressData;
|
|
USHORT *pCSeg;
|
|
DWORD *pSegTable;
|
|
USHORT *pOffsetCounts;
|
|
DWORD *pOffsetTable;
|
|
DWORD dwOffsetCount;
|
|
OFFSETSORT *pOffsetSortStart;
|
|
OFFSETSORT *pOffsetSort;
|
|
|
|
|
|
numsections = p->iptrs.fileHdr->NumberOfSections;
|
|
|
|
pOffsetSortStart =
|
|
pOffsetSort = (OFFSETSORT *) malloc( numsyms * sizeof(OFFSETSORT) );
|
|
|
|
if (pOffsetSort == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
memset( pOffsetSortStart, 0, numsyms * sizeof(OFFSETSORT) );
|
|
|
|
pAddressData = (LPVOID) p->pCvCurr;
|
|
pCSeg = (USHORT *) pAddressData;
|
|
pSegTable = (DWORD *) ((DWORD)pAddressData + sizeof(DWORD));
|
|
pOffsetCounts = (USHORT *) ((DWORD)pSegTable + (sizeof(DWORD) * numsections));
|
|
pOffsetTable = (DWORD *) ((DWORD)pOffsetCounts + ((sizeof(USHORT) * numsections)));
|
|
if (numsections&1) {
|
|
pOffsetTable = (DWORD *) ((DWORD)pOffsetTable + 2);
|
|
}
|
|
|
|
omfSymHash = (OMFSymHash *) p->pCvPublics.ptr;
|
|
dataSymStart =
|
|
dataSym = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash + sizeof(OMFSymHash));
|
|
|
|
*pCSeg = (USHORT)numsections;
|
|
|
|
for (i=0; i<numsyms; i++) {
|
|
pOffsetSort->dwOffset = dataSym->off;
|
|
pOffsetSort->dwSection = dataSym->seg - 1;
|
|
pOffsetSort->dataSym = dataSym;
|
|
pOffsetSort++;
|
|
dataSym = NextSym( dataSym );
|
|
}
|
|
|
|
qsort( (void*)pOffsetSortStart, numsyms, sizeof(OFFSETSORT), OffsetSortCompare );
|
|
|
|
j = (DWORD) (DWORD)pOffsetTable - (DWORD)pAddressData;
|
|
for (i=0; i<numsections; i++,pSegTable++) {
|
|
*pSegTable = (DWORD) j + (i * 4);
|
|
}
|
|
|
|
for (i=0; i<numsections; i++,pOffsetCounts++) {
|
|
dwOffsetCount = 0;
|
|
for (j=0,pOffsetSort=pOffsetSortStart; j<numsyms; j++,pOffsetSort++) {
|
|
if (pOffsetSort->dwSection == i) {
|
|
dwOffsetCount++;
|
|
}
|
|
}
|
|
*pOffsetCounts = (USHORT)dwOffsetCount;
|
|
}
|
|
|
|
dataSymStart = (DATASYM32 *) (PUCHAR)((DWORD)omfSymHash);
|
|
for (i=0,pOffsetSort=pOffsetSortStart; i<numsyms; i++,pOffsetSort++,pOffsetTable++) {
|
|
*pOffsetTable = (DWORD) (DWORD)pOffsetSort->dataSym - (DWORD)dataSymStart;
|
|
}
|
|
|
|
UpdatePtrs( p, &p->pCvAddrSort, (LPVOID)pOffsetTable, numsyms );
|
|
|
|
omfSymHash->addrhash = 5;
|
|
omfSymHash->cbHAddr = p->pCvAddrSort.size;
|
|
|
|
free( pOffsetSortStart );
|
|
|
|
return numsections;
|
|
}
|
|
|
|
DWORD
|
|
CreateSegMap( 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 (see cofftocv.h)
|
|
|
|
|
|
Return Value:
|
|
|
|
The number of segments in the map.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD i;
|
|
SGM *sgm;
|
|
SGI *sgi;
|
|
PIMAGE_SECTION_HEADER sh;
|
|
|
|
|
|
sgm = (SGM *) p->pCvCurr;
|
|
sgi = (SGI *) ((DWORD)p->pCvCurr + sizeof(SGM));
|
|
|
|
sgm->cSeg = p->iptrs.fileHdr->NumberOfSections;
|
|
sgm->cSegLog = p->iptrs.fileHdr->NumberOfSections;
|
|
|
|
sh = p->iptrs.sectionHdrs;
|
|
|
|
for (i=0; i<p->iptrs.fileHdr->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;
|
|
}
|
|
|
|
|
|
void
|
|
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 {
|
|
strcpy( s, &StringTable[Symbol->n_offset] );
|
|
}
|
|
}
|
|
|
|
VOID
|
|
UpdatePtrs( PPOINTERS p, PPTRINFO pi, LPVOID lpv, DWORD count )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called by ALL functions that put data into the
|
|
CV data area. After putting the data into the CV memory this function
|
|
must be called. It will adjust all of the necessary pointers so the
|
|
the next guy doesn't get hosed.
|
|
|
|
|
|
Arguments:
|
|
|
|
p - pointer to a POINTERS structure (see cofftocv.h)
|
|
pi - the CV pointer that is to be updated
|
|
lpv - current pointer into the CV data
|
|
count - the number of items that were placed into the CV data
|
|
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
--*/
|
|
|
|
{
|
|
pi->ptr = p->pCvCurr;
|
|
pi->size = (DWORD) ((DWORD)lpv - (DWORD)p->pCvCurr);
|
|
pi->count = count;
|
|
|
|
p->pCvStart.size += pi->size;
|
|
p->pCvCurr = (PUCHAR) lpv;
|
|
|
|
return;
|
|
}
|
|
|
|
DWORD
|
|
HashASymbol( char *szSym )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will take an ascii character string and generate
|
|
a hash for that string. The hash algorithm is the CV NB08 hash
|
|
algorithm.
|
|
|
|
|
|
Arguments:
|
|
|
|
szSym - a character pointer, the first char is the string length
|
|
|
|
|
|
Return Value:
|
|
|
|
The generated hash value.
|
|
|
|
--*/
|
|
|
|
{
|
|
char *pName = szSym+1;
|
|
int cb = *szSym;
|
|
char *pch;
|
|
DWORD hash = 0;
|
|
DWORD UNALIGNED *pul = (DWORD *) pName;
|
|
static rgMask[] = {0, 0xff, 0xffff, 0xffffff};
|
|
|
|
pch = pName + cb - 1;
|
|
while (isdigit(*pch)) {
|
|
pch--;
|
|
}
|
|
|
|
if (*pch == '@') {
|
|
cb = pch - pName;
|
|
}
|
|
|
|
for (; cb > 3; cb-=4, pul++) {
|
|
hash = _lrotl(hash, 4);
|
|
hash ^= (*pul & 0xdfdfdfdf);
|
|
}
|
|
|
|
if (cb > 0) {
|
|
hash = _lrotl(hash,4);
|
|
hash ^= ((*pul & rgMask[cb]) & 0xdfdfdfdf);
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
SymbolCompare( const void *arg1, const void *arg2 )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sort compare function for sorting COFF symbol records by
|
|
section number and offset.
|
|
|
|
|
|
Arguments:
|
|
|
|
arg1 - record #1
|
|
arg2 - record #2
|
|
|
|
|
|
Return Value:
|
|
|
|
-1 - record #1 is < record #2
|
|
0 - records are equal
|
|
1 - record #1 is > record #2
|
|
|
|
--*/
|
|
|
|
{
|
|
if ((*(PIMAGE_SYMBOL*)arg1)->Value < (*(PIMAGE_SYMBOL*)arg2)->Value) {
|
|
return -1;
|
|
}
|
|
if ((*(PIMAGE_SYMBOL*)arg1)->Value > (*(PIMAGE_SYMBOL*)arg2)->Value) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
SymHashCompare( const void *arg1, const void *arg2 )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sort compare function for sorting SYMHASH records by hashed
|
|
bucket number.
|
|
|
|
|
|
Arguments:
|
|
|
|
arg1 - record #1
|
|
arg2 - record #2
|
|
|
|
|
|
Return Value:
|
|
|
|
-1 - record #1 is < record #2
|
|
0 - records are equal
|
|
1 - record #1 is > record #2
|
|
|
|
--*/
|
|
|
|
{
|
|
if (((SYMHASH*)arg1)->dwHashBucket < ((SYMHASH*)arg2)->dwHashBucket) {
|
|
return -1;
|
|
}
|
|
if (((SYMHASH*)arg1)->dwHashBucket > ((SYMHASH*)arg2)->dwHashBucket) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
OffsetSortCompare( const void *arg1, const void *arg2 )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sort compare function for sorting OFFETSORT records by section number.
|
|
|
|
|
|
Arguments:
|
|
|
|
arg1 - record #1
|
|
arg2 - record #2
|
|
|
|
|
|
Return Value:
|
|
|
|
-1 - record #1 is < record #2
|
|
0 - records are equal
|
|
1 - record #1 is > record #2
|
|
|
|
--*/
|
|
|
|
{
|
|
if (((OFFSETSORT*)arg1)->dwSection < ((OFFSETSORT*)arg2)->dwSection) {
|
|
return -1;
|
|
}
|
|
if (((OFFSETSORT*)arg1)->dwSection > ((OFFSETSORT*)arg2)->dwSection) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|