|
|
/*
* Copyright Microsoft Corporation, 1983-1989 * * This Module contains Proprietary Information of Microsoft * Corporation and should be treated as Confidential. */ /****************************************************************
* * * NEWTP1.C * * * * Pass 1 object module processing routines. * * * ****************************************************************/
#include <minlit.h> /* Basic types and constants */
#include <bndtrn.h> /* More types and constants */
#include <bndrel.h> /* Relocation record definitions */
#include <lnkio.h> /* Linker I/O definitions */
#include <newexe.h> /* DOS & 286 .EXE data structures */
#if EXE386
#include <exe386.h> /* 386 .EXE data structures */
#endif
#include <lnkmsg.h> /* Error messages */
#if OXOUT OR OIAPX286
#include <xenfmt.h> /* Xenix format definitions */
#endif
#include <extern.h> /* External declarations */
#include <undname.h>
#if OVERLAYS
WORD iovFile; /* Overlay number of input file */ #endif
LOCAL FTYPE fP2Start; /* Start of Pass 2 records */ LOCAL FTYPE fModEnd; /* MODEND seen */ LOCAL WORD cSegCode; /* Number of code seg's in module */
#if O68K
#define F68KCODE(ch) ((ch) >= 'A' && (ch) <= 'E')
#endif /* O68K */
/*
* LOCAL FUNCTION PROTOTYPES */
LOCAL void NEAR TypErr(MSGTYPE msg,unsigned char *sb); LOCAL void NEAR DoCommon(APROPUNDEFPTR apropUndef, long length, unsigned short cbEl, unsigned char *sb); LOCAL void NEAR SegUnreliable(APROPSNPTR apropSn); LOCAL void NEAR redefinition(WORD iextWeak, WORD iextDefRes, RBTYPE oldDefRes); LOCAL void NEAR SegRc1(void); LOCAL void NEAR TypRc1(void); LOCAL void NEAR ComDf1(void); LOCAL void NEAR GrpRc1(void); LOCAL void NEAR PubRc1(void); LOCAL void NEAR ExtRc1(void); LOCAL void NEAR imprc1(void); LOCAL void NEAR exprc1(void); LOCAL void NEAR ComRc1(void); LOCAL void NEAR EndRc1(void);
extern void NEAR FixRc1(void);
LOCAL void NEAR redefinition(WORD iextWeak, WORD iextDefRes, RBTYPE oldDefRes) { // Redefinition of default resolution.
// Warn the user.
SBTYPE oldDefault; SBTYPE newDefault; APROPUNDEFPTR undef; AHTEPTR rhte = NULL;
undef = (APROPUNDEFPTR ) FetchSym(oldDefRes, FALSE); while (undef->au_attr != ATTRNIL) { rhte = (AHTEPTR) undef->au_next; /* Try next entry in list */ undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE); /* Fetch it from VM */ } if (rhte) { strcpy(oldDefault, GetFarSb(rhte->cch)); } undef = (APROPUNDEFPTR ) FetchSym(mpextprop[iextDefRes], FALSE); while (undef->au_attr != ATTRNIL) { rhte = (AHTEPTR) undef->au_next; /* Try next entry in list */ undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE); /* Fetch it from VM */ } if (rhte) { strcpy(newDefault, GetFarSb(rhte->cch)); } undef = (APROPUNDEFPTR ) FetchSym(mpextprop[iextWeak], FALSE); while (undef->au_attr != ATTRNIL) { rhte = (AHTEPTR) undef->au_next; /* Try next entry in list */ undef = (APROPUNDEFPTR ) FetchSym((RBTYPE)rhte,FALSE); /* Fetch it from VM */ } if (rhte) { OutWarn(ER_weakredef, 1 + GetFarSb(rhte->cch), &oldDefault[1], &newDefault[1]); } }
/*** IsDebSeg - check is segment is one of the special debug segments
* * Purpose: * Check if segment name and class name match reserved debugger * segment names. * * Input: * - rhteClass - pointer to class name * - rhteSeg - pointer to segment name * * Output: * If this is a debug segment function returns 1 for $$TYPES, and 2 * for $$SYMBOLS. For non-debug segments it returns FALSE. * * Exceptions: * None. * * Notes: * None. * *************************************************************************/
WORD NEAR IsDebSeg(RBTYPE rhteClass, RBTYPE rhteSeg) { if (rhteClass == rhteDebTyp) return ((rhteSeg == rhteTypes || rhteSeg == rhte0Types) ? 1 : FALSE); else if (rhteClass == rhteDebSym) return ((rhteSeg == rhteSymbols || rhteSeg == rhte0Symbols) ? 2 : FALSE); else return(FALSE); }
/****************************************************************
* * * ModRc1: * * * * This function reads the name from a THEADR record and makes * * an entry containing the name in the hash table. * * See p. 26 in "8086 Object Module Formats EPS." * * * ****************************************************************/
void NEAR ModRc1(void) { APROPFILEPTR apropFile;
sbModule[0] = (BYTE) Gets(); /* Read in the length byte */ GetBytes(&sbModule[1],B2W(sbModule[0])); /* Read in the name */ PropSymLookup(sbModule, ATTRNIL, TRUE); /* Make entry in hash table */ apropFile = (APROPFILEPTR ) FetchSym(vrpropFile,TRUE); /* Allocate space in virt mem */
// The name of a module is given by the very first THEADR record
if(apropFile->af_rMod == 0) apropFile->af_rMod = vrhte; /* Load pointer into hash table */ #if FDEBUG
if(fDebug) /* If runtime debugging on */ { OutFileCur(stderr); /* Write current file and module */ NEWLINE(stderr); } #endif
}
long NEAR TypLen() /* Get type length */ { WORD b; /* Byte value */ long l; /* Size */
if(cbRec < 2) InvalidObject(); /* Make sure record long enough */ b = Gets(); /* Get length byte */ if(b < 128) return(B2L(b)); /* One byte length field */ if(b == 129) /* If two byte length */ { if(cbRec < 3) InvalidObject(); /* Make sure record long enough */ return((long) WGets()); /* Return the length */ } if(b == 132) /* If three byte length */ { if(cbRec < 4) InvalidObject(); /* Make sure record long enough */ l = (long) WGets(); /* Get the low word */ return(l + ((long) Gets() << WORDLN)); /* Return the length */ } if(b == 136) /* If four byte length */ { if(cbRec < 5) InvalidObject(); /* Make sure record long enough */ l = (long) WGets(); /* Get the low word */ return(l + ((long) WGets() << WORDLN)); /* Return the length */ } InvalidObject(); /* Bad length specification */ }
/****************************************************************
* * * TypRc1: * * * * This function processes TYPDEF records. These records are * * difficult to understand. They are (poorly) described on * * pp. 40-43 of "8086 Object Module Formats EPS," with some * * additional information on pp. 89-90. * * Microsoft used to used them for communal variables but they * * have been superseded by COMDEF records. * * * ****************************************************************/
LOCAL void NEAR TypRc1(void) { long l; WORD b; WORD typ; /* Near or FAR */ WORD ityp; /* Type index */
if(typMac >= TYPMAX) Fatal(ER_typdef); SkipBytes(Gets()); /* Skip the name field */ Gets(); /* Skip the EN byte */ l = -1L; /* Initialize */ mpityptyp[typMac] = 0; /* Assume no element type */ if(cbRec > 3) /* If at least four bytes left */ { typ = Gets(); /* Get type leaf */ b = Gets(); /* Get next leaf */ if(typ == TYPENEAR) /* If near variable */ { if(b != 0x7B && b != 0x79 && b != 0x77) InvalidObject(); /* Scalar, structure, or array */ fCommon = (FTYPE) TRUE; /* We have communal variables */ l = (TypLen() + 7) >> 3; /* Round length to nearest byte */ } else if(typ == TYPEFAR) /* Else if FAR variable */ { if(b != 0x77) InvalidObject(); /* Must have an array */ fCommon = (FTYPE) TRUE; /* We have communal variables */ l = TypLen(); /* Get number of elements */ ityp = GetIndex(1, (WORD) (typMac - 1)); /* Get type index */ if(mpityptyp[ityp] || mpitypelen[ityp] == -1L) InvalidObject(); /* Must index valid TYPDEF */ mpityptyp[typMac] = ityp; /* Save type index */ /* If element length too big, treat as TYPENEAR */ if(mpitypelen[ityp] > CBELMAX) { l *= mpitypelen[ityp]; mpitypelen[ityp] = 0; } } } mpitypelen[typMac++] = l; /* Store length */ SkipBytes((WORD) (cbRec - 1)); /* Skip all but the checksum */ }
LOCAL void NEAR TypErr(msg,sb) /* Type error message routine */ MSGTYPE msg; /* Message */ BYTE *sb; /* Symbol to which error refers */ { sb[B2W(sb[0]) + 1] = '\0'; /* Null-terminate */ OutError(msg,1 + sb); }
/*
* DoCommon * * Resolves old and new communal definitions of the same symbol. * Does work for both ComDf1() and ExtRc1(). */
LOCAL void NEAR DoCommon (apropUndef, length, cbEl, sb) APROPUNDEFPTR apropUndef; /* Ptr to property cell */ long length; /* Length or number of elements */ WORD cbEl; /* # bytes per array element */ BYTE *sb; /* Name of symbol */ { if(apropUndef->au_len == -1L) /* If not previously a communal */ { apropUndef->au_cbEl = cbEl; /* Set the element size */ MARKVP(); /* Page has changed */ } else if (cbEl == 0 && apropUndef->au_cbEl != 0) { /* Else if near reference to FAR */ apropUndef->au_len *= apropUndef->au_cbEl; /* Calculate FAR variable length */ apropUndef->au_cbEl = 0; /* Force DS-type to near */ MARKVP(); /* Page has changed */ if (apropUndef->au_len > LXIVK) /* If huge variable */ { TypErr(ER_nearhuge,sb); /* Issue error message */ return; /* Skip this symbol */ } } else if (cbEl != 0 && apropUndef->au_cbEl == 0) { /* Else if FAR reference to near */ length *= cbEl; /* Calculate FAR variable length */ cbEl = 0; /* Force DS-type to near */ if (length > LXIVK) /* If huge variable */ { TypErr(ER_nearhuge,sb); /* Issue error message */ return; /* Skip this symbol */ } } else if (cbEl != apropUndef->au_cbEl) { /* If array element sizes don't match */ TypErr(ER_arrmis,sb); return; /* Skip this symbol */ } if (apropUndef->au_len < length) { /* If new length is larger */ apropUndef->au_len = length; /* Save it */ MARKVP(); } }
/*
* ComDf1 * * This function processes COMDEF records on pass 1. */ LOCAL void NEAR ComDf1 (void) { int tmp; /* workaround a cl bug */ SBTYPE sb; /* COMDEF symbol */ REGISTER APROPUNDEFPTR apropUndef; /* Pointer to symbol entry */ long length; /* Communal variable length */ long cbEl; /* Size of array element */ WORD itype; /* Type index */
while(cbRec > 1) /* While there are symbols left */ { if(extMac >= EXTMAX - 1) /* Check for table overflow */ Fatal(ER_extdef); sb[0] = (BYTE) Gets(); /* Get symbol length */ if(rect == COMDEF) GetBytes(&sb[1],B2W(sb[0]));/* Read in text of symbol */ else GetLocName(sb); /* Transform local name */ #if CMDXENIX
if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen; /* Truncate if necessary */ #endif
itype = GetIndex(0,0x7FFF); /* Get type index */ tmp = Gets(); switch(tmp) /* Get data seg type */ { case TYPENEAR: length = TypLen(); /* Get length */ cbEl = 0; break; case TYPEFAR: length = TypLen(); /* Get number of elements */ /* Get element length. If too big, treat as near. Cmerge
* will never generate cbEl > 64K so this is not a problem. */ if((cbEl = TypLen()) > CBELMAX) { length *= cbEl; cbEl = 0; } break; default: InvalidObject(); /* Unrecognized DS type */ } #if FALSE
if(fDebug) { sb[sb[0]+1] = '\0'; fprintf(stdout, "%s has index = %u\r\n", sb+1, extMac); } #endif
apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRPNM, FALSE); /* Look for a matching PUBDEF */ if(apropUndef == PROPNIL) /* If there isn't one */ { /* Insert as undefined symbol */
if (vrhte == RHTENIL) apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRUND, TRUE); else apropUndef = (APROPUNDEFPTR) PropRhteLookup(vrhte, ATTRUND, TRUE);
mpextprop[extMac++] = vrprop; fCommon = (FTYPE) TRUE; /* There are communals */ if (vfCreated) apropUndef->au_flags |= UNDECIDED; else if (apropUndef->au_flags & UNDECIDED) { apropUndef->au_flags &= ~(UNDECIDED | WEAKEXT | SUBSTITUTE); apropUndef->au_flags |= STRONGEXT; } else if (apropUndef->au_flags & WEAKEXT) apropUndef->au_flags |= UNDECIDED;
if (vfCreated || !(apropUndef->au_flags & COMMUNAL)) { /* If not previously defined */ apropUndef->au_flags |= COMMUNAL; /* Mark as communal */ apropUndef->au_len = -1L; #if ILINK
apropUndef->u.au_module = imodFile; /* Save module index. */ #endif
DoCommon(apropUndef, length, (WORD) cbEl, sb); #if SYMDEB
if (fSymdeb && (sb[0] != '\0' && sb[1] > ' ' && sb[1] <= '~')) { #if O68K
/* REVIEW: This should not be under the O68K flag. */ apropUndef->au_CVtype = itype; #endif /* O68K */
DebPublic(mpextprop[extMac-1], rect); } #endif
} else DoCommon(apropUndef, length, (WORD) cbEl, sb); } else { mpextprop[extMac++] = vrprop; if (mpgsnfCod[((APROPNAMEPTR )apropUndef)->an_gsn]) /* Communal matches code PUBDEF */ DupErr(sb); /* Duplicate definition */ } } }
/****************************************************************
* * * LNmRc1: * * * * This function reads LNAME records and stores the names in * * the hash table. The function does not return a meaningful * * value. * * See p. 31 in "8086 Object Module Formats EPS." * * * ****************************************************************/
void NEAR LNmRc1(WORD fLocal) { SBTYPE lname; /* Buffer for lnames */ RBTYPE FAR *lnameTab; #if NOT ALIGN_REC
FILE *f; #endif
WORD cb;
while(cbRec > 1) /* While not at end of record */ { if (lnameMac >= lnameMax) { if (lnameMax >= (LXIVK >> 2)) Fatal(ER_nammax); lnameTab = (RBTYPE FAR *) FREALLOC(mplnamerhte, 2*lnameMax*sizeof(RBTYPE)); if (lnameTab == NULL) Fatal(ER_nammax); mplnamerhte = lnameTab; lnameMax <<= 1; }
#if ALIGN_REC
if (!fLocal) { cb = 1 + *pbRec; PropSymLookup(pbRec, ATTRNIL, TRUE); cbRec -= cb; pbRec += cb; } else { lname[0] = (BYTE)Gets(); /* Get name length */ GetLocName(lname); /* Read in text of name */ PropSymLookup(lname, ATTRNIL, TRUE); } #else
f = bsInput;
if (!fLocal && f->_cnt && (WORD)f->_cnt > (cb = 1 + *(BYTE *)f->_ptr)) { PropSymLookup((BYTE *)f->_ptr, ATTRNIL, TRUE); f->_cnt -= cb; f->_ptr += cb; cbRec -= cb; } else { lname[0] = (BYTE) Gets(); /* Get name length */ DEBUGVALUE(B2W(lname[0])); /* Length of name */ if (lname[0] > SBLEN - 1) Fatal(ER_badobj); if (fLocal) GetLocName(lname); else GetBytes(&lname[1],B2W(lname[0])); /* Read in text of name */ DEBUGSB(lname); /* The name itself */ PropSymLookup(lname, ATTRNIL, TRUE); } #endif
/* Insert symbol in hash table */ mplnamerhte[lnameMac++] = vrhte;/* Save address of hash table entry */ } }
/*
* GetPropName - get the name of a property cell. * * Return pointer to the result, stored in a static buffer. * Alternate between two buffers so we can be used in multi-part * messages. * Terminate result with null byte. */
typedef BYTE SBTYPE1[SBLEN+1];/* 1 extra for null byte */
BYTE * NEAR GetPropName(ahte) AHTEPTR ahte; { static SBTYPE1 msgbuf[2]; static int toggle = 0; char *p;
while(ahte->attr != ATTRNIL) ahte = (AHTEPTR ) FetchSym(ahte->rhteNext,FALSE); p = msgbuf[toggle ^= 1];
/* Copy string to buffer */
FMEMCPY((char FAR *) p, ahte->cch, B2W(ahte->cch[0]) + 1); p[1 + B2W(p[0])] = '\0'; /* Null-terminate */ return(p); }
/*
* SegUnreliable - warning message for 286 bug */
LOCAL void NEAR SegUnreliable (apropSn) APROPSNPTR apropSn; { static FTYPE fReported = FALSE;
MARKVP(); /* Take care of current vp */ if (!fReported) { OutWarn(ER_segunsf,1 + GetPropName(apropSn)); fReported = (FTYPE) TRUE; } }
/*** CheckClass - check segment's class name
* * Purpose: * Check if we have the segment with the same name but with different * class name. * * Input: * apropSn - real pointer to segment symbol table descriptor * rhteClass - hash vector entry for class name * * Output: * Returns real pointer to segment symbol table descriptor. * * Exceptions: * Found same segment with different class name - display error. * * Notes: * None. * *************************************************************************/
APROPSNPTR CheckClass(APROPSNPTR apropSn, RBTYPE rhteClass) { #if ILINK
FTYPE fDifClass = FALSE; #endif
while(apropSn->as_attr != ATTRNIL) { /* Look for class match or list end */ if(apropSn->as_attr == ATTRPSN && apropSn->as_rCla == rhteClass) break; /* Break if pub. with matching class */ apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE); /* Advance down the list */ #if ILINK
fDifClass = (FTYPE) TRUE; /* Same seg exists with dif. class */ #endif
} #if ILINK
if(fIncremental && fDifClass) OutError(ER_difcls, 1 + GetPropName(apropSn)); #endif
if(apropSn->as_attr == ATTRNIL) { /* If attribute not public */ vfCreated = (FTYPE) TRUE; /* New cell */ apropSn = (APROPSNPTR ) PropAdd(vrhte, ATTRPSN); /* Segment is public */ } return(apropSn); }
#if OVERLAYS
void CheckOvl(APROPSNPTR apropSn, WORD iovFile) { SNTYPE gsn; WORD fCanOverlayData; WORD fOverlaySegment;
if (fOverlays) {
// First check if mapping tables are allocated.
//
// SNTYPE mposngsn[OSNMAX];
// SNTYPE htgsnosn[OSNMAX];
if (mposngsn == NULL && htgsnosn == NULL) { mposngsn = (SNTYPE FAR *) GetMem(2*OSNMAX*sizeof(SNTYPE)); htgsnosn = (SNTYPE FAR *) &mposngsn[OSNMAX]; }
fCanOverlayData = IsDataFlg(apropSn->as_flags) && apropSn->as_ggr != ggrDGroup && apropSn->as_fExtra & FROM_DEF_FILE && apropSn->as_iov != (IOVTYPE) NOTIOVL; fOverlaySegment = IsCodeFlg(apropSn->as_flags) || fCanOverlayData; if (fOverlaySegment) { // We allow DATA segment overlaying ONLY if they ar NOT a members
// of DGROUP and HAVE preassigned overlay number form .DEF file.
// If segment is to be overlaid - check overlay number assigments
if ((apropSn->as_iov != (IOVTYPE) NOTIOVL) && (iovFile != apropSn->as_iov)) { if (apropSn->as_fExtra & FROM_DEF_FILE) { // Use .DEF file overlay assigment
iovFile = apropSn->as_iov; } else { // Use current .OBJ file overlay assigment
OutWarn(ER_badsegovl, 1 + GetPropName(apropSn), apropSn->as_iov, iovFile); } } }
if (iovFile != IOVROOT && fOverlaySegment) { if (osnMac < OSNMAX) { gsn = (SNTYPE)(apropSn->as_gsn & ((LG2OSN << 1) - 1)); // Get initial hash index
while (htgsnosn[gsn] != SNNIL) { // While buckets are full
if ((gsn += HTDELTA) >= OSNMAX) gsn -= OSNMAX; // Calculate next hash index
} htgsnosn[gsn] = osnMac; // Save overlay segment number
mposngsn[osnMac++] = apropSn->as_gsn; // Map osn to gsn
apropSn->as_iov = iovFile; // Save overlay number
} else { if (osnMac++ == OSNMAX) OutWarn(ER_osnmax, OSNMAX); apropSn->as_iov = IOVROOT; } } else apropSn->as_iov = IOVROOT; // Not an overlay
} else apropSn->as_iov = IOVROOT; } #endif
/****************************************************************
* * * SegRc1: * * * * This function processes SEGDEF records. * * See pp. 32-35 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR SegRc1(void) { WORD tysn; /* ACBP byte */ LNAMETYPE lname; /* Index into mplnamerhte */ APROPSNPTR apropSn; /* Pointer to seg. record */ SNTYPE gsn; /* Global SEGDEF number */ WORD align; /* This contributuion alignment */ WORD prevAlign; /* Logical segment aligment so FAR */ WORD comb; /* Segment combine-type */ DWORD seglen; /* Segment length */ DWORD contriblen; /* Contribution length */ DWORD cbMaxPrev; /* Segment length previously */ AHTEPTR ahte; /* Pointer to hash table entry */ SATYPE saAbs; /* Address for absolute seg */ BYTE flags; /* Segment attribute flags */ RBTYPE rhteClass; /* Class hash table address */ #if SYMDEB
APROPFILEPTR apropFile; CVINFO FAR *pCvInfo; // Pointer to CodeView information
#endif
if(snMac >= SNMAX) Fatal(ER_segdef); tysn = Gets(); /* Read in the ACBP byte */ align = (WORD) ((tysn >> 5) & 7); /* Get the alignment field */ ASSERT(align != 6); /* Not supported by this linker */ if(align == ALGNABS) /* If absolute LSEG */ { saAbs = (SATYPE) WGets(); /* Get the frame number */ Gets(); /* Punt the frame offset */ } #if OMF386
if(rect & 1) /* If 386 extension */ seglen = LGets(); else #endif
seglen = (DWORD) WGets(); /* Get segment length */ if(tysn & BIGBIT) { #if OMF386
if(rect & 1) seglen = CBMAXSEG32 + 1; /* Force fatal error below */ else #endif
seglen = LXIVK; /* Sixty-four K */ } contriblen = seglen; lname = (LNAMETYPE) GetIndex(1, (WORD) (lnameMac - 1)); /* Get segment name index */ ahte = (AHTEPTR ) FetchSym(mplnamerhte[lname],FALSE); rhteClass = mplnamerhte[(LNAMETYPE) GetIndex(1, (WORD) (lnameMac - 1))]; /* Get class name rhte */ #if SYMDEB
if (IsDebSeg(rhteClass, mplnamerhte[lname])) { /* If MS debug segment */ mpsngsn[snMac++] = 0; if (fSymdeb) /* If debugger support on */ { apropFile = (APROPFILEPTR) FetchSym(vrpropFile, TRUE); if (apropFile->af_cvInfo == NULL) apropFile->af_cvInfo = (CVINFO FAR *) GetMem(sizeof(CVINFO)); pCvInfo = apropFile->af_cvInfo; if (rhteClass == rhteDebTyp) { // "DEBTYP"
pCvInfo->cv_cbTyp = (DWORD) seglen; #ifdef RGMI_IN_PLACE
pCvInfo->cv_typ = NULL; // defer allocation until pass 2 (!)
#else
pCvInfo->cv_typ = GetMem(seglen); #endif
} else if (rhteClass == rhteDebSym) { // "DEBSYM"
pCvInfo->cv_cbSym = (DWORD) seglen; #ifdef RGMI_IN_PLACE
pCvInfo->cv_sym = NULL; // defer allocation until pass 2 (!)
#else
pCvInfo->cv_sym = GetMem(seglen); #endif
} } SkipBytes((WORD) (cbRec - 1)); return; } #endif
GetIndex(0, (WORD) (lnameMac - 1)); /* Eat overlay name index */ DEBUGVALUE(seglen); /* Debug info */ DEBUGVALUE(lname); /* Debug info */ ahte = (AHTEPTR ) FetchSym(rhteClass,FALSE); /* Fetch hash table entry from VM */ if(SbSuffix(GetFarSb(ahte->cch),"\004CODE",TRUE)) flags = FCODE; else flags = 0; #if OMF386
/* Remember if 32-bit segment */ if(tysn & CODE386BIT) { flags |= FCODE386; #if EXE386
/* Must set f386 here because newdeb needs to know in pass 1 */ f386 = (FTYPE) TRUE; #endif
} #endif
#if ILINK
else if (fIncremental && !fLibraryFile && seglen && seglen != LXIVK) { /* Add padding to non-zero-length, non-library, non-64K segment
* contributions. (64K from huge model) * UNDONE: More general overflow check, accounting for previous * UNDONE: contributions. */ seglen += (flags & FCODE) ? cbPadCode : cbPadData; } #endif
switch(align) /* Switch on alignment type */ { case ALGNABS: /* Absolute LSEG */ case ALGNBYT: /* Relocatable byte-aligned LSEG */ case ALGNWRD: /* Relocatable word-aligned LSEG */ case ALGNPAR: /* Relocatable para-aligned LSEG */ case ALGNPAG: /* Relocatable page-aligned LSEG */ #if OMF386
case ALGNDBL: /* double-word-aligned */ #endif
break;
default: /* ABSMAS, LTL LSEG, or error */ mpsngsn[snMac++] = 0; return; } ++snkey; /* Increment segment i.d. key */ if(comb = (WORD) ((tysn >> 2) & 7)) /* If "public" segment */ { apropSn = (APROPSNPTR ) PropRhteLookup(mplnamerhte[lname], ATTRPSN, (FTYPE) TRUE); /* Look up symbol table entry */ if(!vfCreated) /* If it was already there */ { apropSn = CheckClass(apropSn, rhteClass); #if OSEGEXE
if (apropSn->as_fExtra & FROM_DEF_FILE) { /* Override .DEF file segment attributes */ mpgsnfCod[apropSn->as_gsn] = (FTYPE) (flags & FCODE); apropSn->as_tysn = (TYSNTYPE) tysn; /* Save ACBP field */ #if NOT EXE386
if (flags & FCODE386 || seglen > LXIVK) apropSn->as_flags |= NS32BIT; /* Set Big/Default bit */ #endif
apropSn->as_key = snkey;/* Save the key value */ } #endif
} } else /* Else if private segment */ { apropSn = (APROPSNPTR ) PropRhteLookup(mplnamerhte[lname], ATTRPSN, (FTYPE) FALSE); /* Check if defined in .def file - caviar:4767 */ if(apropSn && apropSn->as_fExtra & FROM_DEF_FILE) { OutWarn(ER_farovl, GetPropName(apropSn)+1, "root"); }
vfCreated = (FTYPE) TRUE; /* This is a new segment */ apropSn = (APROPSNPTR ) PropAdd(mplnamerhte[lname],ATTRLSN); } if(vfCreated) /* If a new cell was created */ { if(gsnMac >= gsnMax) Fatal(ER_segmax); /* Check for table overflow */ apropSn->as_gsn = gsnMac; /* Assign new global SEGDEF number */ mpgsnrprop[gsnMac++] = vrprop; /* Save address of property list */ apropSn->as_rCla = rhteClass; /* Save ptr to class hash tab ent */ /* Superclass hash table entry */ DEBUGVALUE(apropSn); /* Debug info */ DEBUGVALUE(apropSn->as_rCla); /* Debug info */ apropSn->as_tysn = (TYSNTYPE) tysn; /* Save ACBP field */ mpgsnfCod[apropSn->as_gsn] = (FTYPE) (flags & FCODE); #if OSEGEXE
#if EXE386
apropSn->as_flags = flags & FCODE ? dfCode : dfData; /* Assume default flags */ #else
apropSn->as_flags = (WORD) (flags & FCODE ? dfCode : dfData); /* Assume default flags */ if (flags & FCODE386 || seglen > LXIVK) apropSn->as_flags |= NS32BIT; /* Set Big/Default bit */ #endif
#else
apropSn->as_flags = flags; #endif
apropSn->as_key = snkey; /* Save the key value */ apropSn->as_ComDat = NULL; /* No COMDATs yet */ #if OVERLAYS
apropSn->as_iov = (IOVTYPE) NOTIOVL; // No overlay assigment yet
#endif
} #if OMF386 AND NOT EXE386
else { /* If segment defined as both 16- and 32-bit, fatal error */
WORD fNew, fOld;
fNew = (WORD) ((flags & FCODE386) ? 1 : 0); fOld = (WORD) ( #if OSEGEXE
(apropSn->as_flags & NS32BIT) ? #else
(apropSn->as_flags & FCODE386) ? #endif
1 : 0); if (fNew != fOld) Fatal(ER_16seg32,1 + GetPropName(apropSn)); } #endif
#if OVERLAYS
CheckOvl(apropSn, iovFile); #endif
#if SYMDEB
if (seglen && (flags & FCODE)) cSegCode++; /* Count code seg's, so CV gets proper */ /* number of sstModule subsections */ #endif
gsn = apropSn->as_gsn; /* Save global SEGDEF no. */ if(comb == COMBSTK) /* If segment combines like stack */ { gsnStack = gsn; /* Set stack global SEGDEF number */ align = ALGNBYT; /* Force to byte alignment */ if (cbStack) seglen = 0L; /* Ignore stack segment size if /STACK given */ } else if(comb == COMBCOM) /* If segment combines like common */ { cbMaxPrev = apropSn->as_cbMx; /* Get previous segment size */ apropSn->as_cbMx = 0L; /* Set size to zero */ if(seglen < cbMaxPrev) seglen = cbMaxPrev; /* Take the larger of the two sizes */ } cbMaxPrev = apropSn->as_cbMx; /* Get previous size */ if(align == ALGNWRD) cbMaxPrev = (~0L<<1) & (cbMaxPrev + (1<<1) - 1); /* Round size up to word boundary */ #if OMF386
else if(align == ALGNDBL) cbMaxPrev = (~0L<<2) & (cbMaxPrev + (1<<2) - 1); #endif /* Round size up to double boundary */
else if(align == ALGNPAR) cbMaxPrev = (~0L<<4) & (cbMaxPrev + (1<<4) - 1); /* Round size up to para. boundary */ else if(align == ALGNPAG) cbMaxPrev = (~0L<<8) & (cbMaxPrev + (1<<8) - 1); /* Round size up to word boundary */
prevAlign = (WORD) ((apropSn->as_tysn >> 5) & 7);
// In Assign Addresses pass the aligment of the whole logical
// segment has to be equal to the biggest aligment of all
// contributions for given logical segment. Here we are checking
// if current contribution has bigger aligment then the
// contributions seen so FAR. The bigger aligment criteria is a
// bit tricky - the aligment constants are defined as follows:
//
// 1 - byte aligment
// 2 - word aligment
// 3 - paragraph aligment
// 4 - page aligment
// 5 - double word aligment
//
// The aligment ordering is as follows:
//
// byte < word < dword < para < page
// 1 2 5 3 4
//
// If align greater than prev. val.
if (prevAlign == ALGNDBL || align == ALGNDBL) { if (prevAlign == ALGNDBL && align >= ALGNPAR) apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5)); /* Use new value */ else if (align == ALGNDBL && prevAlign <= ALGNWRD) apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5)); /* Use new value */ } else if (align > prevAlign) apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 31) | (align << 5)); /* Use new value */
if (align != ALGNABS) /* If not an absolute LSEG */ { seglen += cbMaxPrev; #if EXE386 OR OMF386
if ((flags & FCODE386) != 0 #if O68K
&& iMacType == MAC_NONE #endif
) { #if EXE386
if (seglen < cbMaxPrev) /* errmsg takes # megabytes */ Fatal(ER_seg386, 1 + GetPropName(apropSn), 1 << (LG2SEG32 - 20)); #else
if (seglen > CBMAXSEG32) /* errmsg takes # megabytes */ Fatal(ER_seg386,1 + GetPropName(apropSn),1 << (LG2SEG32 - 20)); #endif
} else #endif
if (seglen > LXIVK) { if (comb != COMBSTK) OutError(ER_segsize,1 + GetPropName(apropSn)); /* Check for segment overflow */ else { if (!cbStack) OutWarn(ER_stack64); cbStack = LXIVK - 2;/* Assume 64k stack segment */ } } apropSn->as_cbMx = seglen; /* Save new segment size */ /*
* If this is a 16-bit code segment, check for unreliable * lengths due to the 286 bug. For DOS exes, assume worst * case, i.e. real mode limit. */ if((flags & FCODE) && !(EXE386 && (flags & FCODE386))) #if OIAPX286
if(seglen == LXIVK) #else
if(seglen > LXIVK - 36) #endif
SegUnreliable(apropSn); } else apropSn->as_cbMx = (long) saAbs; /* "Hack to save origin of abs seg" */ mpgsndra[gsn] = cbMaxPrev; /* Save previous size */ mpsngsn[snMac++] = gsn; /* Map SEGDEF no to global SEGDEF no */ MARKVP(); /* Virtual page has changed */ if (fFullMap && contriblen) AddContributor(gsn, (unsigned long) -1L, contriblen); }
/****************************************************************
* * * GrpRc1: * * * * This function processes GRPDEF records on pass 1. * * See pp. 36-39 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR GrpRc1(void) { LNAMETYPE lnameGroup; /* Group LNAME number */ SNTYPE sn; /* Group (local) segment number */ APROPSNPTR apropSn; APROPGROUPPTR apropGroup; GRTYPE ggr; /* Global GRPDEF number */ WORD gcdesc; /* GRPDEF component descriptor */ #if EXE386
BYTE *pGrName; /* Group name */ #endif
if(grMac >= GRMAX) Fatal(ER_grpdef); lnameGroup = GetIndex(1, (WORD) (lnameMac - 1)); /* Read in group name index */ apropGroup = (APROPGROUPPTR ) PropRhteLookup(mplnamerhte[lnameGroup], ATTRGRP, (FTYPE) TRUE); /* Look up cell in hash table */ if(vfCreated) /* If entry did not exist before */ { if(ggrMac >= GGRMAX) Fatal(ER_grpmax); apropGroup->ag_ggr = ggrMac++; /* Save global GRPDEF no. */ } ggr = apropGroup->ag_ggr; /* Get global GRPDEF no. */ mpggrrhte[ggr] = mplnamerhte[lnameGroup]; /* Save pointer to name */ mpgrggr[grMac++] = ggr; /* Map local to global */ #if EXE386
/* Check for pseudo-group FLAT here */ pGrName = GetFarSb(((AHTEPTR)(FetchSym(mpggrrhte[ggr], FALSE)))->cch); if (SbCompare(pGrName, sbFlat, TRUE)) ggrFlat = ggr; #endif
while(cbRec > 1) /* While not at end of record */ { gcdesc = Gets(); /* Read in the descriptor */ ASSERT(gcdesc == 0xFF); /* Linker doesn't handle others */ sn = GetIndex(1,snMac); /* Get local SEGDEF index */ apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE); /* Fetch from virt mem */ if(apropSn->as_ggr == GRNIL) { /* Store global GRPDEF no. if none */ apropSn->as_ggr = ggr; #if OSEGEXE
/*
* Check if a segment which is part of DGROUP was defined * as class "CODE", also if it was given a sharing attribute * that conflicts with the autodata type. * Could only happen if seg defined in a def-file. Must be * done here because only now do we know that it's in DGROUP. */ if(ggr == ggrDGroup && (apropSn->as_fExtra & FROM_DEF_FILE)) {
#if EXE386
if (IsEXECUTABLE(apropSn->as_flags)) { SetREADABLE(apropSn->as_flags); SetWRITABLE(apropSn->as_flags); apropSn->as_rCla = rhteBegdata; mpgsnfCod[apropSn->as_gsn] = FALSE; OutWarn(ER_cod2dat,1 + GetPropName(apropSn)); apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE); } if (((vFlags & NESOLO) && !IsSHARED(apropSn->as_flags)) || ((vFlags & NEINST) && IsSHARED(apropSn->as_flags))) { if (vFlags & NESOLO) SetSHARED(apropSn->as_flags); else apropSn->as_flags &= ~OBJ_SHARED; OutWarn(ER_adcvt,1 + GetPropName(apropSn)); }
#else
if((apropSn->as_flags & NSTYPE) != NSDATA) { apropSn->as_flags &= ~NSTYPE; apropSn->as_flags |= NSDATA; apropSn->as_rCla = rhteBegdata; mpgsnfCod[apropSn->as_gsn] = FALSE; OutWarn(ER_cod2dat,1 + GetPropName(apropSn)); apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[mpsngsn[sn]],TRUE); } if(((vFlags & NESOLO) && !(apropSn->as_flags & NSSHARED)) || ((vFlags & NEINST) && (apropSn->as_flags & NSSHARED))) { if(vFlags & NESOLO) apropSn->as_flags |= NSSHARED; else apropSn->as_flags &= ~NSSHARED; OutWarn(ER_adcvt,1 + GetPropName(apropSn)); } #endif /* EXE386 */
} #endif /* OSEGEXE */
} else if (apropSn->as_ggr != ggr)/* If segment belongs to other group */ { if(fLstFileOpen) fflush(bsLst); /* Flush list file, if any */ OutWarn(ER_grpmul,1 + GetPropName(apropSn)); } } }
void NEAR DupErr(BYTE *sb)/* Duplicate definition error */ /* Symbol to which error refers */ { BSTYPE bsTmp; /* Temporary file pointer */ MSGTYPE msg; /* Message to use */ #if OSMSDOS
extern char *pExtDic; /* Pointer to extended dictionary */ #endif
SBTYPE sbUndecor; /* a buffer for undecorated name */
/* If this module is in an extended dictionary, suggest /NOEXT in error
* message. */ msg = (MSGTYPE) ( #if OSMSDOS
pExtDic ? ER_symdup1 : #endif
ER_symdup);
UndecorateSb((char FAR*) sb, (char FAR*) sbUndecor, sizeof(sbUndecor) );
OutError(msg,1 + sbUndecor); if(fLstFileOpen && bsErr != bsLst) { bsTmp = bsErr; bsErr = bsLst; OutError(msg,1 + sbUndecor); bsErr = bsTmp; } }
/****************************************************************
* * * PubRc1: * * * * This function processes PUBDEF records on pass 1. * * See pp. 44-46 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR PubRc1(void) { GRTYPE ggr; /* Group definition number */ SNTYPE sn; /* Local SEGDEF no. */ SNTYPE gsn; /* Global SEGDEF no. */ RATYPE dra; SBTYPE sb; /* Public symbol */ RATYPE ra; /* Public symbol offset */ APROPNAMEPTR apropName; /* Table entry for symbol name */ WORD type; /* Local type no. */ int fSkipCv = FALSE;/* Don't register DATA PUBDEF if a COMDEF
for that symbol has already been seen */
DEBUGVALUE(grMac - 1); /* Debug info */ ggr = (GRTYPE) GetIndex(0, (WORD) (grMac - 1));/* Get group index */ DEBUGVALUE(ggr); /* Debug info */ if (!(sn = GetIndex(0, (WORD) (snMac - 1))))/* If frame number present */ { gsn = 0; /* No global SEGDEF no. */ dra = 0; SkipBytes(2); /* Skip the frame number */ } else /* Else if local SEGDEF no. given */ { if (ggr != GRNIL) ggr = mpgrggr[ggr]; /* If group specified, get global no */ gsn = mpsngsn[sn]; /* Get global SEGDEF no. */ dra = mpgsndra[gsn]; } DEBUGVALUE(cbRec); /* Debug info */ while (cbRec > 1) /* While there are symbols left */ { sb[0] = (BYTE) Gets(); /* Get symbol length */ if (TYPEOF(rect) == PUBDEF) GetBytes(&sb[1],B2W(sb[0]));/* Read in symbol text */ else GetLocName(sb); /* Transform local name */ #if CMDXENIX
if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen; /* Truncate if necessary */ #endif
#if OMF386
if (rect & 1) ra = LGets(); else #endif
ra = WGets(); /* Get symbol segment offset */ type = GetIndex(0,0x7FFF); /* Get type index */ if (!vfNewOMF) type = 0;
/* Look for symbol among undefined */
apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRUND, FALSE);
if (apropName != PROPNIL) /* Symbol known to be undefined */ { if (((APROPUNDEFPTR )apropName)->au_flags & COMMUNAL) { if (mpgsnfCod[gsn]) DupErr(sb); /* Communal matches code PUBDEF */ fSkipCv = TRUE; } vfCreated = (FTYPE) TRUE; } else { /* Look for symbol among ALIASes */
if (vrhte == RHTENIL) apropName = PROPNIL; else apropName = (APROPNAMEPTR) PropRhteLookup(vrhte, ATTRALIAS, FALSE);
if (apropName != PROPNIL) { #if FDEBUG
if (fDebug) { sb[sb[0] + 1] = '\0'; OutWarn(ER_ignoalias, &sb[1]); } #endif
continue; }
else if (vrhte == RHTENIL) { apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRPNM, TRUE); }
else { apropName = (APROPNAMEPTR) PropRhteLookup(vrhte, ATTRPNM, TRUE); } }
if (vfCreated) /* If new PUBNAM entry created or */ { /* old UNDEF entry to modify */
// If printable symbol, increment counter and set flags
if (sb[0] != '\0' && sb[1] > ' ' && sb[1] <= '~') { ++pubMac; apropName->an_flags = FPRINT; } else { #if ILINK
++locMac; /* Included in .SYM file */ #endif
}
apropName->an_attr = ATTRPNM; /* Symbol is a public name */ apropName->an_ra = ra + dra;/* Give symbol its adjusted offset */ apropName->an_gsn = gsn; /* Save its global SEGDEF no. */ apropName->an_ggr = ggr; /* Save its global SEGDEF no. */ #if OVERLAYS
apropName->an_thunk = THUNKNIL; #endif
#if ILINK
apropName->an_module = imodFile; #endif
MARKVP(); /* Mark virtual page as changed */ #if SYMDEB
if (fSymdeb && (apropName->an_flags & FPRINT) && !fSkipPublics && !fSkipCv) { // Remember CV type index
apropName->an_CVtype = type; DebPublic(vrprop, rect); } #endif
} else if(apropName->an_gsn != gsn || apropName->an_ra != ra + dra) { DupErr(sb); /* Definitions do not match */ } } }
/****************************************************************
* * * ExtRc1: * * * * This function processes EXTDEF records on pass 1. * * See pp. 47-48 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR ExtRc1(void) { SBTYPE sb; /* EXTDEF symbol */ APROPUNDEFPTR apropUndef; /* Pointer to symbol entry */ APROPALIASPTR apropAlias; /* Pointer to symbol entry */ APROPNAMEPTR apropName; /* Pointer to symbol entry */ APROPCOMDATPTR apropComdat; /* pointer to symbol entry */ WORD itype; /* Type index */ RBTYPE rhte; /* Virt. addr. of hash table entry */ AHTEPTR ahte; // Symbol table hash entry
while (cbRec > 1) /* While there are symbols left */ { if (extMac >= EXTMAX - 1) /* Check for table overflow */ Fatal(ER_extdef);
if (TYPEOF(rect) == CEXTDEF) { itype = GetIndex(0, (WORD) (lnameMac - 1)); rhte = mplnamerhte[itype]; ahte = (AHTEPTR) FetchSym(rhte, FALSE); FMEMCPY((char FAR *) sb, ahte->cch, ahte->cch[0] + 1);
/* Look for a matching PUBDEF */
apropUndef = (APROPUNDEFPTR) PropRhteLookup(rhte, ATTRPNM, FALSE); } else { rhte = RHTENIL;
sb[0] = (BYTE) Gets(); /* Get symbol length */ if (TYPEOF(rect) == EXTDEF) GetBytes(&sb[1], B2W(sb[0])); /* Read in text of symbol */ else GetLocName(sb); /* Get local name */ #if CMDXENIX
if (symlen && B2W(sb[0]) > symlen) sb[0] = symlen; /* Truncate if necessary */ #endif
/* Look for a matching PUBDEF */
apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRPNM, FALSE); }
DEBUGSB(sb); /* Print symbol */
if (!vfNewOMF) /* If old-style OMF */ itype = GetIndex(0, (WORD) (typMac - 1));/* Get type index */ else itype = GetIndex(0, 0x7FFF); /* Get type index (any value OK) */
#if FALSE
if (fDebug) { sb[sb[0]+1] = '\0'; fprintf(stdout, "\r\n%s has index = %u", sb+1, extMac); } #endif
apropName = PROPNIL;
if (apropUndef == PROPNIL) /* If there isn't one */ { /* Look for a matching ALIAS */
if (vrhte == RHTENIL) apropAlias = PROPNIL; else apropAlias = (APROPALIASPTR) PropRhteLookup(vrhte, ATTRALIAS, FALSE);
if (apropAlias != PROPNIL) { /* ALIAS matches this EXTDEF */
mpextprop[extMac++] = apropAlias->al_sym; apropName = (APROPNAMEPTR) FetchSym(apropAlias->al_sym, TRUE); if (apropName->an_attr == ATTRPNM) { // If substitute name is a PUBDEF then use it
if (!vfNewOMF && itype && (mpitypelen[itype] > 0L) && mpgsnfCod[apropName->an_gsn]) /* Communal matches code PUBDEF */ DupErr(sb); /* Duplicate definition */ } else { // The substitute name is an EXTDEF
// Mark substitute name so it causes the library search, because
// we don't know neither the alias nor the substitute
apropUndef = (APROPUNDEFPTR) apropName; apropUndef->au_flags |= SEARCH_LIB; apropName = PROPNIL; #if NEW_LIB_SEARCH
if (fStoreUndefsInLookaside) StoreUndef((APROPNAMEPTR)apropUndef, RhteFromProp((APROPPTR)apropUndef),0,0); #endif
#ifdef DEBUG_SHOWALIAS
sb[sb[0]+1] = '\0'; fprintf(stderr, "extdef alias: %s\r\n", sb+1); fflush(stderr); #endif
} } else { /* Insert as undefined symbol */
if (vrhte == RHTENIL) apropUndef = (APROPUNDEFPTR) PropSymLookup(sb, ATTRUND, TRUE); else apropUndef = (APROPUNDEFPTR) PropRhteLookup(vrhte, ATTRUND, TRUE);
mpextprop[extMac++] = vrprop; if(vfCreated) { apropUndef->au_flags |= UNDECIDED; apropUndef->au_len = -1L; #if NEWLIST
apropUndef->u.au_rbNxt = rbLstUndef; rbLstUndef = vrprop; #endif
} else if (apropUndef->au_flags & UNDECIDED) { apropUndef->au_flags &= ~(UNDECIDED | WEAKEXT | SUBSTITUTE); apropUndef->au_flags |= STRONGEXT;
#if NEW_LIB_SEARCH
if (fStoreUndefsInLookaside) StoreUndef((APROPNAMEPTR)apropUndef, RhteFromProp((APROPPTR)apropUndef),0,0); #endif
} else if (apropUndef->au_flags & WEAKEXT) apropUndef->au_flags |= UNDECIDED;
if (vfNewOMF) continue; /* Skip if module uses COMDEFs */ if(itype) /* If there is reference to TYPDEF */ DoCommon(apropUndef, mpitypelen[itype], (WORD) (mpityptyp[itype] ? mpitypelen[mpityptyp[itype]] : 0), sb);
if (apropUndef->au_len > 0L) apropUndef->au_flags |= COMMUNAL; /* Mark as true communal or not */ MARKVP(); /* Mark virt page as changed */ } } else { apropName = (APROPNAMEPTR ) apropUndef; mpextprop[extMac++] = vrprop; if (!vfNewOMF && itype && (mpitypelen[itype] > 0L) && mpgsnfCod[((APROPNAMEPTR )apropUndef)->an_gsn]) /* Communal matches code PUBDEF */ DupErr(sb); /* Duplicate definition */ }
// If we are processing CEXTDEF/EXTDEF and there is public symbol
// matching the CEXTDEF/EXTDEF symbol, then mark COMDAT descriptor
// as referenced
if (apropName != PROPNIL) { apropComdat = (APROPCOMDATPTR) PropRhteLookup(vrhte, ATTRCOMDAT, #if TCE
FALSE #else
TRUE #endif
);
if (apropComdat != PROPNIL) { apropComdat->ac_flags |= REFERENCED_BIT; #if TCE_DEBUG
fprintf(stdout, "\r\nEXTDEF1 referencing '%s' ", 1+GetPropName(apropComdat)); #endif
} } } }
#if OSEGEXE AND NOT QCLINK
/****************************************************************
* * * imprc1: * * * * This function processes Microsoft OMF extension records of * * type IMPDEF (i.e. IMPort DEFinition records). * * * ****************************************************************/
LOCAL void NEAR imprc1(void) { SBTYPE sbInt; /* Internal name */ SBTYPE sbMod; /* Module name */ SBTYPE sbImp; /* Imported name */ FTYPE fOrd; /* Import-by-ordinal flag */
#if ODOS3EXE
fNewExe = (FTYPE) TRUE; /* Import forces new-format exe */ #endif
fOrd = (FTYPE) Gets(); /* Get ordinal flag */ sbInt[0] = (BYTE) Gets(); /* Get length of internal name */ GetBytes(&sbInt[1],B2W(sbInt[0])); /* Get the internal name */ sbMod[0] = (BYTE) Gets(); /* Get length of module name */ GetBytes(&sbMod[1],B2W(sbMod[0])); /* Get the module name */ if(!(fOrd & 0x1)) /* If import by name */ { sbImp[0] = (BYTE) Gets(); /* Get length of imported name */ if(sbImp[0] != '\0') /* If names differ */ { GetBytes(&sbImp[1],B2W(sbImp[0])); /* Get the imported name */ #if EXE386
NewImport(sbImp,0,sbMod,sbInt, (fOrd & 0x2)); #else
NewImport(sbImp,0,sbMod,sbInt); #endif
/* Enter new import */ } else #if EXE386
NewImport(sbInt,0,sbMod,sbInt, (fOrd & 0x2)); #else
NewImport(sbInt,0,sbMod,sbInt); #endif
/* Enter new import */ } else #if EXE386
NewImport(NULL,WGets(),sbMod,sbInt, (fOrd & 0x2)); #else
NewImport(NULL,WGets(),sbMod,sbInt); #endif
/* Else import by ordinal */ }
/****************************************************************
* * * exprc1: * * * * This function processes Microsoft OMF extension records of * * type EXPDEF (i.e. EXPort DEFinition records). * * * ****************************************************************/
LOCAL void NEAR exprc1(void) { SBTYPE sbInt; /* Internal name */ SBTYPE sbExp; /* Exported name */ WORD OrdNum; /* Ordinal number */ WORD fRec; /* Record flags */
#if ODOS3EXE
fNewExe = (FTYPE) TRUE; /* Export forces new-format exe */ #endif
fRec = (BYTE) Gets(); /* Get record flags */ sbExp[0] = (BYTE) Gets(); /* Get length of exported name */ GetBytes(&sbExp[1],B2W(sbExp[0])); /* Get the exported name */ sbInt[0] = (BYTE) Gets(); /* Get length of internal name */ if (sbInt[0]) GetBytes(&sbInt[1],B2W(sbInt[0])); /* Get the internal name */ if (fRec & 0x80) { /* If ordinal number specified */ OrdNum = WGets(); /* Read it and set highest bit */ OrdNum |= ((fRec & 0x40) << 1); /* if resident name */ } else OrdNum = 0; /* No ordinal number specified */
// Convert flags:
// OMF flags:
// 80h = set if ordinal number specified
// 40h = set if RESIDENTNAME
// 20h = set if NODATA
// 1Fh = # of parameter words
// EXE flags:
// 01h = set if entry is exported
// 02h = set if entry uses global (shared) data segment (!NODATA)
// F8h = # of parameter words
//
// Since the logic is reversed for the NODATA flag, we toggle bit 0x20
// in the OMF flags via the expression ((fRec & 0x20) ^ 0x20).
fRec = (BYTE) (((fRec & 0x1f) << 3) | (((fRec & 0x20) ^ 0x20) >> 4) | 1);
// Mark fRec, so NewExport doesn't try to free name buffers
fRec |= 0x8000;
if (sbInt[0]) NewExport(sbExp, sbInt, OrdNum, fRec); else NewExport(sbExp, NULL, OrdNum, fRec); } #endif /* OSEGEXE */
/****************************************************************
* * * ComRc1: * * * * This function processes COMENT records on pass 1. * * See pp. 86-87 in "8086 Object Module Formats EPS." * * * ****************************************************************/
#pragma check_stack(on)
LOCAL void NEAR ComRc1(void) { #if OXOUT OR OIAPX286
WORD mismatch; /* Model mismatch flag */ #endif
#if FALSE
static BYTE modtype = 0; /* Initial model type */ BYTE curmodtype; /* Current model type */ #endif
SBTYPE text; /* Comment text */ SBTYPE LibName; APROPFILEPTR aprop; WORD iextWeak; WORD iextDefRes; APROPUNDEFPTR undefName; FTYPE fIgnoreCaseSave; BYTE flags; void FAR *pTmp; #if ILINK
SNTYPE noPadSn; APROPSNPTR apropSn; /* Pointer to seg. record */ #endif
#if O68K
BYTE chModel; #endif /* O68K */
Gets(); /* Skip byte 1 of comment type field */ switch(Gets()) /* Switch on comment class */ { #if OEXE
case 0: /* Translator record */ if(fNewExe) break; #if ODOS3EXE
text[0] = (BYTE) (cbRec - 1);/* Get length of comment */ GetBytes(&text[1],(WORD)(cbRec - 1));/* Read in text of comment */ /*
* If translator is pre-3.30 MS/IBM PASCAL or FORTRAN, * force on /DS and /NOG. */ if(SbCompare(text,"\011MS PASCAL", TRUE) || SbCompare(text,"\012FORTRAN 77", TRUE)) vfDSAlloc = fNoGrpAssoc = (FTYPE) TRUE; #endif
break; #endif
case 0x81: /* Library specifier */ #if OSMSDOS OR OSPCDOS
case 0x9F: /* Library specifier (alt.) */ #endif
text[0] = (BYTE) (cbRec - 1);/* Get length of comment */ if (text[0] == 0) break; /* Skip empty spec */ GetBytes(&text[1], (WORD) (cbRec - 1));/* Read in text of comment */ /* Add name to search list */ #if CMDMSDOS
strcpy(LibName, sbDotLib); UpdateFileParts(LibName, text); #endif
#if CMDXENIX
memcpy(LibName, text, B2W(text[0]) + 1); /* Leave name unchanged */ #endif
if(!vfNoDefaultLibrarySearch) { #if OSMSDOS
fIgnoreCaseSave = fIgnoreCase; fIgnoreCase = (FTYPE) TRUE;
/* If the name begins with a drive letter, skip it. This
* is to allow compatibility with old compilers which * generated comments of the form "A:FOO.LIB". */ if(LibName[2] == ':' && B2W(LibName[0]) > 1) { LibName[2] = (BYTE) (LibName[0] - 2); if (PropSymLookup(LibName+2,ATTRSKIPLIB,FALSE) == PROPNIL) AddLibrary(LibName+2); } else #endif
if (PropSymLookup(LibName,ATTRSKIPLIB,FALSE) == PROPNIL) AddLibrary(LibName); fIgnoreCase = fIgnoreCaseSave; } break; #if OEXE
case 0x9E: /* Force segment order directive */ SetDosseg(); /* Set switch */ break; #endif /* OEXE */
case 0x9D: /* Model specifier */ #if FALSE
/* Removed */ mismatch = 0; /* Assume all is well */ while(cbRec > 1) /* While bytes remain */ { curmodtype = Gets(); /* Get byte value */ switch(curmodtype) { case 'c': /* Compact model */ case 's': /* Small model */ case 'm': /* Medium model */ case 'l': /* Large model */ case 'h': /* Huge model */ if (modtype) mismatch = curmodtype != modtype; else modtype = curmodtype; break; } } if(mismatch) OutWarn(ER_memmodel); /* Warn if mismatch found */ #endif
#if OXOUT OR OIAPX286
mismatch = 0; /* Assume all is well */ while(cbRec > 1) /* While bytes remain */ { modtype = Gets(); /* Get byte value */ if (fMixed) continue; /* Mixed model means we don't care */ switch(modtype) { case 'c': /* Compact model */ if(!fLarge || fMedium) mismatch = 1; break; /* Warn if near data or FAR code */
case 's': /* Small model */ if(fLarge || fMedium) mismatch = 1; /* Warn if FAR data or FAR code */ break;
case 'm': /* Medium model */ if(fLarge || !fMedium) mismatch = 1; /* Warn if FAR data or near code */ break;
case 'l': /* Large model */ case 'h': /* Huge model */ if(!fLarge || !fMedium) mismatch = 1; /* Warn if near data or near code */ break; } } if(mismatch) OutError(ER_modelmis); /* Warn if mismatch found */ #endif /* OXOUT OR OIAPX286 */
#if O68K
while (!f68k && cbRec > 1) /* While bytes remain */ { chModel = (BYTE) Gets();/* Get byte value */ f68k = (FTYPE) F68KCODE(chModel); } #endif /* O68K */
break;
#if OSEGEXE AND NOT QCLINK
case 0xA0: /* Microsoft OMF extension */ switch(Gets()) /* Switch on extension record type */ { case 0x01: /* IMPort DEFinition */ imprc1(); /* Call the processing routine */ break; case 0x02: /* EXPort DEFinition */ exprc1(); /* Call the processing routine */ break; case 0x03: break; /* In pass-1 skip INCDEF's for QC */ #if EXE386
case 0x04: // OMF extension - link386
// if (IsDLL(vFlags))
// vFlags |= E32PROTDLL;
// Protected memory library module
break; #endif
case 0x05: // C++ directives
flags = (BYTE) Gets();// Get flags field
#if NOT EXE386
if (flags & 0x01) fNewExe = (FTYPE) TRUE; // PCODE forces segmented exe format
#endif
#if SYMDEB
if (flags & 0x02) fSkipPublics = (FTYPE) TRUE; // In C++ they don't want PUBLIC subsection in CV info
#endif
if ((flags & 0x04) && !fIgnoreMpcRun) // ignore if /PCODE:NOMPC
fMPC = (FTYPE) TRUE; // PCODE app - spawn MPC
break; case 0x06: // target is a big-endian machine
#if O68K
fTBigEndian = (FTYPE) TRUE; #endif /* O68K */
break; case 0x07: // Use SSTPRETYPES instead of SSTTYPES4 in OutSSt
aprop = (APROPFILEPTR ) FetchSym(vrpropFile, TRUE); aprop->af_flags |= FPRETYPES; break;
default: /* Unknown */ InvalidObject(); /* Invalid object module */ } break; #endif
case 0xA1: /* 1st OMF extension: COMDEFs */ vfNewOMF = (FTYPE) TRUE; aprop = (APROPFILEPTR ) FetchSym(vrpropFile, TRUE); aprop->af_flags |= FNEWOMF; break;
case 0xA2: /* 2nd OMF extension */ switch(Gets()) { case 0x01: /* Start linkpass2 records */ /*
* WARNING: It is assumed this comment will NOT be in a * module whose MODEND record contains a program starting * address. If there are overlays, we need to see the * starting address on pass 1 to define the symbol $$MAIN. */ fP2Start = fModEnd = (FTYPE) TRUE; break; default: break; } break;
#if FALSE
case 0xA3: // DON'T use - already used by LIB
break; #endif
case 0xA4: /* OMF extension - EXESTR */ fExeStrSeen = (FTYPE) TRUE; // WARNING: The code in this loop assumes:
//
// ExeStrLen, cBrec and ExeStrMax are 16-bit unsigned WORDS
// An int is 32-bits
// All arithmetic and comparisons are 32-bit
//
while (cbRec > 1) { // Limit total EXESTR to 64K - 2 bytes. We lose 1 because 0 means 0,
// and we lose another because the buffer extension loop tops out at
// 0xFFFE bytes.
if (ExeStrLen + cbRec - 1 > 0xFFFEu) { SkipBytes ( (WORD) (cbRec - 1) ); } else if (ExeStrLen + cbRec - 1 > ExeStrMax) { if (ExeStrBuf == NULL) { ExeStrBuf = GetMem(cbRec - 1); ExeStrMax = cbRec - 1; } else { // This loop doubles the buffer size until it overflows 16 bits. After this,
// it adds one half of the difference between the current value and 0xFFFF
//
while (ExeStrMax < ExeStrLen + cbRec - 1) { ASSERT (ExeStrMax != 0); if ((ExeStrMax << 1) >= 0x10000) ExeStrMax += (~ExeStrMax & 0xFFFF) >> 1; else ExeStrMax <<= 1; } pTmp = GetMem(ExeStrMax); FMEMCPY(pTmp, ExeStrBuf, ExeStrLen); FFREE(ExeStrBuf); ExeStrBuf = pTmp; } } // This must be done first because GetBytes() decrements
// cbRec as a side effect.
ExeStrLen += cbRec - 1; GetBytes(&ExeStrBuf[ExeStrLen-cbRec+1], (WORD) (cbRec - 1));
} break;
case 0xA6: /* OMF extension - INCERR */ Fatal(ER_incerr); /* Invalid object due to aborted incremental compile */ break; #if ILINK
case 0xA7: /* OMF extension - NOPAD */ if (fIncremental && !fLibraryFile) { /* Remove padding from non-zero-length, non-library,
* non-64K segment contributions. (64K from huge model) */ while (cbRec > 1) { noPadSn = GetIndex(1, snMac - 1); apropSn = (APROPSNPTR) FetchSym(mpgsnrprop[mpsngsn[noPadSn]], TRUE); if (apropSn->as_cbMx > 0L && apropSn->as_cbMx != LXIVK) { apropSn->as_cbMx -= mpgsnfCod[mpsngsn[noPadSn]] ? cbPadCode : cbPadData; apropSn->as_fExtra |= NOPAD; } } } break; #endif
case 0xA8: /* OMF extension - WeaK EXTern */ while (cbRec > 1) { iextWeak = GetIndex(1, (WORD) (extMac - 1)); /* Get weak extern index */ iextDefRes = GetIndex(1, (WORD) (extMac - 1)); /* Get default extern index */ #if FALSE
DumpWeakExtern(mpextprop, iextWeak, iextDefRes); #endif
if (mpextprop[iextWeak] != PROPNIL && iextWeak < extMac) { undefName = (APROPUNDEFPTR ) FetchSym(mpextprop[iextWeak], TRUE); if (undefName->au_attr == ATTRUND) { // If this is EXTDEF
if (undefName->au_flags & UNDECIDED) { // This can be one of the following:
// - weakness specified for the first time
// if WEAKEXT is not set
// - redefinition of weakness if the WEAKEXT
// is set.
// In case of weakness redefinition check if
// it specified the same default resolution as
// the first one. Issue warning if different
// default resolutions and override old one
// with new. In both cases reset UNDECIDED bit.
undefName->au_flags &= ~UNDECIDED; if (undefName->au_flags & WEAKEXT) { if (undefName->au_Default != mpextprop[iextDefRes]) redefinition(iextWeak, iextDefRes, undefName->au_Default); undefName->au_Default = mpextprop[iextDefRes]; } else { undefName->au_Default = mpextprop[iextDefRes]; undefName->au_flags |= WEAKEXT; } } // Ignore weakness - must be strong extern form
// some other .OBJ
} } else InvalidObject(); } break; default: /* Unrecognized */ break; } if (cbRec > 1) SkipBytes((WORD) (cbRec - 1)); /* Punt rest of text */ }
/*** AliasRc1 - pass 1 ALIAS record processing
* * Purpose: * Read and decode ALIAS OMF record (Microsoft OMF extension). * ALIAS record introduces pair of names - alias name and substitute * name. Enter both names into linker symbol table. * * Input: * No explicit value is passed. When this function is called the record * type and lenght are already read, so we can start reading name pairs. * * Output: * No explicit value is returned. Names are entered into symbol table. * * Exceptions: * Warning - redefinition of ALIAS <name>; substitute name changed * from <name1> to <name2>. * * Notes: * None. * *************************************************************************/
LOCAL void NEAR AliasRc1(void) { SBTYPE alias; SBTYPE substitute; APROPALIASPTR aliasDsc; RBTYPE vAliasDsc; APROPNAMEPTR pubName; APROPUNDEFPTR undefName; RBTYPE vPtr; WORD fReferenced;
while (cbRec > 1) /* While there are symbols left */ { /* Read alias and its substitute */
alias[0] = (BYTE) Gets(); GetBytes(&alias[1], B2W(alias[0])); substitute[0] = (BYTE) Gets(); GetBytes(&substitute[1], B2W(substitute[0])); aliasDsc = (APROPALIASPTR) PropSymLookup(alias, ATTRALIAS, FALSE); vAliasDsc = vrprop; if (aliasDsc == PROPNIL) { /* New ALIAS - check if we have PUBDEF for the alias name */
pubName = (APROPNAMEPTR ) PropSymLookup(alias, ATTRPNM, FALSE); if (pubName == PROPNIL) { /* Enter ALIAS name in to symbol table */
aliasDsc = (APROPALIASPTR) PropSymLookup(alias, ATTRALIAS, TRUE); vAliasDsc = vrprop; #if SYMDEB
if (fSymdeb) DebPublic(vrprop, ALIAS); #endif
// Check if we have an EXTDEF for alias name. If we have
// this means, that substitute name has to be used in
// the library search.
undefName = (APROPUNDEFPTR ) PropSymLookup(alias, ATTRUND, FALSE); fReferenced = (WORD) (undefName != PROPNIL);
// Check if we know the substitute name as PUBDEF or EXTDEF
pubName = (APROPNAMEPTR ) PropSymLookup(substitute, ATTRPNM, FALSE); if (pubName != PROPNIL) vPtr = vrprop; else { undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, FALSE); if (undefName != NULL) { vPtr = vrprop; undefName->au_flags |= (SUBSTITUTE | SEARCH_LIB); undefName->au_Default = vAliasDsc; #if NEW_LIB_SEARCH
if (fStoreUndefsInLookaside) StoreUndef((APROPNAMEPTR)undefName, RhteFromProp((APROPPTR)undefName),0,0); #endif
} else { /* Enter substitute name into symbol table */ /* as undefined symbol */
if (extMac >= EXTMAX - 1) Fatal(ER_extdef);
undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, TRUE); vPtr = vrprop; mpextprop[extMac++] = vrprop; if (fReferenced) undefName->au_flags |= (STRONGEXT | SUBSTITUTE | SEARCH_LIB); else undefName->au_flags |= (UNDECIDED | SUBSTITUTE); undefName->au_len = -1L; undefName->au_Default = vAliasDsc; #if NEWLIST
undefName->u.au_rbNxt = rbLstUndef; rbLstUndef = vrprop; #endif
} }
/* Attach substitute symbol to the ALIAS */
aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE); aliasDsc->al_sym = vPtr;
} else { #if FDEBUG
if (fDebug) { alias[alias[0] + 1] = '\0'; OutWarn(ER_ignoalias, &alias[1]); } #endif
} } else { /* Check if we have redefinition */
vPtr = aliasDsc->al_sym; pubName = (APROPNAMEPTR ) PropSymLookup(substitute, ATTRPNM, FALSE); if (pubName != PROPNIL) { if (vPtr != vrprop) { aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE); aliasDsc->al_sym = vrprop; OutWarn(ER_aliasredef, &alias[1], 1 + GetPropName(pubName), &substitute[1]); } } else { undefName = (APROPUNDEFPTR ) PropSymLookup(substitute, ATTRUND, FALSE); if (undefName != PROPNIL) { if (vPtr != vrprop) { aliasDsc = (APROPALIASPTR) FetchSym(vAliasDsc, TRUE); aliasDsc->al_sym = vrprop; OutWarn(ER_aliasredef, &alias[1], 1 + GetPropName(undefName), &substitute[1]); } } } } } }
#pragma check_stack(off)
#if OVERLAYS
/****************************************************************
* * * EndRc1: * * * * This function is called to process the information * * contained in a MODEND (type 8AH) record concerning the * * program starting address. The function does not return a * * meaningful value. * * See pp. 80-81 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR EndRc1(void) { WORD modtyp; /* MODEND record modtyp byte */ WORD fixdat; /* Fixdat byte */ SNTYPE gsn; /* Global SEGDEF number */ RATYPE ra; /* Symbol offset */ APROPSNPTR apropSn; /* Pointer to segment info */ WORD frameMethod;
if ((modtyp = Gets()) & FSTARTADDRESS) { /* If execution start address given */ ASSERT(modtyp & 1); /* Must be logical start address */ fixdat = Gets(); /* Get fixdat byte */ ASSERT(!(fixdat & 0x8F)); /* Frame, target must be explicit,
* target must be given by seg index */ frameMethod = (fixdat & 0x70) >> 4; if (frameMethod != F4 && frameMethod != F5) GetIndex(0,IMAX - 1); /* Punt frame index */ gsn = mpsngsn[GetIndex((WORD)1,(WORD)(snMac - 1))]; /* Get gsn from target segment index */ #if OMF386
if(rect & 1) ra = LGets() + mpgsndra[gsn]; else #endif
ra = WGets() + mpgsndra[gsn]; /* Get offset */ apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE); /* Get segment information */ MkPubSym("\006$$MAIN",apropSn->as_ggr,gsn,ra); /* Make public symbol */ } } #endif /* OVERLAYS */
/****************************************************************
* * * ProcP1: * * * * This function controls the processing of an object module * * on pass 1. * * * ****************************************************************/
#pragma check_stack(on)
void NEAR ProcP1(void) { long typlen[TYPMAX]; WORD typtyp[TYPMAX]; RBTYPE extprop[EXTMAX]; FTYPE fFirstRec; /* First record flag */ FTYPE fFirstMod; /* First module flag */ APROPFILEPTR apropFile; /* File name entry */
#if OXOUT OR OIAPX286
RUNTYPE xhdr; LFATYPE lfa; #endif
mpitypelen = typlen; /* Initialize pointer */ mpityptyp = typtyp; /* Initialize pointer */ mpextprop = (RBTYPE FAR *) extprop; /* Initialize pointer */ FMEMSET(mpextprop, 0, sizeof(extprop)); fFirstMod = (FTYPE) TRUE; /* First module */ for(;;) /* Loop to process file */ { snMac = 1; /* Initialize counter */ grMac = 1; /* Initialize */ extMac = 1; /* Initialize counter */ lnameMac = 1; /* Initialize counter */ typMac = 1; /* Initialize counter */ vfNewOMF = FALSE; /* Assume old OMF */ DEBUGVALUE(gsnMac); /* Debug info */ DEBUGVALUE(ggrMac); /* Debug info */ #if OXOUT OR OIAPX286
lfa = ftell(bsInput); /* Save initial file position */ fread(&xhdr,1,CBRUN,bsInput); /* Read x.out header */ if(xhdr.x_magic == X_MAGIC) /* If magic number found */ { #if OXOUT
if((xhdr.x_cpu & XC_CPU) != XC_8086) InvalidObject(); /* Bad if not 8086 */ #else
xhdr.x_cpu &= XC_CPU; /* Get CPU specification */ if(xhdr.x_cpu != XC_286 && xhdr.x_cpu != XC_8086) InvalidObject(); /* Bad if not 286 or 8086 */ #endif
if(xhdr.x_relsym != (XR_R86REL | XR_S86REL)) InvalidObject(); /* Check symbol table type */ if((xhdr.x_renv & XE_VERS) != xever) InvalidObject(); /* Check Xenix version */ } else fseek(bsInput,lfa,0); /* Else return to start */ #endif /* OXOUT OR OIAPX286 */
#if OVERLAYS
if(fOverlays) /* If there are overlays */ iovFile = ((APROPFILEPTR) vrpropFile)->af_iov; /* Save overlay number for file */ else iovFile = 0; /* File contains part of root */ #endif
fFirstRec = (FTYPE) TRUE; /* Looking at first record */ fModEnd = FALSE; /* Not at module's end */ fP2Start = FALSE; /* No p2start record yet */ #if SYMDEB
cSegCode = 0; /* No code segments yet */ #endif
while(!fModEnd) /* Loop to process object module */ { rect = (WORD) getc(bsInput);/* Read record type */ if(fFirstRec) /* If first record */ { if(rect != THEADR && rect != LHEADR) { /* If not header */ if(fFirstMod) break;/* Error if first module */ return; /* Else return */ } fFirstRec = FALSE; /* Not first record any more */ } else if (IsBadRec(rect)) break; /* Break if invalid object */
cbRec = WSGets(); /* Read record length */ lfaLast += cbRec + 3; /* Update current file pos. */
#if ALIGN_REC
if (bsInput->_cnt >= cbRec) { pbRec = bsInput->_ptr; bsInput->_ptr += cbRec; bsInput->_cnt -= cbRec; } else { if (cbRec > sizeof(recbuf)) { // error -- record too large [rm]
InvalidObject(); }
// read record into contiguous buffer
if (fread(recbuf,1,cbRec,bsInput) == cbRec) { pbRec = recbuf; } } #endif
DEBUGVALUE(rect); /* Debug info */ DEBUGVALUE(cbRec); /* Debug info */ switch(TYPEOF(rect)) /* Switch on record type */ { #if TCE
case FIXUPP: if(fTCE) FixRc1(); else SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */ break; #endif
case TYPDEF: TypRc1(); break;
case COMDEF: case LCOMDEF: ComDf1(); break;
case SEGDEF: SegRc1(); break;
case THEADR: ModRc1(); break;
case COMENT: ComRc1(); break;
case LHEADR: ModRc1(); break;
case GRPDEF: GrpRc1(); break;
case EXTDEF: case LEXTDEF: case CEXTDEF: ExtRc1(); break;
case LNAMES: case LLNAMES: LNmRc1((WORD) (TYPEOF(rect) == LLNAMES)); break;
case PUBDEF: case LPUBDEF: PubRc1(); break;
case MODEND: #if OVERLAYS
if(fOverlays) EndRc1(); else #endif
SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */ fModEnd = (FTYPE) TRUE; /* Stop processing module */ break;
case COMDAT: ComDatRc1(); break;
case ALIAS: AliasRc1(); break;
default: if (rect == EOF) InvalidObject(); SkipBytes((WORD) (cbRec - 1)); /* Skip to checksum byte */ break; } if(cbRec != 1) break; /* If record length bad */ Gets(); /* Eat the checksum byte */ } if(!fModEnd) { ChkInput(); /* First check for I/O problems */ InvalidObject(); /* Invalid module */ } ++modkey; /* For local symbols */ #if SYMDEB
if (fSymdeb) { apropFile = (APROPFILEPTR) FetchSym(vrpropFile, TRUE); if (apropFile->af_cvInfo || apropFile->af_Src) ++ObjDebTotal; /* Count the .OBJ with CV info */ } #endif
if(extMac > extMax) /* Possibly set new extMax */ extMax = extMac; if(fLibraryFile || fP2Start) return; fFirstMod = FALSE; /* Not first module */ } }
#pragma check_stack(off)
|