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.
292 lines
8.7 KiB
292 lines
8.7 KiB
//////////////////////////////////////////////////////////////////////////////
|
|
// MLI: Mod linenumber information API implementation
|
|
//
|
|
// Contributed by Amit Mital of VCE, 8/3/93, subsequently C++ized and
|
|
// modified to use DBI buffers and heaps. (Actually, Jan apologizes for
|
|
// largely rewriting, but it seemed the best way to learn the code.)
|
|
|
|
#include "pdbimpl.h"
|
|
#include "dbiimpl.h"
|
|
|
|
inline int adjustLineNumber(LINE lineStart, DWORD line)
|
|
{
|
|
return (line == 0x7fff) ? lineStart : (lineStart + line);
|
|
}
|
|
|
|
BOOL MLI::AddLines(SZ_CONST szSrc, ISECT isect, OFF offCon, CB cbCon, OFF doff,
|
|
LINE lineStart, IMAGE_LINENUMBER *plnumCoff, CB cb)
|
|
|
|
// szSrc the source file name
|
|
// isect section index
|
|
// offMin starting offset
|
|
// offMax ending offset
|
|
// lineStart starting line number
|
|
// plnumCoff pointer to linenumber coff info ??
|
|
// cb byte count
|
|
|
|
{
|
|
assert(cb % sizeof(IMAGE_LINENUMBER) == 0);
|
|
int clnum = cb / sizeof(IMAGE_LINENUMBER);
|
|
|
|
pSrcFile pSrcFile = AddSrcFile(szSrc);
|
|
if (!pSrcFile)
|
|
return FALSE;
|
|
|
|
OFF offMac = offCon + cbCon;
|
|
// If this contribution does not start a function (linenumber != 0),
|
|
// offCon is passed in the first lnum entry.
|
|
if (plnumCoff[0].Linenumber)
|
|
offCon = plnumCoff[0].Type.VirtualAddress + doff;
|
|
|
|
pSectInfo pSectInfo = pSrcFile->AddSectInfo(isect, offCon, offMac, pool);
|
|
if (!pSectInfo)
|
|
return FALSE;
|
|
if (!pSectInfo->AddLineNumbers(adjustLineNumber(lineStart, plnumCoff[0].Linenumber), offCon, pool))
|
|
return FALSE;
|
|
for (IMAGE_LINENUMBER* pln = &plnumCoff[1]; pln < &plnumCoff[clnum]; pln++)
|
|
if (!pSectInfo->AddLineNumbers(adjustLineNumber(lineStart, pln->Linenumber), pln->Type.VirtualAddress + doff, pool))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Find a pointer to the source file linked list structure - add it if it isn't there
|
|
pSrcFile MLI::AddSrcFile(SZ_CONST szFile)
|
|
{
|
|
for (pSrcFile* ppFile = &pSrcFiles; *ppFile; ppFile = &(*ppFile)->pNext)
|
|
if (strcmp((*ppFile)->szFile, szFile) == 0)
|
|
return *ppFile;
|
|
|
|
SZ szName = szCopyPool(szFile, pool);
|
|
if (!szName || !(*ppFile = new (pool) SrcFile(szName)))
|
|
return 0;
|
|
|
|
cfiles++;
|
|
return *ppFile;
|
|
}
|
|
|
|
// Find the section structure within the source file structure - add it if it is not there
|
|
pSectInfo SrcFile::AddSectInfo(ISECT isect, OFF offMin, OFF offMax, POOL& pool)
|
|
{
|
|
for (pSectInfo* ppSI = &pSectInfos; *ppSI; ppSI = &(*ppSI)->pNext) {
|
|
if ((*ppSI)->isect == isect && (*ppSI)->offMax + 1 == offMin) { // see if the new start is close enough to the old end
|
|
(*ppSI)->offMax = offMax;
|
|
return *ppSI;
|
|
}
|
|
}
|
|
if (!(*ppSI = new (pool) SectInfo(isect, offMin, offMax)))
|
|
return 0;
|
|
|
|
csect++;
|
|
return *ppSI;
|
|
}
|
|
|
|
// Add linenumber information to the record
|
|
BOOL SectInfo::AddLineNumbers(int linenumber, int offset, POOL& pool)
|
|
{
|
|
if (!(*ppTail = new (pool) Lines(offset, linenumber)))
|
|
return FALSE;
|
|
ppTail = &(*ppTail)->pNext;
|
|
cPair++;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MLI::Emit(Buffer& buffer)
|
|
{
|
|
if (!CollectSections())
|
|
return FALSE;
|
|
|
|
// emit header information
|
|
if (!buffer.AppendFmt("ss", cfiles, csect))
|
|
return FALSE;
|
|
|
|
// emit base src file offsets
|
|
OFF off = cbAlign(2*sizeof(USHORT) + cfiles*sizeof(ULONG) + csect*(2*sizeof(ULONG) + sizeof(USHORT)));
|
|
OFF offFiles = off;
|
|
for (pSrcFile pFile = pSrcFiles; pFile; pFile = pFile->pNext) {
|
|
if (!buffer.AppendFmt("l", off))
|
|
return FALSE;
|
|
off += pFile->Size();
|
|
}
|
|
|
|
// emit section info
|
|
for (pSectInfo pSI = pSectInfos; pSI; pSI = pSI->pNext)
|
|
if (!buffer.AppendFmt("ll", pSI->offMin, pSI->offMax))
|
|
return FALSE;
|
|
for (pSI = pSectInfos; pSI; pSI = pSI->pNext)
|
|
if (!buffer.AppendFmt("s", pSI->isect))
|
|
return FALSE;
|
|
|
|
if (!buffer.AppendFmt("f", (int)dcbAlign(buffer.Size())))
|
|
return FALSE;
|
|
|
|
// emit each source file's info
|
|
off = offFiles;
|
|
for (pFile = pSrcFiles; pFile; pFile = pFile->pNext) {
|
|
if (!pFile->Emit(buffer, off))
|
|
return FALSE;
|
|
off += pFile->Size();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Given the module's per-file, per-section information, collect
|
|
// section information across files, into a flattened, per-module
|
|
// per-section information summary.
|
|
//
|
|
BOOL MLI::CollectSections()
|
|
{
|
|
pSectInfo* ppsiTail = &pSectInfos;
|
|
for (pSrcFile pFile = pSrcFiles; pFile; pFile = pFile->pNext) {
|
|
for (pSectInfo psiFile = pFile->pSectInfos; psiFile; psiFile = psiFile->pNext) {
|
|
// search the module's section infos for existing info on this section
|
|
for (pSectInfo psi = pSectInfos; psi; psi = psi->pNext)
|
|
if (psi->isect == psiFile->isect) {
|
|
// found: update extent of section
|
|
psi->offMin = __min(psi->offMin, psiFile->offMin);
|
|
psi->offMax = __max(psi->offMax, psiFile->offMax);
|
|
goto nextSIFile;
|
|
}
|
|
// not found: add new section info to module's section info
|
|
if (!(*ppsiTail = new (pool) SectInfo(psiFile->isect, psiFile->offMin, psiFile->offMax)))
|
|
return FALSE;
|
|
++csect;
|
|
ppsiTail = &(*ppsiTail)->pNext;
|
|
nextSIFile:;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// calculate the size of the data for the file pointed to; return it's size
|
|
OFF SrcFile::Size()
|
|
{
|
|
// check memoization
|
|
if (size)
|
|
return size;
|
|
|
|
// header size
|
|
size = 2*sizeof(USHORT); // csect, pad
|
|
size += cbName + 1 + dcbAlign(cbName + 1); // cbname
|
|
|
|
// file table size
|
|
size += csect * 3*sizeof(ULONG); // baseSrcLn, start, end
|
|
|
|
// line table size
|
|
for (pSectInfo pSI = pSectInfos; pSI; pSI = pSI->pNext) {
|
|
pSI->size = sizeof(ULONG);
|
|
pSI->size += pSI->cPair * (sizeof(ULONG) + sizeof(USHORT)); // offset, line number
|
|
if (pSI->cPair & 1)
|
|
pSI->size += sizeof(USHORT); // maintain alignment
|
|
size += pSI->size;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
BOOL SrcFile::Emit(Buffer& buffer, OFF off) const
|
|
{
|
|
if (!buffer.AppendFmt("ss", csect, (USHORT)0 /*pad*/))
|
|
return FALSE;
|
|
off += csect*3*sizeof(ULONG); // space for baseSrcLine offset and start/end
|
|
off += 2*sizeof(USHORT) + cbName + 1 + dcbAlign(cbName + 1);
|
|
|
|
for (pSectInfo pSI = pSectInfos; pSI; pSI = pSI->pNext) {
|
|
if (!buffer.AppendFmt("l", off))
|
|
return FALSE;
|
|
off += pSI->size;
|
|
}
|
|
|
|
for (pSI = pSectInfos; pSI; pSI = pSI->pNext)
|
|
if (!buffer.AppendFmt("ll", pSI->offMin, pSI->offMax))
|
|
return FALSE;
|
|
|
|
if (!buffer.AppendFmt("bzf", (BYTE)cbName, szFile, (int)dcbAlign(cbName + 1)))
|
|
return FALSE;
|
|
|
|
for (pSI = pSectInfos; pSI; pSI = pSI->pNext)
|
|
if (!pSI->Emit(buffer))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SectInfo::Emit(Buffer& buffer) const
|
|
{
|
|
if (!buffer.AppendFmt("ss", isect, cPair))
|
|
return FALSE;
|
|
|
|
for (pLines plines = pHead; plines; plines = plines->pNext)
|
|
if (!buffer.AppendFmt("l", plines->off))
|
|
return FALSE;
|
|
for (plines = pHead; plines; plines = plines->pNext)
|
|
if (!buffer.AppendFmt("s", plines->line))
|
|
return FALSE;
|
|
if (cPair & 1)
|
|
if (!buffer.AppendFmt("s", 0)) \
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MLI::EmitFileInfo(Mod1* pmod1)
|
|
{
|
|
if (!pmod1->initFileInfo(cfiles))
|
|
return FALSE;
|
|
int ifile = 0;
|
|
for (pSrcFile pFile = pSrcFiles; pFile; pFile = pFile->pNext)
|
|
if (!pmod1->addFileInfo(ifile++, pFile->szFile))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MLI::Dump(const Buffer& buffer) const
|
|
{
|
|
PB pb = buffer.Start();
|
|
struct FSB { short cFile; short cSeg; long baseSrcFile[]; };
|
|
FSB* pfsb = (FSB*)pb;
|
|
pb += sizeof(FSB) + sizeof(long)*pfsb->cFile;
|
|
struct SE { long start, end; };
|
|
SE* pse = (SE*)pb;
|
|
pb += sizeof(SE)*pfsb->cSeg;
|
|
short* seg = (short*)pb;
|
|
pb += sizeof(short)*pfsb->cSeg;
|
|
printf("HDR: cFile=%u cSeg=%u\n", pfsb->cFile, pfsb->cSeg);
|
|
for (int ifile = 0; ifile < pfsb->cFile; ifile++)
|
|
printf("baseSrcFile[%d]=%04lx\n", ifile, pfsb->baseSrcFile[ifile]);
|
|
for (int iseg = 0; iseg < pfsb->cSeg; iseg++)
|
|
printf("%d: start=%04lx end=%04lx seg=%02x\n",
|
|
iseg, pse[iseg].start, pse[iseg].end, seg[iseg]);
|
|
|
|
for (ifile = 0; ifile < pfsb->cFile; ifile++) {
|
|
PB pb = buffer.Start() + pfsb->baseSrcFile[ifile];
|
|
struct SPB { short cSeg; short pad; long baseSrcLn[]; };
|
|
SPB* pspb = (SPB*)pb;
|
|
pb += sizeof SPB + sizeof(long)*pspb->cSeg;
|
|
SE* pse = (SE*)pb;
|
|
pb += sizeof(SE)*pspb->cSeg;
|
|
unsigned char cbName = *pb++;
|
|
unsigned char* Name = pb;
|
|
printf(" file[%d]: cSeg=%u pad=%02x cbName=%u, Name=%s\n",
|
|
ifile, pspb->cSeg, pspb->pad, cbName, Name);
|
|
for (int iseg = 0; iseg < pspb->cSeg; iseg++)
|
|
printf(" %d: baseSrcLn=%04lx start=%04lx end=%04lx\n",
|
|
iseg, pspb->baseSrcLn[iseg], pse[iseg].start, pse[iseg].end);
|
|
for (iseg = 0; iseg < pspb->cSeg; iseg++) {
|
|
PB pb = buffer.Start() + pspb->baseSrcLn[iseg];
|
|
struct SPO { short Seg; short cPair; long offset[]; };
|
|
SPO* pspo = (SPO*)pb;
|
|
pb += sizeof(SPO) + sizeof(long)*pspo->cPair;
|
|
short* linenumber = (short*)pb;
|
|
printf(" seg[%d]: Seg=%02x cPair=%u\n", iseg, pspo->Seg, pspo->cPair);
|
|
printf(" ");
|
|
for (int ipair = 0; ipair < pspo->cPair; ipair++) {
|
|
printf(" %4u:%04lx", linenumber[ipair], pspo->offset[ipair]);
|
|
if (ipair < pspo->cPair - 1 && (ipair & 3) == 3)
|
|
printf("\n ");
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
fflush(stdout);
|
|
return TRUE;
|
|
}
|