Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

427 lines
11 KiB

/***********************************************************************
* Microsoft (R) 32-Bit Incremental Linker
*
* Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
*
* File: map.cpp
*
* File Comments:
*
* Prints various types of maps.
*
***********************************************************************/
#include "link.h"
typedef struct MSTAT
{
struct MSTAT *pmstatNext;
char *szName;
PCON pcon;
DWORD ib;
BOOL fFunction;
} MSTAT;
static MSTAT *pmstatHead;
static MSTAT **ppmstatTail = &pmstatHead;
typedef struct MTOC
{
struct MTOC *pmtocNext;
PEXTERNAL pext;
} MTOC;
static MTOC *pmtocHead;
static MTOC **ppmtocTail = &pmtocHead;
void
EmitMapSections(PIMAGE pimage)
{
ENM_SEC enmSec;
if (fM68K) {
fputs(" Start Length Name Class Resource\n", InfoStream);
} else {
fputs(" Start Length Name Class\n", InfoStream);
}
InitEnmSec(&enmSec, &pimage->secs);
while (FNextEnmSec(&enmSec)) {
ENM_GRP enmGrp;
if (enmSec.psec->isec == 0) {
// Ignore anything which isn't a section header in image
continue;
}
if ((enmSec.psec == psecDebug) && !IncludeDebugSection) {
// Don't write headers for non-mapped debug information
continue;
}
InitEnmGrp(&enmGrp, enmSec.psec);
while (FNextEnmGrp(&enmGrp)) {
const char *szClass;
if (FetchContent(enmSec.psec->flags) == IMAGE_SCN_CNT_CODE) {
szClass = "CODE";
} else {
szClass = "DATA";
}
if (fM68K && (enmSec.psec->flags & IMAGE_SCN_CNT_CODE)) {
char szResType[5];
// Provide section-to-resource mapping for code sections
memcpy(szResType, &(enmSec.psec->ResTypeMac), 4);
szResType[4] = '\0';
fprintf(InfoStream, " %04x:%08lx %08lxH %-23s %-9s %s%04d\n",
enmSec.psec->isec,
enmGrp.pgrp->rva - enmSec.psec->rva,
enmGrp.pgrp->cb,
enmGrp.pgrp->szName,
szClass,
szResType,
enmSec.psec->iResMac);
} else if (fPowerMac) {
fprintf(InfoStream, " %04x:%08lx %08lxH %-23s %s\n",
enmSec.psec->isec,
enmGrp.pgrp->rva - enmSec.psec->rva,
(FetchContent(enmSec.psec->flags) == IMAGE_SCN_CNT_CODE)
? (enmGrp.pgrp->cb + 0xF) & ~0xFL : enmGrp.pgrp->cb,
enmGrp.pgrp->szName,
szClass);
} else {
// VxD: don't put out groups that don't make it to image
if (pimage->imaget == imagetVXD && !enmGrp.pgrp->cb) {
continue;
}
fprintf(InfoStream, " %04x:%08lx %08lxH %-23s %s\n",
enmSec.psec->isec,
enmGrp.pgrp->rva - enmSec.psec->rva,
enmGrp.pgrp->cb,
enmGrp.pgrp->szName,
szClass);
}
}
}
}
void
EmitMapSymbol(const char *szName, PCON pcon, BOOL fCommon,
DWORD ib, DWORD valMac,
DWORD dwImageBase, BOOL fFunction)
{
PSEC psec = PsecPCON(pcon);
PMOD pmod = PmodPCON(pcon);
fprintf(InfoStream, " %04x:%08lx %-26s %08lx %c ",
psec->isec,
fM68K ? valMac : (ib + pcon->rva - psec->rva),
szName,
dwImageBase + pcon->rva + ib,
fFunction ? 'f' : ' '
);
if (fCommon) {
fwrite("<common>", 8, 1, InfoStream);
} else if (pmod == pmodLinkerDefined) {
fwrite("<linker-defined>", 16, 1, InfoStream);
} else {
char szFname[_MAX_FNAME];
char szExt[_MAX_EXT];
if (pmod->plibBack != plibCmdLineObjs) {
// Print library name
_splitpath(pmod->plibBack->szName, NULL, NULL, szFname, NULL);
fprintf(InfoStream, "%s:", szFname);
}
// Print module name
_splitpath(SzOrigFilePMOD(pmod), NULL, NULL, szFname, szExt);
fprintf(InfoStream, "%s%s", szFname, szExt);
}
fputc('\n', InfoStream);
}
void
EmitMapStatics(PIMAGE pimage)
{
fputs(" Static symbols\n\n", InfoStream);
while (pmstatHead != NULL) {
MSTAT *pmstatT;
if (!pimage->Switch.Link.fTCE || !FDiscardPCON_TCE(pmstatHead->pcon)) {
EmitMapSymbol(pmstatHead->szName,
pmstatHead->pcon,
FALSE,
pmstatHead->ib,
pmstatHead->ib + pmstatHead->pcon->rva - PsecPCON(pmstatHead->pcon)->rva,
pimage->ImgOptHdr.ImageBase,
pmstatHead->fFunction);
}
pmstatT = pmstatHead->pmstatNext;
FreePv(pmstatHead->szName);
FreePv(pmstatHead);
pmstatHead = pmstatT;
}
}
void
EmitMapToc(PIMAGE pimage)
{
DWORD dwAddrToc;
fputs("\n"
" Offset Rva+Base Publics by TOC Offset\n"
"\n",
InfoStream);
dwAddrToc = pimage->ImgOptHdr.ImageBase + pextToc->FinalValue;
while (pmtocHead != NULL) {
PEXTERNAL pext;
MTOC *pmtocT;
pext = pmtocHead->pext;
fprintf(InfoStream,
" %04hx %08lx %s\n",
pext->ibToc,
dwAddrToc + pext->ibToc,
SzNamePext(pext, pimage->pst));
pmtocT = pmtocHead->pmtocNext;
FreePv(pmtocHead);
pmtocHead = pmtocT;
}
}
void
EmitMapFixups(void)
{
int ichFixupsLine;
LRVA *plrva;
DWORD crva;
DWORD rvaPrev;
// Emit "FIXUPS:" lines showing the RVA's of all relative fixups. At
// present this is just for the profiler.
fputc('\n', InfoStream);
ichFixupsLine = 0;
for (plrva = plrvaFixupsForMapFile, crva = crvaFixupsForMapFile;
plrva != NULL;
plrva = plrva->plrvaNext, crva = crvaInLrva) {
DWORD irva;
for (irva = 0; irva < crva; irva++) {
if (ichFixupsLine == 0) {
ichFixupsLine = fprintf(InfoStream, "FIXUPS:");
rvaPrev = 0;
}
ichFixupsLine += fprintf(InfoStream, " %lx", plrva->rgrva[irva] - rvaPrev);
rvaPrev = plrva->rgrva[irva];
if (ichFixupsLine >= 70) {
fputc('\n', InfoStream);
ichFixupsLine = 0;
}
}
}
if (ichFixupsLine != 0) {
fputc('\n', InfoStream);
}
// free the LRVA's ...
while (plrvaFixupsForMapFile != NULL) {
plrva = plrvaFixupsForMapFile->plrvaNext;
FreePv(plrvaFixupsForMapFile);
plrvaFixupsForMapFile = plrva;
}
}
void
EmitMap(PIMAGE pimage, const char *szOutputFilename)
{
PPEXTERNAL rgpext;
PEXTERNAL pext;
DWORD ipext;
DWORD cpext;
char szFname[_MAX_FNAME];
char *szSymName;
char *szTime;
WORD isec;
DWORD ib;
InternalError.Phase = "EmitMap";
// Print module name.
if (pimage->imaget == imagetVXD && szModuleName[0] != '\0') {
fprintf(InfoStream, " %s\n\n", szModuleName);
} else {
_splitpath(szOutputFilename, NULL, NULL, szFname, NULL);
fprintf(InfoStream, " %s\n\n", szFname);
}
// Print timestamp (the profiler uses this to make sure the .map is
// in sync with the .exe).
szTime = ctime((time_t *)&pimage->ImgFileHdr.TimeDateStamp);
if (szTime != NULL) {
szTime[strlen(szTime) - 1] = '\0'; // remove \n at end
} else {
szTime = "invalid"; // no valid time
}
fprintf(InfoStream, " Timestamp is %08lx (%s)\n\n",
pimage->ImgFileHdr.TimeDateStamp, szTime);
fprintf(InfoStream, " Preferred load address is %08lx\n\n",
pimage->ImgOptHdr.ImageBase);
EmitMapSections(pimage);
fputs("\n"
" Address Publics by Value Rva+Base Lib:Object\n"
"\n",
InfoStream);
if (fM68K) {
rgpext = RgpexternalByMacAddr(pimage->pst);
} else {
rgpext = RgpexternalByAddr(pimage->pst);
}
cpext = Cexternal(pimage->pst);
for (ipext = 0; ipext < cpext; ipext++) {
char szSymNameT[81];
pext = rgpext[ipext];
if (!(pext->Flags & EXTERN_DEFINED)) {
continue;
}
if (pext->pcon == NULL) {
continue;
}
if (pext->pcon->flags & IMAGE_SCN_LNK_REMOVE) {
continue;
}
if (pimage->Switch.Link.fTCE) {
if (FDiscardPCON_TCE(pext->pcon)) {
// Discarded comdat ... don't print to .map file
continue;
}
}
szSymName = SzNamePext(pext, pimage->pst);
// Map the leading \177's we generate (for import table terminators)
// into printable characters.
if (szSymName[0] >= '\177') {
strcpy(szSymNameT, "\\177");
strcpy(szSymNameT+4, szSymName+1);
szSymName = szSymNameT;
}
EmitMapSymbol(szSymName,
pext->pcon,
(pext->Flags & EXTERN_COMMON) != 0,
pext->ImageSymbol.Value,
fM68K ? pext->FinalValue : 0,
pimage->ImgOptHdr.ImageBase,
ISFCN(pext->ImageSymbol.Type));
}
AllowInserts(pimage->pst);
if ((pextEntry != NULL) && ((pextEntry->Flags & EXTERN_DEFINED) != 0)) {
isec = PsecPCON(pextEntry->pcon)->isec;
ib = fM68K ? pextEntry->FinalValue :
pextEntry->ImageSymbol.Value +
pextEntry->pcon->rva -
PsecPCON(pextEntry->pcon)->rva;
} else {
isec = 0;
ib = 0;
}
fprintf(InfoStream, "\n entry point at %04x:%08lx\n\n", isec, ib);
EmitMapStatics(pimage);
if (pmtocHead != NULL) {
EmitMapToc(pimage);
}
if (pimage->Switch.Link.fMapLines) {
// Write linenumber info to .map file.
WriteMapFileLinenums(pimage);
}
EmitMapFixups();
}
void
SaveStaticForMapFile(const char *szName, PCON pcon, DWORD ib, BOOL fFunction)
{
*ppmstatTail = (MSTAT *) PvAlloc(sizeof(MSTAT));
(*ppmstatTail)->szName = SzDup(szName);
(*ppmstatTail)->pcon = pcon;
(*ppmstatTail)->ib = ib;
(*ppmstatTail)->fFunction = fFunction;
(*ppmstatTail)->pmstatNext = NULL;
ppmstatTail = &(*ppmstatTail)->pmstatNext;
}
void
SaveTocForMapFile(PEXTERNAL pext)
{
*ppmtocTail = (MTOC *) PvAlloc(sizeof(MTOC));
(*ppmtocTail)->pext = pext;
(*ppmtocTail)->pmtocNext = NULL;
ppmtocTail = &(*ppmtocTail)->pmtocNext;
}