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.
 
 
 
 
 
 

524 lines
14 KiB

/***********************************************************************
* Microsoft (R) 32-Bit Incremental Linker
*
* Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
*
* File: pdata.cpp
*
* File Comments:
*
* This module handles the re-ordering of the pdata section.
*
***********************************************************************/
#include "link.h"
struct TFIXUP
{
DWORD rva;
WORD ftype;
WORD wAdj;
};
void
LoadPdata(
PIMAGE pimage,
INT FileHandle,
IMAGE_SECTION_HEADER *pshPdata,
IMAGE_SECTION_HEADER *pshReloc,
PIMAGE_RUNTIME_FUNCTION_ENTRY *prgrfe,
DWORD *pcrfe,
TFIXUP **prgtfixup,
DWORD *pctfixup
)
{
*pshPdata = NullSectionHdr;
*pshReloc = NullSectionHdr;
DWORD rvaPdata = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
DWORD rvaReloc = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
DWORD fo = CoffHeaderSeek + sizeof(IMAGE_FILE_HEADER) + pimage->ImgFileHdr.SizeOfOptionalHeader;
FileSeek(FileHandle, fo, SEEK_SET);
for (DWORD i = 0; i < pimage->ImgFileHdr.NumberOfSections; i++) {
IMAGE_SECTION_HEADER sh;
FileRead(FileHandle, &sh, sizeof(sh));
if ((rvaPdata >= sh.VirtualAddress) && (rvaPdata < sh.VirtualAddress+sh.SizeOfRawData)) {
*pshPdata = sh;
continue;
}
if ((rvaReloc >= sh.VirtualAddress) && (rvaReloc < sh.VirtualAddress+sh.SizeOfRawData)) {
*pshReloc = sh;
continue;
}
}
DWORD cbRfe = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
DWORD crfe = cbRfe / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe = (PIMAGE_RUNTIME_FUNCTION_ENTRY) PvAlloc(cbRfe);
FileSeek(FileHandle, pshPdata->PointerToRawData, SEEK_SET);
FileRead(FileHandle, rgrfe, cbRfe);
DWORD foReloc = rvaReloc - pshReloc->VirtualAddress + pshReloc->PointerToRawData;
FileSeek(FileHandle, foReloc, SEEK_SET);
DWORD cbReloc = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
DWORD cbTfixup = (cbReloc ? (cbReloc / sizeof(WORD)) : 1) * sizeof(TFIXUP);
TFIXUP *rgtfixup = (TFIXUP *) PvAlloc(cbTfixup);
DWORD ctfixup = 0;
if (cbReloc != 0) {
WORD *rgwReloc = (WORD *) PvAlloc(0xffff);
while (cbReloc > 0) {
IMAGE_BASE_RELOCATION bre;
FileRead(FileHandle, &bre, IMAGE_SIZEOF_BASE_RELOCATION);
if (bre.SizeOfBlock == 0) {
break;
}
DWORD cbBlock = bre.SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION;
FileRead(FileHandle, rgwReloc, cbBlock);
DWORD cw = cbBlock / sizeof(WORD);
for (DWORD iw = 0; iw < cw; iw++) {
if (rgwReloc[iw] == 0) { // indicates a pad
continue;
}
DWORD ib = rgwReloc[iw] & 0xfff;
rgtfixup[ctfixup].rva = bre.VirtualAddress + ib;
rgtfixup[ctfixup].ftype = rgwReloc[iw] >> 12;
if (rgtfixup[ctfixup].ftype == IMAGE_REL_BASED_HIGHADJ) {
rgtfixup[ctfixup].wAdj = rgwReloc[++iw];
}
ctfixup++;
}
cbReloc -= bre.SizeOfBlock;
}
FreePv(rgwReloc);
}
*prgrfe = rgrfe;
*pcrfe = crfe;
*prgtfixup = rgtfixup;
*pctfixup = ctfixup;
}
int __cdecl cmpPprfePprfeBeginAddress(void const *pprfe1, void const *pprfe2)
{
DWORD addr1 = (*(PIMAGE_RUNTIME_FUNCTION_ENTRY *) pprfe1)->BeginAddress;
DWORD addr2 = (*(PIMAGE_RUNTIME_FUNCTION_ENTRY *) pprfe2)->BeginAddress;
if (addr1 == 0) {
return(1);
}
if (addr2 == 0) {
return(-1);
}
if (addr1 < addr2) {
return(-1);
}
if (addr1 > addr2) {
return(1);
}
return(0);
}
int __cdecl cmpPtfixupPtfixupRva(void const *ptfixup1, void const *ptfixup2)
{
DWORD rva1 = ((TFIXUP *) ptfixup1)->rva;
DWORD rva2 = ((TFIXUP *) ptfixup2)->rva;
if (rva1 < rva2) {
return(-1);
}
if (rva1 > rva2) {
return(1);
}
return(0);
}
void
SortFunctionTable(
PIMAGE pimage
)
/*++
Routine Description:
Re-Order the pdata section according to the beginning address and
also simultaneously adjust the relocations.
Arguments:
none.
Return Value:
none
--*/
{
if (psecException->cbVirtualSize == 0) {
// Nothing to do
return;
}
assert(psecException->rva != 0);
// Read in the section headers for .pdata and .reloc
IMAGE_SECTION_HEADER shPdata;
IMAGE_SECTION_HEADER shReloc;
PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe;
DWORD crfe;
TFIXUP *rgtfixup;
DWORD ctfixup;
LoadPdata(pimage, FileWriteHandle, &shPdata, &shReloc, &rgrfe, &crfe, &rgtfixup, &ctfixup);
PIMAGE_RUNTIME_FUNCTION_ENTRY *rgprfe = (PIMAGE_RUNTIME_FUNCTION_ENTRY *) PvAlloc(crfe * sizeof(PIMAGE_RUNTIME_FUNCTION_ENTRY));
for (DWORD irfe = 0; irfe < crfe; irfe++) {
rgprfe[irfe] = rgrfe + irfe;
}
// Sort the runtime function entries by address
qsort(rgprfe, crfe, sizeof(PIMAGE_RUNTIME_FUNCTION_ENTRY), cmpPprfePprfeBeginAddress);
// Write out the now sorted entries
FileSeek(FileWriteHandle, shPdata.PointerToRawData, SEEK_SET);
for (irfe = 0; irfe < crfe; irfe++) {
FileWrite(FileWriteHandle, rgprfe[irfe], sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY));
}
// Build a map from old RFE index to new RFE index
DWORD *mpirfeOldirfeNew = (DWORD *) PvAlloc(crfe * sizeof(DWORD));
for (irfe = 0; irfe < crfe; irfe++) {
DWORD irfeOld = rgprfe[irfe] - rgrfe;
mpirfeOldirfeNew[irfeOld] = irfe;
}
DWORD rvaMin = psecException->rva;
DWORD rvaMax = rvaMin + psecException->cbVirtualSize;
// Update the temp fixups with the new RVA where each is applied
TFIXUP *ptfixup = rgtfixup;
for (DWORD itfixup = 0; itfixup < ctfixup; itfixup++, ptfixup++) {
if ((ptfixup->rva < rvaMin) || (ptfixup->rva >= rvaMax)) {
continue;
}
DWORD irfeOld = (ptfixup->rva - rvaMin) / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
DWORD irfeNew = mpirfeOldirfeNew[irfeOld];
DWORD ib = (irfeNew - irfeOld) * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
ptfixup->rva += ib;
}
if (pimage->Switch.Link.DebugType & FixupDebug) {
// Update debug FIXUPs (SaveDebugFixup) with the new RVAs
FileSeek(FileWriteHandle, pconFixupDebug->foRawDataDest, SEEK_SET);
DWORD cxfixup = pconFixupDebug->cbRawData / sizeof(XFIXUP);
for (DWORD ixfixup = 0; ixfixup < cxfixup; ixfixup++) {
XFIXUP xfixup;
FileRead(FileWriteHandle, &xfixup, sizeof(XFIXUP));
if ((xfixup.rva < rvaMin) || (xfixup.rva >= rvaMax)) {
continue;
}
DWORD irfeOld = (xfixup.rva - rvaMin) / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
DWORD irfeNew = mpirfeOldirfeNew[irfeOld];
DWORD ib = (irfeNew - irfeOld) * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
if (ib != 0) {
xfixup.rva += ib;
FileSeek(FileWriteHandle, -(long) sizeof(XFIXUP), SEEK_CUR);
FileWrite(FileWriteHandle, &xfixup, sizeof(XFIXUP));
}
}
}
// We are done with these now
FreePv(mpirfeOldirfeNew);
FreePv(rgprfe);
FreePv(rgrfe);
if (ctfixup != 0) {
// Sort the temp fixups by RVA
qsort(rgtfixup, ctfixup, sizeof(TFIXUP), cmpPtfixupPtfixupRva);
// Write out the now sorted entries
WORD *fixups = (WORD *) PvAlloc(0xffff);
DWORD rvaReloc = psecBaseReloc->rva;
DWORD foReloc = rvaReloc - shReloc.VirtualAddress + shReloc.PointerToRawData;
FileSeek(FileWriteHandle, foReloc, SEEK_SET);
DWORD i = 0;
DWORD cb = 0;
while (i < ctfixup) {
DWORD rva = rgtfixup[i].rva & 0xfffff000;
IMAGE_BASE_RELOCATION bre;
bre.VirtualAddress = rva;
DWORD j = 0;
for (;;) {
DWORD ib = rgtfixup[i].rva & 0xfff;
fixups[j] = (WORD) ((rgtfixup[i].ftype << 12) | ib);
if (rgtfixup[i].ftype == IMAGE_REL_BASED_HIGHADJ) {
fixups[++j] = rgtfixup[i].wAdj;
}
i++;
j++;
if ((rgtfixup[i].rva & 0xfffff000) != rva) {
break;
}
if (i == ctfixup) {
break;
}
}
bre.SizeOfBlock = IMAGE_SIZEOF_BASE_RELOCATION + (j * sizeof(WORD));
if (bre.SizeOfBlock & 0x2) {
bre.SizeOfBlock += 2;
fixups[j] = 0;
}
cb += bre.SizeOfBlock;
FileWrite(FileWriteHandle, &bre, IMAGE_SIZEOF_BASE_RELOCATION);
FileWrite(FileWriteHandle, fixups, bre.SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION);
}
pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = cb;
FreePv(fixups);
}
FreePv(rgtfixup);
}
void
DumpDbgFunctionTable(
DWORD foTable,
DWORD cbTable
)
{
DWORD cfe;
DWORD ife = 0;
cfe = cbTable / sizeof(IMAGE_FUNCTION_ENTRY);
fprintf(InfoStream, "\nFunction Table (%lu)\n\n", cfe);
fprintf(InfoStream, " Begin End PrologEnd\n\n");
FileSeek(FileReadHandle, foTable, SEEK_SET);
while (cfe--) {
IMAGE_FUNCTION_ENTRY fe;
FileRead(FileReadHandle, &fe, sizeof(IMAGE_FUNCTION_ENTRY));
fprintf(InfoStream, "%08lX %08lX %08lX %08lX\n",
ife * sizeof(IMAGE_FUNCTION_ENTRY),
fe.StartingAddress,
fe.EndingAddress,
fe.EndOfPrologue);
ife++;
}
}
void
DumpFunctionTable(
PIMAGE pimage,
PIMAGE_SYMBOL rgsym,
const char *StringTable
)
{
IMAGE_SECTION_HEADER shPdata;
IMAGE_SECTION_HEADER shReloc;
PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe;
DWORD crfe;
TFIXUP *rgtfixup;
DWORD ctfixup;
LoadPdata(pimage, FileReadHandle, &shPdata, &shReloc, &rgrfe, &crfe, &rgtfixup, &ctfixup);
fprintf(InfoStream, "\nFunction Table (%lu)\n\n", crfe);
fprintf(InfoStream, " Begin End Excptn ExcpDat Prolog Fixups Function Name\n\n");
DWORD rvaRfe = shPdata.VirtualAddress;
PIMAGE_RUNTIME_FUNCTION_ENTRY prfe = rgrfe;
DWORD itfixup = 0;
while ((itfixup < ctfixup) && (rgtfixup[itfixup].rva < rvaRfe)) {
itfixup++;
}
for (DWORD irfe = 0; irfe < crfe; irfe++, prfe++) {
DWORD ib = irfe * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
fprintf(InfoStream, "%08lX %08lX %08lX %08lX %08lX %08lX ",
ib,
prfe->BeginAddress,
prfe->EndAddress,
(DWORD) prfe->ExceptionHandler,
(DWORD) prfe->HandlerData,
prfe->PrologEndAddress);
DWORD i;
for (i = 0; i < 5; i++) {
if ((itfixup < ctfixup) && (rgtfixup[itfixup].rva == rvaRfe)) {
fputc('Y', InfoStream);
itfixup++;
} else {
fputc('N', InfoStream);
}
rvaRfe += sizeof(DWORD);
}
if (rgsym != NULL) {
DWORD rva = prfe->BeginAddress - pimage->ImgOptHdr.ImageBase;
PIMAGE_SYMBOL psymNext = rgsym;
for (i = 0; i < pimage->ImgFileHdr.NumberOfSymbols; i++) {
PIMAGE_SYMBOL psym;
psym = FetchNextSymbol(&psymNext);
if ((psym->Value == rva) && (psym->NumberOfAuxSymbols == 0)) {
fprintf(InfoStream, " %s", SzNameSymPb(*psym, StringTable));
break;
}
}
}
fputc('\n', InfoStream);
}
FreePv(rgrfe);
FreePv(rgtfixup);
}
void
DumpObjFunctionTable(
PIMAGE_SECTION_HEADER sh,
SHORT SectionNumber
)
{
DWORD crfe;
DWORD irfe = 0;
crfe = sh->SizeOfRawData / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
fprintf(InfoStream, "\nFUNCTION TABLE #%d (%lu)\n\n", SectionNumber, crfe);
fprintf(InfoStream, " Begin End Excptn ExcpDat PrologEnd\n\n");
while (crfe--) {
IMAGE_RUNTIME_FUNCTION_ENTRY rfe;
FileRead(FileReadHandle, &rfe, sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY));
fprintf(InfoStream, "%08lX %08lX %08lX %08lX %08lX %08lX\n",
irfe * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY),
rfe.BeginAddress,
rfe.EndAddress,
(DWORD) rfe.ExceptionHandler,
(DWORD) rfe.HandlerData,
rfe.PrologEndAddress);
irfe++;
}
}
void
DumpPexFunctionTable(
PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe,
DWORD crfe
)
{
fprintf(InfoStream, "\nFUNCTION TABLE (%lu)\n\n", crfe);
fprintf(InfoStream, " Begin End Excptn ExcpDat PrologEnd\n\n");
PIMAGE_RUNTIME_FUNCTION_ENTRY prfe = rgrfe;
for (DWORD irfe = 0; irfe < crfe; irfe++, prfe++) {
fprintf(InfoStream, "%08lX %08lX %08lX %08lX %08lX %08lX\n",
irfe * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY),
DwSwap(prfe->BeginAddress),
DwSwap(prfe->EndAddress),
DwSwap((DWORD) prfe->ExceptionHandler),
DwSwap((DWORD) prfe->HandlerData),
DwSwap(prfe->PrologEndAddress));
}
}