1111 lines
37 KiB
C
1111 lines
37 KiB
C
/* SCCSID = @(#)newpri.c 4.7 86/09/23 */
|
||
/*
|
||
* Copyright Microsoft Corporation, 1983-1987
|
||
*
|
||
* This Module contains Proprietary Information of Microsoft
|
||
* Corporation and should be treated as Confidential.
|
||
*/
|
||
|
||
/* MAP file printer */
|
||
|
||
/****************************************************************
|
||
* *
|
||
* NEWPRI.C *
|
||
* *
|
||
****************************************************************/
|
||
|
||
#include <minlit.h> /* Types and constants */
|
||
#include <bndtrn.h> /* Basic type & const declarations */
|
||
#include <bndrel.h> /* Types and constants */
|
||
#include <lnkio.h> /* Linker I/O definitions */
|
||
#include <lnkmsg.h> /* Error messages */
|
||
#include <newexe.h>
|
||
#include <extern.h> /* External declarations */
|
||
#include <impexp.h>
|
||
#if EXE386
|
||
#include <exe386.h>
|
||
#endif
|
||
#include <undname.h>
|
||
|
||
#define parent(i) (((i) - 1) >> 1)/* Parent of i */
|
||
#define lchild(i) (((i) << 1) + 1)/* Left child of i */
|
||
#define rchild(i) (((i) << 1) + 2)/* Right child of i */
|
||
#define isleft(i) ((i) & 1) /* True if i is a left child */
|
||
|
||
RBTYPE *mpsymrbExtra; /* Sort table for extra symbols */
|
||
RBTYPE *ompsymrb; /* Stack-allocated sort table */
|
||
WORD stkMax; /* Max # of symbols on stack */
|
||
|
||
LOCAL FTYPE fGrps; /* True if there are groups */
|
||
|
||
/*
|
||
* LOCAL FUNCTION PROTOTYPES
|
||
*/
|
||
|
||
LOCAL void NEAR ChkMapErr(void);
|
||
LOCAL void NEAR PrintOne(BYTE *sbName,
|
||
APROPNAMEPTR apropName);
|
||
LOCAL void NEAR PrintProp(RBTYPE rb,
|
||
FTYPE attr);
|
||
LOCAL void NEAR PrintSyms(WORD irbMac,
|
||
FTYPE attr);
|
||
LOCAL void SaveHteSym(APROPNAMEPTR prop,
|
||
RBTYPE rhte,
|
||
RBTYPE rprop,
|
||
WORD fNewHte);
|
||
LOCAL void NEAR PutSpaces(int HowMany);
|
||
LOCAL void NEAR HdrExport(FTYPE attr);
|
||
LOCAL void NEAR ShowExp(AHTEPTR ahte,
|
||
RBTYPE rprop);
|
||
LOCAL void NEAR PrintExps(WORD irbMac,
|
||
FTYPE attr);
|
||
LOCAL void NEAR HdrName(FTYPE attr);
|
||
LOCAL void NEAR HdrValue(FTYPE attr);
|
||
LOCAL void NEAR PrintContributors(SNTYPE gsn);
|
||
|
||
#if AUTOVM
|
||
extern BYTE FAR * NEAR FetchSym1(RBTYPE rb, WORD Dirty);
|
||
#define FETCHSYM FetchSym1
|
||
#else
|
||
#define FETCHSYM FetchSym
|
||
#endif
|
||
|
||
|
||
|
||
LOCAL void NEAR ChkMapErr(void)
|
||
{
|
||
if (ferror(bsLst))
|
||
{
|
||
ExitCode = 4;
|
||
Fatal(ER_spclst); /* Fatal error */
|
||
}
|
||
}
|
||
|
||
|
||
LOCAL void NEAR PrintOne(sbName,apropName)
|
||
BYTE *sbName; /* Symbol name */
|
||
REGISTER APROPNAMEPTR apropName; /* Symbol definition record pointer */
|
||
{
|
||
SBTYPE sbImp; /* Import name */
|
||
SATYPE sa; /* Symbol base */
|
||
RATYPE ra; /* Symbol offset */
|
||
SEGTYPE seg; /* Segment number */
|
||
BYTE FAR *pb;
|
||
#if EXE386
|
||
typedef struct impMod
|
||
{
|
||
DWORD am_Name; // Imported module name
|
||
RBTYPE am_1stImp; // Head of imported names list
|
||
RBTYPE am_lastImp; // Tail of imported names list
|
||
DWORD am_count; // Module number/count of imports
|
||
}
|
||
IMPMOD;
|
||
|
||
DWORD entry;
|
||
IMPMOD *curMod; // Imported module
|
||
#else
|
||
WORD entry;
|
||
#endif
|
||
WORD module;
|
||
WORD flags;
|
||
SNTYPE gsn;
|
||
#if NOT OIAPX286
|
||
APROPSNPTR papropSn;
|
||
SATYPE saGroup;
|
||
#endif
|
||
SBTYPE sbUndecor;
|
||
|
||
|
||
/*
|
||
* Store all needed fields in local variables, because
|
||
* page containing symbol definition record can be
|
||
* swapped out.
|
||
*/
|
||
|
||
ra = apropName->an_ra;
|
||
gsn = apropName->an_gsn;
|
||
flags = apropName->an_flags;
|
||
#if OSEGEXE
|
||
#if EXE386
|
||
entry = apropName->an_name;
|
||
#else
|
||
entry = apropName->an_entry;
|
||
#endif
|
||
module = apropName->an_module;
|
||
#endif
|
||
|
||
if(gsn) /* If not absolute symbol */
|
||
{
|
||
seg = mpgsnseg[gsn]; /* Get segment number */
|
||
sa = mpsegsa[seg]; /* Get base value */
|
||
#if NOT OIAPX286
|
||
if(!fNewExe && seg <= segLast)
|
||
{
|
||
papropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],
|
||
FALSE);
|
||
if(papropSn->as_ggr != GRNIL)
|
||
{
|
||
saGroup = mpsegsa[mpgsnseg[mpggrgsn[papropSn->as_ggr]]];
|
||
ra += (sa - saGroup) << 4;
|
||
sa = saGroup;
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
else sa = 0; /* Else no base */
|
||
if (flags & FUNREF)
|
||
{
|
||
sa = 0;
|
||
ra = 0L;
|
||
}
|
||
#if EXE386
|
||
fprintf(bsLst," %04X:%08lX",sa,ra);
|
||
#else
|
||
#if O68K
|
||
if (f386 || f68k)
|
||
#else
|
||
if (f386)
|
||
#endif
|
||
fprintf(bsLst," %04X:%08lX",sa,ra);
|
||
else
|
||
fprintf(bsLst," %04X:%04X",sa, (WORD) ra);
|
||
#endif
|
||
/* Write address */
|
||
#if OSEGEXE
|
||
if (fNewExe && (flags & FIMPORT))
|
||
fputs(" Imp ",bsLst); /* If public is an import */
|
||
else
|
||
#endif
|
||
if (flags & FUNREF)
|
||
fputs(" Unr ", bsLst);
|
||
else if ((!gsn || seg > segLast))
|
||
fputs(" Abs ",bsLst); /* Segment type */
|
||
#if OVERLAYS
|
||
else if (fOverlays)
|
||
{
|
||
if(mpsegiov[seg] != IOVROOT)
|
||
fputs(" Ovl ",bsLst);
|
||
else
|
||
fputs(" Res ",bsLst);
|
||
}
|
||
#endif
|
||
else
|
||
PutSpaces(7);
|
||
OutSb(bsLst,sbName); /* Output the symbol */
|
||
#if NOT WIN_NT
|
||
if (fFullMap && sbName[1] == '?')
|
||
{
|
||
fputs("\n", bsLst);
|
||
UndecorateSb(sbName, sbUndecor, sizeof(sbUndecor));
|
||
#if EXE386
|
||
PutSpaces(24);
|
||
#else
|
||
#if O68K
|
||
if (f386 || f68k)
|
||
#else
|
||
if (f386)
|
||
#endif
|
||
PutSpaces(24);
|
||
else
|
||
PutSpaces(20);
|
||
#endif
|
||
OutSb(bsLst, sbUndecor);
|
||
fputs("\n", bsLst);
|
||
#if OSEGEXE
|
||
if (fNewExe && flags & FIMPORT)
|
||
PutSpaces(24);
|
||
#endif
|
||
}
|
||
#endif
|
||
#if OSEGEXE
|
||
if (fNewExe && flags & FIMPORT)
|
||
{ /* If public is an import */
|
||
PutSpaces(20 - B2W(sbName[0])); /* Space fill */
|
||
|
||
/* Print the module name */
|
||
|
||
#if EXE386
|
||
// Get known import module descriptor
|
||
|
||
curMod = (IMPMOD *) mapva(AREAMOD + module * sizeof(IMPMOD), FALSE);
|
||
strcpy(&sbImp[1], mapva(AREAIMPMOD + curMod->am_Name, FALSE));
|
||
/* Get module name */
|
||
sbImp[0] = (BYTE) strlen((char *) &sbImp[1]);
|
||
#else
|
||
|
||
pb = &(ImportedName.rgByte[ModuleRefTable.rgWord[module-1]]);
|
||
FMEMCPY(sbImp, pb, pb[0] + 1);
|
||
#endif
|
||
fputs(" (",bsLst); /* Print module name */
|
||
OutSb(bsLst,sbImp);
|
||
if(!(flags & FIMPORD))
|
||
{ /* If not imported by ordinal */
|
||
/* Print the entry name */
|
||
#if EXE386
|
||
strnset((char *) sbImp, '\0', sizeof(sbImp));
|
||
vmmove(sizeof(sbImp) - 1, &sbImp[1], AREAIMPS + entry + sizeof(WORD), FALSE);
|
||
sbImp[0] = (BYTE) strlen((char *) &sbImp[1]);
|
||
fputc('!',bsLst);
|
||
#else
|
||
pb = &(ImportedName.rgByte[entry]);
|
||
FMEMCPY(sbImp, pb, pb[0]+1);
|
||
fputc('.',bsLst);
|
||
#endif
|
||
OutSb(bsLst,sbImp);
|
||
fputc(')',bsLst);
|
||
}
|
||
else
|
||
fprintf(bsLst,".%u)",entry);
|
||
/* Else print entry number */
|
||
NEWLINE(bsLst);
|
||
return;
|
||
}
|
||
#endif /* OSEGEXE */
|
||
#if OVERLAYS
|
||
if (fOverlays && gsn && seg <= segLast && mpsegiov[seg] != IOVROOT)
|
||
fprintf(bsLst," (%XH)",mpsegiov[seg]);
|
||
#endif
|
||
NEWLINE(bsLst);
|
||
ChkMapErr();
|
||
}
|
||
/*
|
||
* PrintProp:
|
||
*
|
||
* Print a symbol, given a virtual property address or hash table
|
||
* entry. Called by PrintSyms.
|
||
*/
|
||
|
||
LOCAL void NEAR PrintProp (rb, attr)
|
||
RBTYPE rb;
|
||
ATTRTYPE attr; /* Symbol attribute */
|
||
{
|
||
#if NOT NEWSYM
|
||
APROPNAMETYPE apropName; /* Buffer for symbol def */
|
||
#endif
|
||
AHTEPTR pahte; /* Pointer to hash table entry */
|
||
APROPPTR paprop; /* Pointer to property cell */
|
||
SBTYPE sbName; /* Public symbol text */
|
||
RBTYPE rprop; /* Property cell virtual address */
|
||
|
||
|
||
paprop = (APROPPTR ) FETCHSYM(rb,FALSE);
|
||
/* Fetch property cell from VM */
|
||
if(paprop->a_attr == ATTRNIL) /* If we have a hash table entry */
|
||
{
|
||
pahte = (AHTEPTR ) paprop; /* Recast pointer */
|
||
memcpy(sbName,GetFarSb(pahte->cch),B2W(pahte->cch[0]) + 1);
|
||
/* Copy the symbol */
|
||
paprop = (APROPPTR ) FETCHSYM(pahte->rprop,FALSE);
|
||
/* Get pointer to property list */
|
||
while(paprop->a_attr != ATTRNIL)
|
||
{ /* Look through properties */
|
||
rprop = paprop->a_next; /* Save link to next cell */
|
||
if(paprop->a_attr == attr)
|
||
{ /* If match found */
|
||
#if NEWSYM
|
||
PrintOne(sbName,(APROPNAMEPTR)paprop);
|
||
#else
|
||
memcpy(&apropName,paprop,CBPROPNAME);
|
||
/* Copy record from virtual memory */
|
||
PrintOne(sbName,&apropName);
|
||
/* Print the symbol entry */
|
||
#endif
|
||
}
|
||
paprop = (APROPPTR ) FETCHSYM(rprop,FALSE);
|
||
/* Try next in list */
|
||
}
|
||
return; /* Done */
|
||
}
|
||
#if NOT NEWSYM
|
||
memcpy(&apropName,paprop,CBPROPNAME);
|
||
/* Save record in buffer */
|
||
#endif
|
||
while(paprop->a_attr != ATTRNIL) /* Find symbol */
|
||
paprop = (APROPPTR ) FETCHSYM(paprop->a_next,FALSE);
|
||
|
||
pahte = (AHTEPTR ) paprop; /* Recast pointer */
|
||
memcpy(sbName,GetFarSb(pahte->cch),B2W(pahte->cch[0]) + 1);
|
||
/* Copy the symbol */
|
||
/* Print the symbol entry */
|
||
#if NEWSYM
|
||
PrintOne(sbName,(APROPNAMEPTR)FETCHSYM(rb,FALSE));
|
||
#else
|
||
PrintOne(sbName,&apropName);
|
||
#endif
|
||
}
|
||
|
||
/****************************************************************
|
||
* *
|
||
* PrintSyms: *
|
||
* *
|
||
****************************************************************/
|
||
|
||
LOCAL void NEAR PrintSyms(irbMac,attr)
|
||
WORD irbMac; /* Table size */
|
||
ATTRTYPE attr; /* Symbol attribute */
|
||
{
|
||
WORD x; /* Sort table index */
|
||
|
||
|
||
for (x = irbMac; x > 0; x--)
|
||
PrintProp(ExtractMin(x), attr);
|
||
}
|
||
|
||
|
||
/***************************************************************
|
||
* *
|
||
* SavePropSym: *
|
||
* *
|
||
****************************************************************/
|
||
|
||
void SavePropSym(APROPNAMEPTR prop,
|
||
RBTYPE rhte,
|
||
RBTYPE rprop,
|
||
WORD fNewHte)
|
||
{
|
||
if(prop->an_attr != ATTRPNM || (prop->an_flags & FPRINT))
|
||
{ /* If printable, save ptr to info */
|
||
Store(rprop);
|
||
}
|
||
return;
|
||
}
|
||
|
||
/****************************************************************
|
||
* *
|
||
* SaveHteSym: *
|
||
* *
|
||
****************************************************************/
|
||
|
||
LOCAL void SaveHteSym(APROPNAMEPTR prop,
|
||
RBTYPE rhte,
|
||
RBTYPE rprop,
|
||
WORD fNewHte)
|
||
{
|
||
if(fNewHte && (prop->an_attr != ATTRPNM || (prop->an_flags & FPRINT)))
|
||
{ /* If first time and printable */
|
||
Store(rhte);
|
||
}
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* FGtAddr:
|
||
*
|
||
* Compare addresses of symbols pointed to by rb1 and rb2. Return
|
||
* -1, 0, or 1 as the address of rb1 is less than, equal to, or greater
|
||
* than the address of rb2.
|
||
*/
|
||
int cdecl FGtAddr(const RBTYPE *rb1, const RBTYPE *rb2)
|
||
{
|
||
APROPNAMEPTR paprop; /* Property cell pointer */
|
||
REGISTER SEGTYPE seg1; /* Segment number */
|
||
REGISTER SEGTYPE seg2;
|
||
WORD sa1; /* Segment base */
|
||
WORD sa2;
|
||
RATYPE ra1;
|
||
RATYPE ra2;
|
||
DWORD ibMem1; /* Memory address */
|
||
DWORD ibMem2;
|
||
|
||
|
||
|
||
paprop = (APROPNAMEPTR ) FETCHSYM(*rb1,FALSE);
|
||
/* Fetch from VM */
|
||
seg1 = paprop->an_gsn? mpgsnseg[paprop->an_gsn]: SEGNIL;
|
||
/* Get segment number */
|
||
sa1 = seg1 != SEGNIL? mpsegsa[seg1]: 0;
|
||
/* Get frame number */
|
||
ra1 = paprop->an_ra;
|
||
|
||
paprop = (APROPNAMEPTR ) FETCHSYM(*rb2,FALSE);
|
||
/* Fetch from VM */
|
||
seg2 = paprop->an_gsn? mpgsnseg[paprop->an_gsn]: SEGNIL;
|
||
/* Get segment number */
|
||
sa2 = seg2 != SEGNIL? mpsegsa[seg2]: 0;
|
||
/* Get frame number */
|
||
ra2 = paprop->an_ra;
|
||
#if OXOUT OR OIAPX286
|
||
if(seg1 != SEGNIL && seg2 != SEGNIL)
|
||
{
|
||
if((mpsegFlags[seg1] & FCODE) &&
|
||
!(mpsegFlags[seg2] & FCODE)) return(-1);
|
||
/* Code before data */
|
||
if((mpsegFlags[seg2] & FCODE) &&
|
||
!(mpsegFlags[seg1] & FCODE)) return(1);
|
||
/* Data after code */
|
||
}
|
||
#endif
|
||
#if OVERLAYS
|
||
if(fOverlays && seg1 != SEGNIL && seg2 != SEGNIL)
|
||
{
|
||
if(mpsegiov[seg1] > mpsegiov[seg2]) return(1);
|
||
if(mpsegiov[seg2] > mpsegiov[seg1]) return(-1);
|
||
}
|
||
#endif
|
||
#if OSEGEXE
|
||
if (fNewExe)
|
||
{
|
||
#if EXE386
|
||
if (sa1 == sa2)
|
||
{
|
||
ibMem1 = ra1;
|
||
ibMem2 = ra2;
|
||
}
|
||
else
|
||
ibMem1 = ibMem2 = 0L;
|
||
#else
|
||
ibMem1 = ((long) sa1 << 16) + ra1;
|
||
ibMem2 = ((long) sa2 << 16) + ra2;
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
#endif
|
||
ibMem1 = ((long) sa1 << 4) + ra1;
|
||
ibMem2 = ((long) sa2 << 4) + ra2;
|
||
#if OSEGEXE
|
||
}
|
||
#endif
|
||
#ifdef LATER
|
||
if ((sa1 != 0 || sa2 != 0) && (sa1 != 0xa9 || sa2 != 0xa9))
|
||
fprintf(stderr, "%x:%x %x:%x (%d)\r\n", sa1, paprop1->an_ra,
|
||
sa2, paprop2->an_ra, (ibMem1 > ibMem2) ? 1 :
|
||
((ibMem1 < ibMem2) ? -1 : 0));
|
||
#endif /*!LATER*/
|
||
if (ibMem1 < ibMem2) return(-1);
|
||
if (ibMem1 > ibMem2) return(1);
|
||
#if EXE386
|
||
if (sa1 < sa2) return(-1);
|
||
if (sa1 > sa2) return(1);
|
||
#endif
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* FGtName:
|
||
*
|
||
* Compare names of two symbols pointed to by rb1 and rb2. Return
|
||
* -1, 0, 1 as the name of rb1 is alphabetically less than, equal to,
|
||
* or greater than the name of rb2.
|
||
* Ignore case.
|
||
*/
|
||
int cdecl FGtName(const RBTYPE *rb1, const RBTYPE *rb2)
|
||
{
|
||
AHTEPTR pahte1; /* Hash table pointer */
|
||
AHTEPTR pahte2;
|
||
REGISTER BYTE *ps1; /* Pointer to first symbol */
|
||
REGISTER BYTE FAR *ps2; /* Pointer to second symbol */
|
||
WORD len1; /* Symbol length */
|
||
WORD len2; /* Symbol length */
|
||
WORD length; /* No. of char.s to compare */
|
||
int value; /* Comparison value */
|
||
|
||
|
||
|
||
pahte1 = (AHTEPTR ) FETCHSYM(*rb1,FALSE);
|
||
/* Fetch from VM */
|
||
ps1 = GetFarSb((BYTE FAR *) pahte1->cch);
|
||
/* Get pointer to first */
|
||
|
||
pahte2 = (AHTEPTR ) FETCHSYM(*rb2,FALSE);
|
||
/* Fetch from VM */
|
||
ps2 = (BYTE FAR *) pahte2->cch; /* Get pointer to second */
|
||
if((len1 = B2W(*ps1)) < (len2 = B2W(*ps2))) length = len1;
|
||
else length = len2; /* Get smallest length */
|
||
while(length--) /* While not at end of symbol */
|
||
if(value = (*++ps1 & 0137) - (*++ps2 & 0137))
|
||
return(value < 0 ? -1 : 1);
|
||
if(len1 < len2)
|
||
return(-1);
|
||
if(len1 > len2)
|
||
return(1);
|
||
return(0);
|
||
}
|
||
|
||
#if OWNSORT
|
||
/*
|
||
* An implementation of heapsort follows. It is only used if
|
||
* quicksort() from the runtime library is not used.
|
||
*/
|
||
LOCAL reheap(a,n,i) /* Reheapify */
|
||
RBTYPE *a; /* Array to reheapify */
|
||
WORD n; /* Size of array */
|
||
REGISTER WORD i; /* Subtree to start with */
|
||
{
|
||
REGISTER WORD j; /* Index */
|
||
RBTYPE t; /* Temporary */
|
||
|
||
for(; (j = rchild(i)) < n; i = j) /* Loop through array */
|
||
{
|
||
if((*cmpf)(&a[i],&a[j]) > 0 && (*cmpf)(&a[i],&a[j - 1]) > 0) return;
|
||
/* Done if subtree is heap */
|
||
if((*cmpf)(&a[j - 1],&a[j]) > 0) --j; /* Pick "greater" child */
|
||
t = a[i]; /* Swap parent and child */
|
||
a[i] = a[j];
|
||
a[j] = t;
|
||
}
|
||
if(--j < n && (*cmpf)(&a[j],&a[i]) > 0) /* If swap needed */
|
||
{
|
||
t = a[i]; /* Swap parent and child */
|
||
a[i] = a[j];
|
||
a[j] = t;
|
||
}
|
||
}
|
||
|
||
LOCAL heap(a,n) /* Heapify */
|
||
RBTYPE *a; /* Array to heapify */
|
||
WORD n; /* Size of array */
|
||
{
|
||
REGISTER WORD k; /* Index to "kid" */
|
||
REGISTER WORD p; /* Index to "parent" */
|
||
RBTYPE t; /* Temporary */
|
||
|
||
if(n && (k = n - 1)) /* If there are kids */
|
||
{
|
||
if(isleft(k)) /* If youngest kid an only child */
|
||
{
|
||
p = parent(k); /* Find the parent */
|
||
if((*cmpf)(&a[k],&a[p]) > 0) /* If swap necessary */
|
||
{
|
||
t = a[k]; /* Swap parent and kid */
|
||
a[k] = a[p];
|
||
a[p] = t;
|
||
}
|
||
--k; /* Index a righty */
|
||
}
|
||
while(k) /* While there are parents */
|
||
{
|
||
p = parent(k); /* Find the parent */
|
||
if((*cmpf)(&a[k],&a[p]) > 0 || (*cmpf)(&a[k - 1],&a[p]) > 0)
|
||
{ /* If a kid is "greater" */
|
||
t = a[p]; /* Swap parent... */
|
||
if((*cmpf)(&a[k],&a[k - 1]) > 0)
|
||
{ /* ...with "greater" kid */
|
||
a[p] = a[k];
|
||
a[k] = t;
|
||
reheap(a,n,k--); /* And reheapify */
|
||
}
|
||
else
|
||
{
|
||
a[p] = a[--k];
|
||
a[k] = t;
|
||
reheap(a,n,k); /* And reheapify */
|
||
}
|
||
}
|
||
else --k; /* Point at left kid */
|
||
--k; /* Point at right kid */
|
||
}
|
||
}
|
||
}
|
||
#endif /* OWNSORT */
|
||
|
||
|
||
/****************************************************************
|
||
* *
|
||
* PrintGroupOrigins: *
|
||
* *
|
||
****************************************************************/
|
||
|
||
void PrintGroupOrigins(APROPNAMEPTR papropGroup,
|
||
RBTYPE rhte,
|
||
RBTYPE rprop,
|
||
WORD fNewHte)
|
||
{
|
||
AHTEPTR hte;
|
||
APROPGROUPPTR pGroup;
|
||
|
||
pGroup = (APROPGROUPPTR) papropGroup;
|
||
if (mpggrgsn[pGroup->ag_ggr] != SNNIL)
|
||
{ /* If group has members */
|
||
if (!fGrps) /* If no groups yet */
|
||
{
|
||
fputs(GetMsg(MAP_group), bsLst);
|
||
/* Header */
|
||
fGrps = (FTYPE) TRUE; /* Yes, there are groups */
|
||
}
|
||
fprintf(bsLst," %04X:0 ", mpsegsa[mpgsnseg[mpggrgsn[pGroup->ag_ggr]]]);
|
||
/* Write the group base */
|
||
hte = (AHTEPTR ) FETCHSYM(rhte,FALSE);
|
||
/* Fetch group name */
|
||
OutSb(bsLst,GetFarSb(hte->cch));/* Output name */
|
||
NEWLINE(bsLst);
|
||
ChkMapErr();
|
||
}
|
||
}
|
||
|
||
#if OSEGEXE
|
||
LOCAL void NEAR HdrExport(ATTRTYPE attr)
|
||
{
|
||
ASSERT(attr == ATTREXP); /* Must be an export */
|
||
fputs(GetMsg(MAP_expaddr), bsLst);
|
||
#if EXE386
|
||
PutSpaces(7);
|
||
#else
|
||
if (f386)
|
||
PutSpaces(7);
|
||
else
|
||
PutSpaces(3);
|
||
#endif
|
||
fputs(GetMsg(MAP_expexp), bsLst);
|
||
PutSpaces(18);
|
||
fputs(GetMsg(MAP_expalias), bsLst);
|
||
/* Header */
|
||
ChkMapErr();
|
||
}
|
||
|
||
LOCAL void NEAR ShowExp(ahte,rprop)
|
||
AHTEPTR ahte; /* Pointer to hash table entry */
|
||
RBTYPE rprop; /* Property cell address */
|
||
{
|
||
SBTYPE sbExport; /* Export name */
|
||
APROPNAMEPTR apropnam; /* Public definition record */
|
||
short i; /* Index */
|
||
|
||
memcpy(sbExport,GetFarSb(ahte->cch),B2W(ahte->cch[0]) + 1);
|
||
/* Save the name */
|
||
apropnam = (APROPNAMEPTR ) FETCHSYM(rprop,FALSE);
|
||
/* Fetch alias record */
|
||
#if EXE386
|
||
fprintf(bsLst," %04X:%08lX ",
|
||
#else
|
||
fprintf(bsLst," %04X:%04X ",
|
||
#endif
|
||
mpsegsa[mpgsnseg[apropnam->an_gsn]],apropnam->an_ra);
|
||
/* Print the address */
|
||
OutSb(bsLst,sbExport); /* Print the exported name */
|
||
for(i = 22 - B2W(sbExport[0]); i > 0; --i) fputc(' ',bsLst);
|
||
/* Fill with spaces */
|
||
fputs(" ",bsLst); /* Skip two spaces */
|
||
ahte = GetHte(apropnam->an_next); /* Get the alias name */
|
||
OutSb(bsLst,GetFarSb(ahte->cch)); /* Output export name */
|
||
NEWLINE(bsLst);
|
||
ChkMapErr();
|
||
}
|
||
LOCAL void NEAR PrintExps(WORD irbMac, ATTRTYPE attr)
|
||
{
|
||
AHTEPTR ahte; /* Pointer to hash table entry */
|
||
APROPEXPPTR apropexp; /* Pointer to property cell */
|
||
RBTYPE rprop; /* Alias record address */
|
||
WORD i; /* Index */
|
||
RBTYPE CurrSym;
|
||
|
||
|
||
for(i = irbMac; i > 0; i--) /* Loop through sorted symbols */
|
||
{
|
||
CurrSym = ExtractMin(i);
|
||
ahte = (AHTEPTR ) FETCHSYM(CurrSym,FALSE);
|
||
/* Fetch hash table entry */
|
||
apropexp = (APROPEXPPTR ) FETCHSYM(ahte->rprop,FALSE);
|
||
/* Fetch property cell */
|
||
while(apropexp->ax_attr != attr)
|
||
{ /* Loop to find property cell */
|
||
apropexp = (APROPEXPPTR ) FETCHSYM(apropexp->ax_next,FALSE);
|
||
/* Fetch the next cell in the chain */
|
||
}
|
||
if((rprop = apropexp->ax_symdef) == RHTENIL) continue;
|
||
|
||
ShowExp((AHTEPTR) FETCHSYM(CurrSym,FALSE),rprop);
|
||
/* Print the export */
|
||
/* Save address of alias */
|
||
}
|
||
}
|
||
#endif /* OSEGEXE */
|
||
|
||
LOCAL void NEAR PutSpaces(int HowMany)
|
||
{
|
||
for (; HowMany > 0; HowMany--)
|
||
putc(' ', bsLst);
|
||
ChkMapErr();
|
||
}
|
||
|
||
|
||
LOCAL void NEAR HdrName(attr)
|
||
ATTRTYPE attr; /* Symbol attribute type */
|
||
{
|
||
fputs(GetMsg(MAP_hdraddr), bsLst);
|
||
PutSpaces(9);
|
||
fputs(GetMsg((MSGTYPE)((attr == ATTRPNM) ? MAP_hdrpubnam : MAP_hdrlocnam)), bsLst);
|
||
/* Header (MAPSYM keys on "Value") */
|
||
ChkMapErr();
|
||
}
|
||
|
||
LOCAL void NEAR HdrValue(attr)
|
||
ATTRTYPE attr; /* Symbol attribute type */
|
||
{
|
||
fputs(GetMsg(MAP_hdraddr), bsLst);
|
||
PutSpaces(9);
|
||
fputs(GetMsg((MSGTYPE)((attr == ATTRPNM) ? MAP_hdrpubval : MAP_hdrlocval)), bsLst);
|
||
/* Header (MAPSYM keys on "Value") */
|
||
ChkMapErr();
|
||
}
|
||
|
||
|
||
/****************************************************************
|
||
* *
|
||
* SortSyms: *
|
||
* *
|
||
* List symbols, sorted. *
|
||
* *
|
||
****************************************************************/
|
||
|
||
void NEAR SortSyms(ATTRTYPE attr,
|
||
/* Symbol attribute type */
|
||
void (*savf)(APROPNAMEPTR prop,
|
||
RBTYPE rhte,
|
||
RBTYPE rprop,
|
||
WORD fNewHte),
|
||
/* Function to save symbols */
|
||
int (cdecl *scmpf)(const RBTYPE *sb1,
|
||
const RBTYPE *sb2),
|
||
/* Function to compare symbols */
|
||
void (NEAR *hdrf)(ATTRTYPE attr),
|
||
/* Function to print header */
|
||
void (NEAR *lstf)(WORD irbMac,
|
||
ATTRTYPE attr))
|
||
/* Function to list symbols */
|
||
{
|
||
symMac = 0; /* Initialize counter to zero */
|
||
cmpf = scmpf; /* Set comparison function */
|
||
EnSyms(savf,attr); /* Apply function to symbols */
|
||
(*hdrf)(attr); /* Print a header */
|
||
(*lstf)(symMac,attr); /* Print them */
|
||
}
|
||
|
||
|
||
/*** AddContributor - add current file to list
|
||
*
|
||
* Purpose:
|
||
* Add current .OBJ file that contribiute to definition of given
|
||
* segment. The list of .OBJ files is kept in virtual memory.
|
||
* Each segment description record has Head and Tail pointers to
|
||
* its contributor list.
|
||
*
|
||
* Input:
|
||
* gsn - global segment number - linker internal way of
|
||
* recognizing segments
|
||
* raComdat - if contribution is comming from a COMDAT symbol
|
||
* this is its initial offset in the segment
|
||
* size - contribution size
|
||
* vrpropFile - pointer to current .OBJ file description - global variable
|
||
*
|
||
* Output:
|
||
* No explicit return value. Updated list of contributors for segment.
|
||
*
|
||
* Exceptions:
|
||
* None.
|
||
*
|
||
*************************************************************************/
|
||
|
||
|
||
void AddContributor(SNTYPE gsn, DWORD raComdat, DWORD size)
|
||
{
|
||
APROPSNPTR apropSn; /* Pointer to seg. record */
|
||
CONTRIBUTOR FAR *NewObj; /* New .OBJ file that contrbiuts to seg */
|
||
|
||
|
||
apropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],FALSE);
|
||
NewObj = (CONTRIBUTOR FAR *) GetMem(sizeof(CONTRIBUTOR));
|
||
|
||
/* Build new list element */
|
||
|
||
NewObj->next = 0L; /* End of list */
|
||
NewObj->file = vrpropFile; /* Save global file description pointer */
|
||
NewObj->len = size; /* Size of contribution */
|
||
if (raComdat != -1L)
|
||
NewObj->offset = raComdat;
|
||
else
|
||
NewObj->offset = mpgsndra[gsn];
|
||
|
||
/* Attach new record at the list end */
|
||
|
||
if (apropSn->as_CHead)
|
||
apropSn->as_CTail->next = NewObj;
|
||
else
|
||
apropSn->as_CHead = NewObj;
|
||
apropSn->as_CTail = NewObj;
|
||
}
|
||
|
||
|
||
|
||
/*** PrintContributors - print out list of files
|
||
*
|
||
* Purpose:
|
||
* Print list of .OBJ files that contribute to form given segment.
|
||
* For each file print number of bytes that it contribute.
|
||
*
|
||
* Input:
|
||
* gsn - global segment number - linker internal way of
|
||
* recognizing segments
|
||
*
|
||
* Output:
|
||
* No explicit return value.
|
||
*
|
||
* Exceptions:
|
||
* None.
|
||
*
|
||
*************************************************************************/
|
||
|
||
|
||
LOCAL void NEAR PrintContributors(SNTYPE gsn)
|
||
{
|
||
|
||
APROPFILEPTR apropFile; /* Pointer to file property cell */
|
||
APROPSNPTR apropSn; /* Pointer to seg. record */
|
||
CONTRIBUTOR FAR *pElem; /* Real pointer to list element */
|
||
AHTEPTR ahte; /* Pointer symbol name */
|
||
SBTYPE sb, sb1; /* String buffers */
|
||
int n; /* String length counter */
|
||
|
||
|
||
apropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],FALSE);
|
||
if (apropSn->as_CHead == NULL)
|
||
return;
|
||
|
||
/* Print list */
|
||
|
||
fprintf(bsLst,"\r\n");
|
||
pElem = apropSn->as_CHead;
|
||
do
|
||
{
|
||
if(fNewExe || OIAPX286)
|
||
{
|
||
#if EXE386
|
||
if (f386)
|
||
fprintf(bsLst," at offset %08lXH %05lXH bytes from", pElem->offset, pElem->len);
|
||
else
|
||
#endif
|
||
fprintf(bsLst," at offset %05lXH %05lXH bytes from", pElem->offset, pElem->len);
|
||
}
|
||
else
|
||
fprintf(bsLst," at offset %05lXH %05lXH bytes from", pElem->offset, pElem->len);
|
||
|
||
apropFile = (APROPFILEPTR ) FETCHSYM(pElem->file,FALSE);
|
||
ahte = GetHte(pElem->file);
|
||
for(n = B2W(ahte->cch[0]), sb[n+1] = 0; n >= 0; sb[n] = ahte->cch[n], --n);
|
||
if (apropFile->af_rMod)
|
||
{
|
||
ahte = (AHTEPTR ) FETCHSYM(apropFile->af_rMod,FALSE);
|
||
while(ahte->attr != ATTRNIL)
|
||
ahte = (AHTEPTR ) FETCHSYM(ahte->rhteNext,FALSE);
|
||
for (n = B2W(ahte->cch[0]); n >= 0; --n)
|
||
sb1[n] = ahte->cch[n];
|
||
sb1[1 + B2W(sb1[0])] = '\0'; /* Null-terminate */
|
||
fprintf(bsLst, " %s (%s)\r\n", 1 + sb, 1 + sb1);
|
||
}
|
||
else
|
||
fprintf(bsLst," %s\r\n", 1 + sb);
|
||
|
||
ChkMapErr();
|
||
pElem = pElem->next;
|
||
|
||
} while (pElem != NULL);
|
||
}
|
||
|
||
|
||
/****************************************************************
|
||
* *
|
||
* PrintMap: *
|
||
* *
|
||
****************************************************************/
|
||
|
||
void PrintMap(void)
|
||
{
|
||
SEGTYPE seg;
|
||
WORD cch;
|
||
APROPSNPTR papropSn;
|
||
AHTEPTR pahte;
|
||
SNTYPE gsn;
|
||
RBTYPE rhteClass; /* Virt. addr. of class name */
|
||
long addrStart;
|
||
long addr;
|
||
#if OVERLAYS
|
||
IOVTYPE iov;
|
||
#endif
|
||
#if OSMSDOS
|
||
int oldbsize; /* Old file buffer size */
|
||
char *oldbase; /* Old file buffer */
|
||
#endif
|
||
WORD flags;
|
||
|
||
|
||
|
||
#if OSMSDOS
|
||
#if OWNSTDIO
|
||
oldbsize = bsLst->_bsize;
|
||
#else
|
||
oldbsize = 512;
|
||
#endif
|
||
oldbase = bsLst->_base;
|
||
setvbuf(bsLst,bigbuf,_IOFBF,sizeof(bigbuf));
|
||
#endif
|
||
#if OSEGEXE
|
||
if(fNewExe && rhteModule != RHTENIL)/* If there is a module name */
|
||
{
|
||
pahte = (AHTEPTR ) FETCHSYM(rhteModule,FALSE);
|
||
/* Fetch the hash table entry */
|
||
fputs("\r\n ",bsLst); /* Indent one space */
|
||
OutSb(bsLst,GetFarSb(pahte->cch));/* Print the module name */
|
||
NEWLINE(bsLst);
|
||
ChkMapErr();
|
||
}
|
||
#endif
|
||
if(fNewExe || OIAPX286)
|
||
{
|
||
fputs(GetMsg(MAP_hdrstart), bsLst);
|
||
#if EXE386
|
||
PutSpaces(9);
|
||
#else
|
||
if (f386)
|
||
PutSpaces(9);
|
||
else
|
||
PutSpaces(5);
|
||
#endif
|
||
fputs(GetMsg(MAP_hdrlen), bsLst);
|
||
PutSpaces(5);
|
||
fputs(GetMsg(MAP_hdrname), bsLst);
|
||
PutSpaces(19);
|
||
fputs(GetMsg(MAP_hdrclass), bsLst);
|
||
}
|
||
else
|
||
{
|
||
fputs(GetMsg(MAP_hdrseg86), bsLst);
|
||
PutSpaces(19);
|
||
fputs(GetMsg(MAP_hdrclass), bsLst);
|
||
}
|
||
ChkMapErr();
|
||
#if OVERLAYS
|
||
for(iov = 0; iov < (IOVTYPE) iovMac; ++iov)
|
||
{
|
||
if(fOverlays)
|
||
{
|
||
if (iov == IOVROOT)
|
||
fputs(GetMsg(MAP_resident), bsLst);
|
||
else
|
||
fprintf(bsLst, GetMsg(MAP_overlay), iov);
|
||
ChkMapErr();
|
||
}
|
||
#endif
|
||
for(seg = 1; seg <= segLast; ++seg) /* Look at all segments */
|
||
{
|
||
#if OVERLAYS
|
||
if(!fOverlays || mpsegiov[seg] == iov)
|
||
{
|
||
#endif
|
||
if(fNewExe || OIAPX286)
|
||
{
|
||
#if EXE386
|
||
fprintf(bsLst," %04X:%08lX", mpsegsa[seg],mpsegraFirst[seg]);
|
||
#else
|
||
if (f386)
|
||
fprintf(bsLst," %04X:%08lX", mpsegsa[seg],mpsegraFirst[seg]);
|
||
else
|
||
fprintf(bsLst," %04X:%04X",mpsegsa[seg],(int)mpsegraFirst[seg]);
|
||
#endif
|
||
ChkMapErr();
|
||
}
|
||
else
|
||
addrStart = (long) mpsegsa[seg] << 4;
|
||
for(gsn = 1; gsn < gsnMac; ++gsn)
|
||
{
|
||
if(mpgsnseg[gsn] == seg)
|
||
{
|
||
papropSn = (APROPSNPTR ) FETCHSYM(mpgsnrprop[gsn],FALSE);
|
||
rhteClass = papropSn->as_rCla;
|
||
/* Save key to class name */
|
||
#if NOT EXE386
|
||
flags = papropSn->as_flags;
|
||
#endif
|
||
if(fNewExe || OIAPX286)
|
||
#if EXE386
|
||
fprintf(bsLst," %09lXH ",papropSn->as_cbMx);
|
||
#else
|
||
fprintf(bsLst," %05lXH ",papropSn->as_cbMx);
|
||
#endif
|
||
else
|
||
{
|
||
addr = addrStart + (long) mpsegraFirst[seg];
|
||
fprintf(bsLst," %05lXH",addr);
|
||
if(papropSn->as_cbMx) addr += papropSn->as_cbMx - 1;
|
||
fprintf(bsLst," %05lXH",addr);
|
||
fprintf(bsLst," %05lXH ",papropSn->as_cbMx);
|
||
}
|
||
pahte = GetHte(papropSn->as_next);
|
||
/* Get the segment name */
|
||
OutSb(bsLst,GetFarSb(pahte->cch));
|
||
/* Write segment name */
|
||
if(B2W(pahte->cch[0]) > 22) cch = 1;
|
||
else cch = 23 - B2W(pahte->cch[0]);
|
||
/* Get number of spaces to emit */
|
||
while(cch--) OutByte(bsLst,' ');
|
||
/* Emit spaces */
|
||
pahte = (AHTEPTR ) FETCHSYM(rhteClass,FALSE);
|
||
/* Fetch class names from VM */
|
||
OutSb(bsLst,GetFarSb(pahte->cch));
|
||
/* Output class name */
|
||
if (fFullMap)
|
||
{
|
||
#if EXE386
|
||
fprintf(bsLst, " 32-bit");
|
||
#else
|
||
if (Is32BIT(flags))
|
||
fprintf(bsLst, " 32-bit");
|
||
else
|
||
fprintf(bsLst, " 16-bit");
|
||
#endif
|
||
PrintContributors(gsn);
|
||
}
|
||
NEWLINE(bsLst);
|
||
ChkMapErr();
|
||
break; /* Exit loop */
|
||
}
|
||
}
|
||
#if OVERLAYS
|
||
}
|
||
#endif
|
||
}
|
||
#if OVERLAYS
|
||
}
|
||
#endif
|
||
fGrps = FALSE; /* Assume no groups */
|
||
EnSyms(PrintGroupOrigins,ATTRGRP); /* Apply function to symbols */
|
||
|
||
#if OSEGEXE
|
||
if(vfMap || expMac)
|
||
#else
|
||
if(vfMap)
|
||
#endif
|
||
{
|
||
AllocSortBuffer(pubMac > expMac ? pubMac : expMac, TRUE);
|
||
}
|
||
#if OSEGEXE
|
||
if(expMac)
|
||
{
|
||
/* Sort or list exported names */
|
||
SortSyms(ATTREXP,SaveHteSym,FGtName,HdrExport, PrintExps);
|
||
}
|
||
#endif
|
||
if(vfMap) /* If publics requested */
|
||
{
|
||
if(!fListAddrOnly)
|
||
SortSyms(ATTRPNM,SaveHteSym,FGtName,HdrName, PrintSyms);
|
||
/* Sort public symbols by name */
|
||
SortSyms(ATTRPNM,SavePropSym,FGtAddr,HdrValue, PrintSyms);
|
||
/* Sort public symbols by value */
|
||
}
|
||
#if LOCALSYMS
|
||
if(fLocals) /* If locals requested */
|
||
{
|
||
SortSyms(ATTRLNM,SaveHteSym,FGtName,HdrName, PrintSyms);
|
||
/* Sort local symbols by name */
|
||
SortSyms(ATTRLNM,SavePropSym,FGtAddr,HdrValue, PrintSyms);
|
||
/* Sort local symbols by value */
|
||
|
||
}
|
||
#endif
|
||
ChkMapErr();
|
||
FreeSortBuffer();
|
||
#if OSMSDOS
|
||
setvbuf(bsLst,oldbase,_IOFBF,oldbsize);
|
||
#endif
|
||
}
|