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.
2339 lines
59 KiB
2339 lines
59 KiB
/** loadomf.c - load
|
|
*
|
|
* Copyright <C> 1989, Microsoft Corporation
|
|
*
|
|
* Purpose:
|
|
*
|
|
* [0] - DOS3ONLY not defined if OSDEBUG is defined -- dn
|
|
*/
|
|
extern "C" {
|
|
#include "shinc.h"
|
|
}
|
|
//#pragma hdrstop // can't do this, because this file is C++
|
|
#include <share.h>
|
|
#include <io.h>
|
|
#include <dos.h>
|
|
#include <stdarg.h>
|
|
#include <fcntl.h>
|
|
|
|
#ifndef HOSTOS2
|
|
#undef WNDPROC // to avoid warning
|
|
#include <windows.h>
|
|
#endif
|
|
#if defined(OSDEBUG4X)
|
|
#include <imagehlp.h>
|
|
#endif
|
|
|
|
#ifdef CLOCK
|
|
#define SETCLOCK(v) v=clock()
|
|
#define SOURCELOAD(t) TimeArray.tSrcModLoad += t;
|
|
#define SYMLOAD(t) TimeArray.tSymLoad += t;
|
|
#define SEEKCOUNT cSeek++
|
|
static WORD cSeek = 0;
|
|
#else
|
|
#define SETCLOCK(v)
|
|
#define SOURCELOAD(t)
|
|
#define SYMLOAD(t)
|
|
#define SEEKCOUNT
|
|
#endif
|
|
#define TIMER(x)
|
|
|
|
#define cbMaxAlloc ((UINT)(0x10000-0x20))
|
|
|
|
#pragma optimize("",off)
|
|
|
|
#define EXE386
|
|
|
|
// The exe file information
|
|
|
|
static LSZ lszFName; // file name
|
|
static LONG lfaBase; // offset of directory info from end of file
|
|
static ULONG cDir; // number of directory entries
|
|
static ULONG iDir; // current directory index
|
|
static OMFDirEntry FAR *lpdss; // far pointer to directory table
|
|
static OMFDirEntry FAR *lpdssCur; // far pointer to current directory entry
|
|
static LONG lcbFilePos = 0;
|
|
static WORD csegExe = 0;
|
|
static WORD btAlign = 0; // Alignment bit
|
|
#undef LOCAL
|
|
#define LOCAL
|
|
|
|
LOCAL SHE PASCAL NEAR CheckSignature (INT , OMFSignature *);
|
|
LOCAL SHE PASCAL NEAR OLStart ( INT*, HEXG, DWORD );
|
|
LOCAL BOOL OLMkSegDir ( HLLI, int, WORD, LPSGD FAR *, LPSGE FAR * );
|
|
LOCAL HMOD FAR * PASCAL NEAR OLBuildModList ( HLLI, int );
|
|
LOCAL SHE PASCAL NEAR OLLoadModules ( INT, HLLI, HEXG );
|
|
LOCAL SHE PASCAL NEAR OLLoadTypes ( INT, HEXG );
|
|
LOCAL SHE PASCAL NEAR OLLoadSym ( HMOD );
|
|
LOCAL SHE PASCAL NEAR OLLoadSrc ( HMOD );
|
|
LOCAL SHE PASCAL NEAR OLGlobalPubs ( INT, HEXG );
|
|
LOCAL SHE PASCAL NEAR OLGlobalSym ( INT, HEXG );
|
|
LOCAL SHE PASCAL NEAR OLStaticSym ( INT, HEXG );
|
|
LOCAL SHE PASCAL NEAR OLLoadSegMap ( INT, HEXG );
|
|
LOCAL SHE PASCAL NEAR OLLoadNameIndex ( INT, HEXG );
|
|
LOCAL LPCH PASCAL NEAR OLRwrSrcMod (OMFSourceModule FAR * );
|
|
LOCAL LPB PASCAL NEAR OLLoadRawSubSec ( INT, ULONG, UINT );
|
|
LOCAL BOOL PASCAL NEAR OLLoadHashSubSec ( INT, BOOL, LPGST );
|
|
|
|
#define MAX_SEARCH_PATH_LEN 512
|
|
|
|
#if defined(HOST32)
|
|
|
|
// This is hard-coded name of the registry location where setup will put the
|
|
// pdb path. This should be changed when we have a general mechanism for the debugger
|
|
// dlls to get the IDE's root registry key name.
|
|
|
|
static TCHAR szDefaultKeyName[] =
|
|
|
|
#ifdef TARGMAC68K
|
|
"Software\\Microsoft\\Developer\\Build System\\Components\\Platforms\\Macintosh\\Directories" ;
|
|
#elif defined (TARGMACPPC)
|
|
"Software\\Microsoft\\Developer\\Build System\\Components\\Platforms\\Power Macintosh\\Directories" ;
|
|
#elif defined (TARGALPHA)
|
|
"Software\\Microsoft\\Developer\\Build System\\Components\\Platforms\\Win32 (ALPHA)\\Directories" ;
|
|
#elif defined (_MIPS_)
|
|
"Software\\Microsoft\\Developer\\Build System\\Components\\Platforms\\Win32 (MIPS)\\Directories" ;
|
|
#else // This must be x86.
|
|
"Software\\Microsoft\\Developer\\Build System\\Components\\Platforms\\Win32 (x86)\\Directories" ;
|
|
#endif
|
|
|
|
static TCHAR szPdbDirs[] = "Pdb Dirs";
|
|
|
|
TCHAR rgSearchPath[MAX_SEARCH_PATH_LEN];
|
|
BOOL fQueriedRegistry = FALSE;
|
|
|
|
LOCAL SHE NB10LoadOmf ( INT hfile, HEXG hexg );
|
|
LOCAL SHE PASCAL NEAR LoadPdb (LPEXG lpexg, INT hfile);
|
|
LOCAL SHE PASCAL NEAR NB10LoadModules ( HLLI hlliMds, HEXG hexg, ULONG* pcMods );
|
|
#endif
|
|
|
|
#if defined(OSDEBUG4X)
|
|
SHE
|
|
LoadFpo(
|
|
LPEXG lpexg,
|
|
int hfile,
|
|
PIMAGE_DEBUG_DIRECTORY dbgDir
|
|
);
|
|
|
|
SHE
|
|
LoadPdata(
|
|
LPEXG lpexg,
|
|
int hfile,
|
|
ULONG loadAddress,
|
|
ULONG imageBase,
|
|
ULONG start,
|
|
ULONG size,
|
|
BOOL fDbgFile
|
|
);
|
|
|
|
SHE
|
|
LoadOmap(
|
|
LPEXG lpexg,
|
|
int hfile,
|
|
PIMAGE_DEBUG_DIRECTORY dbgDir);
|
|
|
|
#endif
|
|
|
|
extern int com_file;
|
|
// [0] -- dn
|
|
//#if defined( DOS3 ) && !defined( WINDOWS3 ) && !defined( OSDEBUG )
|
|
//#define DOS3ONLY
|
|
//#endif // DOS3ONLY
|
|
|
|
/*
|
|
* CFile is a simple helper class which will force its file to be closed
|
|
* as soon as the CFile object is destructed.
|
|
*/
|
|
struct CFile {
|
|
INT m_hfile;
|
|
|
|
CFile() { m_hfile = -1; }
|
|
~CFile()
|
|
{
|
|
if (m_hfile != -1) {
|
|
SYClose ( m_hfile );
|
|
m_hfile = -1;
|
|
}
|
|
}
|
|
operator INT&() { return m_hfile; }
|
|
};
|
|
|
|
/** OLLoadOmf - load omf information from exe
|
|
*
|
|
* error = OLLoadOmf ( hexg )
|
|
*
|
|
* Entry hexg = handle to executable information struct
|
|
*
|
|
* Exit
|
|
*
|
|
* Returns An error code suitable for errno.
|
|
*/
|
|
|
|
|
|
extern "C"
|
|
SHE OLLoadOmf ( HEXG hexg, DWORD dllLoadAddress ) {
|
|
SHE sheRet = sheNone;
|
|
HLLI hlliMds;
|
|
HMOD hmod;
|
|
WORD cbMod = 0;
|
|
#ifdef CLOCK
|
|
clock_t tStart;
|
|
clock_t tEnd;
|
|
#endif
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
CFile hfile; // file handle
|
|
|
|
assert(hfile == -1);
|
|
|
|
if ( lpexg->fOmfLoaded ) {
|
|
#if defined(OSDEBUG4X)
|
|
// Fix up any pdata for functions that have moved.
|
|
LONG diff;
|
|
if (dllLoadAddress != 0 && (0 != (diff = (dllLoadAddress - lpexg->basePdata)))) {
|
|
lpexg->basePdata = dllLoadAddress;
|
|
if (lpexg->debugData.lpIrfe)
|
|
{
|
|
ULONG index;
|
|
ULONG cFunc = lpexg->debugData.cRtf;
|
|
PIMAGE_RUNTIME_FUNCTION_ENTRY rf = lpexg->debugData.lpIrfe;
|
|
for (index=0; index<cFunc; index++) {
|
|
rf[index].BeginAddress += diff;
|
|
rf[index].EndAddress += diff;
|
|
rf[index].PrologEndAddress += diff;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return sheNone;
|
|
}
|
|
|
|
lpexg->fOmfLoaded = TRUE;
|
|
csegExe = 0;
|
|
|
|
// open and verify the exe and read the directory entries
|
|
|
|
if ((sheRet = OLStart ( &(int&)hfile, hexg, dllLoadAddress )) != sheNone) {
|
|
lpexg->debugData.she = sheRet;
|
|
LLUnlock ( hexg );
|
|
//return ( com_file ? sheNoSymbols : sheRet );
|
|
return sheRet;
|
|
}
|
|
lpexg->debugData.she = sheRet;
|
|
#if defined(HOST32)
|
|
if (lpexg->ppdb) {
|
|
sheRet = NB10LoadOmf(hfile, hexg);
|
|
LLUnlock (hexg);
|
|
return sheRet;
|
|
}
|
|
#endif
|
|
|
|
TIMER ( tOmfLoadStart );
|
|
|
|
btAlign = (WORD)(lfaBase & 1);
|
|
|
|
lpdssCur = lpdss;
|
|
iDir = 0;
|
|
|
|
hlliMds = lpexg->hlliMds;
|
|
|
|
// we need to allocate a buffer large enough to read the largest module
|
|
// table entry
|
|
|
|
if ( ( sheRet = OLLoadModules ( hfile, hlliMds, hexg ) ) != sheNone ) {
|
|
return sheRet;
|
|
}
|
|
// move past all the sstModule sections
|
|
while ( iDir < cDir && lpdssCur->SubSection == sstModule ) {
|
|
lpdssCur++;
|
|
iDir++;
|
|
}
|
|
TIMER ( tMkModuleEnd );
|
|
if ( LLSize ( hlliMds ) == 0L ) {
|
|
// if no symbols found
|
|
MHFree ( lpdss );
|
|
LLUnlock ( hexg );
|
|
return sheNoSymbols;
|
|
}
|
|
|
|
// Set up map of modules
|
|
if (
|
|
!OLMkSegDir (
|
|
hlliMds,
|
|
(int) iDir,
|
|
lpexg->csgd = csegExe,
|
|
&lpexg->lpsgd,
|
|
&lpexg->lpsge
|
|
)
|
|
) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
lpexg->rghmod = OLBuildModList ( hlliMds, (int) iDir );
|
|
if ( lpexg->rghmod == NULL ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
// continue through the directory entries
|
|
|
|
for ( ; iDir < cDir; lpdssCur++, iDir++) {
|
|
if ( lpdssCur->iMod != 0xFFFF ) { // Must use 0xFFFF, not -1
|
|
// if the IMOD is -1 then this is one of the special
|
|
// ones and we don't want to substract 1 from it
|
|
// nor do we really want to get hmod from a find
|
|
// since it really isn't an hmod and the following
|
|
// switch statement won't use the hmod for this
|
|
// directory entry.
|
|
hmod = lpexg->rghmod [ lpdssCur->iMod - 1 ];
|
|
}
|
|
else {
|
|
hmod = 0;
|
|
}
|
|
|
|
if ( lpdssCur->cb == 0 ) {
|
|
// if nothing in this entry
|
|
continue;
|
|
}
|
|
if ( lcbFilePos != lpdssCur->lfo
|
|
&& lpdssCur->SubSection != sstAlignSym
|
|
&& lpdssCur->SubSection != sstSrcModule
|
|
) {
|
|
// seek to the current file position
|
|
SYSeek ( hfile, lpdssCur->lfo + lfaBase, SEEK_SET );
|
|
lcbFilePos = lpdssCur->lfo;
|
|
SEEKCOUNT;
|
|
}
|
|
switch ( lpdssCur->SubSection ) {
|
|
|
|
case sstSrcModule:
|
|
|
|
SETCLOCK ( tStart );
|
|
sheRet = OLLoadSrc ( hmod );
|
|
SETCLOCK ( tEnd );
|
|
SOURCELOAD ( tEnd - tStart );
|
|
break;
|
|
|
|
case sstAlignSym:
|
|
SETCLOCK ( tStart );
|
|
sheRet = OLLoadSym ( hmod );
|
|
SETCLOCK ( tEnd );
|
|
SYMLOAD ( tEnd - tStart );
|
|
break;
|
|
|
|
case sstGlobalTypes:
|
|
TIMER (tTypesStart);
|
|
sheRet = OLLoadTypes ( hfile, hexg );
|
|
TIMER (tTypesEnd);
|
|
break;
|
|
|
|
case sstGlobalPub:
|
|
TIMER (tPublicsStart);
|
|
sheRet = OLGlobalPubs ( hfile, hexg );
|
|
TIMER (tPublicsEnd);
|
|
break;
|
|
|
|
case sstGlobalSym:
|
|
TIMER (tGlobalsStart);
|
|
sheRet = OLGlobalSym ( hfile, hexg );
|
|
TIMER (tGlobalsEnd);
|
|
break;
|
|
|
|
case sstSegMap:
|
|
TIMER (tSegMapStart);
|
|
sheRet = OLLoadSegMap ( hfile, hexg );
|
|
TIMER (tSegMapEnd);
|
|
break;
|
|
|
|
case sstLibraries:
|
|
// ignore this table
|
|
break;
|
|
|
|
case sstMPC:
|
|
case sstSegName:
|
|
// until this table is implemented
|
|
break;
|
|
|
|
case sstModule:
|
|
break;
|
|
|
|
case sstFileIndex:
|
|
sheRet = OLLoadNameIndex ( hfile, hexg );
|
|
break;
|
|
|
|
case sstStaticSym:
|
|
sheRet = OLStaticSym ( hfile, hexg );
|
|
break;
|
|
|
|
default:
|
|
sheRet = sheCorruptOmf;
|
|
break;
|
|
}
|
|
|
|
// see if we ran out of ems space
|
|
|
|
if ( sheRet != sheNone) {
|
|
// if we have corrupt source line info, issue warning
|
|
if ( sheRet == sheCorruptOmf ) {
|
|
CHAR szModName[_MAX_CVPATH];
|
|
|
|
_ftcscpy ( szModName, ((LPMDS)LLLock( hmod ))->name);
|
|
LLUnlock( hmod );
|
|
#if defined (CODEVIEW)
|
|
CVMessage (WARNMSG, CORRUPTOMF, CMDWINDOW, szModName);
|
|
#endif
|
|
sheRet = sheNone;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
MHFree ( lpdss );
|
|
|
|
TIMER ( tOmfLoadEnd );
|
|
LLUnlock ( hexg );
|
|
return sheRet;
|
|
}
|
|
|
|
#if defined(HOST32) // {
|
|
LOCAL SHE NB10LoadOmf ( INT hfile, HEXG hexg ) {
|
|
SHE sheRet = sheNone;
|
|
HLLI hlliMds;
|
|
// HMOD hmod;
|
|
WORD cbMod = 0;
|
|
#ifdef CLOCK
|
|
clock_t tStart;
|
|
clock_t tEnd;
|
|
#endif
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
|
|
TIMER ( tOmfLoadStart );
|
|
|
|
btAlign = (WORD)(lfaBase & 1);
|
|
|
|
hlliMds = lpexg->hlliMds;
|
|
|
|
// we need to allocate a buffer large enough to read the largest module
|
|
// table entry
|
|
|
|
if ( ( sheRet = NB10LoadModules ( hlliMds, hexg, &iDir) ) != sheNone ) {
|
|
return sheRet;
|
|
}
|
|
TIMER ( tMkModuleEnd );
|
|
|
|
if ( LLSize ( hlliMds ) == 0L ) {
|
|
// if no symbols found
|
|
LLUnlock ( hexg );
|
|
return sheNoSymbols;
|
|
}
|
|
|
|
lpexg->rghmod = OLBuildModList ( hlliMds, (int) iDir );
|
|
if (( lpexg->rghmod == NULL )
|
|
|| !DBIOpenGlobals(lpexg->pdbi, &(lpexg->pgsiGlobs)) ||
|
|
!DBIOpenPublics(lpexg->pdbi, &(lpexg->pgsiPubs))
|
|
) {
|
|
LLUnlock ( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
if ((sheRet = OLLoadSegMap(hfile, hexg )) != sheNone ||
|
|
(sheRet = OLLoadNameIndex(hfile, hexg)) != sheNone)
|
|
{
|
|
LLUnlock ( hexg );
|
|
return sheRet;
|
|
}
|
|
|
|
#if 0 // {
|
|
// continue through the directory entries
|
|
|
|
for ( ; iDir < cDir; lpdssCur++, iDir++) {
|
|
if ( lpdssCur->iMod != 0xFFFF ) { // Must use 0xFFFF, not -1
|
|
// if the IMOD is -1 then this is one of the special
|
|
// ones and we don't want to substract 1 from it
|
|
// nor do we really want to get hmod from a find
|
|
// since it really isn't an hmod and the following
|
|
// switch statement won't use the hmod for this
|
|
// directory entry.
|
|
hmod = lpexg->rghmod [ lpdssCur->iMod - 1 ];
|
|
}
|
|
else {
|
|
hmod = 0;
|
|
}
|
|
|
|
if ( lpdssCur->cb == 0 ) {
|
|
// if nothing in this entry
|
|
continue;
|
|
}
|
|
if ( lcbFilePos != lpdssCur->lfo
|
|
&& lpdssCur->SubSection != sstAlignSym
|
|
&& lpdssCur->SubSection != sstSrcModule
|
|
) {
|
|
// seek to the current file position
|
|
SYSeek ( hfile, lpdssCur->lfo + lfaBase, SEEK_SET );
|
|
lcbFilePos = lpdssCur->lfo;
|
|
SEEKCOUNT;
|
|
}
|
|
switch ( lpdssCur->SubSection ) {
|
|
|
|
case sstSrcModule:
|
|
|
|
SETCLOCK ( tStart );
|
|
sheRet = OLLoadSrc ( hmod );
|
|
SETCLOCK ( tEnd );
|
|
SOURCELOAD ( tEnd - tStart );
|
|
break;
|
|
|
|
case sstAlignSym:
|
|
SETCLOCK ( tStart );
|
|
sheRet = OLLoadSym ( hmod );
|
|
SETCLOCK ( tEnd );
|
|
SYMLOAD ( tEnd - tStart );
|
|
break;
|
|
|
|
case sstGlobalTypes:
|
|
TIMER (tTypesStart);
|
|
sheRet = OLLoadTypes ( hfile, hexg );
|
|
TIMER (tTypesEnd);
|
|
break;
|
|
|
|
case sstGlobalPub:
|
|
TIMER (tPublicsStart);
|
|
sheRet = OLGlobalPubs ( hfile, hexg );
|
|
TIMER (tPublicsEnd);
|
|
break;
|
|
|
|
case sstGlobalSym:
|
|
TIMER (tGlobalsStart);
|
|
sheRet = OLGlobalSym ( hfile, hexg );
|
|
TIMER (tGlobalsEnd);
|
|
break;
|
|
|
|
case sstSegMap:
|
|
TIMER (tSegMapStart);
|
|
sheRet = OLLoadSegMap ( hfile, hexg );
|
|
TIMER (tSegMapEnd);
|
|
break;
|
|
|
|
case sstLibraries:
|
|
// ignore this table
|
|
break;
|
|
|
|
case sstMPC:
|
|
case sstSegName:
|
|
// until this table is implemented
|
|
break;
|
|
|
|
case sstModule:
|
|
break;
|
|
|
|
case sstFileIndex:
|
|
sheRet = OLLoadNameIndex ( hfile, hexg );
|
|
break;
|
|
|
|
case sstStaticSym:
|
|
sheRet = OLStaticSym ( hfile, hexg );
|
|
break;
|
|
|
|
default:
|
|
sheRet = sheCorruptOmf;
|
|
break;
|
|
}
|
|
|
|
// see if we ran out of ems space
|
|
|
|
if ( sheRet != sheNone) {
|
|
// if we have corrupt source line info, issue warning
|
|
if ( sheRet == sheCorruptOmf ) {
|
|
CHAR szModName[_MAX_CVPATH];
|
|
|
|
_ftcscpy ( szModName, ((LPMDS)LLLock( hmod ))->name);
|
|
LLUnlock( hmod );
|
|
#if defined (CODEVIEW)
|
|
CVMessage (WARNMSG, CORRUPTOMF, CMDWINDOW, szModName);
|
|
#endif
|
|
sheRet = sheNone;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif //}
|
|
|
|
TIMER ( tOmfLoadEnd );
|
|
LLUnlock ( hexg );
|
|
return sheRet;
|
|
}
|
|
|
|
#endif // }
|
|
|
|
#ifndef MAC
|
|
|
|
|
|
BOOL OLCheckPE ( INT hfile ) {
|
|
IMAGE_DOS_HEADER doshdr;
|
|
DWORD dwMagic;
|
|
|
|
/* Go to beginning of file and read old EXE header */
|
|
|
|
if ( SYReadFar ( hfile , ( LPB) &doshdr, sizeof ( doshdr ) ) !=
|
|
sizeof (doshdr )
|
|
) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* Go to beginning of new header, read it in and verify */
|
|
|
|
SYSeek ( hfile, doshdr.e_lfanew, SEEK_SET );
|
|
|
|
if ( SYReadFar ( hfile, (LPB) &dwMagic, sizeof ( dwMagic ) ) != sizeof ( dwMagic ) ||
|
|
dwMagic != IMAGE_NT_SIGNATURE
|
|
) {
|
|
return FALSE;
|
|
}
|
|
else {
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
/*** OLOPENDBGFILE
|
|
*
|
|
* PURPOSE:
|
|
* Helper function to open the .dbg file it the debug info from the
|
|
* original one has been stripped. We might want to make this a callback
|
|
* implemented by the kernel.
|
|
*
|
|
* INPUT:
|
|
* lpszModName -- name of the .dll being loaded
|
|
* lpszDbgName -- Buffer to which the path of the .dbg file is written
|
|
* lpVldChk -- pointer to a validity check structure which is used
|
|
* to ascertain that we have the correct .dbg file.
|
|
* OUTPUT:
|
|
* File handle if a .dbg file was opened succesufully.
|
|
* -1 otherwise
|
|
*
|
|
* EXCEPTIONS:
|
|
*
|
|
* IMPLEMENTATION:
|
|
* Look for the .dbg file in the following order
|
|
* a) The directory which the dll was found in.
|
|
* b) Along the _NT_ALT_SYMBOL_PATH environment variable
|
|
* c) Along the _NT_SYMBOL_PATH environment variable.
|
|
* d) in the %SystemRoot%\symbols\dll directory
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
__inline HFILE OLOpenDbgFile (
|
|
LSZ lpszModName,
|
|
LSZ lpszDbgName,
|
|
LPVLDCHK lpVldChk )
|
|
{
|
|
INT hFile = -1;
|
|
TCHAR szDrive[_MAX_CVDRIVE];
|
|
TCHAR szDir[_MAX_CVDIR];
|
|
TCHAR szName[_MAX_CVFNAME];
|
|
TCHAR szExt[_MAX_CVEXT];
|
|
TCHAR szSearchPath[MAX_SEARCH_PATH_LEN];
|
|
TCHAR szRelName[_MAX_CVFNAME]; // typically something like symbols\dll\foo.dbg
|
|
TCHAR szTmpDbgName[_MAX_CVPATH];
|
|
TCHAR szDbgExt[] = __T(".DBG");
|
|
TCHAR szSymbols[] = __T("SYMBOLS\\");
|
|
|
|
// We will look for the .dbg file along these environment variables in
|
|
// order.
|
|
TCHAR * rgszDbgPath[] =
|
|
{
|
|
__T("_NT_ALT_SYMBOL_PATH"),
|
|
__T("_NT_SYMBOL_PATH"),
|
|
__T("SystemRoot"),
|
|
};
|
|
|
|
|
|
TCHAR pathSep = __T('\\'); // Separates dir names within the PATH env variable
|
|
|
|
assert(lpszModName != NULL);
|
|
assert(lpszDbgName != NULL);
|
|
|
|
|
|
_tsplitpath(lpszModName, szDrive, szDir, szName, szExt);
|
|
|
|
// First look for the dbg file in the same directory as the .dll
|
|
_tmakepath(szTmpDbgName, szDrive, szDir, szName, szDbgExt);
|
|
|
|
hFile = (INT) SYOpen(szTmpDbgName);
|
|
|
|
if ( hFile == -1 )
|
|
{
|
|
TCHAR * lpszCurr = szRelName;
|
|
int i;
|
|
|
|
// create the symbols\ext\file.dbg part of the filename
|
|
|
|
_tcscpy(lpszCurr, szSymbols);
|
|
lpszCurr += _tcslen(szSymbols);
|
|
|
|
_tcscpy(lpszCurr, (szExt + 1));
|
|
lpszCurr += _tcslen(szExt + 1);
|
|
|
|
*lpszCurr++ = pathSep;
|
|
|
|
_tcscpy(lpszCurr, szName);
|
|
lpszCurr += _tcslen(szName);
|
|
|
|
_tcscpy(lpszCurr, szDbgExt);
|
|
|
|
for ( i = 0; i < sizeof(rgszDbgPath)/sizeof(rgszDbgPath[0]); i++ )
|
|
{
|
|
DWORD cbStr;
|
|
|
|
if ( (cbStr = GetEnvironmentVariable(rgszDbgPath[i], szSearchPath,
|
|
MAX_SEARCH_PATH_LEN)) != 0 )
|
|
{
|
|
if (cbStr > MAX_SEARCH_PATH_LEN)
|
|
{
|
|
assert(FALSE); // Shouldn't happen in nature.
|
|
return -1 ;
|
|
}
|
|
|
|
if ( (cbStr = SearchPath(szSearchPath, szRelName, NULL,
|
|
_MAX_CVPATH, szTmpDbgName, NULL)) != 0)
|
|
{
|
|
if ( cbStr > _MAX_CVPATH )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
hFile = SYOpen(szTmpDbgName);
|
|
|
|
if ( hFile != -1 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( hFile != -1 )
|
|
{
|
|
IMAGE_SEPARATE_DEBUG_HEADER sephdr;
|
|
|
|
// Read the header and do the validity check. Note that it we accept
|
|
// the checksum not matching if the timestamp matches. This is for
|
|
// cases where the NT setup program patches dlls at setup time.
|
|
// the file is re-checksumed but the timedatestamp on the dll and
|
|
// dbg will still be the same.
|
|
if ( SYReadFar( hFile, (LPB)&sephdr, sizeof(sephdr)) != sizeof(sephdr) ||
|
|
( sephdr.Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE ) ||
|
|
( (lpVldChk->CheckSum != sephdr.CheckSum) &&
|
|
(lpVldChk->TimeDateStamp != sephdr.TimeDateStamp)
|
|
)
|
|
)
|
|
{
|
|
SYClose(hFile);
|
|
hFile = -1;
|
|
}
|
|
else
|
|
{
|
|
_tcscpy(lpszDbgName, szTmpDbgName);
|
|
}
|
|
}
|
|
|
|
return (hFile);
|
|
}
|
|
|
|
|
|
|
|
/** OLStart - get exe debug information
|
|
*
|
|
* Purpose: To open the file specified and get the offset to the directory
|
|
* and get the base that everyone is offset from.
|
|
*
|
|
* Entry hexg = handle to exe to get info for
|
|
*
|
|
* Exit lfaBase = base offset of debug information
|
|
* cDir = count of number of directory entries
|
|
* lpdss = directory entries
|
|
*
|
|
* Returns file open status
|
|
*/
|
|
|
|
|
|
#ifdef OS2
|
|
#define cbFileMax (_MAX_CVPATH)
|
|
#else
|
|
#define cbFileMax (_MAX_CVFNAME + _MAX_CVEXT)
|
|
#endif
|
|
|
|
|
|
|
|
LOCAL SHE PASCAL NEAR OLStart ( INT* phfile, HEXG hexg, DWORD dllLoadAddress ) {
|
|
SHE sheRet;
|
|
ULONG DirSize;
|
|
OMFSignature Signature;
|
|
OMFDirHeader DirHeader;
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
IMAGE_DOS_HEADER doshdr; /* Old format MZ header */
|
|
IMAGE_FILE_HEADER PEHeader;
|
|
IMAGE_OPTIONAL_HEADER PEOptHeader;
|
|
BOOL fIsPE = FALSE;
|
|
DWORD dwMagic;
|
|
VLDCHK vldChk;
|
|
|
|
lszFName = lpexg->lszName;
|
|
|
|
if ( ( *phfile = (INT) SYOpen ( lszFName ) ) == -1 ) {
|
|
LLUnlock ( hexg );
|
|
return sheFileOpen;
|
|
}
|
|
|
|
/* Go to beginning of file and read old EXE header */
|
|
|
|
if ( SYReadFar ( *phfile, (LPB) &doshdr, sizeof (IMAGE_DOS_HEADER) ) ==
|
|
sizeof (IMAGE_DOS_HEADER)
|
|
) {
|
|
/* Go to beginning of new header, read it in and verify */
|
|
|
|
SYSeek ( *phfile, doshdr.e_lfanew, SEEK_SET );
|
|
|
|
if ( SYReadFar ( *phfile, (LPB) &dwMagic, sizeof ( dwMagic ) ) ==
|
|
sizeof ( dwMagic ) &&
|
|
( dwMagic == IMAGE_NT_SIGNATURE)
|
|
) {
|
|
fIsPE = lpexg->fIsPE = TRUE;
|
|
}
|
|
|
|
if ( fIsPE ) {
|
|
//
|
|
// If this is a PE EXE then get the PE Optional header
|
|
// so that we can scan the objects to find .rdata.
|
|
// .rdata is the section that contains the debug directory
|
|
// which contains a pointer to the debug information.
|
|
//
|
|
|
|
if (SYReadFar ( *phfile, (LPB) &PEHeader, sizeof(IMAGE_FILE_HEADER)) !=
|
|
sizeof(IMAGE_FILE_HEADER)) {
|
|
|
|
LLUnlock ( hexg );
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
if (SYReadFar ( *phfile, (LPB) &PEOptHeader, sizeof(IMAGE_OPTIONAL_HEADER)) !=
|
|
sizeof(IMAGE_OPTIONAL_HEADER)) {
|
|
|
|
LLUnlock ( hexg );
|
|
return sheCorruptOmf;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
LLUnlock ( hexg );
|
|
|
|
// now figure out if this has symbolic information
|
|
// go to the end of the file and read in the original signature
|
|
|
|
if ( fIsPE ) {
|
|
int cObjs = PEHeader.NumberOfSections;
|
|
int cDirs;
|
|
IMAGE_SECTION_HEADER secthdr, dbgsecthdr;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
ulong offDebugDir = 0;
|
|
BOOL foundDbgSect = FALSE;
|
|
|
|
vldChk.TimeDateStamp = PEHeader.TimeDateStamp;
|
|
vldChk.CheckSum = PEOptHeader.CheckSum ;
|
|
|
|
/*
|
|
** At the table of object descriptors, scan through each
|
|
** descriptor looking for the debug information
|
|
*/
|
|
#if !defined(OSDEBUG4X)
|
|
if ( PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress == 0 ) {
|
|
return sheNoSymbols;
|
|
}
|
|
#endif
|
|
/*
|
|
** If size of the optional header in the exe image is different
|
|
** from the expected size, then seek to the correct location
|
|
** just past the optional header. If the size was the expected
|
|
** size, then we don't need to seek anywhere, because we're
|
|
** already at the right place.
|
|
*/
|
|
|
|
if ( PEHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER) ) {
|
|
SYSeek (
|
|
*phfile,
|
|
PEHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER),
|
|
1
|
|
);
|
|
}
|
|
|
|
for (; cObjs != 0; cObjs -= 1) {
|
|
if ( SYReadFar ( *phfile, (LPB) §hdr, IMAGE_SIZEOF_SECTION_HEADER)
|
|
!= IMAGE_SIZEOF_SECTION_HEADER) {
|
|
return sheCorruptOmf;
|
|
}
|
|
if ((foundDbgSect == FALSE) && (PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress >=
|
|
secthdr.VirtualAddress) &&
|
|
(PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress <
|
|
secthdr.VirtualAddress + secthdr.SizeOfRawData)
|
|
) {
|
|
offDebugDir =
|
|
PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress -
|
|
secthdr.VirtualAddress;
|
|
foundDbgSect = TRUE;
|
|
dbgsecthdr = secthdr;
|
|
// break;
|
|
}
|
|
#if defined(OSDEBUG4X)
|
|
if (_ftcscmp((TCHAR*)secthdr.Name, _T(".pdata"))==0) {
|
|
sheRet = LoadPdata( lpexg,
|
|
*phfile,
|
|
dllLoadAddress,
|
|
PEOptHeader.ImageBase,
|
|
secthdr.PointerToRawData,
|
|
secthdr.SizeOfRawData,
|
|
FALSE
|
|
);
|
|
if (sheRet != sheNone) {
|
|
return sheRet;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
#if defined(OSDEBUG4X)
|
|
if ( PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress == 0 ) {
|
|
return sheNoSymbols;
|
|
}
|
|
#endif
|
|
// Note: in the first two cases we will fall through and
|
|
// look for the .dbg file.
|
|
if ( !foundDbgSect ) {
|
|
sheRet = sheCorruptOmf;
|
|
}
|
|
else if ( PEHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED ) {
|
|
sheRet = sheNoSymbols;
|
|
}
|
|
else {
|
|
/*
|
|
** Now look at the debug information header record
|
|
*/
|
|
|
|
cDirs = (USHORT) ( PEOptHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size /
|
|
sizeof ( IMAGE_DEBUG_DIRECTORY ) );
|
|
|
|
if ( cDirs == 0 ) {
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
for ( ; cDirs != 0; cDirs-- ) {
|
|
|
|
if ( SYSeek ( *phfile, dbgsecthdr.PointerToRawData + offDebugDir, SEEK_SET) == -1L) {
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
if ( SYReadFar ( *phfile, (LPB) &dbgDir, sizeof (IMAGE_DEBUG_DIRECTORY )) !=
|
|
sizeof (IMAGE_DEBUG_DIRECTORY )
|
|
) {
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
if (dbgDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW)
|
|
break;
|
|
|
|
#if defined(OSDEBUG4X)
|
|
if (dbgDir.Type == IMAGE_DEBUG_TYPE_FPO) {
|
|
sheRet = LoadFpo( lpexg, *phfile, &dbgDir );
|
|
if (sheRet != sheNone) {
|
|
return sheRet;
|
|
}
|
|
}
|
|
if (dbgDir.Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC ||
|
|
dbgDir.Type == IMAGE_DEBUG_TYPE_OMAP_TO_SRC) {
|
|
sheRet = LoadOmap( lpexg, *phfile, &dbgDir );
|
|
if (sheRet != sheNone) {
|
|
return sheRet;
|
|
}
|
|
}
|
|
#endif
|
|
offDebugDir += sizeof( IMAGE_DEBUG_DIRECTORY );
|
|
}
|
|
|
|
if ( cDirs == 0) {
|
|
return sheNoSymbols;
|
|
}
|
|
|
|
lfaBase = dbgDir.PointerToRawData;
|
|
|
|
if ( SYSeek ( *phfile, lfaBase, SEEK_SET) == -1L) {
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
sheRet = CheckSignature ( *phfile, &Signature );
|
|
}
|
|
}
|
|
else {
|
|
SYSeek ( *phfile, -((LONG)sizeof (OMFSignature)), SEEK_END);
|
|
if ((sheRet = CheckSignature ( *phfile, &Signature)) == sheNone) {
|
|
// seek to the base and read in the new key
|
|
|
|
lfaBase = SYSeek ( *phfile, -Signature.filepos, SEEK_END );
|
|
sheRet = CheckSignature ( *phfile, &Signature);
|
|
}
|
|
}
|
|
|
|
if (sheRet != sheNone) {
|
|
SHE sheSave = sheRet;
|
|
char rgchFname [ cbFileMax + 4 ];
|
|
char rgchDbgName[ cbFileMax + 4 ];
|
|
|
|
_ftcscpy ( rgchFname, lszFName );
|
|
|
|
SYClose ( *phfile );
|
|
*phfile = -1;
|
|
|
|
|
|
if ( fIsPE ) {
|
|
IMAGE_SEPARATE_DEBUG_HEADER dbgHdr;
|
|
unsigned cDirs;
|
|
unsigned cvDir;
|
|
IMAGE_DEBUG_DIRECTORY dbgDir;
|
|
IMAGE_DEBUG_DIRECTORY cvDbgDir;
|
|
|
|
if ( (*phfile = OLOpenDbgFile( rgchFname, rgchDbgName, &vldChk)) == -1 )
|
|
{
|
|
return sheSave;
|
|
}
|
|
|
|
if ( (SYSeek(*phfile, 0, SEEK_SET) == -1L ) ||
|
|
(SYReadFar(*phfile, (LPB) &dbgHdr, sizeof(dbgHdr)) != sizeof(dbgHdr)) ||
|
|
(dbgHdr.Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE)) {
|
|
SYClose(*phfile);
|
|
*phfile = -1;
|
|
return sheNoSymbols;
|
|
}
|
|
|
|
|
|
// Skip section headers and exported names
|
|
|
|
if (SYSeek(*phfile, dbgHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + dbgHdr.ExportedNamesSize, SEEK_CUR) == -1L) {
|
|
SYClose(*phfile);
|
|
*phfile = -1;
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
cDirs = dbgHdr.DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
|
|
cvDir = 0;
|
|
|
|
sheRet = sheNone;
|
|
|
|
for ( ; (cDirs != 0 && sheRet == sheNone) ; cDirs-- ) {
|
|
|
|
if ( SYReadFar ( *phfile, (LPB) &dbgDir, sizeof (IMAGE_DEBUG_DIRECTORY )) !=
|
|
sizeof (IMAGE_DEBUG_DIRECTORY )
|
|
) {
|
|
sheRet = sheCorruptOmf;
|
|
break;
|
|
}
|
|
|
|
if (dbgDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
|
|
cvDir = cDirs;
|
|
cvDbgDir = dbgDir;
|
|
}
|
|
|
|
#if defined(OSDEBUG4X)
|
|
if (dbgDir.Type == IMAGE_DEBUG_TYPE_FPO) {
|
|
sheRet = LoadFpo( lpexg, *phfile, &dbgDir );
|
|
}
|
|
|
|
if (dbgDir.Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC ||
|
|
dbgDir.Type == IMAGE_DEBUG_TYPE_OMAP_TO_SRC) {
|
|
|
|
sheRet = LoadOmap( lpexg, *phfile, &dbgDir );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( cvDir == 0 || sheRet != sheNone) {
|
|
SYClose(*phfile);
|
|
*phfile = -1;
|
|
return sheNoSymbols;
|
|
}
|
|
|
|
lfaBase = cvDbgDir.PointerToRawData;
|
|
|
|
if ( SYSeek ( *phfile, lfaBase, SEEK_SET) == -1L) {
|
|
SYClose(*phfile);
|
|
*phfile = -1;
|
|
return sheCorruptOmf;
|
|
}
|
|
|
|
sheRet = CheckSignature ( *phfile, &Signature );
|
|
}
|
|
else {
|
|
int cchFname = _ftcslen ( lszFName ) - 1;
|
|
int iDot = 0;
|
|
ulong ulDbg = 'D' + 'B' * 0x100 + 'G' * 0x10000;
|
|
|
|
// The .exe file didn't have the correct signature, so
|
|
// try opening the debug file. We can assume full path
|
|
// with .extension at this point.
|
|
|
|
iDot = cchFname;
|
|
while ( iDot > 0 && rgchFname [ iDot ] != '.' ) {
|
|
if (
|
|
rgchFname [ iDot ] == '\\' ||
|
|
rgchFname [ iDot ] == '/' ||
|
|
rgchFname [ iDot ] == ':'
|
|
) {
|
|
iDot = 0;
|
|
break;
|
|
}
|
|
|
|
iDot -= 1;
|
|
|
|
|
|
}
|
|
|
|
if ( iDot == 0 ) {
|
|
iDot = cchFname;
|
|
rgchFname [ iDot ] = '.';
|
|
}
|
|
|
|
|
|
*( (ulong FAR *) &rgchFname [ iDot + 1 ] ) = ulDbg;
|
|
|
|
_ftcscpy(rgchDbgName, rgchFname);
|
|
|
|
if ( ( *phfile = (INT) SYOpen ( rgchFname ) ) == -1 ) {
|
|
return sheSave;
|
|
}
|
|
|
|
SYSeek ( *phfile, -((LONG)sizeof (OMFSignature)), SEEK_END);
|
|
if ((sheRet = CheckSignature ( *phfile, &Signature)) == sheNone) {
|
|
// seek to the base and read in the new key
|
|
|
|
lfaBase = SYSeek ( *phfile, -Signature.filepos, SEEK_END );
|
|
sheRet = CheckSignature ( *phfile, &Signature);
|
|
}
|
|
}
|
|
|
|
if ( sheRet != sheNone ) {
|
|
SYClose(*phfile);
|
|
*phfile = -1;
|
|
return sheRet;
|
|
}
|
|
|
|
// DO NOT free the memory pointed to by lszFName even though we are
|
|
// overwriting the ptr here. lpexg->lszName points to the same memory.
|
|
|
|
if ( ! ( lszFName = (LSZ) MHAlloc ( _ftcslen ( rgchDbgName ) + 1 ) ) ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
_ftcscpy ( lszFName, rgchDbgName );
|
|
lpexg->lszDebug = lszFName;
|
|
}
|
|
|
|
#if defined(HOST32)
|
|
// Read the Pdb File Name if NB10
|
|
if ((Signature.Signature[2] == '1') && (Signature.Signature[3] == '0')) {
|
|
return LoadPdb(lpexg, *phfile);
|
|
}
|
|
|
|
lpexg->ppdb = NULL;
|
|
lpexg->ptpi = NULL;
|
|
lpexg->pdbi = NULL;
|
|
#endif
|
|
// seek to the directory and read the number of directory entries
|
|
// and the directory entries
|
|
|
|
SYSeek ( *phfile, Signature.filepos + lfaBase, SEEK_SET);
|
|
SYReadFar ( *phfile, (LPB) &DirHeader, sizeof ( DirHeader ) );
|
|
cDir = DirHeader.cDir;
|
|
|
|
// check to make sure somebody has not messed with omf structure
|
|
|
|
assert (DirHeader.cbDirEntry == sizeof (OMFDirEntry));
|
|
DirSize = DirHeader.cDir * sizeof (OMFDirEntry);
|
|
assert ( DirSize < cbMaxAlloc );
|
|
if (!( lpdss = (OMFDirEntry FAR *) MHAlloc ( (size_t)(DirSize)))) {
|
|
return sheOutOfMemory;
|
|
}
|
|
SYReadFar ( *phfile, (LPB) lpdss, DirSize);
|
|
return sheNone;
|
|
}
|
|
|
|
#if defined(OSDEBUG4X)
|
|
|
|
SHE
|
|
LoadFpo(
|
|
LPEXG lpexg,
|
|
int hfile,
|
|
PIMAGE_DEBUG_DIRECTORY dbgDir
|
|
)
|
|
{
|
|
LONG fpos;
|
|
|
|
fpos = SYSeek( hfile, 0, SEEK_CUR );
|
|
|
|
SYSeek( hfile, dbgDir->PointerToRawData, SEEK_SET );
|
|
if (!(lpexg->debugData.lpFpo = (PFPO_DATA) MHAlloc( dbgDir->SizeOfData )))
|
|
return sheOutOfMemory;
|
|
SYReadFar( hfile, (LPB) lpexg->debugData.lpFpo, dbgDir->SizeOfData );
|
|
lpexg->debugData.cRtf = dbgDir->SizeOfData / sizeof(FPO_DATA);
|
|
|
|
SYSeek( hfile, fpos, SEEK_SET );
|
|
|
|
return sheNone;
|
|
}
|
|
|
|
SHE
|
|
LoadOmap(
|
|
LPEXG lpexg,
|
|
int hfile,
|
|
PIMAGE_DEBUG_DIRECTORY dbgDir
|
|
)
|
|
{
|
|
LONG fpos;
|
|
LPVOID lpOmap;
|
|
DWORD dwCount;
|
|
|
|
fpos = SYSeek( hfile, 0, SEEK_CUR );
|
|
|
|
SYSeek( hfile, dbgDir->PointerToRawData, SEEK_SET );
|
|
if (!(lpOmap = (LPVOID) MHAlloc( dbgDir->SizeOfData )))
|
|
return sheOutOfMemory;
|
|
SYReadFar( hfile, (LPB) lpOmap, dbgDir->SizeOfData );
|
|
|
|
dwCount = dbgDir->SizeOfData / sizeof(OMAP);
|
|
|
|
SYSeek( hfile, fpos, SEEK_SET );
|
|
|
|
if (dbgDir->Type == IMAGE_DEBUG_TYPE_OMAP_FROM_SRC) {
|
|
lpexg->debugData.lpOmapFrom = (LPOMAP) lpOmap;
|
|
lpexg->debugData.cOmapFrom = dwCount;
|
|
} else
|
|
if (dbgDir->Type == IMAGE_DEBUG_TYPE_OMAP_TO_SRC) {
|
|
lpexg->debugData.lpOmapTo = (LPOMAP) lpOmap;
|
|
lpexg->debugData.cOmapTo = dwCount;
|
|
} else {
|
|
MHFree( lpOmap );
|
|
}
|
|
return sheNone;
|
|
}
|
|
|
|
SHE
|
|
LoadPdata(
|
|
LPEXG lpexg,
|
|
int hfile,
|
|
ULONG loadAddress,
|
|
ULONG imageBase,
|
|
ULONG start,
|
|
ULONG size,
|
|
BOOL fDbgFile
|
|
)
|
|
{
|
|
ULONG cFunc;
|
|
LONG diff;
|
|
ULONG index;
|
|
PIMAGE_RUNTIME_FUNCTION_ENTRY rf;
|
|
PIMAGE_RUNTIME_FUNCTION_ENTRY tf;
|
|
PIMAGE_FUNCTION_ENTRY dbgRf;
|
|
LONG fpos;
|
|
|
|
|
|
if (loadAddress == 0) {
|
|
lpexg->basePdata = imageBase;
|
|
diff = 0;
|
|
}
|
|
else {
|
|
diff = loadAddress - imageBase;
|
|
lpexg->basePdata = loadAddress;
|
|
}
|
|
if (fDbgFile) {
|
|
cFunc = size / sizeof(IMAGE_FUNCTION_ENTRY);
|
|
} else {
|
|
cFunc = size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
|
|
}
|
|
|
|
lpexg->debugData.lpFpo = NULL;
|
|
lpexg->debugData.lpIrfe= NULL;
|
|
lpexg->debugData.cRtf = 0;
|
|
|
|
if (size == 0) {
|
|
return sheNone; // REVIEW: is this an error condition? I don't know
|
|
}
|
|
|
|
fpos = SYSeek( hfile, 0, SEEK_CUR );
|
|
SYSeek( hfile, start, SEEK_SET );
|
|
|
|
if (fDbgFile) {
|
|
if (!(dbgRf = (PIMAGE_FUNCTION_ENTRY) MHAlloc(size)))
|
|
return sheOutOfMemory;
|
|
SYReadFar( hfile, (LPB)dbgRf, size );
|
|
size = cFunc * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
|
|
if (!(tf = rf = (PIMAGE_RUNTIME_FUNCTION_ENTRY) MHAlloc(size))) {
|
|
MHFree( dbgRf );
|
|
return sheOutOfMemory;
|
|
}
|
|
for(index=0; index<cFunc; index++) {
|
|
rf[index].BeginAddress = dbgRf[index].StartingAddress + loadAddress;
|
|
rf[index].EndAddress = dbgRf[index].EndingAddress + loadAddress;
|
|
rf[index].PrologEndAddress = dbgRf[index].EndOfPrologue + loadAddress;
|
|
}
|
|
MHFree( dbgRf );
|
|
|
|
} else {
|
|
if (!(tf = rf = (PIMAGE_RUNTIME_FUNCTION_ENTRY) MHAlloc(size)))
|
|
return sheOutOfMemory;
|
|
SYReadFar( hfile, (LPB)rf, size );
|
|
}
|
|
|
|
|
|
//
|
|
// Find the start of the padded page (end of the real data)
|
|
//
|
|
for(index=0; index<cFunc && tf->BeginAddress; tf++,index++) {
|
|
;
|
|
}
|
|
|
|
if (index < cFunc) {
|
|
cFunc = index;
|
|
size = index * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
|
|
if (!(rf = (PIMAGE_RUNTIME_FUNCTION_ENTRY) MHRealloc(rf, size)))
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
if (diff != 0) {
|
|
for (index=0; index<cFunc; index++) {
|
|
rf[index].BeginAddress += diff;
|
|
rf[index].EndAddress += diff;
|
|
rf[index].PrologEndAddress += diff;
|
|
}
|
|
}
|
|
|
|
lpexg->debugData.lpIrfe = rf;
|
|
lpexg->debugData.cRtf = cFunc;
|
|
|
|
SYSeek( hfile, fpos, SEEK_SET );
|
|
return sheNone;
|
|
}
|
|
#endif
|
|
|
|
/** CheckSignature - check file signature
|
|
*
|
|
* she = CheckSignature (INT hfile, OMFSignature *pSig)
|
|
*
|
|
* Entry hfile = handle to file
|
|
* pSig = location where signature should be written to
|
|
*
|
|
* Exit none
|
|
*
|
|
* Return sheNoSymbols if exe has no signature
|
|
* sheMustRelink if exe has NB00 to NB06 or NB07 (qcwin) signature
|
|
* sheNotPacked if exe has NB08 signature
|
|
* sheNone if exe has NB09 signature
|
|
* sheFutureSymbols if exe has NB10 to NB99 signature
|
|
*/
|
|
|
|
#define uCurSig 9
|
|
|
|
LOCAL SHE NEAR PASCAL CheckSignature ( INT hfile, OMFSignature *pSig ) {
|
|
|
|
UINT uSig;
|
|
|
|
if ( (SYReadFar ( hfile, (LPB) pSig, sizeof ( *pSig ) ) != sizeof ( *pSig )) ||
|
|
(pSig->Signature[0] != 'N') ||
|
|
(pSig->Signature[1] != 'B') ||
|
|
(!isdigit(pSig->Signature[2])) ||
|
|
(!isdigit(pSig->Signature[3])) ) {
|
|
return sheNoSymbols;
|
|
}
|
|
|
|
uSig = ((pSig->Signature[2] - '0') * 10) + (pSig->Signature[3] - '0');
|
|
|
|
if (uSig < 5 || uSig == 7) {
|
|
return sheMustRelink;
|
|
}
|
|
else if (uSig < uCurSig) {
|
|
return sheNotPacked;
|
|
}
|
|
#if defined(HOST32)
|
|
else if (uSig <= (uCurSig + 1)) {
|
|
return sheNone;
|
|
}
|
|
#else
|
|
// we will not handle NB10 for 16 bit hosting
|
|
else if (uSig <= uCurSig) {
|
|
return sheNone;
|
|
}
|
|
#endif
|
|
else {
|
|
return sheFutureSymbols;
|
|
}
|
|
}
|
|
|
|
|
|
/** OLMkSegDir - MakeSegment directory
|
|
*
|
|
*
|
|
* Entry
|
|
* hlliMds = handle to MoDule Struct list
|
|
*
|
|
* Exit
|
|
*
|
|
* Returns non-zero for success
|
|
*
|
|
*/
|
|
|
|
//ragma optimize ( "", off )
|
|
BOOL OLMkSegDir (
|
|
HLLI hlliMds,
|
|
int cmds,
|
|
WORD csgd,
|
|
LPSGD FAR *lplpsgd,
|
|
LPSGE FAR *lplpsge
|
|
) {
|
|
LPSGD lpsgd;
|
|
SGE _HUGE_ * hpsge = NULL;
|
|
int FAR *lpisge;
|
|
int imds = 0;
|
|
HMOD hmod = hmodNull;
|
|
int csgc = 0;
|
|
int isge = 0;
|
|
int isgd = 0;
|
|
|
|
if ( !( lpsgd = (LPSGD) MHAlloc ( csgd * sizeof ( SGD ) ) ) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !( lpisge = (int FAR *) MHAlloc ( csgd * sizeof ( int ) ) ) ) {
|
|
MHFree( lpsgd );
|
|
return FALSE;
|
|
}
|
|
|
|
MEMSET ( lpsgd, 0, csgd * sizeof ( SGD ) );
|
|
MEMSET ( lpisge, 0, csgd * sizeof ( int ) );
|
|
|
|
// Count the number of contributers per segment
|
|
|
|
while ( ( hmod = LLNext ( hlliMds, hmod ) ) != hmodNull ) {
|
|
LPMDS lpmds = (LPMDS) LLLock ( hmod );
|
|
int cseg = lpmds->csgc;
|
|
int iseg = 0;
|
|
int isegT = 0;
|
|
|
|
for ( iseg = 0; iseg < cseg; iseg++ ) {
|
|
isegT = lpmds->lpsgc [ iseg ].seg;
|
|
if ( isegT != 0 ) {
|
|
lpsgd [ isegT - 1 ].csge += 1;
|
|
csgc += 1;
|
|
}
|
|
}
|
|
LLUnlock( hmod );
|
|
}
|
|
|
|
// Allocate subtable for each all segments
|
|
|
|
#ifdef HOST32
|
|
hpsge = (SGE _HUGE_ *) MHAlloc ( csgc * sizeof ( SGE ) );
|
|
#else // HOST32
|
|
hpsge = (SGE _HUGE_ *) MHAllocHuge ( csgc, sizeof ( SGE ) );
|
|
#endif // HOST32
|
|
|
|
if ( !hpsge ) {
|
|
MHFree ( lpsgd );
|
|
MHFree ( lpisge );
|
|
return FALSE;
|
|
}
|
|
|
|
// Set up sgd's with pointers into appropriate places in the sge table
|
|
|
|
isge = 0;
|
|
for ( isgd = 0; isgd < (int) csgd; isgd++ ) {
|
|
lpsgd [ isgd ].lpsge = (LPSGE)( hpsge + isge );
|
|
isge += lpsgd [ isgd ].csge;
|
|
}
|
|
|
|
// Fill in the sge table
|
|
|
|
hmod = hmodNull;
|
|
while ( ( hmod = LLNext ( hlliMds, hmod ) ) != hmodNull ) {
|
|
LPMDS lpmds = (LPMDS) LLLock ( hmod );
|
|
int cseg = lpmds->csgc;
|
|
int iseg = 0;
|
|
|
|
for ( iseg = 0; iseg < cseg; iseg++ ) {
|
|
int isgeT = lpmds->lpsgc [ iseg ].seg - 1;
|
|
|
|
if ( isgeT != -1 ) {
|
|
lpsgd [ isgeT ].lpsge [ lpisge [ isgeT ] ].sgc =
|
|
lpmds->lpsgc [ iseg ];
|
|
lpsgd [ isgeT ].lpsge [ lpisge [ isgeT ] ].hmod = hmod;
|
|
lpisge [ isgeT ] += 1;
|
|
}
|
|
}
|
|
LLUnlock( hmod );
|
|
}
|
|
|
|
MHFree ( lpisge );
|
|
|
|
*lplpsge = (LPSGE)hpsge;
|
|
*lplpsgd = lpsgd;
|
|
|
|
return TRUE;
|
|
}
|
|
//ragma optimize ( "", on )
|
|
|
|
LOCAL HMOD FAR * PASCAL NEAR OLBuildModList ( HLLI hlliMds, int cmds ) {
|
|
int imds = 0;
|
|
HMOD hmod = hmodNull;
|
|
HMOD FAR *rghmod = (HMOD FAR *) MHAlloc ( sizeof ( HMOD ) * cmds );
|
|
|
|
if ( !rghmod ) {
|
|
return NULL;
|
|
}
|
|
|
|
while ( ( hmod = LLNext ( hlliMds, hmod ) ) != hmodNull ) {
|
|
rghmod [ imds ] = hmod;
|
|
imds += 1;
|
|
}
|
|
|
|
return rghmod;
|
|
}
|
|
|
|
|
|
#define cbModBlock 0x4000
|
|
LOCAL SHE PASCAL NEAR OLLoadModules ( INT hfile, HLLI hlliMds, HEXG hexg ) {
|
|
LPB lpbRaw;
|
|
WORD idss = 0;
|
|
WORD idssBase = 0;
|
|
ULONG cbLoaded = 0;
|
|
OMFDirEntry FAR *lpdssBase = lpdssCur;
|
|
LPEXG lpexg = NULL;
|
|
DWORD cbBlockSize = cbModBlock;
|
|
|
|
lpexg = (LPEXG) LLLock ( hexg );
|
|
|
|
lpbRaw = (LPB) MHAlloc ( cbBlockSize );
|
|
if ( lpbRaw == NULL ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
SYSeek ( hfile, lfaBase + lpdssCur->lfo, SEEK_SET );
|
|
|
|
while (
|
|
idss < cDir &&
|
|
lpdssCur->SubSection == sstModule
|
|
) {
|
|
DWORD cb = 0;
|
|
DWORD cbBase = 0;
|
|
|
|
if (lpdssCur->cb + 3 > cbBlockSize) {
|
|
cbBlockSize = lpdssCur->cb + 3;
|
|
lpbRaw = (LPB) MHRealloc( lpbRaw, cbBlockSize);
|
|
if ( lpbRaw == NULL ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
}
|
|
|
|
while (
|
|
idss < cDir &&
|
|
lpdssCur->SubSection == sstModule &&
|
|
cb + lpdssCur->cb < cbModBlock
|
|
) {
|
|
cb += ( lpdssCur->cb + 3) & ~3;
|
|
lpdssCur++;
|
|
idss++;
|
|
}
|
|
|
|
SYReadFar ( hfile, lpbRaw, cb );
|
|
|
|
while ( idssBase < idss ) {
|
|
OMFModule FAR *lpmod = (OMFModule FAR *) (lpbRaw + cbBase);
|
|
LSZ lszModName = NULL;
|
|
LPMDS lpmds = NULL;
|
|
HMOD hmod = hmodNull;
|
|
LPCH lpchName = NULL;
|
|
WORD cbName = 0;
|
|
|
|
|
|
// get the module name
|
|
|
|
lpchName =
|
|
(LPCH) lpmod +
|
|
offsetof (OMFModule, SegInfo) +
|
|
sizeof (OMFSegDesc) * lpmod->cSeg;
|
|
cbName = *((LPB)lpchName);
|
|
lpchName++;
|
|
if ( !( lszModName = (LSZ) MHAlloc ( cbName + 1 ) ) ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
MEMMOVE ( lszModName, lpchName, cbName );
|
|
*(lszModName + cbName) = 0;
|
|
|
|
if ( (hmod = LLCreate ( hlliMds ) ) == 0 ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
lpmds = (LPMDS) LLLock ( hmod );
|
|
|
|
lpmds->imds = lpdssBase->iMod;
|
|
lpmds->hexg = hexg;
|
|
lpmds->name = lszModName;
|
|
|
|
// step thru making the module entries
|
|
|
|
lpmds->csgc = lpmod->cSeg;
|
|
if ( lpmds->lpsgc = (LPSGC) MHAlloc ( lpmod->cSeg * sizeof ( SGC ) ) ) {
|
|
USHORT iseg;
|
|
|
|
for ( iseg = 0; iseg < lpmod->cSeg; iseg++ ) {
|
|
if ( lpmod->SegInfo[iseg].Seg > csegExe ) {
|
|
csegExe = lpmod->SegInfo[iseg].Seg;
|
|
}
|
|
(lpmds->lpsgc + iseg)->seg = lpmod->SegInfo[iseg].Seg;
|
|
(lpmds->lpsgc + iseg)->off = lpmod->SegInfo[iseg].Off;
|
|
(lpmds->lpsgc + iseg)->cb = lpmod->SegInfo[iseg].cbSeg;
|
|
}
|
|
}
|
|
else {
|
|
LLUnlock ( hmod );
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
LLUnlock ( hmod );
|
|
LLAdd ( hlliMds, hmod );
|
|
|
|
cbBase += ( lpdssBase->cb + 3) & ~3;;
|
|
|
|
lpdssBase++;
|
|
idssBase++;
|
|
}
|
|
|
|
cbLoaded += cb;
|
|
}
|
|
MHFree ( lpbRaw );
|
|
|
|
iDir = idss;
|
|
|
|
return sheNone;
|
|
}
|
|
|
|
#if defined(HOST32) //{
|
|
LOCAL SHE PASCAL NEAR NB10LoadModules ( HLLI hlliMds, HEXG hexg, ULONG* pcMods )
|
|
{
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
Mod* pmod = NULL;
|
|
|
|
*pcMods = 0;
|
|
|
|
while (DBIQueryNextMod(lpexg->pdbi, pmod, &pmod) && pmod) {
|
|
HMOD hmod = hmodNull;
|
|
LPMDS lpmds;
|
|
CB cbName;
|
|
if ((hmod = LLCreate (hlliMds)) == 0) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
lpmds = (LPMDS) LLLock ( hmod );
|
|
memset(lpmds, 0, sizeof(MDS));
|
|
|
|
if (!ModQueryImod(pmod, &(lpmds->imds)))
|
|
return sheCorruptOmf;
|
|
// update iDir to be Max of the Imods found
|
|
if (lpmds->imds > *pcMods)
|
|
*pcMods = lpmds->imds;
|
|
lpmds->pmod = pmod;
|
|
lpmds->hexg = hexg;
|
|
lpmds->name = NULL;
|
|
|
|
if (!ModQueryName(pmod, lpmds->name, &cbName))
|
|
return sheCorruptOmf;
|
|
lpmds->name = (LSZ) MHAlloc(cbName);
|
|
if (!lpmds->name)
|
|
return sheOutOfMemory;
|
|
if (!ModQueryName(pmod, lpmds->name, &cbName))
|
|
return sheCorruptOmf;
|
|
if (!ModSetPvClient(pmod, hmod))
|
|
return sheCorruptOmf;
|
|
|
|
LLUnlock ( hmod );
|
|
LLAdd ( hlliMds, hmod );
|
|
|
|
}
|
|
return sheNone;
|
|
}
|
|
#endif // }
|
|
|
|
LOCAL BOOL OLLoadHashTable (
|
|
INT hfile,
|
|
ULONG lfo,
|
|
ULONG cbTable,
|
|
LPSHT lpsht,
|
|
BOOL fDWordChains
|
|
) {
|
|
WORD ccib = 0;
|
|
LPUL rgib = NULL;
|
|
LPUL rgcib = NULL;
|
|
ULONG cbHeader = 0;
|
|
|
|
MEMSET ( lpsht, 0, sizeof ( SHT ) );
|
|
|
|
SYReadFar ( hfile, (LPB) &ccib, sizeof ( ccib ) );
|
|
SYSeek ( hfile, 2, SEEK_CUR );
|
|
cbHeader = sizeof ( ccib ) + sizeof ( WORD );
|
|
|
|
// Read the segment table offsets and counts
|
|
|
|
if ( !( rgib = (LPUL) MHAlloc ( ccib * sizeof ( ULONG ) ) ) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !( rgcib = (LPUL) MHAlloc ( ccib * sizeof ( ULONG ) ) ) ) {
|
|
MHFree( rgib );
|
|
return FALSE;
|
|
}
|
|
|
|
SYReadFar ( hfile, (LPB) rgib, ccib * sizeof ( ULONG ) );
|
|
cbHeader += ccib * sizeof ( ULONG );
|
|
|
|
if ( fDWordChains ) {
|
|
SYReadFar ( hfile, (LPB) rgcib, ccib * sizeof ( ULONG ) );
|
|
cbHeader += ccib * sizeof ( ULONG );
|
|
}
|
|
else {
|
|
LPW rgw = (LPW) rgcib;
|
|
WORD icib = ccib;
|
|
|
|
SYReadFar ( hfile, (LPB) rgcib, ccib * sizeof ( WORD ) );
|
|
cbHeader += ccib * sizeof ( WORD );
|
|
|
|
while ( icib > 0 ) {
|
|
icib -= 1;
|
|
rgcib [ icib ] = (ULONG) rgw [ icib ];
|
|
}
|
|
}
|
|
|
|
lcbFilePos += cbHeader;
|
|
cbTable -= cbHeader;
|
|
|
|
lpsht->ccib = ccib;
|
|
lpsht->rgib = rgib;
|
|
lpsht->rgcib = rgcib;
|
|
lpsht->lpalm = BuildALM (
|
|
FALSE,
|
|
btAlign,
|
|
lszFName,
|
|
lfaBase + lpdssCur->lfo + lfo + cbHeader,
|
|
cbTable,
|
|
cbAlign
|
|
);
|
|
|
|
if ( lpsht->lpalm == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
SYSeek ( hfile, cbTable, SEEK_CUR );
|
|
lcbFilePos += cbTable;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LOCAL BOOL PASCAL NEAR OLLoadHashSubSec ( INT hfile, BOOL fSeq, LPGST lpgst ) {
|
|
LPB lpbTbl = NULL;
|
|
OMFSymHash hash;
|
|
ULONG cbSymbol;
|
|
BOOL fRet = TRUE;
|
|
LPSHT lpshtName = &lpgst->shtName;
|
|
LPSHT lpshtAddr = &lpgst->shtAddr;
|
|
|
|
|
|
MEMSET ( lpshtAddr, 0, sizeof ( SHT ) );
|
|
|
|
SYReadFar ( hfile, (LPB)&hash, sizeof (OMFSymHash) );
|
|
lcbFilePos += sizeof (OMFSymHash);
|
|
|
|
cbSymbol = hash.cbSymbol;
|
|
|
|
lpgst->lpalm = BuildALM (
|
|
fSeq,
|
|
btAlign,
|
|
lszFName,
|
|
lfaBase + lpdssCur->lfo + sizeof ( OMFSymHash ),
|
|
cbSymbol,
|
|
cbAlign
|
|
);
|
|
|
|
if ( lpgst->lpalm == NULL ) {
|
|
return FALSE;
|
|
}
|
|
|
|
SYSeek ( hfile, cbSymbol, SEEK_CUR );
|
|
lcbFilePos += cbSymbol;
|
|
|
|
if ( hash.symhash == 6 || hash.symhash == 10 ) {
|
|
fRet = OLLoadHashTable (
|
|
hfile,
|
|
sizeof ( OMFSymHash ) + cbSymbol,
|
|
hash.cbHSym,
|
|
&lpgst->shtName,
|
|
hash.symhash == 10
|
|
);
|
|
lpgst->shtName.HashIndex = hash.symhash;
|
|
}
|
|
|
|
if ( hash.addrhash == 8 || hash.addrhash == 12 ) {
|
|
fRet = OLLoadHashTable (
|
|
hfile,
|
|
sizeof ( OMFSymHash ) + cbSymbol + hash.cbHSym,
|
|
hash.cbHAddr,
|
|
&lpgst->shtAddr,
|
|
hash.addrhash == 12
|
|
);
|
|
lpgst->shtAddr.HashIndex = hash.addrhash;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
/** OLLoadRawSubSec
|
|
*
|
|
* Purpose: To load into far space the sst entry without any translation
|
|
*
|
|
* Input:
|
|
*
|
|
* Output:
|
|
* Returns: - A pointer to the far space
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL LPB PASCAL NEAR OLLoadRawSubSec ( INT hfile, ULONG lcbOff, UINT cbMax ) {
|
|
LPB lpbTbl = NULL;
|
|
ULONG lcb = lpdssCur->cb;
|
|
UINT cb = (UINT) min( (ULONG) cbMax, (lcb - lcbOff) );
|
|
|
|
// load the table into far space
|
|
if ( lpbTbl = (LPB) MHAlloc ( cb ) ) {
|
|
SYReadFar ( hfile, lpbTbl, cb );
|
|
lcbFilePos += cb;
|
|
}
|
|
|
|
return lpbTbl;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** OLLoadTypes - load compacted types table
|
|
*
|
|
*
|
|
* Input:
|
|
* hlliMds - handle to module list
|
|
* hmod - handle to current module
|
|
*
|
|
* Output:
|
|
* Returns: - An error code
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
|
|
#define cTypeIndChunk 0x2000
|
|
#define cbTypeIndChunk ( cTypeIndChunk * sizeof ( ULONG ) )
|
|
|
|
LOCAL SHE PASCAL NEAR OLLoadTypes ( INT hfile, HEXG hexg ) {
|
|
OMFTypeFlags flags;
|
|
ULONG cType = 0;
|
|
LONG _HUGE_ *rgitd = NULL;
|
|
LPEXG lpexg = NULL;
|
|
ULONG ibType = 0;
|
|
ULONG iType = 0;
|
|
#ifndef HOST32
|
|
LPB lpb;
|
|
ULONG FAR * lpul;
|
|
#endif // !HOST32
|
|
|
|
SYReadFar ( hfile, (LPB)&flags, sizeof (OMFTypeFlags));
|
|
SYReadFar ( hfile, (LPB)&cType, sizeof (ULONG));
|
|
if ( !cType ) {
|
|
return sheNone;
|
|
}
|
|
|
|
#ifdef HOST32
|
|
rgitd = (LONG _HUGE_ *) MHAlloc ( cType * sizeof ( ULONG ) );
|
|
#else
|
|
rgitd = (LONG _HUGE_ *) MHAllocHuge ( cType, sizeof ( ULONG ) );
|
|
#endif
|
|
|
|
if ( rgitd == NULL ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
#ifndef HOST32
|
|
if ( !( lpul = (ULONG FAR *)MHAlloc( cbTypeIndChunk ) ) ) {
|
|
MHFreeHuge( (LPV) rgitd );
|
|
return sheOutOfMemory;
|
|
}
|
|
#endif // !HOST32
|
|
|
|
// Read in the type index table
|
|
|
|
iType = 0;
|
|
#ifdef HOST32
|
|
assert( sizeof( rgitd[ 0 ] ) == sizeof( ULONG ) );
|
|
|
|
SYReadFar( hfile, (LPB)rgitd, cType * sizeof( rgitd[ 0 ] ) );
|
|
#else // HOST32
|
|
while ( iType + cTypeIndChunk < cType ) {
|
|
SYReadFar ( hfile, (LPB) lpul, cbTypeIndChunk );
|
|
if ( HIWORD( (ULONG)( &rgitd[ iType ] ) ) !=
|
|
HIWORD( (ULONG)( &rgitd[ iType + cTypeIndChunk - 1 ] ) ) ) {
|
|
|
|
ULONG cTypeCopy = cTypeIndChunk;
|
|
ULONG FAR * lpulT = lpul;
|
|
|
|
while( cTypeCopy-- ) {
|
|
rgitd[ iType++ ] = *lpulT++;
|
|
}
|
|
}
|
|
else {
|
|
_fmemcpy( &rgitd[ iType ], lpul, cbTypeIndChunk );
|
|
iType += cTypeIndChunk;
|
|
}
|
|
}
|
|
|
|
SYReadFar (
|
|
hfile,
|
|
(LPB) lpul,
|
|
(WORD) ( cType - iType ) * sizeof ( ULONG )
|
|
);
|
|
|
|
lpb = (LPB)lpul;
|
|
while( iType < cType ) {
|
|
rgitd [ iType++ ] = *lpul++;
|
|
}
|
|
|
|
MHFree( lpb );
|
|
#endif // HOST32
|
|
|
|
lpexg = (LPEXG) LLLock ( hexg );
|
|
ibType = sizeof ( OMFTypeFlags ) + ( cType + 1 ) * sizeof ( ULONG );
|
|
#ifdef HOST32
|
|
assert (!lpexg->ppdb);
|
|
#endif
|
|
lpexg->lpalmTypes = BuildALM (
|
|
FALSE,
|
|
btAlign,
|
|
lszFName,
|
|
lfaBase + lpdssCur->lfo + ibType,
|
|
lpdssCur->cb - ibType,
|
|
cbAlignType
|
|
);
|
|
|
|
if ( lpexg->lpalmTypes == NULL ) {
|
|
LLUnlock ( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
lpexg->rgitd = rgitd;
|
|
lpexg->citd = cType;
|
|
LLUnlock ( hexg );
|
|
|
|
return sheNone;
|
|
}
|
|
|
|
|
|
/** OLLoadSym - load symbol information
|
|
*
|
|
* error = OLLoadSym ( pMod)
|
|
*
|
|
* Entry
|
|
* hmod = handle to current module
|
|
*
|
|
* Exit
|
|
*
|
|
* Returns sheNone if symbols loaded
|
|
* sheOutOfMemory if no memory
|
|
*/
|
|
|
|
|
|
LOCAL SHE PASCAL NEAR OLLoadSym ( HMOD hmod ) {
|
|
|
|
|
|
LPMDS lpmds = (LPMDS) LLLock ( hmod );
|
|
|
|
assert ( lpmds != NULL );
|
|
|
|
lpmds->ulsym = lpdssCur->lfo + lfaBase;
|
|
lpmds->cbSymbols = lpdssCur->cb;
|
|
lpmds->symbols = NULL;
|
|
|
|
LLUnlock ( hmod );
|
|
|
|
return sheNone;
|
|
|
|
}
|
|
|
|
/** OLLoadSrc
|
|
*
|
|
* Purpose: To Load the source line data
|
|
*
|
|
* Input:
|
|
* hlliMds - Handle to module list
|
|
* hmod - Handle to module to load information for
|
|
*
|
|
* Output:
|
|
* Returns: - A ems pointer to the loaded source table, or NULL on failure.
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
|
|
LOCAL SHE PASCAL NEAR OLLoadSrc ( HMOD hmod ) {
|
|
|
|
SHE she = sheNone;
|
|
LPMDS lpmds = (LPMDS) LLLock ( hmod );
|
|
|
|
assert ( lpmds != NULL );
|
|
|
|
lpmds->ulhst = lpdssCur->lfo + lfaBase;
|
|
lpmds->cbhst = lpdssCur->cb;
|
|
lpmds->hst = NULL;
|
|
|
|
LLUnlock ( hmod );
|
|
|
|
return she;
|
|
|
|
}
|
|
|
|
/** OLGlobalPubs
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Input:
|
|
*
|
|
* Output:
|
|
* Returns:
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL SHE PASCAL NEAR OLGlobalPubs ( INT hfile, HEXG hexg ) {
|
|
SHE she = sheNone;
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
|
|
if ( !OLLoadHashSubSec (
|
|
hfile,
|
|
TRUE,
|
|
&lpexg->gstPublics) ) {
|
|
she = sheOutOfMemory;
|
|
}
|
|
|
|
LLUnlock( hexg );
|
|
|
|
return she;
|
|
}
|
|
|
|
|
|
/** OLGlobalSym
|
|
*
|
|
* Purpose:
|
|
*
|
|
* Input:
|
|
*
|
|
* Output:
|
|
* Returns:
|
|
*
|
|
* Exceptions:
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
|
|
|
|
LOCAL SHE PASCAL NEAR OLGlobalSym ( INT hfile, HEXG hexg ) {
|
|
SHE she = sheNone;
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
|
|
if ( !OLLoadHashSubSec (
|
|
hfile,
|
|
TRUE,
|
|
&lpexg->gstGlobals
|
|
) ) {
|
|
she = sheOutOfMemory;
|
|
}
|
|
|
|
LLUnlock( hexg );
|
|
|
|
return she;
|
|
}
|
|
|
|
LOCAL SHE PASCAL NEAR OLLoadSegMap ( INT hfile, HEXG hexg ) {
|
|
|
|
LPEXG lpexg;
|
|
LPB lpb;
|
|
|
|
lpexg = (LPEXG) LLLock( hexg );
|
|
|
|
#if defined(HOST32) // {
|
|
if (lpexg->pdbi) {
|
|
CB cb;
|
|
|
|
// load from the pdb
|
|
if (!DBIQuerySecMap(lpexg->pdbi, NULL, &cb)) {
|
|
LLUnlock( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
if (!(lpb = (LPB) MHAlloc (cb))) {
|
|
LLUnlock( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
if (!DBIQuerySecMap(lpexg->pdbi, lpb, &cb)) {
|
|
LLUnlock( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
}
|
|
else
|
|
#endif // }
|
|
{
|
|
if ( !( lpb = OLLoadRawSubSec ( hfile, 0, cbMaxAlloc ) ) ) {
|
|
LLUnlock( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
}
|
|
lpexg->lpgsi = lpb;
|
|
LLUnlock( hexg );
|
|
|
|
return sheNone;
|
|
}
|
|
|
|
LOCAL SHE PASCAL NEAR OLLoadNameIndex ( INT hfile, HEXG hexg ) {
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
OMFFileIndex FAR * lpefi;
|
|
WORD cmod = 0;
|
|
WORD cfile = 0;
|
|
CB cb;
|
|
|
|
assert ( lpexg != NULL );
|
|
|
|
#if defined(HOST32)
|
|
if (lpexg->pdbi) {
|
|
if (!DBIQueryFileInfo(lpexg->pdbi, 0, &cb)) {
|
|
LLUnlock(hexg);
|
|
return sheNoSymbols;
|
|
}
|
|
else if (!(lpefi = (OMFFileIndex FAR *) MHAlloc(cb))) {
|
|
LLUnlock(hexg);
|
|
return sheOutOfMemory;
|
|
}
|
|
else if (!DBIQueryFileInfo(lpexg->pdbi, (PB)lpefi, &cb)) {
|
|
MHFree(lpefi);
|
|
LLUnlock(hexg);
|
|
return sheNoSymbols;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if ( !(lpefi =
|
|
(OMFFileIndex FAR *)OLLoadRawSubSec ( hfile, 0, (UINT) lpdssCur->cb ))
|
|
) {
|
|
LLUnlock( hexg );
|
|
return sheOutOfMemory;
|
|
}
|
|
cb = (CB)lpdssCur->cb;
|
|
}
|
|
|
|
cmod = lpefi->cmodules;
|
|
cfile = lpefi->cfilerefs;
|
|
|
|
lpexg->lpefi = (LPB) lpefi;
|
|
lpexg->cmod = cmod;
|
|
lpexg->rgiulFile = lpefi->modulelist;
|
|
lpexg->rgculFile = &lpefi->modulelist [ cmod ];
|
|
lpexg->rgichFile = (LPUL) &lpefi->modulelist [ cmod * 2];
|
|
|
|
lpexg->lpchFileNames = (LPCH) &lpefi->modulelist [ cmod * 2 + cfile * 2 ];
|
|
|
|
lpexg->cbFileNames =
|
|
(ULONG)( cb - ( (LPB)lpexg->lpchFileNames - (LPB)lpefi + 1 ) );
|
|
LLUnlock( hexg );
|
|
|
|
return sheNone;
|
|
}
|
|
|
|
LOCAL SHE PASCAL NEAR OLStaticSym ( INT hfile, HEXG hexg ) {
|
|
SHE she = sheNone;
|
|
LPEXG lpexg = (LPEXG) LLLock ( hexg );
|
|
|
|
if ( !OLLoadHashSubSec ( hfile, TRUE, &lpexg->gstStatics ) ) {
|
|
she = sheOutOfMemory;
|
|
}
|
|
|
|
LLUnlock( hexg );
|
|
return she;
|
|
|
|
}
|
|
|
|
#if HOST32 // {
|
|
#define LOADPDBBUFSIZE (_MAX_PATH + sizeof(SIG) + sizeof(AGE))
|
|
#define TEXTSIZE (MAX_PATH + 20)
|
|
|
|
SHE mpECToShe[] = {
|
|
sheNone, // EC_OK
|
|
sheNoSymbols, // EC_USAGE (invalid parameter of call order)
|
|
sheOutOfMemory, // EC_OUT_OF_MEMORY (-, out of RAM)
|
|
sheNoSymbols, // EC_FILE_SYSTEM (pdb name, can't write file, out of disk, etc)
|
|
shePdbNotFound, // EC_NOT_FOUND (PDB file not found)
|
|
shePdbBadSig, // EC_INVALID_SIG (PDB::OpenValidate() and its clients only)
|
|
shePdbInvalidAge, // EC_INVALID_AGE (PDB::OpenValidate() and its clients only)
|
|
sheNoSymbols, // EC_PRECOMP_REQUIRED (obj name, Mod::AddTypes only)
|
|
sheNoSymbols, // EC_OUT_OF_TI (pdb name, TPI::QueryTiForCVRecord() only)
|
|
sheNoSymbols, // EC_NOT_IMPLEMENTED
|
|
sheNoSymbols, // EC_V1_PDB (pdb name, PDB::Open() only)
|
|
shePdbOldFormat, // EC_FORMAT (accessing pdb with obsolete format)
|
|
};
|
|
|
|
// Get the name of the pdb file (OMF name) for the specified exe. If the
|
|
// LoadPdb hasn't been called on this exe OR it's not NB10, this will return
|
|
// an empty string! Note: There will only be an lszPdbName if there was
|
|
// an error loading the pdb
|
|
VOID LOADDS PASCAL SHPdbNameFromExe( LSZ lszExe, LSZ lszPdbName, UINT cbMax ) {
|
|
HEXE hexe;
|
|
|
|
// Zero out the destination
|
|
MEMSET( lszPdbName, 0, cbMax );
|
|
|
|
// Look up the exe
|
|
if ( hexe = SHGethExeFromName( lszExe ) ) {
|
|
HEXG hexg = ((LPEXS)LLLock( hexe ))->hexg;
|
|
LPEXG lpexg = (LPEXG)LLLock( hexg );
|
|
|
|
// Only copy if there's a pdbname
|
|
if ( lpexg->lszPdbName ) {
|
|
_ftcsncpy( lszPdbName, lpexg->lszPdbName, cbMax );
|
|
}
|
|
|
|
// Clean up
|
|
LLUnlock( hexg );
|
|
LLUnlock( hexe );
|
|
}
|
|
}
|
|
|
|
|
|
LOCAL SHE PASCAL NEAR LoadPdb (LPEXG lpexg, INT hfile)
|
|
{
|
|
// static uchar PadCount[4] = {4,3,2,1};
|
|
EC ec;
|
|
struct {
|
|
SIG sig;
|
|
AGE age;
|
|
char sz[_MAX_PATH];
|
|
} pdb;
|
|
char szExePath[_MAX_PATH];
|
|
char szPDBOut[cbErrMax];
|
|
char *pcEndOfPath;
|
|
BOOL fOpenValidate;
|
|
|
|
assert(lpexg);
|
|
|
|
SYReadFar(hfile, (LPB)&pdb, sizeof pdb);
|
|
|
|
// figure out the home directory of the exe file - pass that along to
|
|
// OpenValidate this will direct to dbi to search for it in that
|
|
// directory if it fails to find the pdb.
|
|
|
|
_fullpath(szExePath, lpexg->lszName, _MAX_PATH);
|
|
pcEndOfPath = _tcsrchr(szExePath, '\\');
|
|
*pcEndOfPath = '\0'; // null terminate it
|
|
|
|
#ifdef HOST32
|
|
|
|
HKEY hSectionKey = NULL;
|
|
DWORD nType = REG_SZ;
|
|
DWORD nSize = sizeof(rgSearchPath);
|
|
|
|
if (!fQueriedRegistry)
|
|
{
|
|
RegOpenKeyEx(HKEY_CURRENT_USER, szDefaultKeyName, 0, KEY_READ, &hSectionKey);
|
|
if (hSectionKey == NULL || RegQueryValueEx(hSectionKey, (char *)szPdbDirs, NULL,
|
|
&nType, (LPBYTE)rgSearchPath, &nSize) != ERROR_SUCCESS)
|
|
{
|
|
rgSearchPath[0] = 0;
|
|
}
|
|
|
|
fQueriedRegistry = TRUE;
|
|
}
|
|
|
|
fOpenValidate = PDBOpenValidateEx(
|
|
pdb.sz,
|
|
szExePath,
|
|
rgSearchPath,
|
|
pdbRead,
|
|
pdb.sig,
|
|
pdb.age,
|
|
&ec,
|
|
szPDBOut,
|
|
&(lpexg->ppdb)
|
|
);
|
|
|
|
// Save the pdb name in the exg!
|
|
if ( !( lpexg->lszPdbName = (LSZ)MHAlloc( _ftcslen( szPDBOut ) + 1 ) ) ) {
|
|
return sheOutOfMemory;
|
|
}
|
|
|
|
_ftcscpy( lpexg->lszPdbName, szPDBOut );
|
|
|
|
if ( !fOpenValidate ) {
|
|
/*
|
|
** REVIEW: PDBOpenValidate should return a nonzero ec if it returned
|
|
** false. Remove this check after OLYMPUS #11830 is fixed.
|
|
*/
|
|
if ( ec ) {
|
|
return mpECToShe[ ec ];
|
|
}
|
|
else {
|
|
return ( sheNoSymbols );
|
|
}
|
|
}
|
|
|
|
if (!PDBOpenTpi(lpexg->ppdb, pdbRead pdbGetRecordsOnly, &(lpexg->ptpi))) {
|
|
ec = PDBQueryLastError( lpexg->ppdb, NULL );
|
|
return mpECToShe[ ec ];
|
|
}
|
|
|
|
if (!PDBOpenDBI(lpexg->ppdb, pdbRead, lpexg->lszName, &(lpexg->pdbi))) {
|
|
ec = PDBQueryLastError( lpexg->ppdb, NULL );
|
|
return mpECToShe[ ec ];
|
|
}
|
|
return sheNone;
|
|
#else
|
|
MessageBox (NULL, "NB10 support temporarily disabled; please resync your tools and relink", "bad debug format", MB_ICONSTOP | MB_OK);
|
|
return sheNoSymbols;
|
|
#endif
|
|
}
|
|
#endif // }
|