|
|
/* SCCSID = %W% %E% */ /*
* Copyright Microsoft Corporation, 1983-1987 * * This Module contains Proprietary Information of Microsoft * Corporation and should be treated as Confidential. */ /****************************************************************
* * * NEWADR.C * * * * Common address-assignment routines. * * * ****************************************************************/
#include <minlit.h> /* Types and constants */
#include <bndtrn.h> /* Types and constants */
#include <bndrel.h> /* Reloc. type 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 */
#include <extern.h> /* External function declarations */
/*
* FUNCTION PROTOTYPES */
LOCAL void FixSymRa(APROPNAMEPTR papropName, RBTYPE rhte, RBTYPE rprop, WORD fNewHte); LOCAL void AllocateCommon(APROPNAMEPTR papropName, RBTYPE rhte, RBTYPE rprop, WORD fNewHte); #if OSEGEXE AND SYMDEB AND NOT EXE386
LOCAL void GenImports(APROPNAMEPTR papropName, RBTYPE rhte, RBTYPE rprop, FTYPE fNewHte); #endif
LOCAL void NEAR AssignClasses(unsigned short (NEAR *ffun)(APROPSNPTR prop)); LOCAL WORD NEAR IsNotAbs(APROPSNPTR apropSn); LOCAL WORD NEAR IsCode(APROPSNPTR prop); LOCAL WORD NEAR IsNotDGroup(APROPSNPTR prop); LOCAL WORD NEAR IsBegdata(APROPSNPTR prop); LOCAL WORD NEAR IsNotBssStack(APROPSNPTR prop); LOCAL WORD NEAR IsNotStack(APROPSNPTR prop);
#if QBLIB
extern RBTYPE rhteFarData; /* "FARDATA" class name */ extern RBTYPE rhteFarBss; /* "FARBSS" class name */ extern SEGTYPE segFD1st, segFDLast; extern SEGTYPE segFB1st, segFBLast; #endif
#define IsAbsTysn(tysn) ((tysn & ~(BIGBIT | CODE386BIT)) == TYSNABS)
SNTYPE gsnText; /* Global SEGDEF for _TEXT */
/* Local variables */ LOCAL long cbCommon; /* Count of bytes in COMMON */ LOCAL long cbFar; /* Count of bytes in far common */ LOCAL GRTYPE ggrCommon; /* Global group no. for common */ LOCAL SNTYPE gsnCommon; /* Global SEGDEF for common */ LOCAL SNTYPE gsnFar; /* Far common SEGDEF number */ LOCAL FTYPE fNoEdata = (FTYPE) TRUE; LOCAL FTYPE fNoEnd = (FTYPE) TRUE;
#if SYMDEB
LOCAL int NEAR IsDebug(APROPSNPTR propSn);
/************************************************************
* * * Returns true if segment definition record is a debug * * segment: private and a recognized class. * * * ************************************************************/
LOCAL int NEAR IsDebug(APROPSNPTR propSn) { return (fSymdeb && propSn->as_attr == ATTRLSN && (propSn->as_rCla == rhteDebTyp || propSn->as_rCla == rhteDebSym || propSn->as_rCla == rhteDebSrc)); } #else
#define IsDebug(a) FALSE
#endif
AHTEPTR GetHte(rprop) /* Get hash table entry */ RBTYPE rprop; /* Property cell address */ { REGISTER AHTEPTR ahte; /* Hash table entry pointer */
ahte = (AHTEPTR ) FetchSym(rprop,FALSE); /* Fetch property cell */ /* While not at hash table entry, get next cell in chain */ while(ahte->attr != ATTRNIL) ahte = (AHTEPTR ) FetchSym(ahte->rhteNext,FALSE); return(ahte); /* Return ptr to hash table entry */ }
/****************************************************************
* * * FixSymRa: * * * * Fix symbol offset. Called by EnSyms. * * * ****************************************************************/
LOCAL void FixSymRa (papropName,rhte,rprop,fNewHte) APROPNAMEPTR papropName; /* Symbol property cell */ RBTYPE rhte; /* Hash table virt address */ RBTYPE rprop; /* Symbol virt address */ WORD fNewHte; { SNTYPE gsn; #if O68K
SATYPE sa; #endif /* O68K */
if(!(gsn = papropName->an_gsn)) return; papropName->an_ra += mpgsndra[gsn];
#if O68K
if (iMacType != MAC_NONE && IsDataFlg(mpsaflags[sa = mpsegsa[mpgsnseg[gsn]]])) papropName->an_ra += mpsadraDP[sa]; #endif /* O68K */
MARKVP(); }
/****************************************************************
* * * GenSeg: * * * * Generate a segment definition. * * * ****************************************************************/
#if EXE386
APROPSNPTR GenSeg(sbName,sbClass,ggr,fPublic) #else
APROPSNPTR NEAR GenSeg(sbName,sbClass,ggr,fPublic) #endif
BYTE *sbName; /* Segment name */ BYTE *sbClass; /* Class name */ GRTYPE ggr; /* Global GRPDEF number */ WORD fPublic; /* True if public segment */ { APROPSNPTR apropSn; /* Pointer to SEGDEF */ RBTYPE rhteClass; /* Class name virt addr */
PropSymLookup(sbClass, ATTRNIL, TRUE);/* Insert class name in hash table */ rhteClass = vrhte; /* Save class name virt addr */ if(fPublic) /* If public segment */ { apropSn = (APROPSNPTR ) PropSymLookup(sbName, ATTRPSN, TRUE); /* Create segment */ if(!vfCreated) return(apropSn); /* If it existed, return pointer */ #if EXE386
apropSn->as_tysn = DWORDPUBSEG; /* Segment is public */ #else
apropSn->as_tysn = PARAPUBSEG; /* Segment is public */ #endif
} else /* Else if private segment */ { PropSymLookup(sbName, ATTRNIL, TRUE); /* Look up name */ apropSn = (APROPSNPTR ) PropAdd(vrhte,ATTRLSN); /* Segment is local */ #if EXE386
apropSn->as_tysn = DWORDPRVSEG; /* Segment is private */ #else
apropSn->as_tysn = PARAPRVSEG; /* Segment is private */ #endif
} if(gsnMac >= gsnMax) Fatal(ER_segmax); /* Check for table overflow */ apropSn->as_rCla = rhteClass; /* Save segment's class */ mpgsnrprop[gsnMac] = vrprop; /* Save property cell address */ apropSn->as_gsn = gsnMac++; /* Give it a global SEGDEF number */ apropSn->as_ggr = ggr; /* Give specified group association */ return(apropSn); /* Return global SEGDEF */ }
#if FALSE AND OSEGEXE AND SYMDEB AND NOT EXE386
/* Postponed CV not ready yet */
/*** GenImports - fill in $$IMPORTS segment for CV
* * Purpose: * Build $$IMPORTS segment for CV. This segment enables symbolic information * in CV for dyncalls. The $$IMPORTS segment contains sequence of entries * in the following format: * * 16-bit 16-bit 32-bit * +--------+--------+-----------------+ * | iMod | iName | far address | * +--------+--------+-----------------+ * * Where: * - iMod - index to Module Reference Table in .EXE * - iName - index to Imported Names Table in .EXE (32-bit for 386) * - address - import's address fixed up by loader * * Input: * This function is called by EnSyms, so it takes standard set of arguments. * papropName - pointer to import property cell * rprop - virtual address of property cell * rhte - virt address of hash table entry * fNewHte - TRUE if name has been written * * Output: * No explicit value is returned. Segment data is created and run-time * fiuxps. * * Exceptions: * None. * * Notes: * None. * *************************************************************************/
LOCAL void GenImports(papropName,rhte,rprop,fNewHte) APROPNAMEPTR papropName; RBTYPE rhte; RBTYPE rprop; FTYPE fNewHte; { static WORD raImpSeg = 0; APROPIMPPTR lpImport; APROPNAMEPTR lpPublic; CVIMP cvImp; RELOCATION r; /* Relocation item */
lpImport = (APROPIMPPTR) papropName; if (lpImport->am_mod) return; /* Skip module name */
/* Build CV import descriptor and save it in $$IMPORTS segment */
cvImp.iName = lpImport->am_offset; /* Save index to Imported Name Table */ cvImp.address = (char far *) 0L; lpPublic = (APROPNAMEPTR) FetchSym((RBTYPE)lpImport->am_public, FALSE); cvImp.iMod = lpPublic->an_module; /* Save index to Module Reference Table */ vgsnCur = gsnImports; MoveToVm(sizeof(CVIMP), (BYTE *) &cvImp, mpgsnseg[gsnImports], raImpSeg);
/* Emit run-time fixup for import, so loader will fill in addrss field */
#if EXE386
R32_SOFF(r) = (WORD) ((raImpSeg + 6) % OBJPAGELEN); #else
NR_SOFF(r) = (WORD) raImpSeg + 4; #endif
NR_STYPE(r) = (BYTE) NRSPTR; /* Save fixup type - 16:16 pointer */ NR_FLAGS(r) = (lpPublic->an_flags & FIMPORD) ? NRRORD : NRRNAM; #if EXE386
R32_MODORD(r) = lpPublic->an_module;/* Get module specification */ if (NR_FLAGS(r) & NRRNAM) /* Get entry specification */ { if (cbImports < LXIVK) R32_PROCOFF16(r) = (WORD) lpPublic->an_entry; /* 16-bit offset */ else { /* 32-bit offset */ R32_PROCOFF32(r) = lpPublic->an_entry; NR_FLAGS(r) |= NR32BITOFF; } } else R32_PROCORD(r) = (WORD) lpPublic->an_entry; SaveFixup(mpsegsa[mpgsnseg[gsnImports]], ((raImpSeg + 6) >> pageAlign) + 1, &r); #else
NR_MOD(r) = lpPublic->an_module; /* Get module specification */ NR_PROC(r) = lpPublic->an_entry; /* Get entry specification */ SaveFixup(mpsegsa[mpgsnseg[gsnImports]],&r); #endif
raImpSeg += sizeof(CVIMP); } #endif
/****************************************************************
* * * AllocateCommon: * * * * Allocate space for C common variables. Called by EnSyms. * * * ****************************************************************/ LOCAL void AllocateCommon(papropName,rhte,rprop,fNewHte) APROPNAMEPTR papropName; RBTYPE rhte; RBTYPE rprop; WORD fNewHte; { APROPUNDEFPTR papropUndef; /* Pointer to undefined symbol */ APROPSNPTR apropSn; /* SEGDEF pointer */ long len; /* Length of common variable */ WORD cbElem; /* Bytes per element */ long cbSeg; /* Number of bytes per segment */
papropUndef = (APROPUNDEFPTR ) papropName; /* Recast pointer */ if (papropUndef->au_flags & COMMUNAL)/* If symbol is defined common */ { len = papropUndef->au_len; /* Get object's length */ cbElem = papropUndef->au_cbEl; /* Get number of bytes per element */ papropName->an_attr = ATTRPNM; /* Give it the public attribute */ papropName->an_flags = FPRINT; /* Symbol is printable */ #if ILINK
papropName->an_module = 0; /* Special "module" for communals */ #endif
MARKVP(); /* Mark virtual page as dirty */ ++pubMac; /* Increment count of public symbols */ if(!cbElem) /* If near variable */ { #if OMF386
if (f386) /* DWORD-align objects >= len 4 */ { if(len >= 4 && cbCommon + 3 > cbCommon) cbCommon = (cbCommon + 3) & ~3L; } else #endif
if(!(len & 1)) cbCommon = (cbCommon + 1) & ~1L; /* Word-align even-lengthed objects */ papropName->an_ra = (RATYPE) cbCommon; /* Assign an offset */ papropName->an_gsn = gsnCommon; /* Assign to c_common segment */ papropName->an_ggr = ggrCommon; /* Set up group association */ #if OMF386
if(f386) { if(cbCommon + len < cbCommon) Fatal(ER_32comarea); else cbCommon += len; } else #endif
if((cbCommon += len) > LXIVK) Fatal(ER_comarea); /* Fatal if too much common */ } else if ((len *= cbElem) < LXIVK) { /* Else if object not "huge" */ if (cbFar + len > LXIVK) /* If new segment needed */ { if (gsnFar != SNNIL) /* If there is an "old" segment */ { apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnFar],TRUE); /* Get old SEGDEF */ apropSn->as_cbMx = cbFar; /* Save old length */ } apropSn = GenSeg((BYTE *) "\007FAR_BSS", (BYTE *) "\007FAR_BSS", GRNIL, FALSE); /* Generate one */ apropSn->as_flags = dfData; /* Use default data flags */ #if EXE386
apropSn->as_flags &= ~OBJ_INITDATA; // Clear initialized data bit
apropSn->as_flags |= OBJ_UNINITDATA; // Set uninitialized data bit
#endif
#if O68K
if(f68k) apropSn->as_flags |= NS32BIT; // 32-bit data
#endif
gsnFar = apropSn->as_gsn; /* Get global SEGDEF number */ cbFar = 0L; /* Initialize size */ papropName = (APROPNAMEPTR ) FetchSym(rprop,TRUE); /* Refetch */ } if (!(len & 1)) cbFar = (cbFar + 1) & ~1L; /* Word-align even-lengthed objects */ papropName->an_ra = (RATYPE) cbFar; /* Assign an offset */ papropName->an_gsn = gsnFar;/* Assign to far segment */ papropName->an_ggr = GRNIL; /* No group association */ cbFar += len; /* Update length */ } else /* Else if "huge" object */ { cbSeg = (LXIVK / cbElem)*cbElem; /* Calculate bytes per seg */ papropName->an_ra = LXIVK - cbSeg; /* Assign offset so last element in
first seg. not split */ papropName->an_gsn = gsnMac;/* Assign to segment */ papropName->an_ggr = GRNIL; /* No group association */ while(len) /* While bytes remain */ { if(cbSeg > len) cbSeg = len; /* Clamp segment length to len */ apropSn = GenSeg((BYTE *) "\010HUGE_BSS", (BYTE *) "\010HUGE_BSS",GRNIL,FALSE); /* Create segment */ apropSn->as_cbMx = len > LXIVK ? LXIVK : len; /* Set segment size */ apropSn->as_flags = dfData; /* Use default data flags */ #if EXE386
apropSn->as_flags &= ~OBJ_INITDATA; // Clear initialized data bit
apropSn->as_flags |= OBJ_UNINITDATA; // Set uninitialized data bit
#endif
#if O68K
if(f68k) apropSn->as_flags |= NS32BIT; // 32-bit data
#endif
len -= cbSeg; /* Decrement length */ } } } }
/****************************************************************
* * * AssignClasses: * * * * Assign the ordering of all segments in all classes that * * pass the given test function. * * * ****************************************************************/
LOCAL void NEAR AssignClasses(WORD (NEAR *ffun)(APROPSNPTR prop)) { REGISTER SNTYPE gsn; /* Index */ REGISTER APROPSNPTR apropSn; /* Segment definition pointer */ SNTYPE gsnFirst; /* Index of first segment in class */ RBTYPE rhteClass; /* Class name */
for(gsnFirst = 1; gsnFirst < gsnMac; ++gsnFirst) { /* Loop through the segments */ rhteClass = RHTENIL; /* Initialize */ for(gsn = gsnFirst; gsn < gsnMac; ++gsn) { /* Loop to examine segment records */ if(mpgsnseg[gsn] != SEGNIL) continue; /* Skip assigned segments */ apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE); /* Fetch SEGDEF from virt. mem. */ if(rhteClass == RHTENIL) rhteClass = apropSn->as_rCla; /* Get class if we don't have one */ if(apropSn->as_rCla == rhteClass && (ffun == ((WORD (NEAR *)(APROPSNPTR)) 0) || (*ffun)(apropSn))) { /* If class member found */ mpgsnseg[gsn] = ++segLast; /* Save ordering number */ #if QBLIB
if(fQlib) { if(rhteClass == rhteFarData && segFD1st == SEGNIL) segFD1st = segLast; else if(rhteClass == rhteFarBss && segFB1st == SEGNIL) segFB1st = segLast; } #endif
mpseggsn[segLast] = gsn;// Map the other way
if(IsCodeFlg(apropSn->as_flags)) { #if OSEGEXE AND ODOS3EXE
/* Set FCODE here for 3.x segments. FNOTEMPTY later */ if(!fNewExe) mpsegFlags[segLast] = FCODE; #endif
segCodeLast = segLast; /* Remember last code segment */ } else if(IsDataFlg(apropSn->as_flags)) segDataLast = segLast; /* Remember last data segment */ #if NOT OSEGEXE
mpsegFlags[segLast] = apropSn->as_flags; #endif
} } #if QBLIB
if(fQlib) { if(rhteClass == rhteFarData && segFD1st != SEGNIL) segFDLast = segLast; else if(rhteClass == rhteFarBss && segFB1st != SEGNIL) segFBLast = segLast; } #endif
} }
#if OEXE
/****************************************************************
* * * MkPubSym: * * * * Adds a public symbol record with the given parameters * * to the symbol table. Used for things like "$$MAIN". * * * ****************************************************************/
void MkPubSym(sb,ggr,gsn,ra) BYTE *sb; /* Length-prefixed symbol name */ GRTYPE ggr; /* Global GRPDEF number */ SNTYPE gsn; /* Global SEGDEF number */ RATYPE ra; /* Segment offset */ { APROPNAMEPTR apropName; /* Public name pointer */
if(PropSymLookup(sb,ATTRPNM,FALSE) != PROPNIL) { /* If symbol already defined */ OutError(ER_pubdup,sb + 1); return; /* And return */ } /* If not undefined, create as public */ if((apropName = (APROPNAMEPTR ) PropSymLookup(sb,ATTRUND,FALSE)) == PROPNIL) apropName = (APROPNAMEPTR ) PropSymLookup(sb,ATTRPNM,TRUE); apropName->an_attr = ATTRPNM; /* Public symbol */ apropName->an_gsn = gsn; /* Save segment definition number */ apropName->an_ra = ra; /* Starts at 4th byte of segment */ apropName->an_ggr = ggr; /* Save group definition number */ ++pubMac; /* Increment public count */ apropName->an_flags = FPRINT; /* Public is printable */ MARKVP(); /* Page has changed */ #if SYMDEB
if (fSymdeb) /* If ISLAND support on */ DebPublic(vrprop, PUBDEF); /* Make a PUBLICS entry */ #endif
#if ILINK
if (fIncremental) apropName->an_module = imodFile; #endif
} #endif /* OEXE */
LOCAL WORD NEAR IsNotAbs(apropSn) APROPSNPTR apropSn; /* Pointer to segment record */ { return(!IsDebug(apropSn) && !IsAbsTysn(apropSn->as_tysn)); /* Return true if not absolute segment */ }
#if EXE386
LOCAL WORD NEAR IsImportData(prop) APROPSNPTR prop; /* Pointer to segment record */ { return(prop->as_gsn == gsnImport); /* Return true if import data segment */ } #endif
LOCAL WORD NEAR IsCode(prop) APROPSNPTR prop; /* Pointer to segment record */ { return(IsCodeFlg(prop->as_flags) && !IsAbsTysn(prop->as_tysn)); /* Return true if code segment */ }
#if OEXE
LOCAL WORD NEAR IsNotDGroup(prop) APROPSNPTR prop; /* Pointer to segment record */ { return(prop->as_ggr != ggrDGroup && !IsDebug(prop) && !IsAbsTysn(prop->as_tysn)); /* True if segment not in DGROUP */ }
LOCAL WORD NEAR IsBegdata(prop) APROPSNPTR prop; /* Pointer to segment record */ { return(prop->as_rCla == rhteBegdata && !IsAbsTysn(prop->as_tysn)); /* True if segment class BEGDATA */ }
LOCAL WORD NEAR IsNotBssStack(prop) APROPSNPTR prop; /* Pointer to segment record */ { return(prop->as_rCla != rhteBss && prop->as_rCla != rhteStack && !IsDebug(prop) && !IsAbsTysn(prop->as_tysn)); /* True if neither BSS nor STACK */ }
LOCAL WORD NEAR IsNotStack(prop) APROPSNPTR prop; /* Pointer to segment record */ { return(prop->as_rCla != rhteStack && !IsDebug(prop) && !IsAbsTysn(prop->as_tysn)); /* True if not class STACK */ } #endif /* OEXE */
#if INMEM
WORD saExe = FALSE;
void SetInMem () { WORD cparExe; WORD cparSave;
if(fOverlays || fSymdeb) return; cparExe = mpsegsa[segLast] + ((mpsegraFirst[segLast] + mpsegcb[segLast] + 0xf) >> 4); cparSave = cparExe; if(!(saExe = Dos3AllocMem(&cparExe))) return; if(cparExe != cparSave) { Dos3FreeMem(saExe); saExe = 0; return; } Dos3ClrMem(saExe,cparExe); } #endif /* INMEM */
/****************************************************************
* * * AssignAddresses: * * * * This function scans the set of segments, given their * * ordering, and assigns segment registers and addresses. * * * ****************************************************************/
void NEAR AssignAddresses() { APROPSNPTR apropSn; /* Ptr to a segment record */ #if FDEBUG
SNTYPE gsn; /* Current global segment number */ long dbsize; /* Length of segment */ RBTYPE rbClass; /* Pointer to segment class */ #endif
BSTYPE bsTmp; #if QBLIB
SNTYPE gsnQbSym; /* gsn of SYMBOL segment for .QLB */ #endif
#if OSEGEXE
extern FTYPE fNoNulls; /* True if not inserting 16 nulls */ #else
#define fNoNulls FALSE
#endif
// Set up stack allocation
if (gsnStack != SNNIL) /* If stack segment exists */ { apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnStack],TRUE); /* Fetch segment definition */ #if OEXE
apropSn->as_tysn = (BYTE) ((apropSn->as_tysn & 0x1F) | (ALGNPAR << 5)); /* Force paragraph alignment */ #if EXE386
if (!cbStack) cbStack = apropSn->as_cbMx; cbStack = (cbStack + 3) & ~3; /* Must be even number of bytes */ apropSn->as_cbMx = cbStack; #else
if (!cbStack) cbStack = (WORD) apropSn->as_cbMx; cbStack = (cbStack + 1) & ~1; /* Must be even number of bytes */ apropSn->as_cbMx = (DWORD) cbStack; #endif /* Save size of stack segment */
#else
/* Force size to 0 for Xenix executables */ apropSn->as_cbMx = 0L; #endif
} #if OEXE
#if OSEGEXE
else if(cbStack == 0 && #if O68K
iMacType == MAC_NONE && #endif
#if EXE386
IsAPLIPROG(vFlags)) #else
!(vFlags & NENOTP) && !fBinary) #endif
#else
else if(cbStack == 0 && !fBinary) #endif
{ /* Else if no stack and not library */ #if 0
/* Issue warning message */ if(fLstFileOpen && bsLst != stderr) { bsTmp = bsErr; bsErr = bsLst; OutWarn(ER_nostack); bsErr = bsTmp; } OutWarn(ER_nostack); #endif
} #endif
if(fCommon) /* If there are communal variables */ { apropSn = GenSeg((BYTE *) "\010c_common", (BYTE *) "\003BSS",ggrDGroup,TRUE); /* Generate communal variable seg */ if(vfCreated) apropSn->as_flags = dfData; /* Use default data flags */ gsnCommon = apropSn->as_gsn; /* Save common segment number */ ggrCommon = apropSn->as_ggr; /* Save common group number */ cbCommon = apropSn->as_cbMx; /* Initialize size of common */ gsnFar = SNNIL; /* No far BSS yet */ #if NOT EXE386
#if OMF386
if(f386) { cbFar = ~0L; apropSn->as_flags |= FCODE386; } else #endif
#if O68K
if(f68k) { cbFar = LXIVK + 1; /* Force creation of far BSS segment */ apropSn->as_flags |= NS32BIT; } else #endif
#endif
cbFar = LXIVK + 1; /* Force creation of far BSS segment */ DEBUGVALUE(cbCommon); /* Debug info */ EnSyms(AllocateCommon,ATTRUND); /* Assign common variables */ /* Don't use SmallEnEnsyms - symbol */ /* table may grow while in EnSyms */ apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnCommon],TRUE); apropSn->as_cbMx = cbCommon; /* Save segment size */ if(gsnFar != SNNIL) /* If far BSS created */ { apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnFar],TRUE); apropSn->as_cbMx = cbFar; /* Save segment size */ } } #if FALSE AND OSEGEXE AND SYMDEB AND NOT EXE386
if (fSymdeb && fNewExe && cImpMods) { apropSn = GenSeg("\011$$IMPORTS", "\010FAR_DATA", GRNIL, FALSE); /* Support for dyncalls for CV */ gsnImports = apropSn->as_gsn; apropSn->as_flags = dfData; /* Use default data flags */ apropSn->as_cbMx = cbImpSeg; /* Save segment size */ } #endif
#if EXE386
GenImportTable(); #endif
/* Initialize segment-based tables for pass 2 */
InitP2Tabs(); #if OVERLAYS
if(fOverlays) SetupOverlays(); #endif
#if OEXE
/*
* If /DOSSEG is enabled and /NONULLSDOSSEG is not enabled, look for * segment _TEXT. If found, increase size by 16 in preparation for * reserving first 16 addresses for the sake of signal(). */ if(fSegOrder && !fNoNulls) { apropSn = (APROPSNPTR ) PropSymLookup((BYTE *) "\005_TEXT",ATTRPSN,FALSE); /* Look for public segment _TEXT */ if(apropSn != PROPNIL) /* If it exists */ { gsnText = apropSn->as_gsn; /* Save the segment index */ if ((apropSn->as_tysn)>>5 == ALGNPAG) NullDelta = 256; #if EXE386
if (apropSn->as_cbMx > CBMAXSEG32 - NullDelta) Fatal(ER_txtmax); else apropSn->as_cbMx += NullDelta; #else
if((apropSn->as_cbMx += NullDelta) > LXIVK) Fatal(ER_txtmax); #endif
fTextMoved = TRUE; /* Bump the size up */ MARKVP(); /* Page has changed */ } } #endif
#if FDEBUG
if(fDebug && fLstFileOpen) /* If debugging on */ { /* Dump segments and lengths */ for(gsn = 1; gsn < gsnMac; ++gsn) { apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn],FALSE); dbsize = apropSn->as_cbMx; rbClass = apropSn->as_rCla; FmtPrint("%3d segment \"%s\"",gsn,1 + GetPropName(apropSn)); FmtPrint(" class \"%s\" length %lxH bytes\r\n", 1 + GetPropName(FetchSym(rbClass,FALSE)),dbsize); } } #endif
#if OSEGEXE
if (gsnAppLoader) { // Make sure that aplication loder gets its own segment
mpgsnseg[gsnAppLoader] = ++segLast; mpseggsn[segLast] = gsnAppLoader; } #endif
#if OEXE
if (fSegOrder) /* If forcing segment ordering */ { AssignClasses(IsCode); /* Code first,... */ #if EXE386
AssignClasses(IsImportData); /* ...then import data */ #endif
AssignClasses(IsNotDGroup); /* ...then non-DGROUP,... */ AssignClasses(IsBegdata); /* ...then class BEGDATA,... */ AssignClasses(IsNotBssStack); /* ...then all but BSS and STACK,... */ AssignClasses(IsNotStack); /* ...then all but class STACK */ } #endif
#if OXOUT OR OIAPX286
if(fIandD) /* If separate code and data */ AssignClasses(IsCode); /* Assign ordering to code */ #endif
AssignClasses(IsNotAbs); /* Assign order to segments */ #if QBLIB
/* If building QB userlib, generate the symbol segment last */ if(fQlib) { gsnQbSym = GenSeg("\006SYMBOL", "", GRNIL, FALSE)->as_gsn; mpgsnseg[gsnQbSym] = ++segLast; } #endif
#if NOT EXE386
if (fBinary && cbStack && mpgsnseg[gsnStack] == 1) { /*
* In .COM file first segment is a stack and it has non zero * size. We warn user about making his stack segment size * equal zero. */ apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsnStack],TRUE); apropSn->as_cbMx = 0L; OutWarn(ER_stksize);
} #endif
/* Assign addresses according to which format exe is being produced */
#if OIAPX286
AssignXenAddr(); #endif
#if OSEGEXE AND ODOS3EXE
if (fNewExe) AssignSegAddr(); else AssignDos3Addr();
#else
#if OSEGEXE
AssignSegAddr(); #endif
#if ODOS3EXE
AssignDos3Addr(); #endif
#endif
// Remember index for first debug segment
segDebFirst = segLast + #if ODOS3EXE
csegsAbs + #endif
(SEGTYPE) 1; #if OEXE
// If /DOSSEG enabled and segment _TEXT found, initialize offset
// of _TEXT to 16 to reserve addresses 0-15. WARNING: gsnText must
// be initialized to SNNIL.
if (gsnText != SNNIL) { mpgsndra[gsnText] += NullDelta;
// If no program starting address, initialize it to 0:NullDelta
if (segStart == SEGNIL && !raStart && !mpsegsa[mpgsnseg[gsnText]]) raStart = NullDelta;
// If /DOSSEG enabled and segment _TEXT found, initialize offset
// of _TEXT to NulDelta to reserve addresses 0-NullDelta-1.
// This was done after the COMDAT's were allocated so the offsets
// of COMDAT's allocated in _TEXT segment are off by NullDelta bytes.
// Here we adjust them, so the data block associated with COMDAT
// is placed in the right spot in the memory image. The matching
// public symbol will be shifted by the call to EnSyms(FixSymRa, ATTRPNM).
FixComdatRa(); } #endif
EnSyms(FixSymRa, ATTRPNM); #if LOCALSYMS
if (fLocals) EnSyms(FixSymRa, ATTRLNM); #endif
#if INMEM
SetInMem(); #endif
// Allocate memory blocks for the final program's memory image
if (fNewExe) { // Segmented-executable
mpsaMem = (BYTE FAR * FAR *) GetMem(saMac * sizeof(BYTE FAR *)); } else { // DOS executable
mpsegMem = (BYTE FAR * FAR *) GetMem((segLast + 1) * sizeof(BYTE FAR *)); }
#if OVERLAYS
if (fOverlays && gsnOvlData != SNNIL) FixOvlData(); // Initialize overlay data tables
#endif
#if QBLIB
if(fQlib) BldQbSymbols(gsnQbSym); /* Build QB SYMBOL segment */ #endif
}
/*** Define_edata_end - define special C run-time symbols
* * Purpose: * Define special symbols _edata and _end used by the C run-time. * These symbols are defined as follows: * * The DGROUP layout * * +------------+ * | | * | | * | | * | Near Heap | * | | * | | * +------------+ * | | * | | * | STACK | * | | * | | * +------------+ <-- _end * | | * | _BSS | * | | * +------------+ <-- _edata * | | * | _CONST | * | | * +------------+ * | | * | _DATA | * | | * +------------+ * * Input: * papropSn - pointer to segment descriptor * * Output: * None. * * Exceptions: * None. * * Notes: * None. * *************************************************************************/
void NEAR Define_edata_end(APROPSNPTR papropSn) { APROPNAMEPTR apropName; // Public name pointer
SNTYPE gsn; // Global segment number
// Symbols were defined by SwDosseg(), now adjust addresses.
if (papropSn->as_tysn != TYSNABS && papropSn->as_ggr == ggrDGroup) { // This is not absolute segment and it belong to DGROUP
gsn = papropSn->as_gsn; if (fNoEdata && papropSn->as_rCla == rhteBss) { fNoEdata = FALSE; apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\006_edata",ATTRPNM,FALSE); // Fetch symbol
apropName->an_gsn = gsn; // Save segment definition number
apropName->an_ggr = ggrDGroup; // Save group definition number
MARKVP(); // Page has changed
} else if (fNoEnd && papropSn->as_rCla == rhteStack) { fNoEnd = FALSE; apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE); // Fetch symbol
apropName->an_gsn = gsn; // Save segment definition number
apropName->an_ggr = ggrDGroup; // Save group definition number
MARKVP(); // Page has changed
} } }
/*** Check_edata_end - check the definiton of special C run-time symbols
* * Purpose: * Check the definition of special symbols _edata and _end used * by the C run-time. * * Input: * None. * * Output: * None. * * Exceptions: * None. * * Notes: * None. * *************************************************************************/
void NEAR Check_edata_end(SNTYPE gsnTop, SEGTYPE segTop) { APROPNAMEPTR apropName; // Public name pointer
APROPNAMEPTR apropName1; // Public name pointer
// Check if both symbols are defined properly
if (fNoEdata) { // No class 'BSS' segment defined;
// make _edata point to end of 'DATA' segments
apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\006_edata",ATTRPNM,FALSE); // Fetch symbol
if (fNoEnd) { // No class 'STACK' segment defined;
// set _edata to end of DGROUP
if (fNewExe) { apropName->an_gsn = mpggrgsn[ggrDGroup]; // Save segment definition number
apropName->an_ggr = ggrDGroup; // Save group definition number
apropName->an_ra = mpsacb[mpsegsa[mpgsnseg[apropName->an_gsn]]]; // Save 'DATA' segments size
} #if NOT EXE386
else { apropName->an_gsn = gsnTop; apropName->an_ggr = ggrDGroup; apropName->an_ra = mpsegcb[segTop]; } #endif
} else { // set _edata to _end
apropName1 = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE); // Fetch symbol
apropName->an_gsn = apropName1->an_gsn; // Save segment definition number
apropName->an_ggr = apropName1->an_ggr; // Save group definition number
apropName->an_ra = apropName1->an_ra; // Save 'DATA' segments size
} MARKVP(); // Page has changed
}
if (fNoEnd) { // No class 'STACK' segment defined;
// make _end point to end of 'BSS' or 'DATA' segments
apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE); // Fetch symbol
if (fNewExe) { apropName->an_gsn = mpggrgsn[ggrDGroup]; // Save segment definition number
apropName->an_ggr = ggrDGroup; // Save group definition number
apropName->an_ra = mpsacb[mpsegsa[mpgsnseg[apropName->an_gsn]]]; // Save 'BSS' segments size
} #if NOT EXE386
else { apropName->an_gsn = gsnTop; apropName->an_ggr = ggrDGroup; apropName->an_ra = mpsegcb[segTop]; } #endif
MARKVP(); // Page has changed
}
// Make __end and __edata the same as _end and _edata
apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\006_edata",ATTRPNM,FALSE); apropName1 = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\007__edata",ATTRPNM,TRUE); apropName1->an_gsn = apropName->an_gsn; apropName1->an_ggr = apropName->an_ggr; apropName1->an_ra = apropName->an_ra;
apropName = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\004_end",ATTRPNM,FALSE); apropName1 = (APROPNAMEPTR ) PropSymLookup((BYTE *) "\005__end",ATTRPNM,TRUE); apropName1->an_gsn = apropName->an_gsn; apropName1->an_ggr = apropName->an_ggr; apropName1->an_ra = apropName->an_ra; }
|