mirror of https://github.com/lianthony/NT4.0
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.
1184 lines
30 KiB
1184 lines
30 KiB
/***********************************************************************
|
|
* Microsoft (R) 32-Bit Incremental Linker
|
|
*
|
|
* Copyright (C) Microsoft Corp 1992-95. All rights reserved.
|
|
*
|
|
* File: mppcdbg.cpp
|
|
*
|
|
* File Comments:
|
|
*
|
|
* This module contains all ppc debugging specific code.
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "link.h"
|
|
#define MAX_INSTR_CACHED 16
|
|
|
|
// Code for MppcPefDisasmSection is in disasm.c
|
|
// in the disasm subdirectory
|
|
VOID
|
|
MppcPefDisasmSection(
|
|
DWORD dwRawDataSize,
|
|
DWORD dwRawDataPtr,
|
|
FILE *InfoStream);
|
|
|
|
DWORD
|
|
MapMsFile
|
|
(
|
|
const char *msName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Map the pef file for the dumper
|
|
|
|
Arguments:
|
|
msName name of the pef file
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BYTE *filePtr;
|
|
HANDLE hFile;
|
|
HANDLE hMappedFile;
|
|
|
|
hFile = CreateFile(msName, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, 0, NULL );
|
|
|
|
if (hFile == NULL) {
|
|
fprintf(stderr,"File Map to %s failed\n", msName);
|
|
exit(1);
|
|
}
|
|
|
|
hMappedFile = CreateFileMapping(hFile, NULL, PAGE_READONLY,
|
|
0, 0, NULL );
|
|
if (!hMappedFile) {
|
|
fprintf(stderr,"Create map of %s failed \n", msName);
|
|
CloseHandle(hFile);
|
|
exit(1);
|
|
}
|
|
|
|
filePtr = (BYTE *) MapViewOfFile(hMappedFile, FILE_MAP_READ, 0, 0, 0);
|
|
|
|
CloseHandle(hMappedFile);
|
|
|
|
if (!filePtr) {
|
|
fprintf(stderr,"Map of %s failed\n", msName);
|
|
CloseHandle(hFile);
|
|
exit(1);
|
|
}
|
|
|
|
return (DWORD) filePtr;
|
|
}
|
|
|
|
STATIC
|
|
INT
|
|
PrintPpcHeader
|
|
(
|
|
DWORD filePtr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintPpcHeader
|
|
|
|
Arguments:
|
|
filePtr mapped file pointer
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PPC_FILE_HEADER P;
|
|
|
|
printf("\n Ppc Header:\n\n");
|
|
|
|
memcpy(&P, (PVOID)filePtr, sizeof(PPC_FILE_HEADER));
|
|
|
|
SwapBytes((BYTE *) &P.magic1, 2);
|
|
SwapBytes((BYTE *) &P.magic2, 2);
|
|
SwapBytes((BYTE *) &P.containerId, 4);
|
|
SwapBytes((BYTE *) &P.architectureId, 4);
|
|
SwapBytes((BYTE *) &P.version, 4);
|
|
SwapBytes((BYTE *) &P.timestamp, 4);
|
|
SwapBytes((BYTE *) &P.oldDefVersion, 4);
|
|
SwapBytes((BYTE *) &P.oldImpVersion, 4);
|
|
SwapBytes((BYTE *) &P.currentVersion, 4);
|
|
SwapBytes((BYTE *) &P.nSections, 2);
|
|
SwapBytes((BYTE *) &P.nLoadableSections, 2);
|
|
SwapBytes((BYTE *) &P.memoryAddress, 4);
|
|
|
|
printf(" magic1 = 0x%04x\n", P.magic1);
|
|
printf(" magic2 = 0x%04x\n", P.magic2);
|
|
printf(" containerId = 0x%08x\n", P.containerId);
|
|
printf(" architectureId = 0x%08x\n", P.architectureId);
|
|
printf(" version = 0x%08x\n", P.version);
|
|
printf(" timeStamp = 0x%08x\n", P.timestamp);
|
|
printf(" oldDefVersion = 0x%08x\n", P.oldDefVersion);
|
|
printf(" oldImpVersion = 0x%08x\n", P.oldImpVersion);
|
|
printf(" currentVersion = 0x%08x\n", P.currentVersion);
|
|
printf(" nSections = %d\n", P.nSections);
|
|
printf(" nLoadableSect = %d\n", P.nLoadableSections);
|
|
printf(" memoryAddress = 0x%08x\n", P.memoryAddress);
|
|
|
|
return P.nSections;
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintRawSection
|
|
(
|
|
const char *name,
|
|
DWORD filePtr,
|
|
LONG numOfBytes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintRawSection - prints raw data sections in the same
|
|
format as the dumper
|
|
|
|
Arguments:
|
|
name of the section
|
|
filePtr
|
|
numOfBytes in the section
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD start;
|
|
DWORD pos = 0;
|
|
char str[18];
|
|
DWORD strPos = 0;
|
|
|
|
if (!numOfBytes) {
|
|
return;
|
|
}
|
|
|
|
printf("\n %s Section Raw Data:\n", name);
|
|
|
|
start = filePtr;
|
|
str[0] = '\0';
|
|
while (filePtr < (numOfBytes + start)) {
|
|
union {
|
|
DWORD l;
|
|
char c[4];
|
|
} x;
|
|
|
|
if (!(pos % 16)) {
|
|
printf(" %s\n%08x ", str, pos);
|
|
strPos = 0;
|
|
} else if (pos && !(pos % 8)) {
|
|
printf("| ");
|
|
str[strPos] = '|';
|
|
strPos++;
|
|
}
|
|
|
|
x.l = *((DWORD *)filePtr);
|
|
printf("%02x %02x %02x %02x ",
|
|
x.c[0] & 0xFF, x.c[1] & 0xFF, x.c[2] & 0xFF, x.c[3] & 0xFF);
|
|
str[strPos] = isprint(x.c[0]) ? x.c[0] : '.';
|
|
str[strPos+1] = isprint(x.c[1]) ? x.c[1] : '.';
|
|
str[strPos+2] = isprint(x.c[2]) ? x.c[2] : '.';
|
|
str[strPos+3] = isprint(x.c[3]) ? x.c[3] : '.';
|
|
str[strPos+4] = '\0';
|
|
|
|
filePtr += 4;
|
|
pos += 4;
|
|
strPos += 4;
|
|
}
|
|
|
|
printf(" %s\n", str);
|
|
}
|
|
|
|
|
|
STATIC
|
|
VOID
|
|
PrintImportTable
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintImportTable
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT i;
|
|
IMPORT_TABLE_PTR importPtr;
|
|
DWORD strTableOffset;
|
|
|
|
if (!loaderHdr->nImportSymTableEntries) {
|
|
return;
|
|
}
|
|
|
|
printf("\n Import Symbol Table:\n\n");
|
|
importPtr = (IMPORT_TABLE_PTR)
|
|
(loaderOffset + sizeof(LOADER_HEADER) +
|
|
(loaderHdr->nImportIdTableEntries *
|
|
sizeof(CONTAINER_TABLE)));
|
|
|
|
strTableOffset = loaderOffset + loaderHdr->stringTableOffset;
|
|
|
|
for (i = 0; i < (INT)loaderHdr->nImportSymTableEntries; i++) {
|
|
union
|
|
{
|
|
DWORD l;
|
|
char c[4];
|
|
} x;
|
|
const char *namePtr;
|
|
DWORD nameOffset;
|
|
BYTE symClass;
|
|
|
|
memcpy(&x, importPtr, sizeof(IMPORT_TABLE));
|
|
|
|
SwapBytes((BYTE *) &x, 4);
|
|
nameOffset = x.l & 0xFFFFFF;
|
|
symClass = x.c[3];
|
|
|
|
namePtr = (char *) strTableOffset + nameOffset;
|
|
printf(" Imp %3d %02d \"%s\"\n", i, symClass, namePtr);
|
|
importPtr++;
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintImportContainers
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintImportContainers
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
CONTAINER_TABLE_PTR containerPtr;
|
|
CONTAINER_TABLE container;
|
|
DWORD strTableOffset;
|
|
INT i;
|
|
|
|
if (!loaderHdr->nImportIdTableEntries) {
|
|
return;
|
|
}
|
|
|
|
printf("\n Import Container Id Table:\n\n");
|
|
containerPtr = (CONTAINER_TABLE_PTR)
|
|
(loaderOffset + sizeof(LOADER_HEADER));
|
|
|
|
strTableOffset = loaderOffset + loaderHdr->stringTableOffset;
|
|
|
|
for (i = 0; i < (INT)loaderHdr->nImportIdTableEntries; i++) {
|
|
const char *namePtr;
|
|
|
|
memcpy(&container, containerPtr, sizeof(CONTAINER_TABLE));
|
|
|
|
SwapBytes((BYTE *) &container.nameOffset, 4);
|
|
SwapBytes((BYTE *) &container.oldDefVersion, 4);
|
|
SwapBytes((BYTE *) &container.currentVersion, 4);
|
|
SwapBytes((BYTE *) &container.numImports, 4);
|
|
SwapBytes((BYTE *) &container.impFirst, 4);
|
|
|
|
namePtr = (char *) strTableOffset + container.nameOffset;
|
|
printf(" Import File %d: \"%s\"\n", i, namePtr);
|
|
printf(" oldDefVersion = 0x%08x\n", container.oldDefVersion);
|
|
printf(" currentVersion = 0x%08x\n", container.currentVersion);
|
|
printf(" numImports = %d\n", container.numImports);
|
|
printf(" impFirst = %d\n", container.impFirst);
|
|
printf(" initBefore = 0x%02x\n", container.initBefore);
|
|
printf(" reservedB = 0x%02x\n", 0); /* FIX later */
|
|
printf(" reservedH = 0x%04x\n", 0); /* FIX later */
|
|
containerPtr++;
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintLoaderHeader
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintLoaderHeader
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
LOADER_HEADER_PTR loaderPtr;
|
|
|
|
printf("\n Loader Section Header:\n\n");
|
|
|
|
loaderPtr = (LOADER_HEADER_PTR) loaderOffset;
|
|
|
|
memcpy(loaderHdr, (PVOID)loaderPtr, sizeof(LOADER_HEADER));
|
|
|
|
SwapBytes((BYTE *) &loaderHdr->entryPointSectionNumber, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->entryPointDescrOffset, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->initRoutineSectionNumber, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->initRoutineDescrOffset, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->termRoutineSectionNumber, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->termRoutineDescrOffset, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->nImportIdTableEntries, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->nImportSymTableEntries, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->nSectionsWithRelocs, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->relocTableOffset, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->stringTableOffset, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->hashSlotTableOffset, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->hashSlotCount, 4);
|
|
SwapBytes((BYTE *) &loaderHdr->nExportedSymbols, 4);
|
|
|
|
printf(" ");
|
|
printf("entryPointSection = %d\n", loaderHdr->entryPointSectionNumber);
|
|
printf(" ");
|
|
printf("entryPointOffset = %08lx\n", loaderHdr->entryPointDescrOffset);
|
|
printf(" ");
|
|
printf("initPointSection = %d\n", loaderHdr->initRoutineSectionNumber);
|
|
printf(" ");
|
|
printf("initPointOffset = %08lx\n", loaderHdr->initRoutineDescrOffset);
|
|
printf(" ");
|
|
printf("termPointSection = %d\n", loaderHdr->termRoutineSectionNumber);
|
|
printf(" ");
|
|
printf("termPointOffset = %08lx\n", loaderHdr->termRoutineDescrOffset);
|
|
printf(" ");
|
|
printf("numImportFiles = %08lx\n", loaderHdr->nImportIdTableEntries);
|
|
printf(" ");
|
|
printf("numImportSyms = %08lx\n", loaderHdr->nImportSymTableEntries);
|
|
printf(" ");
|
|
printf("numSections = %d\n", loaderHdr->nSectionsWithRelocs);
|
|
printf(" ");
|
|
printf("relocationsOffset = %08lx\n", loaderHdr->relocTableOffset);
|
|
printf(" ");
|
|
printf("stringsOffset = %08lx\n", loaderHdr->stringTableOffset);
|
|
printf(" ");
|
|
printf("hashSlotTable = %08lx\n", loaderHdr->hashSlotTableOffset);
|
|
printf(" ");
|
|
printf("hashSlotTabSize = %d (%d)\n", loaderHdr->hashSlotCount,
|
|
(1 << loaderHdr->hashSlotCount));
|
|
printf(" ");
|
|
printf("numExportedSyms = %08lx\n", loaderHdr->nExportedSymbols);
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintRelocHeaders
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintRelocHeaders
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
RELOCATION_HEADER_PTR relocPtr;
|
|
RELOCATION_HEADER relocHdr;
|
|
DWORD i;
|
|
|
|
if (!loaderHdr->nSectionsWithRelocs) {
|
|
return;
|
|
}
|
|
|
|
printf("\n Relocation Header:\n\n");
|
|
relocPtr = (RELOCATION_HEADER_PTR)
|
|
(loaderOffset + sizeof(LOADER_HEADER) +
|
|
(loaderHdr->nImportIdTableEntries *
|
|
sizeof(CONTAINER_TABLE)) +
|
|
(loaderHdr->nImportSymTableEntries *
|
|
sizeof(IMPORT_TABLE)));
|
|
|
|
for (i = 0; i < loaderHdr->nSectionsWithRelocs; i++) {
|
|
memcpy(&relocHdr, (PVOID)relocPtr, sizeof(RELOCATION_HEADER));
|
|
|
|
SwapBytes((BYTE *) &relocHdr.sectionNumber, 2);
|
|
SwapBytes((BYTE *) &relocHdr.nRelocations, 4);
|
|
SwapBytes((BYTE *) &relocHdr.firstRelocationOffset, 4);
|
|
|
|
printf(" sectionNumber = %d\n", relocHdr.sectionNumber);
|
|
printf(" numRelocations = %d\n", relocHdr.nRelocations);
|
|
printf(" relocOffset = 0x%08x\n", relocHdr.firstRelocationOffset);
|
|
|
|
relocPtr++;
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintRelocationInstructions
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintRelocationInstructions
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
RELOCATION_HEADER_PTR relocHdrPtr;
|
|
RELOCATION_HEADER relocHdr;
|
|
DWORD relocOffset;
|
|
WORD relocInstr;
|
|
DWORD byteOffset = 0;
|
|
DWORD i;
|
|
DWORD rgCacheOffsets[MAX_INSTR_CACHED];
|
|
INT cacheIndex = 0;
|
|
|
|
if (!loaderHdr->nSectionsWithRelocs) {
|
|
return;
|
|
}
|
|
|
|
relocHdrPtr = (RELOCATION_HEADER_PTR)
|
|
(loaderOffset + sizeof(LOADER_HEADER) +
|
|
(loaderHdr->nImportIdTableEntries *
|
|
sizeof(CONTAINER_TABLE)) +
|
|
(loaderHdr->nImportSymTableEntries *
|
|
sizeof(IMPORT_TABLE)));
|
|
|
|
printf("\n Relocation Instructions:\n\n");
|
|
relocOffset = (loaderOffset + sizeof(LOADER_HEADER) +
|
|
(loaderHdr->nImportIdTableEntries *
|
|
sizeof(CONTAINER_TABLE)) +
|
|
(loaderHdr->nImportSymTableEntries *
|
|
sizeof(IMPORT_TABLE)) +
|
|
(loaderHdr->nSectionsWithRelocs *
|
|
sizeof(RELOCATION_HEADER)));
|
|
|
|
for (i = 0; i < loaderHdr->nSectionsWithRelocs; i++, relocHdrPtr++) {
|
|
INT relocType;
|
|
DWORD j;
|
|
|
|
memcpy(&relocHdr, (PVOID)relocHdrPtr, sizeof(RELOCATION_HEADER));
|
|
|
|
SwapBytes((BYTE *) &relocHdr.sectionNumber, 2);
|
|
SwapBytes((BYTE *) &relocHdr.nRelocations, 4);
|
|
SwapBytes((BYTE *) &relocHdr.firstRelocationOffset, 4);
|
|
|
|
for (j = 0; j < relocHdr.nRelocations; j++) {
|
|
INT count;
|
|
INT words;
|
|
INT subOp;
|
|
INT loop;
|
|
DWORD tempByteOffset;
|
|
|
|
|
|
memcpy(&relocInstr, (PVOID)relocOffset, sizeof(WORD));
|
|
SwapBytes((BYTE *) &relocInstr, 2);
|
|
|
|
if (relocInstr >> 15) {
|
|
relocType = (relocInstr >> (16 - 4));
|
|
} else if ((relocInstr >> 14) == 0) {
|
|
relocType = (relocInstr >> (16 - 2));
|
|
} else {
|
|
relocType = (relocInstr >> (16 - 3));
|
|
}
|
|
|
|
switch (relocType) {
|
|
case 0:
|
|
|
|
// DDAT
|
|
words = (relocInstr & ~0xC000) >> 6;
|
|
count = relocInstr & 0x3F;
|
|
|
|
byteOffset += words * 4;
|
|
rgCacheOffsets[cacheIndex] = words * 4;
|
|
|
|
printf(" (%04x) DDAT %3d,%d\n",
|
|
byteOffset, words * 4, count);
|
|
|
|
byteOffset += count * 4;
|
|
rgCacheOffsets[cacheIndex] += count * 4;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
subOp = ((relocInstr >> 9) & 0xF);
|
|
switch (subOp)
|
|
{
|
|
case 0:
|
|
|
|
// CODE
|
|
count = (relocInstr & 0x3FF);
|
|
printf(" (%04x) CODE %3d\n",
|
|
byteOffset, (count + 1));
|
|
byteOffset += (count + 1) * 4;
|
|
rgCacheOffsets[cacheIndex] = (count + 1) * 4;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// DESC
|
|
count = (relocInstr & 0x3FF);
|
|
printf(" (%04x) DESC %3d\n",
|
|
byteOffset, (count + 1));
|
|
byteOffset += (count + 1) * 3 * 4;
|
|
rgCacheOffsets[cacheIndex] = (count + 1) * 3 * 4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
// SYMR
|
|
count = (relocInstr & 0x1FF);
|
|
printf(" (%04x) SYMR %3d\n",
|
|
byteOffset, (count + 1));
|
|
byteOffset += (count + 1) * 4;
|
|
rgCacheOffsets[cacheIndex] = (count + 1) * 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
printf("Bad Relocation found\n");
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
subOp = ((relocInstr >> 9) & 0xF);
|
|
if (subOp == 0) {
|
|
// SYMB
|
|
count = (relocInstr & 0x3FF);
|
|
printf(" (%04x) SYMB %3d\n", byteOffset, count);
|
|
byteOffset += 4;
|
|
rgCacheOffsets[cacheIndex] = 4;
|
|
} else {
|
|
printf("Bad Relocation found\n");
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
|
|
// DELTA
|
|
count = (relocInstr & 0xFFF);
|
|
printf(" (%04x) DELTA %3d\n", byteOffset, (count + 1));
|
|
byteOffset += count + 1;
|
|
rgCacheOffsets[cacheIndex] = count + 1;
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
// RPT
|
|
subOp = ((relocInstr >> 8) & 0xF);
|
|
count = (relocInstr & 0xFF);
|
|
printf(" (%04x) RPT %3d,%d\n",
|
|
byteOffset, subOp + 1, (count + 1));
|
|
|
|
// Calculating new byte Offsets
|
|
for (loop = subOp + 1, tempByteOffset = 0; loop > 0; loop--) {
|
|
tempByteOffset += rgCacheOffsets[(cacheIndex + MAX_INSTR_CACHED - loop) % MAX_INSTR_CACHED];
|
|
}
|
|
|
|
byteOffset += (count + 1) * tempByteOffset;
|
|
rgCacheOffsets[cacheIndex] = 0;
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
// LSYM
|
|
subOp = ((relocInstr >> 10) & 0x3);
|
|
count = (relocInstr & 0x3FF);
|
|
|
|
relocOffset += 2; j++;
|
|
memcpy(&relocInstr, (PVOID)relocOffset, sizeof(WORD));
|
|
SwapBytes((BYTE *) &relocInstr, 2);
|
|
|
|
printf(" (%04x) LSYM %3d,%d\n",
|
|
byteOffset, count, relocInstr);
|
|
byteOffset += 4;
|
|
rgCacheOffsets[cacheIndex] = 4;
|
|
cacheIndex = (cacheIndex+1) % MAX_INSTR_CACHED;
|
|
rgCacheOffsets[cacheIndex] = 0;
|
|
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
// LRPT
|
|
DWORD dwCount;
|
|
if ((relocInstr >> 10) & 0x3 != 0 ) {
|
|
// It could be for LSEC
|
|
printf("Bad Relocation found\n");
|
|
break;
|
|
}
|
|
subOp = ((relocInstr >> 6) & 0xF);
|
|
dwCount = (relocInstr & 0x3F) << 16;
|
|
|
|
relocOffset += 2; j++;
|
|
memcpy(&relocInstr, (PVOID)relocOffset, sizeof(WORD));
|
|
SwapBytes((BYTE *) &relocInstr, 2);
|
|
dwCount |= relocInstr;
|
|
printf(" (%04x) LRPT %3d,%d\n",
|
|
byteOffset, subOp + 1, dwCount);
|
|
|
|
// Calculating new byte Offsets
|
|
for (loop = subOp + 1, tempByteOffset = 0; loop > 0; loop--) {
|
|
tempByteOffset += rgCacheOffsets[(cacheIndex + MAX_INSTR_CACHED - loop) % MAX_INSTR_CACHED];
|
|
}
|
|
|
|
byteOffset += dwCount * tempByteOffset;
|
|
rgCacheOffsets[cacheIndex] = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
printf("Bad Relocation found %x\n", relocInstr);
|
|
break;
|
|
}
|
|
|
|
relocOffset += 2;
|
|
cacheIndex = (cacheIndex+1) % MAX_INSTR_CACHED;
|
|
}
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintHashSlotTable
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintHashSlotTable
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD slotPtr;
|
|
DWORD slotTable;
|
|
INT i;
|
|
|
|
if (!loaderHdr->hashSlotCount) {
|
|
return;
|
|
}
|
|
|
|
printf("\n Hash Slot Table:\n\n");
|
|
|
|
slotPtr = loaderOffset + loaderHdr->hashSlotTableOffset;
|
|
|
|
for (i = 0; i < (1 << loaderHdr->hashSlotCount); i++) {
|
|
DWORD count;
|
|
DWORD index;
|
|
|
|
memcpy(&slotTable, (PVOID)slotPtr, sizeof(DWORD));
|
|
SwapBytes((BYTE *) &slotTable, 4);
|
|
|
|
count = (slotTable >> 18);
|
|
index = (slotTable & 0x3FFFF);
|
|
|
|
printf(" HashSlot %3d: chain count %3d index %3d\n",
|
|
i, count, index);
|
|
|
|
slotPtr += 4;
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintExportedSymbols
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintExportedSymbols
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD exportOffset;
|
|
DWORD strTableOffset;
|
|
DWORD chainTableOffset;
|
|
DWORD i;
|
|
|
|
if (!loaderHdr->nExportedSymbols) {
|
|
return;
|
|
}
|
|
|
|
printf("\n Exported Symbols:\n\n");
|
|
chainTableOffset = (loaderOffset + loaderHdr->hashSlotTableOffset +
|
|
((1 << loaderHdr->hashSlotCount) * sizeof(DWORD)));
|
|
|
|
exportOffset = (chainTableOffset + (loaderHdr->nExportedSymbols *
|
|
sizeof(HASH_CHAIN_TABLE)));
|
|
|
|
strTableOffset = loaderOffset + loaderHdr->stringTableOffset;
|
|
|
|
for (i = 0; i < loaderHdr->nExportedSymbols; i++) {
|
|
HASH_CHAIN_TABLE hash;
|
|
BYTE SymbolClass;
|
|
DWORD nameOffset;
|
|
DWORD offset;
|
|
const char *namePtr;
|
|
WORD section;
|
|
union
|
|
{
|
|
DWORD l;
|
|
BYTE c[4];
|
|
} temp;
|
|
|
|
memcpy(&hash, (PVOID)chainTableOffset, sizeof(HASH_CHAIN_TABLE));
|
|
chainTableOffset += sizeof(HASH_CHAIN_TABLE);
|
|
|
|
memcpy(&temp.l, (PVOID)exportOffset, sizeof(DWORD));
|
|
exportOffset += 4;
|
|
|
|
memcpy(&offset, (PVOID)exportOffset, sizeof(DWORD));
|
|
exportOffset += 4;
|
|
|
|
memcpy(§ion, (PVOID)exportOffset, sizeof(WORD));
|
|
exportOffset += 2;
|
|
|
|
SwapBytes((BYTE *) &hash, 4);
|
|
SwapBytes((BYTE *) &temp, 4);
|
|
SwapBytes((BYTE *) &offset, 4);
|
|
SwapBytes((BYTE *) §ion, 2);
|
|
|
|
nameOffset = temp.l & 0xFFFFFF;
|
|
SymbolClass = temp.c[3];
|
|
|
|
namePtr = (char *) strTableOffset + nameOffset;
|
|
printf(" Exp %3d: sec %d offset 0x%08x hash 0x%x class %d \"%s\"\n",
|
|
i, section, offset, hash, SymbolClass, namePtr);
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintLoaderStringTable
|
|
(
|
|
DWORD loaderOffset,
|
|
LOADER_HEADER_PTR loaderHdr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
PrintLoaderStringTable
|
|
|
|
Arguments:
|
|
loaderOffset includes filePtr
|
|
loaderHdr
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD strTableOffset;
|
|
DWORD curOffset;
|
|
INT offset = 0;
|
|
|
|
if (loaderHdr->stringTableOffset == loaderHdr->hashSlotTableOffset) {
|
|
return;
|
|
}
|
|
|
|
printf("\n Loader String Table:\n\n");
|
|
strTableOffset = loaderOffset + loaderHdr->stringTableOffset;
|
|
curOffset = loaderHdr->stringTableOffset;
|
|
|
|
while (curOffset < loaderHdr->hashSlotTableOffset &&
|
|
*((char *) strTableOffset + offset))
|
|
{
|
|
PCHAR namePtr;
|
|
INT len;
|
|
|
|
namePtr = (PCHAR) strTableOffset + offset;
|
|
printf(" %08x: \"%s\"\n", offset, namePtr);
|
|
|
|
len = strlen(namePtr) + 1;
|
|
offset += len;
|
|
curOffset += len;
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintLoaderSection
|
|
(
|
|
DWORD loaderOffset
|
|
)
|
|
|
|
{
|
|
LOADER_HEADER loaderHdr;
|
|
|
|
PrintLoaderHeader(loaderOffset, &loaderHdr);
|
|
PrintImportContainers(loaderOffset, &loaderHdr);
|
|
PrintImportTable(loaderOffset, &loaderHdr);
|
|
PrintRelocHeaders(loaderOffset, &loaderHdr);
|
|
PrintRelocationInstructions(loaderOffset, &loaderHdr);
|
|
PrintHashSlotTable(loaderOffset, &loaderHdr);
|
|
PrintExportedSymbols(loaderOffset, &loaderHdr);
|
|
PrintLoaderStringTable(loaderOffset, &loaderHdr);
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintPpcSection
|
|
(
|
|
INT sectNumber,
|
|
DWORD filePtr,
|
|
DWORD strTableOffset,
|
|
BOOL wantRawData,
|
|
BOOL fDisasm
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Print a Ppc section
|
|
|
|
Arguments:
|
|
sectNumber
|
|
filePtr mapped file pointer
|
|
strTableOffset
|
|
loaderHeaderOffset
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PPC_SECTION_HEADER_PTR secPtr;
|
|
PPC_SECTION_HEADER secHdr;
|
|
const char *namePtr;
|
|
|
|
printf("\n Section Header %d:\n\n", sectNumber);
|
|
|
|
secPtr = (PPC_SECTION_HEADER_PTR)
|
|
(filePtr + sizeof(PPC_FILE_HEADER) +
|
|
(sectNumber * sizeof(PPC_SECTION_HEADER)));
|
|
|
|
memcpy(&secHdr, (PVOID)secPtr, sizeof(PPC_SECTION_HEADER));
|
|
|
|
SwapBytes((BYTE *) &secHdr.sectionName, 4);
|
|
SwapBytes((BYTE *) &secHdr.sectionAddress, 4);
|
|
SwapBytes((BYTE *) &secHdr.execSize, 4);
|
|
SwapBytes((BYTE *) &secHdr.initSize, 4);
|
|
SwapBytes((BYTE *) &secHdr.rawSize, 4);
|
|
SwapBytes((BYTE *) &secHdr.containerOffset, 4);
|
|
|
|
namePtr = (char *) (filePtr + strTableOffset + secHdr.sectionName);
|
|
printf(" sectionName = 0x%08x \"%s\"\n", secHdr.sectionName, namePtr);
|
|
printf(" sectionAddress = 0x%08x\n", secHdr.sectionAddress);
|
|
printf(" execSize = 0x%08x\n", secHdr.execSize);
|
|
printf(" initSize = 0x%08x\n", secHdr.initSize);
|
|
printf(" rawSize = 0x%08x\n", secHdr.rawSize);
|
|
printf(" containerOff = 0x%08x\n", secHdr.containerOffset);
|
|
printf(" regionKind = 0x%02x\n", secHdr.regionKind);
|
|
printf(" shareKind = 0x%02x\n", secHdr.sharingKind);
|
|
printf(" alignment = 0x%02x\n", secHdr.alignment);
|
|
printf(" reserved = 0x%02x\n", secHdr.reserved);
|
|
|
|
if (wantRawData && (secHdr.regionKind == 0 || secHdr.regionKind == 1)) {
|
|
PrintRawSection(namePtr,
|
|
filePtr + secHdr.containerOffset, secHdr.rawSize);
|
|
} else if (secHdr.regionKind == 4) {
|
|
PrintLoaderSection(filePtr + secHdr.containerOffset);
|
|
}
|
|
|
|
if (fDisasm && secHdr.regionKind == 0) {
|
|
// The disasm switch is true and the section is code (.text)
|
|
MppcPefDisasmSection(secHdr.rawSize,
|
|
filePtr + secHdr.containerOffset, InfoStream);
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
PpcDumpPef
|
|
(
|
|
const char *Filename,
|
|
BOOL wantRawData,
|
|
BOOL fDisasm
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Called by the link dumper utility to dump ppcpef files
|
|
Uses mapped IO
|
|
|
|
Arguments:
|
|
Filename
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD filePtr;
|
|
DWORD strTableOffset;
|
|
INT nSections;
|
|
INT i;
|
|
|
|
printf("Dump of \"%s\"\n", Filename);
|
|
|
|
filePtr = MapMsFile(Filename);
|
|
nSections = PrintPpcHeader(filePtr);
|
|
|
|
strTableOffset = sizeof(PPC_FILE_HEADER) +
|
|
(nSections * sizeof(PPC_SECTION_HEADER));
|
|
for (i = 0; i < nSections; i++) {
|
|
PrintPpcSection(i,
|
|
filePtr,
|
|
strTableOffset,
|
|
wantRawData,
|
|
fDisasm);
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
PrintExternals
|
|
(
|
|
PST pst
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Loop thru the external symbol table printing the symbols.
|
|
|
|
Arguments:
|
|
pst
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PEXTERNAL pexternal;
|
|
PPEXTERNAL rgpexternal;
|
|
DWORD ipexternal;
|
|
DWORD cpexternal;
|
|
PCHAR name;
|
|
|
|
cpexternal = Cexternal(pst);
|
|
rgpexternal = RgpexternalByName(pst);
|
|
|
|
for (ipexternal = 0; ipexternal < cpexternal; ipexternal++) {
|
|
pexternal = rgpexternal[ipexternal];
|
|
|
|
if (pexternal->Flags & EXTERN_DEFINED) {
|
|
name = SzNamePext(pexternal, pst);
|
|
|
|
printf("EXTERNAL %s\n", name);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PrintRelocTable
|
|
(
|
|
RELOCATION_INFO_PTR pRelocTable
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Loop for the number of relocation instructions printing them.
|
|
|
|
Arguments:
|
|
None.
|
|
|
|
Return Value:
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT i;
|
|
RELOCATION_INFO_PTR curRelocTable;
|
|
|
|
printf("i\trelInst\trelCnt\tsecOff\tsymIndex\n");
|
|
|
|
curRelocTable = pRelocTable;
|
|
for (i = 0; i < mppc_numRelocations; i++) {
|
|
printf("%6d ", i);
|
|
|
|
switch (curRelocTable->type) {
|
|
case DDAT_RELO :
|
|
printf("DDAT ");
|
|
break;
|
|
|
|
case DESC_RELO :
|
|
printf("DESC ");
|
|
break;
|
|
|
|
case SYMB_RELO :
|
|
printf("SYMB ");
|
|
break;
|
|
|
|
case DATA_RELO :
|
|
printf("DATA ");
|
|
break;
|
|
|
|
case CODE_RELO :
|
|
printf("CODE ");
|
|
break;
|
|
|
|
default:
|
|
printf("JUNK ", curRelocTable->type);
|
|
break;
|
|
}
|
|
|
|
printf("%4d %08lx %04lx \n", curRelocTable->relocInstr.count,
|
|
curRelocTable->sectionOffset, curRelocTable->symIndex);
|
|
|
|
curRelocTable++;
|
|
}
|
|
}
|
|
|
|
const char *SzMPPCRelocationType(WORD wType)
|
|
{
|
|
const char *szName;
|
|
|
|
switch (wType) {
|
|
case IMAGE_REL_MPPC_TOCCALLREL:
|
|
szName = "TOCCALLREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_LCALL:
|
|
szName = "LCALL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_DATAREL:
|
|
szName = "DATAREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_TOCINDIRCALL:
|
|
szName = "TOCINDIRCALL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_TOCREL:
|
|
szName = "TOCREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_DESCREL:
|
|
szName = "DESCREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_DATADESCRREL:
|
|
szName = "DATADESCRREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_CREATEDESCRREL:
|
|
szName = "CREATEDESCRREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_JMPADDR:
|
|
szName = "JMPADDR";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_SECTION:
|
|
szName = "SECTION";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_SECREL:
|
|
szName = "SECREL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_CV :
|
|
szName = "CV";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_PCODECALL :
|
|
szName = "PCODECALL";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_PCODECALLTONATIVE :
|
|
szName = "PCODECALLTONATIVE";
|
|
break;
|
|
|
|
case IMAGE_REL_MPPC_PCODENEPE :
|
|
szName = "PCODENEPE";
|
|
break;
|
|
|
|
default:
|
|
szName = NULL;
|
|
break;
|
|
}
|
|
|
|
return(szName);
|
|
}
|