mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1110 lines
37 KiB
1110 lines
37 KiB
/* 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
|
|
}
|