NT4/private/sdktools/vctools/cvpack/symbols7.c
2020-09-30 17:12:29 +02:00

741 lines
17 KiB
C

/*** symbols7.c
*
* engine routines for C7 symbols.
*
*/
#include "compact.h"
LOCAL void RewritePublics (uchar *, DirEntry *, PMOD);
LOCAL void RewriteSymbols (uchar *, DirEntry *, char *, PMOD);
LOCAL void CheckSearchSym (ushort, ushort *);
// Called through Fixup function table
LOCAL void C7DecLevel (void);
LOCAL void C7IncLevel (void);
LOCAL void BPRelSym16 (void);
LOCAL void BPRelSym32 (void);
LOCAL void RegRel16 (void);
LOCAL void RegRel32 (void);
LOCAL void ProcSym16 (void);
LOCAL void ProcSym32 (void);
LOCAL void ProcSymMips (void);
LOCAL void LData16 (void);
LOCAL void LData32 (void);
LOCAL void LThread32 (void);
LOCAL void GData16 (void);
LOCAL void GData32 (void);
LOCAL void GThread32 (void);
LOCAL void ExeModelSym16 (void);
LOCAL void ExeModelSym32 (void);
LOCAL void RegSym (void);
LOCAL void ConstantSym (void);
LOCAL void ObjNameSym (void);
LOCAL void UDTSym (void);
LOCAL void SkipSym (void);
LOCAL BOOL CodeAddrInCurMod (PMOD pMod, unsigned short Seg, unsigned long Off);
extern ushort recursive;
extern ushort AddNewSymbols;
extern uchar Signature[];
extern ulong PublicSymbols;
extern uchar ptr32;
extern uchar *SymbolSegment;
extern ushort SymbolSizeAdd;
extern ushort SymbolSizeSub;
extern uchar **ExtraSymbolLink;
extern uchar *ExtraSymbols;
extern ulong InitialSymInfoSize;
extern ulong FinalSymInfoSize;
extern ulong ulCVTypeSignature; // The signature from the modules type segment
extern ushort segnum[MAXCDF];
// These are shared by the fixup functions
LOCAL uchar *pNewSym; // Where the symbol is that needs to be fixed up
LOCAL int iLevel;
LOCAL int DiscardProc;
LOCAL uchar *pOldSym;
typedef struct {
ushort sym; // Old C7 Symbol record type
void (*pfcn) (void);
} C7fixupsymfcn;
C7fixupsymfcn C7FixSymFcn[] = {
{S_BPREL32, BPRelSym32},
{S_BLOCK32, C7IncLevel},
{S_LPROC32, ProcSym32},
{S_GPROC32, ProcSym32},
{S_END, C7DecLevel},
{S_LDATA32, LData32},
{S_GDATA32, GData32},
{S_PUB32, LData32},
{S_LABEL32, NULL},
{S_REGISTER, RegSym},
{S_LTHREAD32, LData32}, // REVIEW:HACK lthread uses same functions as ldata
{S_GTHREAD32, GData32}, // REVIEW:HACK gthread uses same functions as gdata
{S_SLINK32, NULL},
{S_BPREL16, BPRelSym16},
{S_BLOCK16, C7IncLevel},
{S_LPROC16, ProcSym16},
{S_GPROC16, ProcSym16},
{S_LDATA16, LData16},
{S_GDATA16, GData16},
{S_PUB16, LData16},
{S_LABEL16, NULL},
{S_UDT, UDTSym},
{S_REGREL32, RegRel32},
{S_LPROCMIPS, ProcSymMips},
{S_GPROCMIPS, ProcSymMips},
{S_ENDARG, NULL},
{S_REGREL16, RegRel16},
{S_WITH16, C7IncLevel},
{S_WITH32, C7IncLevel},
{S_THUNK16, C7IncLevel},
{S_THUNK32, C7IncLevel},
{S_CEXMODEL16, NULL},
{S_CEXMODEL32, NULL},
{S_CONSTANT, ConstantSym},
{S_SSEARCH, NULL},
{S_SKIP, NULL},
{S_COMPILE, NULL},
{S_OBJNAME, ObjNameSym},
};
#define C7FIXUPSYMCNT (sizeof C7FixSymFcn / sizeof (C7FixSymFcn[0]))
/** C7CalcNewSizeOfSymbols - calculate amount of space needed for padding
*
* Takes a buffer containing unaligned C7 symbol records and calculates
* how much additional space will be required on write for pad bytes.
* In preperation for a RISC processor misaligned memory reads are avoided.
*
* C7CalcNewSizeOfSymbols (Symbols, SymbolCount)
*
* Entry Symbols = Buffer containing C7 unaligned symbols
* SymbolCount = count of bytes in buffer
*
* Exit *Add = increased by the num of pad bytes to add
* *Sub = increased by the num of bytes in S_SKIP records
*/
void C7CalcNewSizeOfSymbols (uchar *Symbols, ulong SymbolCount,
ushort *Add, ushort *Sub)
{
uchar * pOldSym;
uchar * End;
ushort usRecSize; // Size of symbol including the length field
ushort usRecType; // Symbol record type
ushort AddInit = *Add;
ushort SubInit = *Sub;
cSeg = 0;
pOldSym = Symbols;
End = pOldSym + SymbolCount;
pOldSym += sizeof (ulong); //Skip signature
while (pOldSym < End) {
if (!((ulong)pOldSym & 0x1)){
// if this record aligned on a word boundry
// Read by words because data aligned on word bounderies
usRecSize = ((SYMPTR)pOldSym)->reclen + LNGTHSZ;
usRecType = ((SYMPTR)pOldSym)->rectyp;
}
else {
// Just make sure bytewise read remains correct
DASSERT ((sizeof (((SYMPTR)pOldSym)->reclen) == 2) &&
(sizeof (((SYMPTR)pOldSym)->rectyp) == 2) &&
(offsetof (SYMTYPE, reclen) == 0) &&
(offsetof (SYMTYPE, rectyp) == 2));
// Read by bytes because not aligned on word bounderies
usRecSize = (*pOldSym + (*(pOldSym + 1) << (ushort)8)) + LNGTHSZ;
usRecType = *(pOldSym + 2) + (*(pOldSym + 3) << (ushort)8);
}
// Calculate the size change
if (usRecType != S_SKIP){
// Reserve space for pad bytes we will add at rewrite time.
*Add += PAD4 (usRecSize);
switch (usRecType) {
case S_GPROC16:
case S_LPROC16:
CheckSearchSym (((PROCPTR16)pOldSym)->seg, Add);
break;
case S_GPROC32:
case S_LPROC32:
CheckSearchSym (((PROCPTR32)pOldSym)->seg, Add);
break;
case S_GPROCMIPS:
case S_LPROCMIPS:
CheckSearchSym (((PROCPTRMIPS)pOldSym)->seg, Add);
break;
case S_UDT:
// have to call HashUDTLocal to make
// sure this is the index that we resolve the local decl's
// for the TDB, otherwise stale UDT typedefs could screw up
// the local UDT resolution
// sps - 10/16/92
HashFwdLocal (((UDTPTR)pOldSym)->name, ((UDTPTR)pOldSym)->typind);
if (NeedToClearTDB) {
NeedToClearTDB = TDBStayedResident = FALSE;
*Add = AddInit;
*Sub = SubInit;
InitModTypeTable ();
ClearHashFwdLocal ();
ReadTDB(NULL);
if (PreviousMaxIndex == 0) {
PreviousMaxIndex = MaxIndex;
}
C7CalcNewSizeOfSymbols (Symbols, SymbolCount, Add, Sub);
return;
}
break;
}
}
else {
// S_SKIP records are removed, so subtract the size of the record
*Sub += usRecSize;
}
pOldSym += usRecSize; // to next record
}
}
LOCAL void CheckSearchSym (ushort seg, ushort *Add)
{
if (!SegmentPresent (seg)) {
*Add += MAXPAD + sizeof (SEARCHSYM);
segnum[cSeg++] = seg;
if (cSeg > MAXCDF) {
ErrorExit (ERR_TOOMANYSEG, FormatMod (pCurMod), NULL);
}
}
}
/** RewriteSymbols - reformat symbols to new format and store in VM
*
* RewriteSymbols (addr, pDir, psstMod);
*
* Entry addr = address of publics table
* pDir = address of directory entry
* psstMod = pointer to the module table entry
* pMod = module table entry
*
* Exit pDir->lfo = address of rewritten table
* pDir->Size = size of rewritten table
*
* Return none
*
*/
void C7RewriteAndFixupSymbols (uchar *OldSym, OMFDirEntry *pDir, PMOD pMod,
ushort *Add, ushort *Sub)
{
uchar *End;
ushort i;
_vmhnd_t pNewSymAddr;
ulong cbNewSymbol; // Count of bytes used by new symbols
C7fixupsymfcn * pFixFcn;
ushort usRecSize; // Size of symbol including the length field
ushort usRecType; // Symbol record type
ushort iPad;
SYMPTR pStartSym;
pOldSym = OldSym;
iLevel = DiscardProc = 0;
End = pOldSym + pDir->cb;
cbNewSymbol = pDir->cb + *Add - *Sub;
if ((pNewSymAddr = (_vmhnd_t)TrapMalloc ((size_t)cbNewSymbol)) == NULL) {
ErrorExit (ERR_NOMEM, NULL, NULL);
}
pNewSym = (uchar *) pNewSymAddr;
pStartSym = (SYMPTR)pNewSym;
// Rewrite CV4/C7 debug info format signature.
*((ulong *)pNewSym)++ = *((ulong *)pOldSym)++;
for (i = 0; i < cSeg; i++) {
pNewSym += AddSearchSym (pNewSym, segnum[i]);
}
while (pOldSym < End) {
// Get the size and type without causing any miss-aligned reads
if( !((ulong)pOldSym & 0x1) ){ // Is this record aligned on a word boundry
// Read by words because data aligned on word bounderies
usRecSize = ((SYMPTR)pOldSym)->reclen + LNGTHSZ;
usRecType = ((SYMPTR)pOldSym)->rectyp;
}
else {
// Just make sure bytewise read remains correct
DASSERT ((sizeof (((SYMPTR)pOldSym)->reclen) == 2) &&
(sizeof (((SYMPTR)pOldSym)->rectyp) == 2) &&
(offsetof (SYMTYPE, reclen) == 0) &&
(offsetof (SYMTYPE, rectyp) == 2));
// Read by bytes because not aligned on word bounderies
usRecSize = (*pOldSym + (*(pOldSym + 1) << (ushort)8)) + LNGTHSZ;
usRecType = *(pOldSym + 2) + (*(pOldSym + 3) << (ushort)8);
}
// Don't Rewrite S_SKIP Symbols
if (usRecType != S_SKIP ){
// Find the appropriate fixup function
for( pFixFcn = C7FixSymFcn, i = 0; i < C7FIXUPSYMCNT; i++, pFixFcn++ ){
if( pFixFcn->sym == usRecType ){
break; // Ok, found the entry
}
}
//M00BUG This definitly should be a fatal exit
assert( i != C7FIXUPSYMCNT ); // Make sure type was in the table
// Fixup the type indexes by packing the types
if( pFixFcn->pfcn ){
pFixFcn->pfcn (); // Fixup the symbol
}
DASSERT (!recursive);
if (((SYMPTR)pOldSym)->rectyp != S_CVRESERVE) {
// the symbol was not deleted so copy it to the new buffer
// and pad to the long boundary.
memcpy (pNewSym, pOldSym, usRecSize);
iPad = PAD4 (usRecSize);
((SYMTYPE *)pNewSym)->reclen = usRecSize + iPad - LNGTHSZ;
pNewSym += usRecSize;
PADLOOP (iPad, pNewSym);
}
}
// Move to the next symbol
pOldSym += usRecSize;
}
DASSERT (iLevel >= 0);
DASSERT ((ulong)(pNewSym - (uchar *)pStartSym) <= cbNewSymbol);
cbNewSymbol = pNewSym - (uchar *)pStartSym;
if (LinkScope ((uchar *)pStartSym, cbNewSymbol) == FALSE) {
// error linking scopes, delete symbol table
Warn (WARN_SCOPE, FormatMod (pCurMod), NULL);
cbNewSymbol = 0;
}
else {
extern void BuildStatics ( SYMPTR, ulong, int );
BuildStatics ( pStartSym, cbNewSymbol, pMod->ModuleIndex );
}
pDir->lfo = (ulong)pNewSymAddr;
pDir->cb = cbNewSymbol;
FinalSymInfoSize += cbNewSymbol;
pMod->SymbolSize = cbNewSymbol;
pMod->SymbolsAddr = (ulong)pNewSymAddr;
}
/** C7RewritePublics - reformat publics
*
* C7RewritePublics (addr, pDir);
*
* Entry addr = address of publics table
* pDir = address of directory entry
*
* Exit Public symbols added to HTPub
*
* Return none
*
* Note Not called through Symbol Rewrite funtion table.
*/
void C7RewritePublics (uchar *pOldPublics, OMFDirEntry *pDir)
{
uchar *pNewPublics;
uchar *End;
ushort usRecSize; // Size of symbol including the length field
ushort usRecType; // Symbol record type
uchar buf[512];
iLevel = 0;
if (pDir->cb == 0) {
// if publics directory entry but no data
return;
}
End = pOldPublics + pDir->cb;
pOldPublics += sizeof (ulong);
while (pOldPublics < End) {
pNewPublics = buf;
// Get the size and type without causing any miss-aligned reads
if( !((ulong)pOldPublics & 0x1) ){ // Is this record aligned on a word boundry
// Read by words because data aligned on word bounderies
usRecSize = ((SYMPTR)pOldPublics)->reclen + LNGTHSZ;
usRecType = ((SYMPTR)pOldPublics)->rectyp;
}
else {
// Just make sure bytewise read remains correct
DASSERT ((sizeof (((SYMPTR)pOldPublics)->reclen) == 2) &&
(sizeof (((SYMPTR)pOldPublics)->rectyp) == 2) &&
(offsetof (SYMTYPE, reclen) == 0) &&
(offsetof (SYMTYPE, rectyp) == 2));
// Read by bytes because not aligned on word bounderies
usRecSize = (*pOldPublics + (*(pOldPublics + 1) << (ushort)8)) + LNGTHSZ;
usRecType = *(pOldPublics + 2) + (*(pOldPublics + 3) << (ushort)8);
}
// Copy the existing symbol to virtual memory and convert type index
DASSERT (usRecSize < sizeof (buf));
memcpy (pNewPublics, pOldPublics, usRecSize);
switch (usRecType) {
case S_PUB16:
switch (ulCVTypeSignature) {
case CV_SIGNATURE_C7:
if (fDelete) {
if (((DATAPTR16)pNewPublics)->typind >= CV_FIRST_NONPRIM) {
((DATAPTR16)pNewPublics)->typind = T_NOTYPE;
}
}
else {
((DATAPTR16)pNewPublics)->typind =
C7GetCompactedIndex (((DATAPTR16)pNewPublics)->typind);
}
break;
default:
if (fDelete) {
((DATAPTR16)pNewPublics)->typind = T_NOTYPE;
}
else {
((DATAPTR16)pNewPublics)->typind =
C6GetCompactedIndex (((DATAPTR16)pNewPublics)->typind);
}
break;
}
break;
case S_PUB32:
switch (ulCVTypeSignature) {
case CV_SIGNATURE_C7:
if (fDelete) {
if (((DATAPTR32)pNewPublics)->typind >= CV_FIRST_NONPRIM) {
((DATAPTR32)pNewPublics)->typind = T_NOTYPE;
}
}
else {
((DATAPTR32)pNewPublics)->typind =
C7GetCompactedIndex (((DATAPTR32)pNewPublics)->typind);
}
break;
default:
if (fDelete) {
((DATAPTR16)pNewPublics)->typind = T_NOTYPE;
}
else {
((DATAPTR32)pNewPublics)->typind =
C6GetCompactedIndex (((DATAPTR32)pNewPublics)->typind);
}
break;
}
break;
default:
DASSERT (FALSE);
}
DASSERT (!recursive);
PackPublic ((SYMPTR)&buf, HASHFUNC);
// Move to the next symbol
pOldPublics += usRecSize; // to next record
}
DASSERT (iLevel == 0);
}
static INLINE void MarkSymRecDiscard (void) {
((SYMPTR)pOldSym)->rectyp = S_CVRESERVE;
}
static INLINE int InDiscardableProc (void) {
if (DiscardProc) {
MarkSymRecDiscard();
}
return(DiscardProc);
}
LOCAL void C7IncLevel (void)
{
iLevel++;
if (DiscardProc) {
MarkSymRecDiscard();
DiscardProc++;
}
}
LOCAL void C7DecLevel (void)
{
iLevel--;
if (DiscardProc) {
MarkSymRecDiscard();
DiscardProc--;
}
}
LOCAL void BPRelSym16 (void)
{
if (InDiscardableProc()) {
return;
}
((BPRELPTR16)pOldSym)->typind =
C7GetCompactedIndex (((BPRELPTR16)pOldSym)->typind);
}
LOCAL void BPRelSym32 (void)
{
if (InDiscardableProc()) {
return;
}
((BPRELPTR32)pOldSym)->typind =
C7GetCompactedIndex (((BPRELPTR32)pOldSym)->typind);
}
LOCAL void RegSym (void)
{
if (InDiscardableProc()) {
return;
}
((REGPTR)pOldSym)->typind =
C7GetCompactedIndex (((REGPTR)pOldSym)->typind);
}
LOCAL void RegRel16 (void)
{
if (InDiscardableProc()) {
return;
}
((REGREL16 *)pOldSym)->typind =
C7GetCompactedIndex (((REGREL16 *)pOldSym)->typind);
return;
}
LOCAL void RegRel32 (void)
{
if (InDiscardableProc()) {
return;
}
((REGREL32 *)pOldSym)->typind =
C7GetCompactedIndex (((REGREL32 *)pOldSym)->typind);
return;
}
LOCAL void ConstantSym (void)
{
if (InDiscardableProc()) {
return;
}
((CONSTPTR)pOldSym)->typind =
C7GetCompactedIndex (((CONSTPTR)pOldSym)->typind);
if (iLevel == 0) {
// do not pack function scoped constants
PackSymbol ((SYMPTR)pOldSym, HASHFUNC);
}
}
LOCAL void ObjNameSym (void)
{
OBJNAMEPTR pSym;
DASSERT(DiscardProc == 0);
if (PackingPreComp) {
pSym = (OBJNAMEPTR) pOldSym;
if ((pCurMod->pName = TrapMalloc ((size_t)(pSym->name[0] + 1))) == NULL) {
ErrorExit(ERR_NOMEM, NULL, NULL);
}
DASSERT(pCurMod->signature == pSym->signature);
memmove (pCurMod->pName, &pSym->name[0], pSym->name[0] + 1);
}
}
LOCAL void LData16 (void)
{
if (InDiscardableProc()) {
return;
}
((DATAPTR16)pOldSym)->typind =
C7GetCompactedIndex (((DATAPTR16)pOldSym)->typind);
}
LOCAL void GData16 (void)
{
if (InDiscardableProc()) {
return;
}
((DATAPTR16)pOldSym)->typind =
C7GetCompactedIndex (((DATAPTR16)pOldSym)->typind);
PackSymbol ((SYMPTR)pOldSym, HASHFUNC);
}
LOCAL void LData32 (void)
{
if (InDiscardableProc()) {
return;
}
((DATAPTR32)pOldSym)->typind =
C7GetCompactedIndex (((DATAPTR32)pOldSym)->typind);
}
LOCAL void GData32 (void)
{
if (InDiscardableProc()) {
return;
}
((DATAPTR32)pOldSym)->typind =
C7GetCompactedIndex (((DATAPTR32)pOldSym)->typind);
PackSymbol ((SYMPTR)pOldSym, HASHFUNC);
}
LOCAL void ProcSym16 (void)
{
iLevel++;
if (!CodeAddrInCurMod(pCurMod, ((PROCPTR16)pOldSym)->seg, ((PROCPTR16)pOldSym)->off)) {
DiscardProc++;
MarkSymRecDiscard();
}
else {
((PROCPTR16)pOldSym)->typind =
C7GetCompactedIndex (((PROCPTR16)pOldSym)->typind);
}
}
LOCAL void ProcSym32 (void)
{
iLevel++;
if (!CodeAddrInCurMod(pCurMod, ((PROCPTR32)pOldSym)->seg, ((PROCPTR32)pOldSym)->off)) {
DiscardProc++;
MarkSymRecDiscard();
}
else {
((PROCPTR32)pOldSym)->typind =
C7GetCompactedIndex (((PROCPTR32)pOldSym)->typind);
}
}
LOCAL void ProcSymMips (void)
{
iLevel++;
if (!CodeAddrInCurMod(pCurMod, ((PROCPTRMIPS)pOldSym)->seg, ((PROCPTRMIPS)pOldSym)->off)) {
DiscardProc++;
MarkSymRecDiscard();
}
else {
((PROCPTRMIPS)pOldSym)->typind =
C7GetCompactedIndex (((PROCPTRMIPS)pOldSym)->typind);
}
}
LOCAL void UDTSym (void)
{
if (InDiscardableProc()) {
return;
}
((UDTPTR)pOldSym)->typind =
C7GetCompactedIndex (((UDTPTR)pOldSym)->typind);
if (iLevel == 0) {
// do not pack function scoped UDTs
PackSymbol ((SYMPTR)pOldSym, HASHFUNC);
}
}
BOOL CodeAddrInCurMod (PMOD pMod, unsigned short Seg, unsigned long Off)
{
OMFModule *psstMod;
char *pModTable;
OMFSegDesc *pSegDesc;
unsigned short i;
if ((pModTable = (char *) pMod->ModulesAddr) == NULL) {
ErrorExit(ERR_NOMEM, NULL, NULL);
}
psstMod = (OMFModule *)pModTable;
for (i = 0, pSegDesc = psstMod->SegInfo;
i < psstMod->cSeg;
i++, pSegDesc++) {
if (((Off - pSegDesc->Off) < pSegDesc->cbSeg) &&
(Seg == pSegDesc->Seg)) {
return(TRUE);
}
}
return (FALSE);
}