Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1278 lines
37 KiB

/*** engine.c
*
* basic engine routine to be called for each module; also, rewrite routines
* to convert to CodeView 4 format.
*
*/
#include "compact.h"
LOCAL void RewriteSrcLnSeg (uchar *, OMFDirEntry *, PMOD);
LOCAL void CopySrcMod (uchar *, OMFDirEntry *, PMOD);
LOCAL void ReformatMod (ulong, PMOD);
LOCAL void CopyModule (OMFDirEntry *, PMOD);
LOCAL void ReadTypes (OMFDirEntry *, bool_t);
LOCAL void ReadPublics (ulong, OMFDirEntry *);
LOCAL void ReadSymbols (ulong, OMFDirEntry *);
LOCAL void ReadSrcLnSeg (ulong, OMFDirEntry *);
LOCAL void ReadSrcModule (ulong, OMFDirEntry *);
LOCAL void ReadPublicSym (ulong, OMFDirEntry *);
LOCAL int VerifySrcMod (PMOD);
LOCAL void FixSrcMod (PMOD);
LOCAL void FixEnds (OMFModule *, OMFSourceModule *);
void DebugBreak (void);
extern ushort recursive;
extern ushort AddNewSymbols;
extern uchar Signature[];
extern ulong PublicSymbols;
uchar ptr32;
uchar *SymbolSegment;
ushort SymbolSizeAdd;
ushort SymbolSizeSub;
ushort UDTAdd;
uchar **ExtraSymbolLink;
uchar *ExtraSymbols;
ulong InitialSymInfoSize = 0;
ulong InitialPubInfoSize = 0;
ulong FinalSymInfoSize = 0;
char *ModAddr;
ushort usCurFirstNonPrim; // The current first non primitive type index
ulong ulCVTypeSignature; // The signature from the modules type segment
ulong iSym;
ulong iPub;
ulong iPubSym;
ulong iSrcLn;
ulong iSrcMod;
ushort SeekCnt = 0;
CV_typ_t maxPreComp; // maximum type index allowed during precomp
bool_t PackingPreComp;
/** CompactOneModule - compact next module
*
* CompactOneModule (iMod)
*
* Entry iMod = module index
*
* Exit information for module iMod compacted
*
* Returns TRUE if module compacted
* FALSE if module not found
*
*/
bool_t CompactOneModule (ushort iPData)
{
ulong i;
PACKDATA *pPData;
ushort iMod;
ptr32 = fLinearExe;
SymbolSizeAdd = 0;
SymbolSizeSub = 0;
UDTAdd = 0;
ExtraSymbols = NULL;
AddNewSymbols = FALSE;
ulCVTypeSignature = 0xFFFFFFFL; // We don't know the type signature yet
// search directory table for module table entry and following
// sstTypes, sstPublics, sstSymbols and sstSrcLnSeg
iSym = 0;
iPub = 0;
iPubSym = 0;
iSrcLn = 0;
iSrcMod = 0;
maxPreComp = 0;
PackingPreComp = FALSE;
pPData = PackOrder + iPData;
i = pPData->iDir;
pCurMod = pPData->pMod;
pRefMod = NULL;
iMod = pPData->iMod;
if (pDir[i].SubSection == SSTMODULE) {
ReformatMod (i, pCurMod);
}
else if (pDir[i].SubSection == sstModule) {
CopyModule (&pDir[i], pCurMod);
}
else {
// we should have been pointing at a module entry
DASSERT (FALSE);
}
while ((++i < cSST) && (pDir[i].iMod == iMod)) {
if (pDir[i].cb != 0) {
switch (pDir[i].SubSection) {
case SSTTYPES:
case sstTypes:
ReadTypes (&pDir[i], FALSE);
break;
case sstPreComp:
PackingPreComp = TRUE;
ReadTypes (&pDir[i], TRUE);
PackPreComp (pCurMod);
break;
case SSTPUBLIC:
case sstPublic:
ReadPublics (i, &pDir[i]);
break;
case sstPublicSym:
ReadPublicSym (i, &pDir[i]);
break;
case SSTSYMBOLS:
case sstSymbols:
ReadSymbols (i, &pDir[i]);
break;
case SSTSRCLNSEG:
case sstSrcLnSeg:
ReadSrcLnSeg (i, &pDir[i]);
break;
case sstSrcModule:
ReadSrcModule (i, &pDir[i]);
break;
}
}
}
if (iPub != 0) {
FixupPublicsC6 (pPublics, pDir[iPub].cb);
RewritePublicsC6 (pPublics, &pDir[iPub]);
}
else if (iPubSym != 0) {
switch (*((ulong *)pPublics)) {
case CV_SIGNATURE_C7:
// compensate for signature which is not copied
C7RewritePublics (pPublics, &pDir[iPubSym]);
InitialPubInfoSize += pDir[iPubSym].cb;
break;
default:
DASSERT (FALSE);
}
}
if (iSym != 0) {
if (delete == TRUE) {
pDir[iSym].cb = 0;
}
else {
switch (*((ulong *)pSymbols)) {
case CV_SIGNATURE_C7:
// C7 format symbols
InitialSymInfoSize += pDir[iSym].cb;
C7CalcNewSizeOfSymbols (pSymbols, pDir[iSym].cb,
&SymbolSizeAdd, &SymbolSizeSub);
C7RewriteAndFixupSymbols (pSymbols, &pDir[iSym],
pCurMod, &SymbolSizeAdd, &SymbolSizeSub);
break;
default:
// C6 format symbols
C6CalcNewSizeOfSymbols (pSymbols, pDir[iSym].cb);
C6RewriteAndFixupSymbols (pSymbols, &pDir[iSym], ModAddr, pCurMod);
break;
}
}
}
if (iSrcLn != 0) {
RewriteSrcLnSeg (pSrcLn, &pDir[iSrcLn], pCurMod);
}
else if (iSrcMod != 0) {
CopySrcMod (pSrcLn, &pDir[iSrcMod], pCurMod);
}
return (TRUE);
}
LOCAL void ReadTypes (OMFDirEntry *pDir, bool_t fPreComp)
{
pTypes = pTypeSeg[0];
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
} else {
DASSERT( lseek(exefile, 0, SEEK_CUR) == filepos + lfoBase );
}
// Read in the signature byte
if (read (exefile, pTypes, sizeof (ulong)) != sizeof (ulong)) {
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
}
// Read in according to signature.
switch (ulCVTypeSignature = *((ulong *)pTypes)) {
case CV_SIGNATURE_C7:
// C7 format types
usCurFirstNonPrim = CV_FIRST_NONPRIM;
C7ReadTypes (pDir->cb - sizeof (ulong), fPreComp);
filepos += pDir->cb;
break;
default:
{
ulong cbToRead = pDir->cb - sizeof (ulong);
if (*pTypes != 0x01) {
ErrorExit (ERR_INVALIDTABLE, "Types", FormatMod (pCurMod));
}
ulCVTypeSignature = CV_SIGNATURE_C6;
usCurFirstNonPrim = 512;
if (read (exefile, pTypes + sizeof (ulong), (int)cbToRead) != (int)cbToRead) {
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
}
filepos += pDir->cb;
C6ReadTypes (pTypes, pDir->cb);
break;
}
}
}
void ReadPublics (ulong i, OMFDirEntry *pDir)
{
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if (read (exefile, pPublics, (int)pDir->cb) != (int)pDir->cb) {
ErrorExit (ERR_INVALIDTABLE, "Publics", FormatMod (pCurMod));
}
filepos += pDir->cb;
iPub = i;
}
void ReadSymbols (ulong i, OMFDirEntry *pDir)
{
if (pDir->cb > maxSymbolsSub) {
ErrorExit (ERR_SYMLARGE, FormatMod (pCurMod), NULL);
}
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if (read (exefile, pSymbols, (int)pDir->cb) != (int)pDir->cb) {
ErrorExit (ERR_INVALIDTABLE, "Symbols", FormatMod (pCurMod));
}
filepos += pDir->cb;
SymbolSegment = pSymbols;
iSym = i;
}
void ReadPublicSym (ulong i, OMFDirEntry *pDir)
{
DASSERT (pDir->cb <= maxPublicsSub);
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if (read (exefile, pPublics, (int)pDir->cb) != (int)pDir->cb) {
ErrorExit (ERR_INVALIDTABLE, "Publics", FormatMod (pCurMod));
}
filepos += pDir->cb;
iPubSym = i;
}
void ReadSrcLnSeg (ulong i, OMFDirEntry *pDir)
{
DASSERT (pDir->cb <= maxSrcLnSub);
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if (read (exefile, pSrcLn, (int)pDir->cb) != (int)pDir->cb) {
ErrorExit (ERR_INVALIDEXE, "SrcLnSeg", FormatMod (pCurMod));
}
filepos += pDir->cb;
iSrcLn = i;
}
void ReadSrcModule (ulong i, OMFDirEntry *pDir)
{
DASSERT (pDir->cb <= maxSrcLnSub);
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if (read (exefile, pSrcLn, (int)pDir->cb) != (int)pDir->cb) {
ErrorExit (ERR_INVALIDEXE, "Source Module", FormatMod (pCurMod));
}
filepos += pDir->cb;
iSrcMod = i;
}
void CopyModule (OMFDirEntry *pDir, PMOD pMod)
{
_vmhnd_t vp;
// read the module table into virtual memory
if ((vp = (_vmhnd_t)VmAlloc ((int)pDir->cb)) == _VM_NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if (pDir->lfo != filepos) {
filepos = pDir->lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if ((ModAddr = (char *) VmLoad (vp, _VM_DIRTY)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if (read (exefile, ModAddr, (int)pDir->cb) != (int)pDir->cb) {
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
}
filepos += pDir->cb;
pDir->lfo = (ulong)vp;
pMod->ModuleSize = pDir->cb;
pMod->ModulesAddr = (ulong)vp;
}
void ReformatMod (ulong iSST, PMOD pMod)
{
ushort NewSize;
ushort cbName;
OMFModule *pOMFMod;
ushort cSeg;
ushort i;
oldnsg *pOldNsg;
oldnsg32 *pOldNsg32;
char *pName;
_vmhnd_t vp;
// read the module table into real memory
if (pDir[iSST].lfo != filepos) {
filepos = pDir[iSST].lfo;
SeekCnt++;
lseek (exefile, filepos + lfoBase, SEEK_SET);
}
if (read (exefile, pSSTMOD, (int)pDir[iSST].cb) != (int)pDir[iSST].cb) {
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
}
filepos += pDir[iSST].cb;
// compute length of sstModule table
NewSize = sizeof (OMFModule);
if (fLinearExe) {
cSeg = ((oldsmd32 *) pSSTMOD)->cSeg;
}
else {
cSeg = pSSTMOD->cSeg;
}
if (cSeg == 0) {
cSeg = 1;
}
NewSize += sizeof (OMFSegDesc) * (cSeg - 1);
if (fLinearExe) {
cbName = ((oldsmd32 *) pSSTMOD)->cbName[0];
pOldNsg32 = (oldnsg32 *)(((char *)pSSTMOD) +
offsetof (oldsmd32, cbName[0]) + sizeof (pSSTMOD->cbName) + cbName);
NewSize += ((cbName + sizeof (ushort) + sizeof (ulong) - 1) /
sizeof (ulong)) * sizeof (ulong);
}
else {
cbName = pSSTMOD->cbName[0];
pOldNsg = (oldnsg *)(((char *)pSSTMOD) + offsetof (oldsmd, cbName[0]) +
sizeof (pSSTMOD->cbName) + cbName);
NewSize += ((cbName + sizeof (ushort) + sizeof (ulong) - 1) /
sizeof (ulong)) * sizeof (ulong);
}
if ((vp = (_vmhnd_t)VmAlloc (NewSize)) == _VM_NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if ((ModAddr = (char *) VmLoad (vp, _VM_DIRTY)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
pOMFMod = (OMFModule *)ModAddr;
pOMFMod->cSeg = cSeg;
pOMFMod->Style[0] = 'C';
pOMFMod->Style[1] = 'V';
pOMFMod->SegInfo[0].pad = 0;
if (fLinearExe) {
pOMFMod->ovlNumber = ((oldsmd32 *) pSSTMOD)->ovlNbr;
pOMFMod->iLib = ((oldsmd32 *) pSSTMOD)->iLib;
pOMFMod->SegInfo[0].Off = ((oldsmd32 *) pSSTMOD)->SegInfo.Off;
pOMFMod->SegInfo[0].cbSeg = ((oldsmd32 *) pSSTMOD)->SegInfo.cbSeg;
pOMFMod->SegInfo[0].Seg = ((oldsmd32 *) pSSTMOD)->SegInfo.Seg;
}
else {
pOMFMod->ovlNumber = pSSTMOD->ovlNbr;
pOMFMod->iLib = pSSTMOD->iLib;
pOMFMod->SegInfo[0].Off = (CV_uoff32_t)pSSTMOD->SegInfo.Off;
pOMFMod->SegInfo[0].cbSeg = (ulong)pSSTMOD->SegInfo.cbSeg;
pOMFMod->SegInfo[0].Seg = pSSTMOD->SegInfo.Seg;
}
// copy information about additional segments
for (i = 1; i < cSeg; i++) {
pOMFMod->SegInfo[i].pad = 0;
if (fLinearExe) {
pOMFMod->SegInfo[i].Seg = pOldNsg32[i-1].Seg;
pOMFMod->SegInfo[i].Off = pOldNsg32[i-1].Off;
pOMFMod->SegInfo[i].cbSeg = pOldNsg32[i-1].cbSeg;
}
else {
pOMFMod->SegInfo[i].Seg = pOldNsg[i-1].Seg;
pOMFMod->SegInfo[i].Off = (CV_uoff32_t)pOldNsg[i-1].Off;
pOMFMod->SegInfo[i].cbSeg = (ulong)pOldNsg[i-1].cbSeg;
}
}
pName = ((char *)pOMFMod) + sizeof (OMFModule) + sizeof (OMFSegDesc) * (cSeg - 1);
*((uchar *)pName)++ = (uchar) cbName;
if (fLinearExe) {
memmove (pName, &((oldsmd32 *) pSSTMOD)->cbName[1], cbName);
}
else {
memmove (pName, &pSSTMOD->cbName[1], cbName);
}
pDir[iSST].SubSection = sstModule;
pDir[iSST].lfo = (ulong)vp;
pDir[iSST].cb = NewSize;
pMod->ModuleSize = sizeof (OMFModule) + (sizeof (OMFSegDesc) * (cSeg - 1)) +
sizeof (cbName) + cbName;
pMod->ModulesAddr = (ulong)vp;
}
uchar *GetSymString (ushort SymOffset)
{
return (SymbolSegment + SymOffset);
}
/** CopySrcMod - copy sstSrcModule table to VM
*
* CopySrcMod (addr, pDir, pMod);
*
* Entry addr = address of SrcLnSeg table
* pDir = address of directory entry
* pMod = module table entry
*
* Exit pDir->lfo = address of rewritten table
* pDir->Size = size of rewritten table
*
* Return none
*
*/
LOCAL void CopySrcMod (uchar *OldSrcMod, OMFDirEntry *pDir, PMOD pMod)
{
_vmhnd_t SrcModAddr;
char *pSrcMod;
if ((SrcModAddr = (_vmhnd_t)VmAlloc (pDir->cb)) == _VM_NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if ((pSrcMod = (char *) VmLoad (SrcModAddr, _VM_DIRTY)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
memcpy (pSrcMod, OldSrcMod, (int)pDir->cb);
pDir->lfo = (ulong)SrcModAddr;
pMod->SrcLnSize = pDir->cb;
pMod->SrcLnAddr = (ulong)SrcModAddr;
}
/** RewriteSrcLnSeg - reformat source line to new format and store in VM
*
* RewriteSrcLnSeg (addr, pDir, pMod);
*
* Entry addr = address of SrcLnSeg table
* pDir = address of directory entry
* pMod = module table entry
*
* Exit pDir->lfo = address of rewritten table
* pDir->Size = size of rewritten table
*
* Return none
*
*/
#define MAXSEG 256
#define MAXFILE 20
LOCAL void RewriteSrcLnSeg (uchar *OldSrcLn, OMFDirEntry *pDir, PMOD pMod)
{
ushort cFile = 0; // number of files in module
ushort SegFile[MAXSEG]; // list of segments for current file
ushort cSegMod = 0; // number of segments for module
ushort SegMod[MAXSEG]; // list of segments for module
ushort Seg; // current segment
ushort PairSize; // sizeof offset/line pair
ushort cPair; // number of pairs in current line table
ulong cbLineTable; // total size of OMFSourceLine table
ulong cbFileTable; // total size of OMFSourceFile table
ulong cbModTable = 0; // total size of OMFSourceModule table
uchar *pOld;
uchar *pEnd;
char *pFileName = NULL;
char *pLineBase;
char *pLineLim;
char *pFile;
char *pOffset;
char *pLine;
char *pLineTable;
ushort cbFileName;
ushort i;
ushort fAdd;
ulong cbModHeader = 0;
ulong cbFileHeader[MAXFILE];
ulong FileBase[MAXFILE]; // OMFSourceFile base offsets
ushort LineFile[MAXFILE]; // number of line tables per file
ushort SegPerFile[MAXFILE];// number of segments per file
_vmhnd_t SrcModAddr;
char *pSrcMod;
char *pFileMod;
char *Save;
if (fLinearExe) {
PairSize = sizeof (CV_uoff32_t) + sizeof (ushort);
}
else {
PairSize = sizeof (CV_uoff16_t) + sizeof (ushort);
}
// sweep the SrcLnSeg table and compute the size of the SrcModule table
pOld = pSrcLn;
pEnd = pOld + pDir->cb;
while (pOld < pEnd) {
if ((pFileName == NULL) ||
(strncmp ((char *)pOld, pFileName, cbFileName + 1) != 0)) {
if (pFileName != NULL) {
// the file name has changed.
FileBase[cFile] = cbModTable;
cbFileHeader[cFile] = offsetof (OMFSourceFile, baseSrcLn[0]) +
SegPerFile[cFile] * sizeof (ulong) +
SegPerFile[cFile] * 2 * sizeof (CV_uoff32_t);
cbFileHeader[cFile] += sizeof (ushort);
cbFileHeader[cFile] += cbFileName;
cbFileHeader[cFile] = ((cbFileHeader[cFile] +
sizeof (ulong) - 1) / sizeof (ulong)) * sizeof (ulong);
cbFileTable += cbFileHeader[cFile];
cFile++;
cbModTable += cbFileTable;
DASSERT (cbFileTable % sizeof (ulong) == 0);
cbModTable += cbFileTable;
}
// set pointer to file name and name length
pFileName = (char *)pOld;
cbFileName = *pFileName;
// initialize sizeof OMFSourceFile header for this file
cbFileTable = 0;
// initialize sount of segments for this file
SegPerFile[cFile] = 0;
// set base offset of the OMFSourceFile header (will bias by cbModHeader)
FileBase[cFile] = cbModTable;
LineFile[cFile] = 0;
}
pOld += *pOld + sizeof (char);
// we now have a new segment index for this source file. We verify
// that it is not already known to this source file.
Seg = *((ushort UNALIGNED *)pOld)++;
if (SegPerFile[cFile] < MAXSEG) {
SegFile[SegPerFile[cFile]++] = Seg;
}
else {
// M00NOTDONE - this should be a warning message and the
// table purged
DASSERT (FALSE);
}
// we now add the segment to the module table if it is not
// already referenced
for (fAdd = TRUE, i = 0; i < cSegMod; i++) {
if (SegMod[i] == Seg) {
fAdd = FALSE;
break;
}
}
if (fAdd == TRUE) {
if (cSegMod < MAXSEG) {
SegMod[cSegMod++] = Seg;
}
else {
// M00NOTDONE - this should be a warning message and the
// table purged
DASSERT (FALSE);
}
}
// M00NOTDONE - need to compute seg start/end per file and segment
LineFile[cFile]++;
cPair = *((ushort UNALIGNED *)pOld)++;
pOld += cPair * PairSize;
cbLineTable = offsetof (OMFSourceLine, offset[0]) +
cPair * sizeof (ulong) +
cPair * sizeof (ushort);
if (cPair & 1) {
// the next OMFSourceLine table will not be long aligned
cbLineTable += sizeof (ushort);
}
DASSERT (cbLineTable % sizeof (ulong) == 0);
cbFileTable += cbLineTable;
}
// compute size of final OMFSourceFile table and size of OMFSourceModule
cbFileHeader[cFile] = offsetof (OMFSourceFile, baseSrcLn[0]) +
SegPerFile[cFile] * sizeof (ulong) +
SegPerFile[cFile] * 2 * sizeof (CV_uoff32_t);
cbFileHeader[cFile] += sizeof (uchar);
cbFileHeader[cFile] += cbFileName;
cbFileHeader[cFile] = ((cbFileHeader[cFile] +
sizeof (ulong) - 1) / sizeof (ulong)) * sizeof (ulong);
cbFileTable += cbFileHeader[cFile];
cFile++;
cbModTable += cbFileTable;
DASSERT (cbFileTable % sizeof (ulong) == 0);
cbModHeader = offsetof (OMFSourceModule, baseSrcFile[0]) +
cFile * sizeof (ulong) +
cSegMod * sizeof (ushort) +
2 * sizeof (CV_uoff32_t) * cSegMod;
if (cSegMod & 1) {
// the next subsection will not be long aligned
cbModHeader += sizeof (ushort);
}
cbModTable += cbModHeader;
DASSERT (cbModTable < 0x10000);
DASSERT (cbModTable % sizeof (ulong) == 0);
if ((SrcModAddr = (_vmhnd_t)VmAlloc (cbModTable)) == _VM_NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if ((pSrcMod = (char *)VmLoad (SrcModAddr, _VM_DIRTY)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
Save = pSrcMod;
pOld = OldSrcLn;
// at the end of the above loop, we have the following information
// cbModHeader = size of the OMFSourceModule Structure
// cbModTable = size of sstSrcModule table
// cFile = number of source files in the module
// cbFileHeader[] = length of the OMFSourceFile structure for each file
// FileBase[] = offset of OMFSourceFile structure from end of OMFSourceModule
*((ushort *)pSrcMod)++ = cFile;
*((ushort *)pSrcMod)++ = cSegMod;
for (i = 0; i < cFile; i++) {
*((ulong *)pSrcMod)++ = FileBase[i] + cbModHeader;
}
for (i = 0; i < cSegMod; i++) {
*((CV_uoff32_t *)pSrcMod)++ = 0; // M00BUG - should insert seg start/end
*((CV_uoff32_t *)pSrcMod)++ = 0;
}
for (i = 0; i < cSegMod; i++) {
*((ushort *)pSrcMod)++ = SegMod[i];
}
if (cSegMod & 1) {
*((ushort *)pSrcMod)++ = 0;
}
// we now sweep the old source line table actually doing the rewrite
cFile = 0;
pFileName = NULL;
while (pOld < pEnd) {
if ((pFileName == NULL) ||
(strncmp ((char *)pOld, pFileName, cbFileName + 1) != 0)) {
// set the base address of OMFSourceFile for this file
pFileMod = Save + FileBase[cFile] + cbModHeader;
// set the base address of the first OMFSourceLine for this file
pLineTable = pFileMod + cbFileHeader[cFile];
// set the number of segments for this file
*((ushort *)pFileMod)++ = SegPerFile[cFile];
*((ushort *)pFileMod)++ = 0;
pLineBase = pFileMod;
pLineLim = pFileMod + SegPerFile[cFile] * sizeof (ulong);
pFile = pLineLim + SegPerFile[cFile] * 2 * sizeof (CV_uoff32_t);
pFileName = (char *)pOld;
cbFileName = *pFileName;
*((uchar *)pFile)++ = (uchar) cbFileName;
memcpy (pFile, pFileName + 1, cbFileName);
pFile += cbFileName;
while (pFile < pLineTable) {
*pFile++ = 0;
}
cFile++;
}
pOld += *pOld + sizeof (char);
Seg = *((ushort UNALIGNED *)pOld)++;
cPair = *((ushort UNALIGNED *)pOld)++;
*((ulong *)pLineBase)++ = pLineTable - Save;
*((CV_off32_t *)pLineLim)++ = 0; //M00BUG - needs start here
*((CV_off32_t *)pLineLim)++ = 0;
pOffset = pLineTable;
*((ushort *)pOffset)++ = Seg;
*((ushort *)pOffset)++ = cPair;
pLine = pOffset + cPair * sizeof (CV_uoff32_t);
for (i = 0; i < cPair; i++) {
*((ushort *)pLine)++ = *((ushort UNALIGNED *)pOld)++;
if (fLinearExe) {
*((ulong *)pOffset)++ = *((ulong UNALIGNED *)pOld)++;
}
else {
*((ulong *)pOffset)++ = *((ushort UNALIGNED *)pOld)++;
}
}
if (cPair & 1) {
*((ushort *)pLine)++ = 0;
}
pLineTable = pLine;
}
pDir->lfo = (ulong)SrcModAddr;
pDir->cb = (ushort)cbModTable;
pMod->SrcLnSize = (ushort)cbModTable;
pMod->SrcLnAddr = (ulong)SrcModAddr;
if (pCurMod->SrcLnAddr != 0) {
FixSrcMod (pCurMod);
}
}
typedef struct _OFP {
ulong offStart;
ulong offEnd;
} OFP;
typedef OFP *POFP;
typedef struct _SGI {
ushort seg;
ushort pad;
OFP ofp;
ushort cln;
char rgbVar [ 0 ]; // Offsets & line numbers
} SGI;
typedef SGI *PSGI;
typedef struct _FLI {
ushort cseg;
uchar *szName;
PSGI rgpsgi [ 0 ];
} FLI;
typedef FLI *PFLI;
LOCAL void FixSrcMod (PMOD pmod) {
OMFModule *pmds = NULL;
OMFSourceModule *psrc = NULL;
OMFSourceModule *psrcT = NULL;
_vmhnd_t vpsrc = _VM_NULL;
unsigned int cbsrcT = 0;
unsigned int cbsrc = 0;
ushort ifile = 0;
ushort ifli = 0;
// Set the top line source table contributers to be the same
// as the module contributers
if ((pmds = (OMFModule *)VmLock ((_vmhnd_t)pmod->ModulesAddr)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if ((psrc = (OMFSourceModule *)VmLoad ((_vmhnd_t)pmod->SrcLnAddr, _VM_CLEAN)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
cbsrcT =
sizeof (short) * 2 +
psrc->cFile * sizeof (long) +
pmds->cSeg * (sizeof (ushort) + sizeof (OFP));
// Long-align cbsrcT
cbsrcT = (cbsrcT + 3) & ~0x03;
cbsrc = cbsrcT;
if ((psrcT = malloc (cbsrcT)) == NULL) {
ErrorExit (ERR_NOMEM, NULL, NULL);
}
memset (psrcT, 0, cbsrcT);
psrcT->cFile = psrc->cFile;
psrcT->cSeg = pmds->cSeg;
// Fixup the seg-start/ends for the module level source table
{
POFP rgofp;
ushort *rgseg;
ushort iseg;
rgofp = (POFP) &psrcT->baseSrcFile [ psrcT->cFile ];
rgseg = (ushort *) &psrcT->baseSrcFile [ psrcT->cFile + psrcT->cSeg * 2 ];
for (iseg = 0; iseg < pmds->cSeg; iseg++) {
OMFSegDesc *psgd = &pmds->SegInfo [ iseg ];
rgseg [ iseg ] = psgd->Seg;
rgofp [ iseg ].offStart = psgd->Off;
rgofp [ iseg ].offEnd = psgd->Off + psgd->cbSeg;
}
}
for (ifile = 0; ifile < psrc->cFile; ifile++) {
int cbfli = sizeof (FLI) + sizeof (PSGI) * psrcT->cSeg;
PFLI pfli = NULL;
OMFSourceFile *psf = (OMFSourceFile *) ((char *) psrc + psrc->baseSrcFile [ ifile ]);
uchar *lpb = (uchar *) &psf->baseSrcLn [ psf->cSeg * 3 ];
int cln = 0;
ushort isgi = 0;
ushort isegM = 0;
ushort isegF = 0;
if ((pfli = malloc (cbfli)) == NULL) {
ErrorExit (ERR_NOMEM, NULL, NULL);
}
psrcT->baseSrcFile [ ifile ] = (ulong) pfli;
memset (pfli, 0, cbfli);
if ((pfli->szName = malloc (*lpb + 1)) == NULL) {
ErrorExit (ERR_NOMEM, NULL, NULL);
}
memcpy (pfli->szName, lpb, *lpb + 1);
// Find the number of line number pairs in the entire file
for (isegF = 0; isegF < psf->cSeg; isegF++) {
OMFSourceLine *psl = (OMFSourceLine *)
((char *) psrc + psf->baseSrcLn [ isegF ]);
cln += psl->cLnOff;
}
for (isegM = 0; isegM < pmds->cSeg; isegM++) {
OMFSegDesc *psi = &pmds->SegInfo [ isegM ];
PSGI psgi = NULL;
ushort clnT = 0;
ulong UNALIGNED *rgoff;
ushort *rgln;
// Find the number of line number pairs associated with
// the segment contributer isegM
for (isegF = 0; isegF < psf->cSeg; isegF++) {
OMFSourceLine *psl = (OMFSourceLine *)
((char *) psrc + psf->baseSrcLn [ isegF ]);
if (psl->Seg == psi->Seg) {
ushort iln = 0;
for (iln = 0; iln < psl->cLnOff; iln++) {
if (
psl->offset [ iln ] >= psi->Off &&
psl->offset [ iln ] < psi->Off + psi->cbSeg
) {
clnT += 1;
}
}
}
}
// Now that we know how big the table will be, allocate it.
if (clnT > 0) {
// Add the size of the source line table
cbsrc +=
sizeof (OMFSourceLine) +
(sizeof (ulong) + sizeof (ushort)) * (clnT - 1);
// Long-align cbsrc
cbsrc = (cbsrc + 3) & ~0x03;
psgi = malloc (
sizeof (SGI) +
(sizeof (ulong) + sizeof (ushort)) * clnT
);
pfli->rgpsgi [ isgi ] = psgi;
psgi->seg = psi->Seg;
psgi->cln = clnT;
rgoff = (ulong *) psgi->rgbVar;
rgln = (ushort *) &psgi->rgbVar [ clnT * sizeof (ulong) ];
clnT = 0;
for (isegF = 0; isegF < psf->cSeg; isegF++) {
OMFSourceLine *psl = (OMFSourceLine *)
((char *) psrc + psf->baseSrcLn [ isegF ]);
if (psl->Seg == psi->Seg) {
ushort iln = 0;
for (iln = 0; iln < psl->cLnOff; iln++) {
if (
psl->offset [ iln ] >= psi->Off &&
psl->offset [ iln ] < psi->Off + psi->cbSeg
) {
rgoff [ clnT ] = psl->offset [ iln ];
rgln [ clnT ] = *((ushort *)
&psl->offset [ psl->cLnOff ] + iln
);
clnT += 1;
}
}
}
if (clnT == psgi->cln) {
break;
}
DASSERT (clnT < psgi->cln);
}
psgi->ofp.offStart = rgoff [ 0 ];
psgi->ofp.offEnd = rgoff [ clnT - 1 ];
isgi += 1;
}
}
pfli->cseg = isgi;
// Add the size of the source file table
cbsrc +=
sizeof (OMFSourceFile) -
(sizeof (long) + sizeof (char)) +
(sizeof (long) + sizeof (OFP) + sizeof (ushort)) * isgi +
*pfli->szName;
// At this point we must long-align cbsrc
cbsrc = (cbsrc + 3) & ~0x03;
}
// Now we allocate VM and write out the fixed source table
if ((vpsrc = (_vmhnd_t)VmAlloc (cbsrc)) == _VM_NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
if ((psrc = (OMFSourceModule *)VmLoad (vpsrc, _VM_CLEAN)) == NULL) {
ErrorExit (ERR_NOVM, NULL, NULL);
}
memset (psrc, 0, cbsrc);
// Copy the base source module table into virtual memory
memcpy (psrc, psrcT, cbsrcT);
// Now move each of the source file tables
for (ifli = 0; ifli < psrc->cFile; ifli++) {
PFLI pfli = (PFLI) psrc->baseSrcFile [ ifli ];
OMFSourceFile *psf = (OMFSourceFile *) ((char *) psrc + cbsrcT);
uchar *lpb = pfli->szName;
ushort isgi = 0;
psrc->baseSrcFile [ ifli ] = cbsrcT;
psf->cSeg = pfli->cseg;
psf->reserved = 0;
memcpy (
(uchar *) &psf->baseSrcLn [ 0 ] +
psf->cSeg * 3 * sizeof (ulong),
pfli->szName,
*pfli->szName + 1
);
// Add the size of the source file table
cbsrcT +=
sizeof (OMFSourceFile) -
(sizeof (long) + sizeof (char)) +
(sizeof (long) + sizeof (OFP) + sizeof (ushort)) * pfli->cseg +
*pfli->szName;
cbsrcT = (cbsrcT + 3) & ~0x03;
// Now move each of the source line tables and place the
// pertinent information in the source file table at
// the same time.
for (isgi = 0; isgi < pfli->cseg; isgi++) {
PSGI psgi = pfli->rgpsgi [ isgi ];
OMFSourceLine *psl = (OMFSourceLine *) ((char *) psrc + cbsrcT);
psf->baseSrcLn [ isgi ] = cbsrcT;
psf->baseSrcLn [ pfli->cseg + isgi * 2 ] = psgi->ofp.offStart;
psf->baseSrcLn [ pfli->cseg + isgi * 2 + 1 ] = psgi->ofp.offEnd;
psl->Seg = psgi->seg;
psl->cLnOff = psgi->cln;
memcpy (
&psl->offset [ 0 ],
&psgi->rgbVar [ 0 ],
(sizeof (ulong) + sizeof (ushort)) * psgi->cln
);
cbsrcT +=
sizeof (OMFSourceLine) +
(sizeof (ulong) + sizeof (ushort)) * (psgi->cln - 1);
cbsrcT = (cbsrcT + 3) & ~0x03;
free (psgi);
}
free (pfli->szName);
free (pfli);
}
DASSERT (cbsrcT == cbsrc);
free (psrcT);
FixEnds (pmds, psrc);
VmFree ((_vmhnd_t) pmod->SrcLnAddr);
pmod->SrcLnAddr = (ulong) vpsrc;
VmUnlock ((_vmhnd_t) pmod->ModulesAddr, _VM_DIRTY);
pmod->SrcLnSize = cbsrc;
}
typedef struct _SS {
ushort seg;
ulong offStart;
ulong *poffEnd;
} SS; // Source line Sort structure
typedef SS *PSS;
LOCAL int _CRTAPI1 SLCmp (void const * pv1, void const * pv2)
{
PSS pss1 = (PSS) pv1;
PSS pss2 = (PSS) pv2;
int fRet = 0;
fRet = (int) pss1->seg - (int) pss2->seg;
if (fRet == 0) {
if ( pss1->offStart < pss2->offStart ) {
fRet = -1;
}
else if ( pss1->offStart > pss2->offStart ) {
fRet = 1;
}
else {
fRet = 0;
}
}
return fRet;
}
LOCAL void FixEnds (OMFModule *pmds, OMFSourceModule *psrc)
{
ushort isf = 0;
ushort csl = 0;
ushort iss = 0;
PSS pss = NULL;
ushort iseg = 0;
// Calculate the number of segment contributers
for (isf = 0; isf < psrc->cFile; isf++) {
OMFSourceFile *psf = (OMFSourceFile *)
((char *) psrc + psrc->baseSrcFile [ isf ]);
csl += psf->cSeg;
}
if (csl == 0)
DebugBreak();
// Now copy the relevent info into our temporary structure
pss = malloc (csl * sizeof (SS));
for (isf = 0; isf < psrc->cFile; isf++) {
OMFSourceFile *psf = (OMFSourceFile *)
((char *) psrc + psrc->baseSrcFile [ isf ]);
ushort isl;
for (isl = 0; isl < psf->cSeg; isl++) {
OMFSourceLine *psl = (OMFSourceLine *)
((char *) psrc + psf->baseSrcLn [ isl ]);
pss [ iss ].seg = psl->Seg;
pss [ iss ].offStart = psf->baseSrcLn [ psf->cSeg + isl * 2 ];
pss [ iss ].poffEnd = &psf->baseSrcLn [ psf->cSeg + isl * 2 + 1 ];
iss += 1;
}
}
// Now sort it by segment/offset
qsort ((void *) pss, csl, sizeof (SS), SLCmp);
// Now do the actual back/patch of the ends
for (iss = 0; iss < csl; iss++) {
OMFSegDesc *psi = NULL;
// Find the least module segment contributer that has an end
// greater than the start of the source line table
for (iseg = 0; iseg < pmds->cSeg; iseg++) {
OMFSegDesc *psiT = &pmds->SegInfo [ iseg ];
if (
psiT->Seg == pss [ iss ].seg &&
psiT->Off + psiT->cbSeg > pss [ iss ].offStart &&
(psi == NULL || psi->Off > psiT->Off)
) {
psi = psiT;
}
}
DASSERT (psi != NULL);
if (
(ushort) (iss + 1) < csl &&
pss [ iss ].seg == pss [ iss + 1 ].seg &&
pss [ iss + 1 ].offStart < psi->Off + psi->cbSeg
) {
*(pss [ iss ].poffEnd) = pss [ iss + 1 ].offStart - 1;
}
else {
*(pss [ iss ].poffEnd) = psi->Off + psi->cbSeg - 1;
}
}
// For each sstModule segment contributer, find the first associated
// source line contributer and make the source line start == the
// module start.
for ( iseg = 0; iseg < pmds->cSeg; iseg++ ) {
OMFSegDesc *psi = &pmds->SegInfo [ iseg ];
iss = 0;
while ( TRUE ) {
// We have gone one past the desired source segment contributer
// so back up one and break;
// This will happen if the module segment is strictly greater
// than the source segment or if the segments are equal and
// the module offset is strictly greater than the source segment.
if (
iss > 0 &&
( psi->Seg < pss [ iss ].seg ||
( psi->Seg == pss [ iss ].seg &&
psi->Off > pss [ iss ].offStart
)
)
) {
iss -= 1;
break;
}
// We are exactly on the desired source segment, so just break;
if (
psi->Seg == pss [ iss ].seg &&
psi->Off == pss [ iss ].offStart
) {
break;
}
iss += 1;
// We went off the end of the table, so (hopefully) the last
// source contributer was the one we were looking for.
if ( iss == csl ) {
iss -= 1;
break;
}
}
// The linker/compiler is sometimes inserting a segment that has
// no source but is listed in the module contributers. In this
// case we will have passed the above tests but ended up on
// the wrong segment, so just ignore it.
#if 0
// I don't understand what this is doing but it must be wrong.
if ( pss [ iss ].seg == psi->Seg) {
*(pss [ iss ].poffEnd - 1) = psi->Off;
}
#endif
}
// Free up the temporary memory
free (pss);
}