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.
1942 lines
55 KiB
1942 lines
55 KiB
/*
|
|
* to build module list
|
|
*
|
|
*
|
|
*/
|
|
|
|
#undef FAR
|
|
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
|
|
#include "compact.h"
|
|
#include "exehdr.h"
|
|
#include "writebuf.h"
|
|
|
|
|
|
#define IMAGE_DEBUG_TYPE_MISC 4
|
|
#define FileAlign(a) (((a) + 511) & ~511)
|
|
|
|
enum SIG {
|
|
SIG02 = 0, // NB02 signature
|
|
SIG05, // NB05 signature
|
|
SIG06 // NB06 signature
|
|
};
|
|
|
|
|
|
uchar Signature[4];
|
|
uchar NewSig[ 8] = "NB08";
|
|
ushort ModuleIndex;
|
|
uchar fLinearExe = FALSE;
|
|
OMFDirEntry * pDir;
|
|
|
|
_vmhnd_t Libraries = _VM_NULL;
|
|
_vmhnd_t SegMap = _VM_NULL;
|
|
_vmhnd_t SegName = _VM_NULL;
|
|
ulong LibSize = 0;
|
|
ulong SegMapSize = 0;
|
|
ulong SegNameSize = 0;
|
|
ushort cMod = 0;
|
|
OMFDirHeader DirHead = {0};
|
|
ulong SeekCount;
|
|
|
|
PMOD ModuleList = NULL;
|
|
extern ushort NewIndex;
|
|
ushort Sig; // signature enumeration
|
|
long cbSrcModule = 0;
|
|
PACKDATA *PackOrder = NULL;
|
|
|
|
ulong lfoObject;
|
|
ulong lfoHeader;
|
|
|
|
LOCAL ushort CheckSignature (void);
|
|
LOCAL int _CRTAPI1 modsort02 (const void *, const void *);
|
|
LOCAL int _CRTAPI1 modsort (const void *, const void *);
|
|
LOCAL int _CRTAPI1 sstsort (const void *, const void *);
|
|
LOCAL ulong WriteTypes (void);
|
|
LOCAL void WriteSST (ulong);
|
|
LOCAL void ReadNB02 (void);
|
|
LOCAL void ReadNB05 (bool_t);
|
|
#if defined (INCREMENTAL)
|
|
LOCAL void ReadNB06 (void);
|
|
LOCAL void RestoreNB05 (void);
|
|
LOCAL void RestoreGlobalTypes (OMFDirEntry *);
|
|
LOCAL void RestoreGlobalPub (OMFDirEntry *);
|
|
LOCAL void RestoreGlobalSym (OMFDirEntry *);
|
|
LOCAL void RestoreTable (PMOD, OMFDirEntry *);
|
|
#endif
|
|
LOCAL void SetTableSizes (void);
|
|
LOCAL void CopyTable (OMFDirEntry *, _vmhnd_t *, ulong *);
|
|
|
|
LOCAL ulong lfoDbgDirBase;
|
|
|
|
// table for sorting NB02 subsection tables
|
|
|
|
int MapArray02 [9][9] = {
|
|
{ 0, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 0, 1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, -1, 0, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 0, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 0, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 0, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 0, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 0, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 0}
|
|
};
|
|
|
|
|
|
|
|
// table for sorting NB05 subsection tables
|
|
|
|
int MapArray [17][17] = {
|
|
{ 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, -1},
|
|
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0},
|
|
};
|
|
|
|
char Zero[4] = {0};
|
|
int PadCount;
|
|
|
|
IMAGE_SECTION_HEADER secHdrDebug; // .debug section header
|
|
|
|
BOOL bDebugDirPresent = FALSE;
|
|
|
|
struct {
|
|
BOOL exists;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
IMAGE_COFF_SYMBOLS_HEADER dbgInfo;
|
|
ULONG lfo;
|
|
ULONG cb;
|
|
char * pb;
|
|
} DbgDataCoff;
|
|
|
|
struct {
|
|
BOOL exists;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
ULONG lfo;
|
|
ULONG cb;
|
|
char * pb;
|
|
} DbgDataFpo;
|
|
|
|
struct {
|
|
BOOL exists;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
ULONG lfo;
|
|
ULONG cb;
|
|
char * pb;
|
|
} DbgDataMisc;
|
|
|
|
/** ReadDir - read subsection directory from exe
|
|
*
|
|
* ReadDir ()
|
|
*
|
|
* Entry exefile = file handle for .exe
|
|
*
|
|
* Exit cSST = count of number of subsection entries
|
|
* cMod = number of modules in file
|
|
* pDir = pointer to subsection directories
|
|
* subsection entries sorted into ascending module order
|
|
*
|
|
* Returns none
|
|
*/
|
|
|
|
|
|
void ReadDir (void)
|
|
{
|
|
long dlfaBase;
|
|
ushort segremain = 0;
|
|
struct exe_hdr exehdr;
|
|
IMAGE_NT_HEADERS pehdr;
|
|
ulong cbCur = 0;
|
|
ulong i;
|
|
uint cbAlloc;
|
|
ulong loc;
|
|
|
|
/*
|
|
* Try reading in a DOS (MZ) header
|
|
*/
|
|
|
|
filepos = 0;
|
|
if ((lseek (exefile, 0L, SEEK_SET) == -1L) ||
|
|
(read (exefile, &exehdr, sizeof (struct exe_hdr)) !=
|
|
sizeof (struct exe_hdr))) {
|
|
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
if (exehdr.e_magic == EMAGIC) {
|
|
/*
|
|
* Got a DOS header now see if there is a pointer to a newer
|
|
* header. We are specifically looking for a PE header as
|
|
* the rules for finding the debug informationare different.
|
|
*/
|
|
|
|
if ((lseek (exefile, exehdr.e_lfanew, SEEK_SET) != -1L) &&
|
|
(read (exefile, &pehdr, sizeof (pehdr)) == sizeof (pehdr))) {
|
|
|
|
if (pehdr.Signature == IMAGE_NT_SIGNATURE) {
|
|
fLinearExe = TRUE;
|
|
}
|
|
|
|
lfoHeader = exehdr.e_lfanew;
|
|
}
|
|
}
|
|
/*
|
|
* It may be that there was not dos header and the exe started with
|
|
* a PE image header.
|
|
*/
|
|
|
|
else if (exehdr.e_magic == IMAGE_NT_SIGNATURE) {
|
|
lseek( exefile, 0, SEEK_SET);
|
|
if (read(exefile, &pehdr, sizeof(pehdr)) != sizeof(pehdr)) {
|
|
ErrorExit(ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
if (pehdr.Signature == IMAGE_NT_SIGNATURE) {
|
|
fLinearExe = TRUE;
|
|
} else {
|
|
ErrorExit(ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
lfoHeader = exehdr.e_lfanew;
|
|
}
|
|
|
|
/*
|
|
* Move the file pointer to the debug information. For non-PE files
|
|
* this is simple. Seek to the end of the file and look for the
|
|
* CVInfo signature. For PE files we need to process through the
|
|
* header looking for the section with the debug information descriptors
|
|
*/
|
|
|
|
if (fLinearExe) {
|
|
int cObjs;
|
|
IMAGE_SECTION_HEADER secHdr;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
ULONG offDbgDir;
|
|
ULONG lfoObjDir = tell(exefile);
|
|
|
|
if (pehdr.FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) {
|
|
lseek( exefile,
|
|
pehdr.FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER),
|
|
SEEK_CUR);
|
|
}
|
|
|
|
/*
|
|
* find the .debug section as save it away. it will be needed when the
|
|
* coff & fpo data is written out so that the debug directory entries
|
|
* can be fixup to have the correct file pointer and virtual address
|
|
*/
|
|
|
|
for (cObjs = pehdr.FileHeader.NumberOfSections; cObjs != 0; cObjs -= 1) {
|
|
if (read(exefile, &secHdrDebug, sizeof(secHdrDebug)) != sizeof(secHdrDebug)) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
if (strncmp(".debug", secHdrDebug.Name, 6) == 0) {
|
|
bDebugDirPresent = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
lseek(exefile, lfoObjDir, SEEK_SET);
|
|
if (pehdr.FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) {
|
|
lseek( exefile,
|
|
pehdr.FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER),
|
|
SEEK_CUR);
|
|
}
|
|
|
|
/*
|
|
** Now at the table of object descriptors, scan through each
|
|
** descriptor looking for the debug information
|
|
*/
|
|
|
|
for (cObjs = pehdr.FileHeader.NumberOfSections; cObjs != 0; cObjs -= 1) {
|
|
if (read(exefile, &secHdr, sizeof(secHdr)) != sizeof(secHdr)) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
if ((secHdr.VirtualAddress <=
|
|
pehdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) &&
|
|
(pehdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress <
|
|
secHdr.VirtualAddress + secHdr.SizeOfRawData)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cObjs == 0) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
/*
|
|
* Seek to the point where the debug directory is and read it in
|
|
* looking for a CV4 debug info directory entry.
|
|
*/
|
|
|
|
offDbgDir = secHdr.PointerToRawData +
|
|
pehdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress -
|
|
secHdr.VirtualAddress;
|
|
|
|
if (lseek(exefile, offDbgDir, SEEK_SET) == -1L) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
for (i=0;
|
|
i<pehdr.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size/sizeof(dbgDir);
|
|
i++) {
|
|
IMAGE_DEBUG_DIRECTORY dbgDirT;
|
|
|
|
loc = lseek(exefile, 0, SEEK_CUR);
|
|
|
|
if (read(exefile, &dbgDirT, sizeof(dbgDirT)) != sizeof(dbgDirT)) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
if (dbgDirT.Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
|
|
lfoDbgDirBase = loc;
|
|
dbgDir = dbgDirT;
|
|
}
|
|
|
|
if (dbgDirT.Type == IMAGE_DEBUG_TYPE_COFF) {
|
|
DbgDataCoff.exists = TRUE;
|
|
DbgDataCoff.lfo = loc;
|
|
DbgDataCoff.dbgDir = dbgDirT;
|
|
}
|
|
|
|
if (dbgDirT.Type == IMAGE_DEBUG_TYPE_FPO) {
|
|
DbgDataFpo.exists = TRUE;
|
|
DbgDataFpo.lfo = loc;
|
|
DbgDataFpo.dbgDir = dbgDirT;
|
|
}
|
|
|
|
if (dbgDirT.Type == IMAGE_DEBUG_TYPE_MISC) {
|
|
DbgDataMisc.exists = TRUE;
|
|
DbgDataMisc.lfo = loc;
|
|
DbgDataMisc.dbgDir = dbgDirT;
|
|
}
|
|
}
|
|
|
|
if (dbgDir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) {
|
|
ErrorExit( ERR_NOINFO, NULL, NULL );
|
|
}
|
|
|
|
if (!bDebugDirPresent) {
|
|
secHdrDebug.VirtualAddress = 0;
|
|
secHdrDebug.PointerToRawData = dbgDir.PointerToRawData;
|
|
if (DbgDataFpo.exists) {
|
|
if (DbgDataFpo.dbgDir.PointerToRawData <
|
|
secHdrDebug.PointerToRawData) {
|
|
secHdrDebug.VirtualAddress = DbgDataFpo.dbgDir.PointerToRawData;
|
|
secHdrDebug.PointerToRawData = DbgDataFpo.dbgDir.PointerToRawData;
|
|
}
|
|
}
|
|
|
|
if (DbgDataMisc.exists) {
|
|
if (DbgDataMisc.dbgDir.PointerToRawData <
|
|
secHdrDebug.PointerToRawData) {
|
|
secHdrDebug.VirtualAddress = DbgDataMisc.dbgDir.PointerToRawData;
|
|
secHdrDebug.PointerToRawData = DbgDataMisc.dbgDir.PointerToRawData;
|
|
}
|
|
}
|
|
|
|
if (DbgDataCoff.exists) {
|
|
if (DbgDataCoff.dbgDir.PointerToRawData <
|
|
secHdrDebug.PointerToRawData) {
|
|
secHdrDebug.VirtualAddress = DbgDataCoff.dbgDir.PointerToRawData;
|
|
secHdrDebug.PointerToRawData = DbgDataCoff.dbgDir.PointerToRawData;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
lfoBase = dbgDir.PointerToRawData;
|
|
|
|
/*
|
|
* Now locate the section which contains the debug info
|
|
*/
|
|
|
|
if (dbgDir.AddressOfRawData != 0) {
|
|
if (lseek(exefile, lfoObjDir, SEEK_SET) == -1L) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
cObjs = pehdr.FileHeader.NumberOfSections;
|
|
for (; cObjs != 0; cObjs -= 1) {
|
|
lfoObject = tell(exefile);
|
|
|
|
if (read(exefile, &secHdr, sizeof(secHdr)) != sizeof(secHdr)) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
if ((secHdr.VirtualAddress <= dbgDir.AddressOfRawData) &&
|
|
(dbgDir.AddressOfRawData <secHdr.VirtualAddress + secHdr.SizeOfRawData)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Cache up any COFF debug information we might have and
|
|
* stash it where we can find it later.
|
|
*/
|
|
|
|
if (DbgDataCoff.exists) {
|
|
if (lseek(exefile, DbgDataCoff.dbgDir.PointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
|
|
if (read(exefile, &DbgDataCoff.dbgInfo, sizeof(DbgDataCoff.dbgInfo)) != sizeof(DbgDataCoff.dbgInfo)) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
|
|
DbgDataCoff.cb = DbgDataCoff.dbgDir.SizeOfData -
|
|
DbgDataCoff.dbgInfo.LvaToFirstSymbol;
|
|
|
|
DbgDataCoff.pb = malloc(DbgDataCoff.cb);
|
|
|
|
if (lseek(exefile, DbgDataCoff.dbgInfo.LvaToFirstSymbol + DbgDataCoff.dbgDir.PointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
|
|
if (read(exefile, DbgDataCoff.pb, DbgDataCoff.cb) != (int) DbgDataCoff.cb) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Cache up any FPO debug information we might have and
|
|
* stash it where we can find it later.
|
|
*/
|
|
|
|
if (DbgDataFpo.exists) {
|
|
DbgDataFpo.cb = DbgDataFpo.dbgDir.SizeOfData;
|
|
DbgDataFpo.pb = malloc(DbgDataFpo.cb);
|
|
|
|
if (lseek(exefile, DbgDataFpo.dbgDir.PointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
|
|
if (read(exefile, DbgDataFpo.pb, DbgDataFpo.cb) != (int) DbgDataFpo.cb) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Cache up any MISC debug information we might have and
|
|
* stash it where we can find it later.
|
|
*/
|
|
|
|
if (DbgDataMisc.exists) {
|
|
DbgDataMisc.cb = DbgDataMisc.dbgDir.SizeOfData;
|
|
DbgDataMisc.pb = malloc(DbgDataMisc.cb);
|
|
|
|
if (lseek(exefile, DbgDataMisc.dbgDir.PointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
|
|
if (read(exefile, DbgDataMisc.pb, DbgDataMisc.cb) != (int) DbgDataMisc.cb) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Seek to the first byte of CodeView Info Data and
|
|
* check for signatures
|
|
*/
|
|
|
|
if (lseek(exefile, lfoBase, SEEK_SET) == -1L) {
|
|
ErrorExit( ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
Sig = CheckSignature ();
|
|
}
|
|
else {
|
|
|
|
/*
|
|
* Non PE exes have the debug information appended
|
|
* to the file
|
|
*/
|
|
|
|
|
|
if (lseek (exefile, -8L, SEEK_END) == -1L) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
Sig = CheckSignature ();
|
|
|
|
if ((read (exefile, (char *)&dlfaBase, sizeof (long)) != sizeof (long)) ||
|
|
(lseek (exefile, -dlfaBase, SEEK_END) == -1L)) {
|
|
ErrorExit (ERR_NOINFO, NULL, NULL);
|
|
}
|
|
lfoBase = tell (exefile);
|
|
if (CheckSignature () != Sig) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* locate directory, read number of entries, allocate space, read
|
|
* directory entries and sort into ascending module index order
|
|
*/
|
|
|
|
switch (Sig) {
|
|
case SIG02:
|
|
ReadNB02 ();
|
|
SetTableSizes ();
|
|
break;
|
|
|
|
case SIG05:
|
|
ReadNB05 (TRUE);
|
|
if (DirHead.lfoNextDir != 0) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
SetTableSizes ();
|
|
break;
|
|
|
|
#if defined (INCREMENTAL)
|
|
case SIG06:
|
|
ReadNB05 (FALSE);
|
|
RestoreNB05 ();
|
|
while (DirHead.lfoNextDir != 0) {
|
|
ReadNB06 ();
|
|
SetTableSizes ();
|
|
if (DirHead.lfoNextDir != 0) {
|
|
// not ready to process multiple ilinks
|
|
DASSERT (FALSE);
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
maxPublicsSub = (size_t)min (_HEAP_MAXREQ, maxPublics);
|
|
maxSymbolsSub = (size_t)min (_HEAP_MAXREQ, maxSymbols);
|
|
maxSrcLnSub = (size_t)min (_HEAP_MAXREQ, maxSrcLn);
|
|
maxModSub = (size_t)min (_HEAP_MAXREQ, maxMod);
|
|
|
|
if ((maxModSub != 0) &&
|
|
((pSSTMOD = (oldsmd *)malloc (maxModSub)) == NULL)) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
if ((pPublics = malloc (maxPublicsSub)) == NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
if ((pSymbols = malloc (maxSymbolsSub)) == NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
if ((pSrcLn = malloc (maxSrcLnSub)) == NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
|
|
// pad size up by possibly missing signature for C6 objects
|
|
|
|
maxTypes += sizeof (ulong);
|
|
cTypeSeg = (ushort)(maxTypes / _HEAP_MAXREQ + 2);
|
|
if ((pTypeSeg = CAlloc (cTypeSeg * sizeof (char *))) == 0) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
|
|
// allocate only first type segment
|
|
|
|
cbAlloc = (uint)min (maxTypes, _HEAP_MAXREQ);
|
|
if ((pTypeSeg[iTypeSeg] = malloc (cbAlloc)) == 0) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** SetTableSizes - set maximum sizes of tables
|
|
*
|
|
* SetTableSizes ()
|
|
*
|
|
* Entry none
|
|
*
|
|
* Exit cMod = number of modules
|
|
* maxSSTMod = maximum old module table size
|
|
* maxPublics = maximum public symblol table size
|
|
* maxSrcLn = maximum line number table size
|
|
* maxSymbol = maximum symbol table size
|
|
* Libraries = address of read sstLibraries table
|
|
* LibrariesSize = size of sstLibraries table
|
|
* SegMap = address of read sstSegMap table if encountered
|
|
* SegMapSize = size of sstSegMap table
|
|
* SegName = address of sstSegName table if encountered
|
|
* SegNameSize = address of sstSegName table
|
|
* PackOrder = pointer to array of packing data in pack order
|
|
*
|
|
* Returns none
|
|
*/
|
|
|
|
|
|
LOCAL void SetTableSizes (void)
|
|
{
|
|
ulong i;
|
|
ushort iPData;
|
|
ushort j;
|
|
long iDir;
|
|
ushort iMod;
|
|
PACKDATA *pPData;
|
|
bool_t fPreComp = FALSE;
|
|
|
|
// determine number of modules in file. Remember that module indices
|
|
// of 0 and 0xffff are not for actual modules
|
|
|
|
cMod = 0;
|
|
maxTypes = 0;
|
|
maxPublics = 0;
|
|
maxSymbols = 0;
|
|
maxSrcLn = 0;
|
|
maxMod = 0;
|
|
for (i = 0; i < cSST; i++) {
|
|
switch (pDir[i].SubSection) {
|
|
case SSTMODULE:
|
|
if (pDir[i].iMod != 0xffff) {
|
|
cMod++;
|
|
maxMod = max (maxMod, pDir[i].cb);
|
|
}
|
|
break;
|
|
|
|
case sstModule:
|
|
if (pDir[i].iMod != 0xffff) {
|
|
cMod++;
|
|
}
|
|
break;
|
|
|
|
case sstPreComp:
|
|
fPreComp = TRUE;
|
|
maxTypes = max (maxTypes, pDir[i].cb);
|
|
break;
|
|
|
|
case SSTTYPES:
|
|
case sstTypes:
|
|
maxTypes = max (maxTypes, pDir[i].cb);
|
|
break;
|
|
|
|
case SSTSYMBOLS:
|
|
case sstSymbols:
|
|
maxSymbols = max (maxSymbols, pDir[i].cb);
|
|
break;
|
|
|
|
case SSTPUBLIC:
|
|
case sstPublic:
|
|
case sstPublicSym:
|
|
maxPublics = max (maxPublics, pDir[i].cb);
|
|
break;
|
|
|
|
case SSTSRCLNSEG:
|
|
case sstSrcLnSeg:
|
|
case sstSrcModule:
|
|
maxSrcLn = max (maxSrcLn, pDir[i].cb);
|
|
break;
|
|
|
|
case sstLibraries:
|
|
case SSTLIBRARIES:
|
|
CopyTable (&pDir[i], &Libraries, &LibSize);
|
|
break;
|
|
|
|
case sstSegMap:
|
|
CopyTable (&pDir[i], &SegMap, &SegMapSize);
|
|
break;
|
|
|
|
case sstSegName:
|
|
CopyTable (&pDir[i], &SegName, &SegNameSize);
|
|
break;
|
|
|
|
default:
|
|
ErrorExit (ERR_RELINK, NULL, NULL);
|
|
}
|
|
}
|
|
// if (cMod > 0x10000 / sizeof (PACKDATA)) { // for dos only (mikeol)
|
|
if (cMod > 0x10000) {
|
|
DASSERT (FALSE);
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
if ((PackOrder = (PACKDATA *)CAlloc (cMod * sizeof (PACKDATA))) == 0) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
iMod = 0;
|
|
iPData = 0;
|
|
if (fPreComp == TRUE) {
|
|
// precompiled types were encountered in the scan above
|
|
// sweep through the directory and put all modules with
|
|
// precompiled types in the pack order array
|
|
|
|
for (i = 0; i < cSST; i++) {
|
|
switch (pDir[i].SubSection) {
|
|
case SSTMODULE:
|
|
// precomp is not allowed with an NB02 linker
|
|
DASSERT (FALSE);
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
|
|
case sstModule:
|
|
if ((pDir[i].iMod != 0xffff) && (pDir[i].iMod != 0)) {
|
|
// save the module index and the starting directory entry
|
|
iDir = i;
|
|
}
|
|
break;
|
|
|
|
case sstPreComp:
|
|
pPData = PackOrder + iPData;
|
|
pPData->iMod = pDir[i].iMod;
|
|
pPData->iDir = iDir;
|
|
pPData->pMod = GetModule (pDir[i].iMod, TRUE);
|
|
iPData++;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < cSST; i++) {
|
|
// now sweep through the directory and add all modules that were
|
|
// not added in the first pass
|
|
|
|
switch (pDir[i].SubSection) {
|
|
case SSTMODULE:
|
|
case sstModule:
|
|
for (j = 0; j < iPData; j++) {
|
|
pPData = PackOrder + j;
|
|
if (pPData->iMod == pDir[i].iMod) {
|
|
break;
|
|
}
|
|
}
|
|
if (j == iPData) {
|
|
// we did not find the module in the pack order array
|
|
pPData = PackOrder + iPData;
|
|
pPData->iMod = pDir[i].iMod;
|
|
pPData->iDir = i;
|
|
pPData->pMod = GetModule (pDir[i].iMod, TRUE);
|
|
iPData++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** CopyTable - copy table to VM
|
|
*
|
|
* CopyTable (pDir);
|
|
*
|
|
* Entry pDir = address of directory entry
|
|
*
|
|
* Exit pDir->lfo = address of rewritten table
|
|
* pDir->Size = size of rewritten table
|
|
*
|
|
* Return none
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL void CopyTable (OMFDirEntry *pDir, _vmhnd_t *pAddr, ulong *pSize)
|
|
{
|
|
_vmhnd_t TableAddr;
|
|
char *pTable;
|
|
|
|
if ((TableAddr = (_vmhnd_t)VmAlloc (pDir->cb)) == _VM_NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
if ((pTable = (char *)VmLoad (TableAddr, _VM_DIRTY)) == NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
lseek (exefile, pDir->lfo + lfoBase, SEEK_SET);
|
|
if (read (exefile, pTable, pDir->cb) != (int)pDir->cb) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
*pAddr = TableAddr;
|
|
*pSize = pDir->cb;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Get module - find or create module entry in list
|
|
*
|
|
* pMod = GetModule (iMod, fAdd)
|
|
*
|
|
* Entry iMod = module index
|
|
* fAdd = TRUE if module to be added to list
|
|
*
|
|
* Exit new module structure added if iMod not in list
|
|
*
|
|
* Returns pointer to module structure
|
|
*/
|
|
|
|
|
|
PMOD GetModule (ushort iMod, bool_t fAdd)
|
|
{
|
|
PMOD new;
|
|
PMOD prev;
|
|
PMOD ptr;
|
|
|
|
prev = NULL;
|
|
ptr = ModuleList;
|
|
|
|
// search to end of module list
|
|
|
|
while (ptr != NULL) {
|
|
if (ptr->ModuleIndex == iMod) {
|
|
return (ptr);
|
|
}
|
|
else if (ptr->ModuleIndex > iMod) {
|
|
break;
|
|
}
|
|
prev = ptr;
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
// since the module was not found, create a blank ModuleList entry
|
|
|
|
if (fAdd == TRUE) {
|
|
new = (PMOD) malloc (sizeof (MOD));
|
|
memset (new, 0, sizeof (MOD));
|
|
new->ModuleIndex = iMod;
|
|
|
|
// do sorted list insertion into ModuleList
|
|
|
|
if (prev == NULL) {
|
|
ModuleList = new;
|
|
}
|
|
else {
|
|
prev->next = new;
|
|
}
|
|
new->next = ptr;
|
|
return (new);
|
|
}
|
|
else {
|
|
ErrorExit (ERR_NEWMOD, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/** FixupExeFile - write new Debug OMF to exe
|
|
*
|
|
* FixupExeFile ()
|
|
*
|
|
* Entry
|
|
*
|
|
* Exit
|
|
*
|
|
* Returns none
|
|
*/
|
|
|
|
|
|
void FixupExeFile ()
|
|
{
|
|
long newDlfaBase;
|
|
long newLfoDir;
|
|
PMOD mod;
|
|
ulong i;
|
|
ulong cbDbgInfo;
|
|
DWORD dwVirtualAddress = 0;
|
|
DWORD dwPointerToRawData = 0;
|
|
|
|
|
|
|
|
dwVirtualAddress = secHdrDebug.VirtualAddress;
|
|
dwPointerToRawData = secHdrDebug.PointerToRawData;
|
|
|
|
/*
|
|
* Write out any MISC debug information which may
|
|
* have been saved
|
|
*/
|
|
|
|
if (DbgDataMisc.exists) {
|
|
if (lseek(exefile, dwPointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
if (write(exefile, DbgDataMisc.pb, DbgDataMisc.cb) != (int) DbgDataMisc.cb) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
lfoBase = lseek(exefile, 0, SEEK_CUR);
|
|
|
|
if (lseek(exefile, DbgDataMisc.lfo, SEEK_SET) == -1) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
DbgDataMisc.dbgDir.AddressOfRawData = dwVirtualAddress;
|
|
DbgDataMisc.dbgDir.PointerToRawData = dwPointerToRawData;
|
|
|
|
if (bDebugDirPresent) {
|
|
dwVirtualAddress += DbgDataMisc.dbgDir.SizeOfData;
|
|
}
|
|
dwPointerToRawData += DbgDataMisc.dbgDir.SizeOfData;
|
|
|
|
if (write(exefile, &DbgDataMisc.dbgDir, sizeof(DbgDataMisc.dbgDir)) != sizeof(DbgDataMisc.dbgDir)) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Write out any FPO debug information which may
|
|
* have been saved
|
|
*/
|
|
|
|
if (DbgDataFpo.exists) {
|
|
if (lseek(exefile, dwPointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
if (write(exefile, DbgDataFpo.pb, DbgDataFpo.cb) != (int) DbgDataFpo.cb) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
lfoBase = lseek(exefile, 0, SEEK_CUR);
|
|
|
|
if (lseek(exefile, DbgDataFpo.lfo, SEEK_SET) == -1) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
DbgDataFpo.dbgDir.AddressOfRawData = dwVirtualAddress;
|
|
DbgDataFpo.dbgDir.PointerToRawData = dwPointerToRawData;
|
|
|
|
if (bDebugDirPresent) {
|
|
dwVirtualAddress += DbgDataFpo.dbgDir.SizeOfData;
|
|
}
|
|
dwPointerToRawData += DbgDataFpo.dbgDir.SizeOfData;
|
|
|
|
if (write(exefile, &DbgDataFpo.dbgDir, sizeof(DbgDataFpo.dbgDir)) != sizeof(DbgDataFpo.dbgDir)) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Write out any COFF debug information which may have been saved
|
|
*
|
|
* The pointer to raw data and address of raw data fields will not
|
|
* be changed. Only the size of data field should be changes.
|
|
*
|
|
* Size of data includes both the data and the header.
|
|
*/
|
|
|
|
if (DbgDataCoff.exists) {
|
|
IMAGE_DEBUG_DIRECTORY dbgDir = {0};
|
|
IMAGE_NT_HEADERS pehdr;
|
|
|
|
|
|
if ((lseek(exefile, lfoHeader, SEEK_SET) == -1) ||
|
|
(read(exefile, &pehdr, sizeof(pehdr)) != sizeof(pehdr))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
if (lseek(exefile, dwPointerToRawData, SEEK_SET) == -1) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
DbgDataCoff.dbgInfo.LvaToFirstSymbol = sizeof(DbgDataCoff.dbgInfo);
|
|
DbgDataCoff.dbgInfo.NumberOfLinenumbers = 0;
|
|
DbgDataCoff.dbgInfo.LvaToFirstLinenumber = 0;
|
|
|
|
if (write(exefile, &DbgDataCoff.dbgInfo, sizeof(DbgDataCoff.dbgInfo)) != sizeof(DbgDataCoff.dbgInfo)) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
pehdr.FileHeader.PointerToSymbolTable = lseek(exefile, 0, SEEK_CUR);
|
|
|
|
if (write(exefile, DbgDataCoff.pb, DbgDataCoff.cb) != (int) DbgDataCoff.cb) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
lfoBase = lseek(exefile, 0, SEEK_CUR);
|
|
|
|
DbgDataCoff.dbgDir.SizeOfData = DbgDataCoff.cb + sizeof(DbgDataCoff.dbgInfo);
|
|
DbgDataCoff.dbgDir.AddressOfRawData = dwVirtualAddress;
|
|
DbgDataCoff.dbgDir.PointerToRawData = dwPointerToRawData;
|
|
|
|
if (bDebugDirPresent) {
|
|
dwVirtualAddress += DbgDataCoff.dbgDir.SizeOfData;
|
|
}
|
|
dwPointerToRawData += DbgDataCoff.dbgDir.SizeOfData;
|
|
|
|
if (lseek(exefile, DbgDataCoff.lfo, SEEK_SET) == -1) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
if (write(exefile, &DbgDataCoff.dbgDir, sizeof(DbgDataCoff.dbgDir)) != sizeof(DbgDataCoff.dbgDir)) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
if ((lseek(exefile, lfoHeader, SEEK_SET) == -1) ||
|
|
(write(exefile, &pehdr, sizeof(pehdr)) != sizeof(pehdr))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
DASSERT (cSST < UINT_MAX);
|
|
|
|
// sweep module table and count number of directory entries needed
|
|
|
|
i = 0;
|
|
for (mod = ModuleList; mod != NULL; mod = mod->next) {
|
|
i++;
|
|
|
|
// publics are accumulated and written out later
|
|
|
|
if (mod->SymbolSize != 0) {
|
|
i++;
|
|
}
|
|
if (mod->SrcLnSize != 0) {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// make sure the number of subsections did not increase during the pack.
|
|
// Note that the size of the directory is actuall four larger than cSST
|
|
// to contain global publics, global symbols, global types and libraries.
|
|
|
|
DASSERT (i < cSST);
|
|
cSST = i;
|
|
i = 0;
|
|
|
|
// sweep the module list and create the directory entries that
|
|
// will be written out. Publics are accumulated and written out later
|
|
|
|
for (mod = ModuleList; mod != NULL; mod = mod->next) {
|
|
pDir[i].SubSection = sstModule;
|
|
pDir[i].iMod = mod->ModuleIndex;
|
|
pDir[i].lfo = (ulong)mod->ModulesAddr;
|
|
pDir[i].cb = mod->ModuleSize;
|
|
i++;
|
|
if (mod->SymbolSize != 0) {
|
|
pDir[i].SubSection = sstAlignSym;
|
|
pDir[i].iMod = mod->ModuleIndex;
|
|
pDir[i].cb = mod->SymbolSize;
|
|
pDir[i].lfo = (ulong)mod->SymbolsAddr;
|
|
i++;
|
|
}
|
|
if (mod->SrcLnSize != 0) {
|
|
pDir[i].SubSection = sstSrcModule;
|
|
pDir[i].iMod = mod->ModuleIndex;
|
|
pDir[i].cb = mod->SrcLnSize;
|
|
pDir[i].lfo = (ulong)mod->SrcLnAddr;
|
|
cbSrcModule += mod->SrcLnSize;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
#ifndef WINDOWS
|
|
if (logo == TRUE) {
|
|
printf ("Line/Address size = %8.ld\n", cbSrcModule);
|
|
}
|
|
#endif
|
|
// sort directory by type placing module entries first
|
|
|
|
qsort (pDir, (size_t)cSST, sizeof (OMFDirEntry), sstsort);
|
|
|
|
// round up base address
|
|
|
|
lfoBase = ((lfoBase + sizeof (ulong) - 1) / sizeof (ulong)) * sizeof (ulong);
|
|
if (lseek (exefile, lfoBase, SEEK_SET) == -1L) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
// CAUTION:
|
|
// We are doing buffering of our writes from this call
|
|
// InitWriteBuf() to nearly the end of the function when
|
|
// CloseWriteBuf() is called. Between this points there should
|
|
// be no writing to the exefile except via BWrite(). Also, it
|
|
// is assumed that all these writes that are taking place are
|
|
// consecutive writes. So there should not be any lseek between
|
|
// these two points.
|
|
|
|
InitWriteBuf (exefile);
|
|
|
|
if (!BWrite ((char *)NewSig, 8)) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
// write out all subsection tables except accumulated publics table,
|
|
// the global symbol table, the libraries table and the compacted
|
|
// types table.
|
|
|
|
filepos = BTell ();
|
|
|
|
for (i = 0; i < cSST; i++) {
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
WriteSST (i);
|
|
}
|
|
filepos = BTell ();
|
|
|
|
WritePublics (&pDir[cSST], filepos - lfoBase);
|
|
cSST++;
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
WriteGlobalSym (&pDir[cSST], filepos - lfoBase);
|
|
cSST++;
|
|
|
|
// write libraries SST
|
|
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
pDir[cSST].SubSection = sstLibraries;
|
|
pDir[cSST].iMod = (ushort) -1;
|
|
pDir[cSST].lfo = (ulong)Libraries;
|
|
pDir[cSST].cb = LibSize;
|
|
WriteSST (cSST);
|
|
|
|
// write compacted types table
|
|
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
cSST++;
|
|
pDir[cSST].SubSection = sstGlobalTypes;
|
|
pDir[cSST].iMod = (ushort) -1;
|
|
pDir[cSST].cb = WriteTypes ();
|
|
pDir[cSST].lfo = filepos - lfoBase;
|
|
#ifndef WINDOWS
|
|
if (logo == TRUE) {
|
|
printf ("Initial type size = %8.ld\n", InitialTypeInfoSize);
|
|
printf ("Compacted type size = %8.ld\n", pDir[cSST].cb);
|
|
}
|
|
#endif
|
|
|
|
// write sstSegMap table
|
|
|
|
if (SegMap != _VM_NULL) {
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
cSST++;
|
|
pDir[cSST].SubSection = sstSegMap;
|
|
pDir[cSST].iMod = (ushort) -1;
|
|
pDir[cSST].lfo = (ulong)SegMap;
|
|
pDir[cSST].cb = SegMapSize;
|
|
WriteSST (cSST);
|
|
}
|
|
|
|
// write sstSegName table
|
|
|
|
if (SegName != _VM_NULL) {
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
cSST++;
|
|
pDir[cSST].SubSection = sstSegName;
|
|
pDir[cSST].iMod = (ushort) -1;
|
|
pDir[cSST].lfo = (ulong)SegName;
|
|
pDir[cSST].cb = SegNameSize;
|
|
WriteSST (cSST);
|
|
}
|
|
|
|
filepos = BTell ();
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
cSST++;
|
|
|
|
// write out number of pDir entries and pDir entries
|
|
|
|
DirHead.cbDirHeader = sizeof (OMFDirHeader);
|
|
DirHead.cbDirEntry = sizeof (OMFDirEntry);
|
|
DirHead.cDir = cSST;
|
|
DirHead.lfoNextDir = 0;
|
|
DirHead.flags = 0;
|
|
newLfoDir = BTell () - lfoBase;
|
|
DASSERT ((newLfoDir % sizeof (ulong)) == 0);
|
|
if (!BWrite ((char *)&DirHead, sizeof (OMFDirHeader)) ||
|
|
!BWrite ((char *) pDir,
|
|
(sizeof (OMFDirEntry) * DirHead.cDir))) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
newDlfaBase = BTell () + 8 - lfoBase;
|
|
DASSERT ((newDlfaBase % sizeof (ulong)) == 0);
|
|
if ((!BWrite ((char *)NewSig, sizeof (long))) ||
|
|
(!BWrite ((char *)&newDlfaBase, sizeof (long)))) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
// Write Buffering ends.
|
|
if (!CloseWriteBuf ())
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
|
|
filepos = tell (exefile);
|
|
DASSERT ((filepos % sizeof (ulong)) == 0);
|
|
|
|
cbDbgInfo = filepos - lfoBase;
|
|
|
|
if (fLinearExe) {
|
|
filepos = (filepos + 511) & ~(512-1);
|
|
}
|
|
|
|
/*
|
|
* Grab the number of bytes in the debug info section
|
|
*/
|
|
|
|
#ifdef HACK
|
|
_chsize (exefile, filepos);
|
|
#else
|
|
lseek(exefile, filepos, SEEK_SET);
|
|
SetEndOfFile((HANDLE) _get_osfhandle(exefile));
|
|
#endif
|
|
|
|
|
|
if ((lseek (exefile, lfoBase + sizeof (long), SEEK_SET) == -1L) ||
|
|
(write (exefile, (char *)&newLfoDir, sizeof (long)) != sizeof (long))) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
/*
|
|
* If we are a PE exe file then there are two things that need to be
|
|
* done. In all cases we must rewrite the debug directory entry
|
|
* to reflect the fact that the cvinfo has been packed. Additionally
|
|
* if the file is using mapped debug information (i.e. it is part
|
|
* of a section) then we must update the appropirate header structures.
|
|
*/
|
|
|
|
if (fLinearExe) {
|
|
IMAGE_SECTION_HEADER secHdr;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
long cbDbgInfoDelta;
|
|
|
|
/*
|
|
* Update the size of the debug info in the debug header record
|
|
*/
|
|
|
|
if ((lseek(exefile, lfoDbgDirBase, SEEK_SET) == -1) ||
|
|
(read(exefile, &dbgDir, sizeof(dbgDir)) != sizeof(dbgDir))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
cbDbgInfoDelta = cbDbgInfo - dbgDir.SizeOfData;
|
|
|
|
dbgDir.SizeOfData = cbDbgInfo;
|
|
dbgDir.PointerToRawData = lfoBase;
|
|
if (bDebugDirPresent) {
|
|
dbgDir.AddressOfRawData = dwVirtualAddress;
|
|
}
|
|
|
|
if ((lseek(exefile, lfoDbgDirBase, SEEK_SET) == -1) ||
|
|
(write(exefile, &dbgDir, sizeof(dbgDir)) != sizeof(dbgDir))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
if (dbgDir.AddressOfRawData != 0) {
|
|
IMAGE_NT_HEADERS pehdr;
|
|
|
|
/*
|
|
* Update the Object section header. The fields to be changed
|
|
* are: Size of Raw Data
|
|
*/
|
|
|
|
if ((lseek(exefile, lfoObject, SEEK_SET) == -1L) ||
|
|
(read(exefile, &secHdr, sizeof(secHdr)) != sizeof(secHdr))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
secHdr.Misc.VirtualSize =
|
|
secHdr.SizeOfRawData =
|
|
filepos - secHdr.PointerToRawData;
|
|
|
|
if ((lseek(exefile, lfoObject, SEEK_SET) == -1L) ||
|
|
(write(exefile, &secHdr, sizeof(secHdr)) != sizeof(secHdr))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
if ((lseek(exefile, lfoHeader, SEEK_SET) == -1) ||
|
|
(read(exefile, &pehdr, sizeof(pehdr)) != sizeof(pehdr))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
pehdr.OptionalHeader.SizeOfInitializedData += secHdr.SizeOfRawData;
|
|
|
|
pehdr.OptionalHeader.SizeOfImage = secHdr.VirtualAddress +
|
|
secHdr.SizeOfRawData;
|
|
pehdr.OptionalHeader.SizeOfImage =
|
|
(pehdr.OptionalHeader.SizeOfImage +
|
|
pehdr.OptionalHeader.SectionAlignment - 1) &
|
|
~(pehdr.OptionalHeader.SectionAlignment - 1);
|
|
|
|
if ((lseek(exefile, lfoHeader, SEEK_SET) == -1) ||
|
|
(write(exefile, &pehdr, sizeof(pehdr)) != sizeof(pehdr))) {
|
|
ErrorExit(ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void WriteSST (ulong i)
|
|
{
|
|
char *addr;
|
|
|
|
if (pDir[i].cb) {
|
|
if ((addr = (char *) VmLoad ((_vmhnd_t)pDir[i].lfo, (size_t)pDir[i].cb))
|
|
== _VM_NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
if (!BWrite (addr, pDir[i].cb)) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
pDir[i].lfo = filepos - lfoBase;
|
|
PadCount = (int)(sizeof (ulong) - (pDir[i].cb % sizeof (ulong)));
|
|
if ((PadCount != 4) &&
|
|
(!BWrite (Zero, PadCount))) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** CheckSignature - check file signature
|
|
*
|
|
* Sig = CheckSignature ()
|
|
*
|
|
* Entry none
|
|
*
|
|
* Exit none
|
|
*
|
|
* Return SIG02 if exe has NB02 signature
|
|
* SIG05 if exe has NB05 signature
|
|
* SIG06 if exe has NB06 signature
|
|
* aborts if any other signature
|
|
*/
|
|
|
|
|
|
LOCAL ushort CheckSignature (void)
|
|
{
|
|
if (read (exefile, Signature, 4) == 4) {
|
|
if ((Signature[0] != 'N') ||
|
|
(Signature[1] != 'B') ||
|
|
(Signature[2] != '0') ||
|
|
(Signature[3] < '2') ||
|
|
(Signature[3] == '3') ||
|
|
(Signature[3] == '4') ||
|
|
(Signature[3] == '7')) {
|
|
ErrorExit (ERR_RELINK, NULL, NULL);
|
|
}
|
|
if (Signature[3] == '8') {
|
|
Warn (WARN_PACKED, NULL, NULL);
|
|
exit (0);
|
|
}
|
|
if (Signature[3] == '2') {
|
|
return (SIG02);
|
|
}
|
|
else if (Signature[3] == '5') {
|
|
return (SIG05);
|
|
}
|
|
#if defined (INCREMENTAL)
|
|
else if (Signature[3] == '6') {
|
|
return (SIG06);
|
|
}
|
|
#else
|
|
ErrorExit (ERR_RELINK, NULL, NULL);
|
|
#endif
|
|
}
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
|
|
|
|
LOCAL ulong WriteTypes ()
|
|
{
|
|
ulong FinalInfoSize;
|
|
VBlock * TypeBlock;
|
|
ulong TypeEntries = NewIndex - CV_FIRST_NONPRIM;
|
|
ulong ulZero = 0; // Used for writing pad bytes
|
|
ushort usTotal; // Size of type record including length field
|
|
ushort usPad; // Number of bytes necessary to pad type
|
|
uchar * pchType; // The type string to write
|
|
uchar * pchEnd; // The end of the global type block
|
|
ulong i = 0;
|
|
#if 0
|
|
ulong **pBuf;
|
|
ulong cnt;
|
|
#endif
|
|
OMFTypeFlags flags = {0};
|
|
|
|
flags.sig = CV_SIGNATURE_C7;
|
|
PrepareGlobalTypeTable ();
|
|
|
|
// Write the flag word and number of types to disk
|
|
if (!BWrite ((char *)&flags, sizeof (OMFTypeFlags)))
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
|
|
if (!BWrite ((char *) &TypeEntries, sizeof (ulong)))
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
|
|
FinalInfoSize = 2 * sizeof (ulong);
|
|
|
|
// Write the global type table to disk
|
|
// (Global type table gives file offset from type #
|
|
|
|
for (i=0; i<TypeEntries; i++) {
|
|
if (!BWrite((char *) &RgGType[i].pbType, sizeof(ulong))) {
|
|
ErrorExit( ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
#if 0
|
|
while (i < TypeEntries) {
|
|
cnt = min (GTYPE_INC, TypeEntries - i);
|
|
DASSERT (cnt * sizeof (ulong) <= UINT_MAX);
|
|
pBuf = (ulong **)pGType[i / GTYPE_INC];
|
|
if (!BWrite ((char *) pBuf, (size_t)(cnt * sizeof (ulong))))
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
i += cnt;
|
|
}
|
|
#endif
|
|
FinalInfoSize += sizeof (ulong) * TypeEntries;
|
|
|
|
// Write the compacted type strings in virtual memory to disk.
|
|
|
|
for (TypeBlock = VBufFirstBlock (&TypeBuf);
|
|
TypeBlock;
|
|
TypeBlock = VBufNextBlock (TypeBlock)) {
|
|
for (pchType = TypeBlock->Address,
|
|
pchEnd = TypeBlock->Address + TypeBlock->Size; pchType < pchEnd; ) {
|
|
|
|
usTotal = ((TYPPTR)pchType)->len + LNGTHSZ;
|
|
|
|
// Write the type string
|
|
if (!BWrite (pchType, usTotal)) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
|
|
// Write any padding necessary
|
|
usPad = PAD4 (usTotal);
|
|
if (usPad){
|
|
if (!BWrite ((uchar *)&ulZero, usPad)) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
// Move to the next type
|
|
pchType += usTotal;
|
|
FinalInfoSize += usTotal + usPad;
|
|
}
|
|
}
|
|
PadCount = (int)(sizeof (ulong) - (FinalInfoSize % sizeof (ulong)));
|
|
if ((PadCount != 4) &&
|
|
(!BWrite (Zero, PadCount))) {
|
|
ErrorExit (ERR_NOSPACE, NULL, NULL);
|
|
}
|
|
return (FinalInfoSize);
|
|
}
|
|
|
|
|
|
/** modsort02 - sort module table for NB02 signature files
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL int _CRTAPI1 modsort02 (const void * pv1, const void * pv2)
|
|
{
|
|
OMFDirEntry *d1 = (OMFDirEntry *) pv1;
|
|
OMFDirEntry *d2 = (OMFDirEntry *) pv2;
|
|
ushort i1;
|
|
ushort i2;
|
|
|
|
// sort by module index
|
|
|
|
if (d1->iMod < d2->iMod) {
|
|
return (-1);
|
|
}
|
|
else if (d1->iMod > d2->iMod) {
|
|
return (1);
|
|
}
|
|
|
|
// if the module indices are equal, sort into order
|
|
// module, types, symbols, publics, srclnseg
|
|
|
|
i1 = (d1->SubSection) - SSTMODULE;
|
|
i2 = (d2->SubSection) - SSTMODULE;
|
|
return (MapArray02[i1][i2]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL int _CRTAPI1 sstsort (const void * pv1, const void * pv2)
|
|
{
|
|
OMFDirEntry *d1 = (OMFDirEntry *) pv1;
|
|
OMFDirEntry *d2 = (OMFDirEntry *) pv2;
|
|
|
|
if ((d1->SubSection == sstModule) || (d2->SubSection == sstModule)) {
|
|
// we alway sort the module subsections to the top in order
|
|
// of the module index
|
|
|
|
if ((d1->SubSection == sstModule) && (d2->SubSection != sstModule)) {
|
|
return (-1);
|
|
}
|
|
else if ((d1->SubSection != sstModule) && (d2->SubSection == sstModule)) {
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
// sort by module
|
|
|
|
if (d1->iMod < d2->iMod) {
|
|
return (-1);
|
|
}
|
|
else if (d1->iMod > d2->iMod) {
|
|
return (1);
|
|
}
|
|
|
|
// if the modules are the same, sort by subsection type index
|
|
|
|
if (d1->SubSection < d2->SubSection) {
|
|
return (-1);
|
|
}
|
|
else if (d1->SubSection > d2->SubSection) {
|
|
return (1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL int _CRTAPI1 modsort (const void * pv1, const void * pv2)
|
|
{
|
|
OMFDirEntry *d1 = (OMFDirEntry *) pv1;
|
|
OMFDirEntry *d2 = (OMFDirEntry *) pv2;
|
|
ushort i1;
|
|
ushort i2;
|
|
|
|
// sort by module index
|
|
DASSERT ((d1->SubSection >= sstModule) &&
|
|
(d1->SubSection <= sstPreCompMap));
|
|
DASSERT ((d2->SubSection >= sstModule) &&
|
|
(d2->SubSection <= sstPreCompMap));
|
|
|
|
if (d1->iMod < d2->iMod) {
|
|
return (-1);
|
|
}
|
|
else if (d1->iMod > d2->iMod) {
|
|
return (1);
|
|
}
|
|
|
|
// if the module indices are equal, sort into order
|
|
// module, types, symbols, publics, srclnseg
|
|
|
|
i1 = (d1->SubSection) - sstModule;
|
|
i2 = (d2->SubSection) - sstModule;
|
|
return (MapArray[i1][i2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** ReadNB02 - read file with NB02 signature
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL void ReadNB02 (void)
|
|
{
|
|
ulong i;
|
|
DirEntry Dir;
|
|
ulong cnt;
|
|
|
|
// locate directory, read number of entries, allocate space, read
|
|
// directory entries and sort into ascending module index order
|
|
|
|
if ((read (exefile, (char *)&lfoDir, sizeof (long)) != sizeof (long)) ||
|
|
(lseek (exefile, lfoDir + lfoBase, SEEK_SET) == -1L) ||
|
|
(read (exefile, (char *)&cSST, 2) != 2)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
|
|
// reformat directory entries one entry at a time
|
|
|
|
cnt = (cSST + 6) * sizeof (OMFDirEntry);
|
|
DASSERT (cnt <= UINT_MAX);
|
|
if ((pDir = (OMFDirEntry *)malloc ((size_t)cnt)) == NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
for (i = 0; i < cSST; i++) {
|
|
if (read (exefile, (char *)&Dir, sizeof (DirEntry)) != sizeof (DirEntry)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
pDir[i].SubSection = Dir.SubSectionType;
|
|
pDir[i].iMod = Dir.ModuleIndex;
|
|
pDir[i].lfo = Dir.lfoStart;
|
|
pDir[i].cb = (ulong)Dir.Size;
|
|
}
|
|
qsort (pDir, (size_t)cSST, sizeof (OMFDirEntry), modsort02);
|
|
}
|
|
|
|
|
|
|
|
|
|
/** ReadNB05 - read file with NB05 signature
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL void ReadNB05 (bool_t fSort)
|
|
{
|
|
ulong cnt;
|
|
ushort tMod = 0;
|
|
ulong i;
|
|
|
|
// locate directory, read number of entries, allocate space, read
|
|
// directory entries and sort into ascending module index order
|
|
|
|
if ((read (exefile, (char *)&lfoDir, sizeof (long)) != sizeof (long)) ||
|
|
(lseek (exefile, lfoDir + lfoBase, SEEK_SET) == -1L) ||
|
|
(read (exefile, (char *)&DirHead, sizeof (DirHead)) !=
|
|
sizeof (OMFDirHeader))) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cSST = DirHead.cDir;
|
|
|
|
// read directory into local memory to sort, then copy to far memory buffer
|
|
|
|
cnt = (cSST + 6) * sizeof (OMFDirEntry);
|
|
DASSERT (cnt <= UINT_MAX);
|
|
if ((pDir = (OMFDirEntry *)malloc ((size_t)cnt)) == NULL) {
|
|
ErrorExit (ERR_NOMEM, NULL, NULL);
|
|
}
|
|
if (read (exefile, (char *)pDir, (size_t)(sizeof (OMFDirEntry) * cSST)) !=
|
|
(int)(sizeof (OMFDirEntry) * cSST)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
if (fSort) {
|
|
for (i = 0; i < cSST; i++) {
|
|
if ((pDir[i].iMod != 0) && (pDir[i].iMod != 0xffff)) {
|
|
if (pDir[i].iMod != tMod) {
|
|
if (pDir[i].SubSection != sstModule) {
|
|
// module entry not first, need to sort
|
|
break;
|
|
}
|
|
else {
|
|
tMod = pDir[i].iMod;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (i != cSST) {
|
|
qsort (pDir, (size_t)cSST, sizeof (OMFDirEntry), modsort);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/** ReadNB06 - read next directory from file with NB06 signature
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL void ReadNB06 (void)
|
|
{
|
|
// locate directory, read number of entries, read directory
|
|
// entries and sort into ascending module index order
|
|
|
|
if ((lseek (exefile, lfoBase + DirHead.lfoNextDir, SEEK_SET) == -1L) ||
|
|
(read (exefile, (char *)&DirHead, sizeof (DirHead)) !=
|
|
sizeof (OMFDirHeader))) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
if (cSST < DirHead.cDir) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cSST = DirHead.cDir;
|
|
|
|
// read directory into memory and then sort into ascending module order
|
|
|
|
if (read (exefile, (char *)pDir, (size_t)(sizeof (OMFDirEntry) * cSST)) !=
|
|
(int)(sizeof (OMFDirEntry) * cSST)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
qsort (pDir, (size_t)cSST, sizeof (OMFDirEntry), modsort);
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined (INCREMENTAL)
|
|
/** RestoreNB05 - restore original cvpack tables
|
|
*
|
|
* RestoreNB05 ()
|
|
*
|
|
* Entry pDir = pointer to directory table
|
|
*
|
|
* Exit cMod = number of modules
|
|
* LibrariesSize = size of sstLibraries table
|
|
* SegMap = address of read sstSegMap table if encountered
|
|
* SegMapSize = size of sstSegMap table
|
|
* SegName = address of sstSegName table if encountered
|
|
* SegNameSize = address of sstSegName table
|
|
* For other valid tables, the module table entry is built,
|
|
* the table is read into memory and the prober values established
|
|
*
|
|
* Returns none
|
|
*/
|
|
|
|
|
|
LOCAL void RestoreNB05 (void)
|
|
{
|
|
ushort i;
|
|
ushort oldMod;
|
|
PMOD pMod;
|
|
|
|
// determine number of modules in file. Remember that module indices
|
|
// of 0 and 0xffff are not for actual modules
|
|
|
|
cMod = 0;
|
|
for (i = 0; i < cSST; i++) {
|
|
if ((pDir[i].iMod != 0) && (pDir[i].iMod != 0xffff)) {
|
|
if (pDir[i].iMod != oldMod) {
|
|
oldMod = pDir[i].iMod;
|
|
pMod = GetModule (pDir[i].iMod, TRUE);
|
|
}
|
|
}
|
|
switch (pDir[i].SubSection) {
|
|
case sstModule:
|
|
cMod++;
|
|
case sstAlignSym:
|
|
case sstSrcModule:
|
|
RestoreTable (pMod, &pDir[i]);
|
|
break;
|
|
|
|
case sstGlobalTypes:
|
|
RestoreGlobalTypes (&pDir[i]);
|
|
break;
|
|
|
|
case sstGlobalSym:
|
|
RestoreGlobalSym (&pDir[i]);
|
|
break;
|
|
|
|
case sstGlobalPub:
|
|
RestoreGlobalPub(&pDir[i]);
|
|
break;
|
|
|
|
case sstLibraries:
|
|
CopyTable (&pDir[i], &Libraries, &LibSize);
|
|
break;
|
|
|
|
case sstSegMap:
|
|
CopyTable (&pDir[i], &SegMap, &SegMapSize);
|
|
break;
|
|
|
|
case sstSegName:
|
|
CopyTable (&pDir[i], &SegName, &SegNameSize);
|
|
break;
|
|
|
|
default:
|
|
ErrorExit (ERR_RELINK, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/** RestoreTable - copy table to VM
|
|
*
|
|
* RestoreTable (pMod, pDir);
|
|
*
|
|
* Entry pMod = pointer to module table entry
|
|
* pDir = address of directory entry
|
|
*
|
|
* Exit pDir->lfo = address of rewritten table
|
|
* pDir->Size = size of rewritten table
|
|
*
|
|
* Return none
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL void RestoreTable (PMOD pMod, OMFDirEntry *pDir)
|
|
{
|
|
_vmhnd_t TableAddr;
|
|
char *pTable;
|
|
|
|
if ((TableAddr = (_vmhnd_t)VmAlloc (pDir->cb)) == _VM_NULL) {
|
|
ErrorExit (ERR_NOVM, NULL, NULL);
|
|
}
|
|
if ((pTable = (char *)VmLoad (TableAddr, _VM_DIRTY)) == NULL) {
|
|
ErrorExit (ERR_NOVM, NULL, NULL);
|
|
}
|
|
lseek (exefile, pDir->lfo + lfoBase, SEEK_SET);
|
|
if (read (exefile, pTable, pDir->cb) != (int)pDir->cb) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
switch (pDir->SubSection) {
|
|
case sstModule:
|
|
pMod->ModulesAddr = (ulong)TableAddr;
|
|
pMod->ModuleSize = pDir->cb;
|
|
break;
|
|
|
|
case sstAlignSym:
|
|
pMod->SymbolSize = pDir->cb;
|
|
pMod->SymbolsAddr = (ulong)TableAddr;
|
|
break;
|
|
|
|
case sstSrcModule:
|
|
pMod->SrcLnAddr = (ulong)TableAddr;
|
|
pMod->SrcLnSize = pDir->cb;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOCAL void RestoreGlobalTypes (OMFDirEntry *pDir)
|
|
{
|
|
long cType;
|
|
long cbType;
|
|
ushort cb;
|
|
long pos;
|
|
size_t pad;
|
|
long temp;
|
|
plfClass plf;
|
|
uchar **pBuf;
|
|
TYPPTR pType;
|
|
CV_typ_t i;
|
|
|
|
if ((lseek (exefile, pDir->lfo + lfoBase, SEEK_SET) == -1L) ||
|
|
(read (exefile, (char *)&cType, sizeof (cType)) != sizeof (cType))) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cbType = pDir->cb - sizeof (ulong) * (cType + 1);
|
|
if (lseek (exefile, cType * sizeof (ulong), SEEK_CUR) == -1L) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
while (cbType > 0) {
|
|
cType--;
|
|
if (read (exefile, &cb, sizeof (cb)) != sizeof (cb)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cbType -= cb + sizeof (cb);
|
|
RestoreIndex (cb);
|
|
pos = tell (exefile);
|
|
if ((pad = (size_t)PAD4 (pos)) != 0) {
|
|
read (exefile, (char *)&temp, pad);
|
|
cbType -= pad;
|
|
}
|
|
}
|
|
for (i = CV_FIRST_NONPRIM; i < NewIndex; i++) {
|
|
pBuf = pGType[(i - CV_FIRST_NONPRIM) / GTYPE_INC];
|
|
pType = (TYPPTR)pBuf[(i - CV_FIRST_NONPRIM) % GTYPE_INC];
|
|
if ((pType->leaf == LF_CLASS) ||
|
|
(pType->leaf == LF_STRUCTURE)) {
|
|
plf = (plfClass)&(pType->leaf);
|
|
DoDerivationList (i, plf->field);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void RestoreGlobalPub (OMFDirEntry *pDir)
|
|
{
|
|
OMFSymHash hash;
|
|
long cbSym;
|
|
uchar SymBuf[512];
|
|
int cb;
|
|
|
|
if ((lseek (exefile, pDir->lfo + lfoBase, SEEK_SET) == -1L) ||
|
|
(read (exefile, (char *)&hash, sizeof (OMFSymHash)) !=
|
|
sizeof (OMFSymHash))) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cbSym = hash.cbSymbol;
|
|
while (cbSym > 0) {
|
|
if (read (exefile, &cb, sizeof (cb)) != sizeof (cb)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
*(ushort *)&SymBuf = cb;
|
|
if (read (exefile, &SymBuf[2], cb) != cb) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cbSym -= cb + sizeof (cb);
|
|
if (PackPublic ((SYMPTR)&SymBuf, HASHFUNCTION) != GPS_added) {
|
|
DASSERT (FALSE);
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL void RestoreGlobalSym (OMFDirEntry *pDir)
|
|
{
|
|
OMFSymHash hash;
|
|
long cbSym;
|
|
uchar SymBuf[512];
|
|
int cb;
|
|
|
|
if ((lseek (exefile, pDir->lfo + lfoBase, SEEK_SET) == -1L) ||
|
|
(read (exefile, (char *)&hash, sizeof (OMFSymHash)) !=
|
|
sizeof (OMFSymHash))) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cbSym = hash.cbSymbol;
|
|
while (cbSym > 0) {
|
|
if (read (exefile, &cb, sizeof (cb)) != sizeof (cb)) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
*(ushort *)&SymBuf = cb;
|
|
if (read (exefile, &SymBuf[2], cb) != cb) {
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
cbSym -= cb + sizeof (cb);
|
|
if (PackSymbol ((SYMPTR)&SymBuf, HASHFUNCTION) != GPS_added) {
|
|
DASSERT (FALSE);
|
|
ErrorExit (ERR_INVALIDEXE, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|