|
|
/* SCCSID = %W% %E% */ /*
* Copyright Microsoft Corporation, 1983-1987 * * This Module contains Proprietary Information of Microsoft * Corporation and should be treated as Confidential. */ /****************************************************************
* * * NEWTP2.C * * * * This module contains functions to process object modules on * * pass 2. * * * ****************************************************************/
#include <minlit.h> /* Types, constants, macros */
#include <bndtrn.h> /* Types and constants */
#include <bndrel.h> /* More types and constants */
#include <lnkio.h> /* Linker I/O definitions */
#include <newexe.h> /* DOS & 286 .EXE structure definitions */
#if EXE386
#include <exe386.h> /* 386 .EXE structure definitions */
#endif
#include <lnkmsg.h> /* Error messages */
#if OXOUT OR OIAPX286
#include <xenfmt.h> /* Xenix format definitions */
#endif
#include <extern.h> /* External declarations */
#if OSEGEXE
extern RLCPTR rlcLidata; /* Pointer to LIDATA fixup array */ extern RLCPTR rlcCurLidata; /* Pointer to current LIDATA fixup */ #endif
/*
* LOCAL FUNCTION PROTOTYPES */
LOCAL void NEAR DataRec(void); BYTE * ObExpandIteratedData(unsigned char *pb, unsigned short cBlocks, WORD *pSize); LOCAL void NEAR DataBlockToVM(void); LOCAL void NEAR SegRec2(void); LOCAL void NEAR GrpRec2(void); LOCAL void NEAR ExtRec2(void); LOCAL void NEAR ComDef2(void);
#if ALIGN_REC
#else
/*
* GetBytesNoLim : just like GetBytes but no fixed limit */
void NEAR GetBytesNoLim(pb,n) BYTE *pb; /* Pointer to buffer */ WORD n; /* Number of bytes to read in */ { FILE *f = bsInput;
if (n <= f->_cnt) { memcpy(pb,f->_ptr, n); f->_cnt -= n; f->_ptr += n; } else fread(pb,1,n,bsInput); /* Ask for n bytes */
// ChkInput();
cbRec -= n; /* Update byte count */ } #endif
/****************************************************************
* * * DataRec: * * * * This function takes no arguments. It processes a LEDATA * * record or an LIDATA record. It does not return a * * meaningful value. See "8086 Object Formats EPS." * * * ****************************************************************/
LOCAL void NEAR DataRec(void) /* Process a data record */ { SNTYPE sn; /* SEGDEF number */ RATYPE ra; /* Segment offset */ SNTYPE gsn; /* Global SEGDEF number */
fSkipFixups = FALSE; // Make sure that we don't skip fixups
sn = GetIndex((WORD)1,(WORD)(snMac - 1)); /* Get segment number */ #if OMF386
if(rect & 1) ra = LGets(); else #endif
ra = WGets(); /* Get relative address */ vcbData = cbRec - 1; /* Get no. of data bytes in rec */ if(vcbData > DATAMAX) Fatal(ER_datarec); /* Check if record too large */ #if NOT RGMI_IN_PLACE
GetBytesNoLim(rgmi,vcbData); /* Fill the buffer */ #endif
gsn = mpsngsn[sn]; /* Map SEGDEF no. to global SEGDEF */ vgsnCur = gsn; /* Set global */
fDebSeg = (fSymdeb) ? (FTYPE) ((0x8000 & gsn) != 0) : fSymdeb; /* If debug option on check for debug segs*/ if (fDebSeg) { /* If debug segment */ vraCur = ra; /* Set current relative address */ vsegCur = vgsnCur = 0x7fff & gsn; /* Set current segment */ } else { /* If not a valid segment, don't process datarec */ #if SYMDEB
if(gsn == 0xffff || !gsn || mpgsnseg[gsn] > segLast) #else
if(!gsn || mpgsnseg[gsn] > segLast) #endif
{ vsegCur = SEGNIL; vrectData = RECTNIL; #if RGMI_IN_PLACE
SkipBytes(vcbData); /* must skip bytes for this record...*/ #endif
fSkipFixups = TRUE; /* plus skip any associated fixups */ return; /* Good-bye! */ } vraCur = ra + mpgsndra[gsn]; /* Set current relative address */ vsegCur = mpgsnseg[gsn]; /* Set current segment */ } vrectData = rect; /* Set the record type */
#if RGMI_IN_PLACE
if(TYPEOF(rect) == LIDATA) /* If LIDATA record */ { rgmi = bufg; /* use general purpose buffer for read*/ } else { rgmi = PchSegAddress(vcbData,vsegCur,vraCur); /* read data in place... */ } GetBytesNoLim(rgmi,vcbData); /* Fill the buffer */ #endif
if(TYPEOF(vrectData) == LIDATA) /* If LIDATA record */ { #if OSEGEXE
if(fNewExe) { if (vcbData >= DATAMAX) Fatal(ER_lidata); rlcLidata = (RLCPTR ) &rgmi[(vcbData + 1) & ~1]; /* Set base of fixup array */ rlcCurLidata = rlcLidata; /* Initialize pointer */ return; } #endif
#if ODOS3EXE OR OIAPX286
if(vcbData > (DATAMAX / 2)) { OutError(ER_lidata); memset(&rgmi[vcbData],0,DATAMAX - vcbData); } else memset(&rgmi[vcbData],0,vcbData); ompimisegDstIdata = (char *) rgmi + vcbData; #endif
} }
/****************************************************************
* * * SegRec2: * * * * This function processes SEGDEF records on pass 2. * * See pp. 32-35 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR SegRec2(void) { WORD tysn; /* ACBP field */ WORD align; /* Alignment subfield of ACBP */ SATYPE saAbs; /* Frame number of absolute LSEG */ LNAMETYPE lname; /* Segment name index */ WORD comb; /* Segment combining information */ APROPSNPTR apropSn; /* Pointer to segment hash tab entry */ SNTYPE gsn; /* Global SEGDEF no. */ RATYPE dra; RBTYPE rhteClass; /* Segment class name rhte */ WORD DebKind; /* Debug seg kind; 1-$$TYPES; 2-$$SYMBOLS */ DWORD gsnLen; /* Segment length */ #if ILINK
WORD cbPad; /* size of padding used */ #endif
ASSERT(snMac < SNMAX); /* No overflow on Pass 2 */ tysn = Gets(); /* Read in ACBP byte */ align = (tysn >> 5) & 7; /* Get alignment subfield */ ASSERT(align != 5); /* Unnamed absolute not supported */ ASSERT(align != 6); /* LTL LSEG not supported */ if(align == ALGNABS) /* If absolute LSEG */ { saAbs = WGets(); /* Read in frame number */ Gets(); /* Skip frame offset */ } #if OMF386
if(rect & 1) gsnLen = LGets(); else #endif
gsnLen = (long) WGets(); /* Read in segment length */ /* Don't need to check for 386 record, done in pass 1: */ if(tysn & BIGBIT) gsnLen = LXIVK; /* Length 64K if big bit set */ lname = GetIndex((WORD)1,(WORD)(lnameMac - 1)); /* Get segment name index */ rhteClass = mplnamerhte[GetIndex((WORD)1,(WORD)(lnameMac - 1))]; /* Get segment class name rhte */ #if SYMDEB
if (DebKind = IsDebSeg(rhteClass, mplnamerhte[lname])) { /* If MS debug segment then mark it */ if (!fSymdeb) mpsngsn[snMac++] = 0xffff; else mpsngsn[snMac++] = ((DebKind == 1) ? segDebFirst + segDebLast : segDebFirst + segDebLast + ObjDebTotal ) | 0x8000; /* Set debug global number */ SkipBytes((WORD)(cbRec - 1)); return; } #endif
GetIndex((WORD)0,(WORD)(lnameMac - 1)); /* Skip overlay name index */ switch(align) /* Switch on alignment type */ { case ALGNABS: /* Absolute LSEG */ case ALGNWRD: /* Word-aligned LSEG */ case ALGNBYT: /* Byte-aligned LSEG */ case ALGNPAR: /* Paragraph-aligned LSEG */ case ALGNPAG: /* Page-aligned LSEG */ #if OMF386
case ALGNDBL: /* Double-aligned LSEG */ #endif
break;
default: /* Unsupported or illegal types */ mpsngsn[snMac++] = 0; /* Map to nothing */ return; /* And return */ } ++snkey; /* Increment segment i.d. key */ if(comb = (tysn >> 2) & 7) /* If not a private segment */ { apropSn = (APROPSNPTR ) PropRhteLookup(mplnamerhte[lname],ATTRPSN,FALSE); /* Look up property cell */ ASSERT(apropSn != PROPNIL); /* Should always be true */ while(apropSn->as_attr != ATTRNIL) { /* Look for matching class */ if(apropSn->as_attr == ATTRPSN && apropSn->as_rCla == rhteClass) break; /* Break if a match is found */ apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE); /* Try next link in list */ } ASSERT(apropSn->as_attr == ATTRPSN); } else /* Else if private segment */ { apropSn = (APROPSNPTR ) PropRhteLookup(mplnamerhte[lname],ATTRLSN,FALSE); /* Look up property cell */ ASSERT(apropSn != PROPNIL); /* Should always be true */ while(apropSn->as_attr != ATTRNIL) { /* Search for match */ if(apropSn->as_attr == ATTRLSN && apropSn->as_key == snkey) break; /* Break when match found */ apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE); /* Try next link in list */ } ASSERT(apropSn->as_attr == ATTRLSN); } gsn = apropSn->as_gsn; /* Get global SEGDEF no. */ #if ILINK
if (fIncremental && !fLibraryFile && !(apropSn->as_fExtra & NOPAD) && gsnLen && gsnLen != LXIVK) /* Add code/data padding to non-library segments if it doesn't
* overflow. */ gsnLen += (cbPad = ((apropSn->as_flags & NSTYPE) == NSCODE) ? cbPadCode : cbPadData); else cbPad = 0; /* no padding please */ #endif
if(comb == COMBSTK) mpgsndra[gsn] = mpsegraFirst[mpgsnseg[gsn]] + apropSn->as_cbMx - gsnLen; else { /* If combine-type public, start at end of combined segment. */ if(comb != COMBCOM) dra = mpgsndra[gsn] + apropSn->as_cbPv; /*
* Else if common, start at beginning of segment. Save current * combined size, except this portion, in as_cbPv. If this * portion is bigger as_cbPv is reset below. */ else { dra = mpsegraFirst[mpgsnseg[gsn]]; apropSn->as_cbPv += mpgsndra[gsn] - dra; } switch(align) /* Switch on alignment type */ { case ALGNWRD: /* Word-aligned LSEG */ mpgsndra[gsn] = (~0L<<1) & (dra + (1<<1) - 1); /* Round to next word offset */ break; #if OMF386
case ALGNDBL: /* Double-aligned LSEG */ mpgsndra[gsn] = (~0L<<2) & (dra + (1<<2) - 1); /* Round to next double offset */ break; #endif
case ALGNPAR: /* Paragraph-aligned LSEG */ mpgsndra[gsn] = (~0L<<4) & (dra + (1<<4) - 1); /* Round to next paragraph offset */ break;
case ALGNPAG: /* Page-aligned LSEG */ mpgsndra[gsn] = (~0L<<8) & (dra + (1<<8) - 1); /* Round to next page offset */ break;
default: /* All others */ mpgsndra[gsn] = dra; /* Use byte offset */ break; } } /*
* If public, as_cbPv is size of this public portion; if common, * as_cbPv is the larger of total combined publics and this * common portion. Skip empty SEGDEFs. */ if (/*gsnLen != 0L && */(comb != COMBCOM || gsnLen > apropSn->as_cbPv)) apropSn->as_cbPv = gsnLen; mpsngsn[snMac++] = gsn; /* Map SEGDEF no. to gsn */ if(align == ALGNABS) mpsegsa[mpgsnseg[gsn]] = saAbs; /* Map seg base to frame number */ MARKVP(); /* Mark page as changed */ #if ILINK
if (fIncremental) { AddContribution(gsn, (WORD) (mpgsndra[gsn] - mpsegraFirst[mpgsnseg[gsn]]), (WORD) (mpgsndra[gsn] - mpsegraFirst[mpgsnseg[gsn]] + gsnLen), cbPad); gsnLen -= cbPad; /* Don't include padding for CV */ } #endif
#if SYMDEB
if(fSymdeb && gsnLen && IsCodeFlg(apropSn->as_flags)) SaveCode(gsn, gsnLen, (DWORD) -1L); #endif
}
/****************************************************************
* * * GrpRec2: * * * * This function processes GRPDEF records on pass 2. * * See pp. 36-39 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR GrpRec2(void) { LNAMETYPE lnameGroup; /* Group name index */ APROPGROUPPTR apropGroup; /* Pointer to property cell */
lnameGroup = GetIndex((WORD)1,(WORD)(lnameMac - 1)); /* Read in group name index */ apropGroup = (APROPGROUPPTR ) PropRhteLookup(mplnamerhte[lnameGroup],ATTRGRP,FALSE); /* Look up entry in hash table */ ASSERT(grMac < GRMAX); /* Should have been caught on pass 1 */ mpgrggr[grMac++] = apropGroup->ag_ggr; /* Map GRPDEF to global GRPDEF */ SkipBytes((WORD)(cbRec - 1)); /* Skip to checksum byte */ }
/*
* AddVmProp : Add a symbol-table property address to a list * * Returns: pointer to the new list element; the pointer is * a word offset from the start of the list area in VM */
PLTYPE FAR * NEAR AddVmProp (PLTYPE FAR *list, RBTYPE rprop) { PLTYPE FAR *new;
new = (PLTYPE FAR *) GetMem(sizeof(PLTYPE));
// Add unresolved external at the list head
new->pl_next = list; new->pl_rprop = rprop;
return(new); }
/****************************************************************
* * * ExtRec2: * * * * This function processes EXTDEF records on pass 2. Note * * that in pass 2, any undefined externals are errors. * * See pp. 47-48 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR ExtRec2(void) { SBTYPE sb; /* External symbol name */ APROPNAMEPTR apropName; /* Property cell pointer */ APROPUNDEFPTR apropUndef; /* Property cell pointer */ APROPALIASPTR apropAlias; /* Property cell pointer */ RBTYPE rhte; /* Virt. addr. of hash table entry */ #if OSEGEXE
APROPEXPPTR apropExp; /* Export cell pointer */ #endif
while (cbRec > 1) /* While not at end of record */ { ASSERT(extMac < EXTMAX); /* Should be checked on Pass 1 */
if (TYPEOF(rect) == CEXTDEF) { /* Look for symbol among PUBDEFs */
rhte = mplnamerhte[GetIndex(1, (WORD)(lnameMac - 1))]; apropName = (APROPNAMEPTR) PropRhteLookup(rhte, ATTRPNM, FALSE); } else { sb[0] = (BYTE) Gets(); /* Read in symbol length */ if(TYPEOF(rect) == EXTDEF) GetBytes(&sb[1], B2W(sb[0])); /* Read in the text of the symbol */ else GetLocName(sb); /* Transform local name */ #if CMDXENIX
if (symlen && B2W(sb[0]) > symlen) sb[0] = symlen; /* Truncate if necessary */ #endif
/* Look for symbol among PUBDEFs */
apropName = (APROPNAMEPTR) PropSymLookup(sb, ATTRPNM, FALSE); rhte = vrhte; }
GetIndex(0, 0x7FFF); /* Skip the type index */
apropUndef = PROPNIL;
if (apropName == PROPNIL) { /* Look for symbol among ALIASES */
apropAlias = (APROPALIASPTR) PropRhteLookup(rhte, ATTRALIAS, FALSE);
if (apropAlias != PROPNIL) { // Every call to PropRhteLookup as a side effect sets
// the global variable 'vrprop' pointing to the
// just retrieved proprety cell from symbol table.
// Because for substitute symbols we don't call
// PropRhteLookup instead we use direct pointer from
// alias property cell, then we have to reset the
// 'vrprop' here.
vrprop = apropAlias->al_sym; apropName = (APROPNAMEPTR) FetchSym(apropAlias->al_sym, FALSE); if (apropName->an_attr == ATTRUND) { apropUndef = (APROPUNDEFPTR) apropName; apropName = PROPNIL; } }
#if OSEGEXE
/* If public definition not found and this is segmented DLL,
* handle the possibility that this is a self-imported alias. */ if (apropName == PROPNIL && fNewExe && (vFlags & NENOTP)) { /* Look up exported name. */
apropExp = (APROPEXPPTR) PropRhteLookup(rhte, ATTREXP, FALSE);
/* If found, get the symbol definition which might be different
* from the export name (i.e. an alias). If not marked public, * assume not found. */
if (apropExp != PROPNIL && apropExp->ax_symdef != RHTENIL) apropName = (APROPNAMEPTR) FetchSym(apropExp->ax_symdef, FALSE); } #endif
if (apropName == PROPNIL) { /* If not among PUBDEFs, ALIASes, or EXPORTs */
/* Look among undefs */
if (apropUndef == PROPNIL) apropUndef = (APROPUNDEFPTR) PropRhteLookup(rhte, ATTRUND, FALSE);
if (apropUndef != PROPNIL) /* Should always exist */ { if ((apropUndef->au_flags & STRONGEXT) || (apropUndef->au_flags & UNDECIDED) ) { /* "Strong" extern */
apropUndef->au_flags &= ~(WEAKEXT | UNDECIDED); apropUndef->au_flags |= STRONGEXT; fUndefinedExterns = (FTYPE) TRUE; /* There are undefined externals */ apropUndef->u.au_rFil = AddVmProp(apropUndef->u.au_rFil,vrpropFile); } else { /* "Weak" extern - find default resolution */
apropName = (APROPNAMEPTR) FetchSym(apropUndef->au_Default, FALSE); } } } }
if (apropName != PROPNIL) /* If among PUBDEFs or EXPDEF's or "weak" extern or ALIASes */ { mpextprop[extMac] = vrprop; /* Save the property addr */ #if OSEGEXE
if(fNewExe) mpextflags[extMac] = apropName->an_flags; /* Save the flags */ #if ODOS3EXE
else #endif
#endif
#if ODOS3EXE OR OIAPX286
mpextggr[extMac] = apropName->an_ggr; /* Save the global GRPDEF number */ #endif
#if OSEGEXE
if(apropName->an_flags & FIMPORT) { /* If we have a dynamic link */ #if EXE386
mpextgsn[extMac] = gsnImport; /* Save the thunk segment no. */ mpextra[extMac] = apropName->an_thunk; /* Save the offset in thunk segment */ #else
mpextgsn[extMac] = apropName->an_module; /* Save the module specification */ mpextra[extMac] = apropName->an_entry; /* Save the entry specification */ #endif
} else /* Else if internal reference */ #endif
{ mpextra[extMac] = apropName->an_ra; /* Save the offset */ mpextgsn[extMac] = apropName->an_gsn; /* Save the global SEGDEF number */ } }
else { /* External is undefined */
mpextra[extMac] = 0; mpextgsn[extMac] = SNNIL; mpextprop[extMac] = PROPNIL; #if OSEGEXE
if (fNewExe) mpextflags[extMac] = 0; #if ODOS3EXE
else #endif
#endif
#if ODOS3EXE OR OIAPX286
mpextggr[extMac] = GRNIL; #endif
}
++extMac; /* Increment public symbol counter */ } }
LOCAL void NEAR ComDef2(void) { int tmp; /* workaround a cl bug */ SBTYPE sb; /* External symbol name */ APROPNAMEPTR apropName; /* Property cell pointer */
while(cbRec > 1) /* While not at end of record */ { sb[0] = (BYTE) Gets(); /* Read in symbol length */ if(rect == COMDEF) GetBytes(&sb[1],B2W(sb[0]));/* Read in the text of the symbol */ else GetLocName(sb); /* Transform local name */ #if CMDXENIX
if(symlen && B2W(sb[0]) > symlen) sb[0] = symlen; /* Truncate if necessary */ #endif
GetIndex(0,0x7FFF); /* Skip the type index */ tmp = Gets(); switch(tmp) { case TYPEFAR: TypLen(); /* Skip num. elems. field */ /* Fall through ... */ case TYPENEAR: TypLen(); /* Skip length field */ } apropName = (APROPNAMEPTR ) PropSymLookup(sb,ATTRPNM,FALSE); /* Look for symbol among PUBDEFs */ if (apropName == PROPNIL) { ExitCode = 4; Fatal(ER_unrcom); /* Internal error */ } #if OSEGEXE
if(fNewExe) mpextflags[extMac] = apropName->an_flags; /* Save the flags */ #if ODOS3EXE
else #endif
#endif
#if ODOS3EXE OR OIAPX286
mpextggr[extMac] = apropName->an_ggr; /* Save the global GRPDEF number */ #endif
#if OSEGEXE
if(fNewExe && (apropName->an_flags & FIMPORT)) DupErr(sb); /* Communal vars can't resolve to dynamic links */ #endif
mpextra[extMac] = apropName->an_ra; /* Save the offset */ mpextgsn[extMac] = apropName->an_gsn; /* Save the global SEGDEF number */ mpextprop[extMac] = vrprop; /* Save the property address */ ++extMac; /* Increment public symbol counter */ } }
/****************************************************************
* * * ObExpandIteratedData: * * * * This function expands a LIDATA record and moves it to * * virtual memory. The function returns a pointer to the * * start of the next iterated data block (if any). This is a * * recursive function. * * See pp. 68-69,63 in "8086 Object Module Formats EPS." * * * ****************************************************************/
BYTE * ObExpandIteratedData(pb,cBlocks, pSize) BYTE *pb; /* Pointer into LIDATA buffer */ WORD cBlocks; /* Current block count subfield */ WORD *pSize; /* != NULL if all the caller wants
is the size of expanded block */ { WORD cNextLevelBlocks; /* Block count for next level */ RATYPE cRepeat; /* Repeat count */ WORD cbContent; /* Size of content subfield in bytes */ BYTE *pbRet; /* Recursion return value */
DEBUGVALUE(pb); /* Debug info */ DEBUGVALUE(cBlocks); /* Debug info */ DEBUGVALUE(vraCur); /* Debug info */ if(!cBlocks) /* If block count subfield is zero */ { cbContent = B2W(*pb++); /* Get size of content subfield */ if (pSize!=NULL) *pSize += cbContent;
#if OIAPX286
if(pSize==NULL) MoveToVm(cbContent,pb,vsegCur,vraCur - mpsegraFirst[vsegCur]); /* Move data to virtual memory */ #endif
#if NOT OIAPX286
#if OSEGEXE
if (fNewExe && (pSize==NULL)) DoIteratedFixups(cbContent,pb);/* Do any iterated fixups */ #endif
if(pSize==NULL) MoveToVm(cbContent,pb,vsegCur,vraCur); /* Move data to virtual memory */ #if ODOS3EXE
if(!fNewExe) { while(cbContent--) { if(pb[vcbData] && (pSize==NULL)) RecordSegmentReference(vsegCur,(long)vraCur,B2W(pb[vcbData])); ++vraCur; /* Increment current offset */ ++pb; /* Increment buffer pointer */ } cbContent++; } #endif
#endif /* NOT OIAPX286 */
vraCur += cbContent; /* Adjust current offset */ pb += cbContent; /* Move ahead in buffer */ } else /* Else if non-zero block count */ { while(cBlocks--) /* While there are blocks to do */ { #if OMF386
if(vrectData & 1) { cRepeat = getword(pb) + ((long)(getword(&pb[2])) << 16); cNextLevelBlocks = getword(&pb[4]); pb += 6; } else #endif
{ cRepeat = getword(pb); /* Get repeat count */ cNextLevelBlocks = getword(&pb[2]); /* Get block count */ pb += 4; /* Skip over fields */ } ASSERT(cRepeat != 0); /* One hopes it won't happen */ if(!cRepeat) InvalidObject(); /* Must have non-zero repeat count */ while(cRepeat--) pbRet = ObExpandIteratedData(pb,cNextLevelBlocks, pSize); /* Recurse to expand record */ pb = pbRet; /* Skip over expanded block */ } } DEBUGVALUE(pb); /* Debug info */ DEBUGVALUE(rgmi + vcbData + 1); /* Debug info */ ASSERT(pb <= rgmi + vcbData + 1); /* Should be true always */ if(pb > rgmi + vcbData + 1) InvalidObject(); /* Length must agree with format */ return(pb); /* Ret ptr to next iterated data blk */ }
/****************************************************************
* * * DataBlockToVm: * * * * This function moves data from a LEDATA record or a LIDATA * * record into virtual memory. * * See pp. 66-69 in "8086 Object Module Formats EPS." * * * ****************************************************************/
LOCAL void NEAR DataBlockToVM(void) { REGISTER BYTE *pb; /* Pointer to data buffer */ REGISTER RECTTYPE MYrect; /* Record type */
DEBUGVALUE(vcbData); /* Debug info */ /*
* In new-format exes, disallow initialization of the stack segment * if it is in DGROUP. */ if(fNewExe && vgsnCur == gsnStack && ggrDGroup != GRNIL && mpsegsa[mpgsnseg[mpggrgsn[ggrDGroup]]] == mpsegsa[mpgsnseg[gsnStack]]) return; MYrect = vrectData; /* Get record type */ /*
* Mask off all but the low bit of vrectData here, since ObExp. * will call RecordSegmentReference for runtime relocations which * were postponed until the LIDATA record was expanded. * RecordSegmentReference will think it's at the earlier phase if * vrectData is LIDATA, and the reloc won't get generated. * Leave low bit of vrectData so ObExp. can tell if OMF 386. */ #if OMF386
vrectData &= 1; #else
vrectData = RECTNIL; #endif
if(TYPEOF(MYrect) == LEDATA) /* If enumerated data record */ { DEBUGVALUE(vraCur); /* Debug info */ #if RGMI_IN_PLACE
if (!fDebSeg && fNewExe) { // If data is going up to or past current end of initialized data,
// omit any trailing null bytes and reset mpsacbinit. Mpsacbinit
// will usually go up but may go down if a common segment over-
// writes previous end data with nulls.
SATYPE sa = mpsegsa[vsegCur]; WORD cb = vcbData; long cbtot = (long)cb + vraCur;
if ((DWORD) cbtot >= mpsacbinit[sa]) { if ((DWORD) vraCur < mpsacbinit[sa] || (cb = zcheck(rgmi, cb)) != 0) mpsacbinit[sa] = (long)vraCur + cb; } } #else
#if OIAPX286
if (fDebSeg) MoveToVm(vcbData,rgmi,vsegCur,vraCur); else MoveToVm(vcbData,rgmi,vsegCur,vraCur - mpsegraFirst[vsegCur]); #else
MoveToVm(vcbData,rgmi,vsegCur,vraCur); #endif
#endif
/* Move data to virtual memory */ vraCur += vcbData; /* Update current offset */ } else /* Else if iterated data record */ { pb = rgmi; /* Get address of buffer */ while((pb = ObExpandIteratedData(pb,1, NULL)) < rgmi + vcbData); /* Expand and move to VM */ } DEBUGVALUE(vsegCur); /* Debug info */ #if ODOS3EXE OR OIAPX286
if (!fNewExe && !fDebSeg) mpsegFlags[vsegCur] |= FNOTEMPTY; #endif
#if OMF386
vrectData = RECTNIL; #endif
}
/****************************************************************
* * * LinRec2: * * * * This function processes LINNUM records on pass 2. * * See pp. 51-52 in "8086 Object Module Formats EPS." * * * ****************************************************************/
void NEAR LinRec2(void) { SNTYPE sn; /* SEGDEF index value */ SNTYPE gsn; /* Global SEGDEF no. */ SEGTYPE seg; WORD ln; /* Line number */ RATYPE ra; /* Offset */ APROPPTR aprop; AHTEPTR ahte; // Pointer to hash table entry
WORD attr; // COMDAT flags
WORD comdatIdx; // COMDAT index
APROPCOMDATPTR comdat; // Pointer to symbol table entry
DWORD comdatRa; // Offset of the COMDAT symbol
/*
* Get the group index and ignore it, so the linker can work with * other compilers. */
if ((rect & ~1) == LINNUM) { // Read regular LINNUM record
GetIndex((WORD)0,(WORD)(grMac - 1)); sn = GetIndex(1, (WORD)(snMac - 1)); gsn = mpsngsn[sn]; /* Get global SEGDEF number */ comdatRa = 0L; } else { // Read LINSYM record - line numbers for COMDAT
attr = (WORD) Gets(); comdatIdx = GetIndex(1, (WORD)(lnameMac - 1)); comdat = (APROPCOMDATPTR ) PropRhteLookup(mplnamerhte[comdatIdx], ATTRCOMDAT, FALSE); if (comdat != NULL) { gsn = comdat->ac_gsn; comdatRa = comdat->ac_ra; } else InvalidObject(); /* Invalid module */ }
/* If LINNUM record is empty, don't do anything. */
if(cbRec == 1) return;
seg = mpgsnseg[gsn]; if(gsn != vgsnLineNosPrev) /* If we weren't doing line numbers */ { /* for this segment last time */ if(vcln) NEWLINE(bsLst); /* Newline */ fputs("\r\nLine numbers for ",bsLst); /* Message */ OutFileCur(bsLst); /* File name */ fputs(" segment ",bsLst); /* Message */ aprop = (APROPPTR ) FetchSym(mpgsnrprop[gsn],FALSE); /* Fetch from virtual memory */ ASSERT(aprop != PROPNIL); /* Should never happen! */ ahte = GetHte(aprop->a_next); /* Get hash table entry */ OutSb(bsLst,GetFarSb(ahte->cch)); /* Segment name */ fputs("\r\n\r\n",bsLst); /* End line, skip a line */ vgsnLineNosPrev = gsn; /* Save global SEGDEF number */ vcln = 0; /* No entries on line yet */ } while(cbRec > 1) /* While not at checksum */ { if(vcln >= 4) /* If four entries on this line */ { vcln = 0; /* Reset counter */ NEWLINE(bsLst); /* Newline */ } ln = WGets() + QCLinNumDelta; /* Read in line number */ #if OMF386
if (rect & 1) ra = LGets(); else #endif
ra = (RATYPE) WGets(); ra += mpgsndra[gsn] + comdatRa; /* Get fixed segment offset */ if(gsn == gsnText && comdatRa && fTextMoved) ra -= NullDelta; fprintf(bsLst," %4d %04x:",ln,mpsegsa[seg]); #if EXE386
if (f386) fprintf(bsLst,"%08lx",(long) ra); else #endif
fprintf(bsLst,"%04x",(WORD) ra); ++vcln; /* Increment counter */ } }
/****************************************************************
* * * ProcP2: * * * * This function controls the processing of object modules * * during pass 2. * * * ****************************************************************/
#pragma check_stack(on)
void NEAR ProcP2(void) { #if EXE386
WORD extflags[EXTMAX]; #else
BYTE extflags[EXTMAX]; #endif
SNTYPE extgsn[EXTMAX]; RATYPE extra[EXTMAX]; FTYPE fFirstMod; FTYPE fModEnd; #if SYMDEB
WORD bTmp=TRUE; #endif
#if OXOUT OR OIAPX286
LFATYPE lfa; /* Seek value */ #endif
/* Group associations for EXTDEFs are only used for old exes and
* EXTDEF flags are only used for new exes, so they can share the * same space. */ #if OSEGEXE
if(fNewExe) mpextflags = extflags; /* Initialize pointer */ #if ODOS3EXE
else #endif
#endif
#if ODOS3EXE OR OIAPX286
mpextggr = extflags; #endif
mpextgsn = extgsn; /* Initialize pointer */ mpextra = extra; /* Initialize pointer */ vgsnLineNosPrev = SNNIL; /* No line numbers from this module */ fFirstMod = (FTYPE) TRUE; /* First module */ for(;;) /* Loop to process modules */ { snMac = 1; /* Initialize counter */ grMac = 1; /* Initialize counter */ extMac = 1; /* Initialize counter */ lnameMac = 1; /* Initialize counter */ QCExtDefDelta = 0; /* Initialize QC deltas */ QCLinNumDelta = 0; vrectData = RECTNIL; /* Initialize record type variable */ cbBakpat = 0; /* Initialize */ #if OXOUT OR OIAPX286
lfa = ftell(bsInput); /* Save initial file position */
cbRec = WSGets(); /* Read record length */
if(cbRec == X_MAGIC) fseek(bsInput,(long) CBRUN - sizeof(WORD),1); /* Skip x.out header if any */ else fseek(bsInput,lfa,0); /* Else return to start */ #endif
#if RGMI_IN_PLACE
rgmi = NULL; /* There is no data available */ vcbData = 0; /* There is really no data, honest */ #endif
fModEnd = FALSE; /* Not end of module */ while(!fModEnd) /* Loop to process object module */ { rect = getc(bsInput); /* Read record type */ if (IsBadRec(rect)) { if(fFirstMod) break; /* Break if 1st module invalid */ return; /* Else return */ } cbRec = getc(bsInput) | (getc(bsInput) << 8); /* Read record length */ #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
lfaLast += cbRec + 3; /* Update current file position */ DEBUGVALUE(rect); /* Debug info */ DEBUGVALUE(cbRec); /* Debug info */ /* If FIXUPP, perform relocation */ if (TYPEOF(rect) == FIXUPP) FixRc2(); else /* Else if not fixup record */ { if (vrectData != RECTNIL) { DataBlockToVM(); /* Move data to virtual memory */ fFarCallTrans = fFarCallTransSave; /* Restore the /FARCALL state */ } fDebSeg = FALSE; switch(TYPEOF(rect)) /* Switch on record type */ { case SEGDEF: SegRec2(); break;
case THEADR: case LHEADR: fSkipFixups = FALSE; ModRc1(); break;
case GRPDEF: GrpRec2(); break;
case EXTDEF: case LEXTDEF: case CEXTDEF: ExtRec2(); break;
case COMDEF: case LCOMDEF: ComDef2(); break;
case LNAMES: case LLNAMES: LNmRc1((WORD)(TYPEOF(rect) == LLNAMES)); break;
case LINNUM: case LINSYM:
#if SYMDEB
if (fSymdeb) bTmp=DoDebSrc(); #endif
if (fLstFileOpen && vfLineNos #if SYMDEB
&& bTmp #endif
) LinRec2(); else SkipBytes((WORD)(cbRec - 1)); break;
case LEDATA: case LIDATA: DataRec(); break;
case MODEND: #if OVERLAYS
if (!fOverlays) EndRec(); else SkipBytes((WORD)(cbRec - 1)); #else
EndRec(); #endif
fModEnd = (FTYPE) TRUE; break;
case BAKPAT: case NBAKPAT: BakPat(); break;
case COMENT: /* COMENT records are processed in */ /* pass 2 for support of INCDEF for QC */ Gets(); /* Skip byte 1 of comment type field */ if (Gets() == 0xA0) { /* if Microsoft OMF extension */ if (Gets() == 0x03) { /* QC 2.0 - INCremental DEFinition */ QCExtDefDelta += WGets(); QCLinNumDelta += WGets(); } } SkipBytes((WORD)(cbRec - 1)); break;
case COMDAT: ComDatRc2(); break;
default: if (rect == EOF) InvalidObject(); SkipBytes((WORD)(cbRec - 1)); /* Skip to checksum byte */ break; } } DEBUGVALUE(cbRec); /* Debug info */ 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) DebMd2(); /* Module post-processing for ISLAND */ #endif
if(cbBakpat) /* Fix up backpatches if any */ FixBakpat(); if(fLibraryFile) return; /* One at a time from libraries */ fFirstMod = FALSE; /* No longer first module */ } }
#pragma check_stack(off)
|