mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 06:05:58 -06:00
231 lines
8.9 KiB
C++
231 lines
8.9 KiB
C++
#include "uld.h"
|
|
#pragma hdrstop
|
|
|
|
class FileDump
|
|
{
|
|
public:
|
|
FileDump() : dump_stabs(false), dump_globals(false) {}
|
|
|
|
void Run(const char *fn);
|
|
|
|
private:
|
|
void RunCOFF();
|
|
void RunSymbols(int symoff, int symcnt);
|
|
void RunStab(int staboff, int stablen, int stroff, int strlen);
|
|
|
|
private:
|
|
String filename;
|
|
FileMapping mapping;
|
|
int ne_offset;
|
|
bool dump_stabs;
|
|
bool dump_globals;
|
|
};
|
|
|
|
void FileDump::RunSymbols(int symoff, int symcnt)
|
|
{
|
|
const COFF_IMAGE_SYMBOL *sym = (COFF_IMAGE_SYMBOL *)&mapping[symoff];
|
|
const COFF_IMAGE_SYMBOL *end = sym + symcnt;
|
|
const char *strtbl = (const char *)end;
|
|
puts(NFormat("Global symbol table (%d entries)", symcnt));
|
|
puts("Sect Value Type Cl Name");
|
|
for(; sym < end; sym++)
|
|
{
|
|
puts(NFormat("%4>04x %08x %04x %02x %s",
|
|
sym->SectionNumber, (int)sym->Value, sym->Type, sym->StorageClass, COFFSymbolName(*sym, strtbl)));
|
|
if(sym->NumberOfAuxSymbols)
|
|
{
|
|
if(sym->StorageClass == COFF_IMAGE_SYM_CLASS_FILE)
|
|
puts(NFormat("\tFile: %s", (const char *)(sym + 1)));
|
|
}
|
|
sym += sym->NumberOfAuxSymbols;
|
|
}
|
|
}
|
|
|
|
void FileDump::RunStab(int staboff, int stablen, int stabstroff, int stabstrlen)
|
|
{
|
|
int entries = stablen / STAB_STABSIZE;
|
|
puts(NFormat("STAB debug info (%d entries)", entries));
|
|
const STAB_INFO *info = (const STAB_INFO *)&mapping[staboff];
|
|
const char *str = (const char *)&mapping[stabstroff];
|
|
int counts[256], sizes[256];
|
|
ZeroArray(counts);
|
|
ZeroArray(sizes);
|
|
int strtotal = 0;
|
|
static VectorMap<String, int> old_histogram;
|
|
VectorMap<String, int> histogram;
|
|
for(int i = 0; i < entries; i++, info++)
|
|
{
|
|
counts[info->type]++;
|
|
int sl = strlen(str + info->strdx) + 1;
|
|
sizes[info->type] += sl;
|
|
strtotal += sl;
|
|
puts(NFormat("%06x %02x %02x %04x %08x %s",
|
|
i, info->type, info->other, info->desc, info->value, str + info->strdx));
|
|
String hentry = NFormat("%02x %02x %04x %08x %s", info->type, info->other, info->desc, 0/*info->value*/, str + info->strdx);
|
|
histogram.GetAdd(hentry, 0)++;
|
|
}
|
|
puts(NFormat("%d B, compressed %d B = %d%%",
|
|
strtotal, stabstrlen, 100 * (1 - stabstrlen / double(max(strtotal, 1)))));
|
|
for(int i = 0; i < 256; i++)
|
|
if(counts[i])
|
|
puts(NFormat("[%02x]: %6>d times, %8>d B", i, counts[i], sizes[i]));
|
|
puts("\nHistogram:");
|
|
Vector<int> order = GetSortOrder(histogram.GetValues(), StdGreater<int>());
|
|
for(int i = 0; i < order.GetCount(); i++)
|
|
puts(NFormat("%4>d * %s", histogram[order[i]], histogram.GetKey(order[i])));
|
|
if(!old_histogram.IsEmpty())
|
|
{
|
|
puts("\nDifferential histogram:");
|
|
VectorMap<String, int> diff;
|
|
diff <<= histogram;
|
|
for(int i = 0; i < old_histogram.GetCount(); i++)
|
|
diff.GetAdd(old_histogram.GetKey(i), 0) -= old_histogram[i];
|
|
for(int i = diff.GetCount(); --i >= 0;)
|
|
if(!diff[i])
|
|
diff.Remove(i);
|
|
order = GetSortOrder(diff.GetValues(), StdGreater<int>());
|
|
for(int i = 0; i < order.GetCount(); i++)
|
|
{
|
|
String key = diff.GetKey(order[i]);
|
|
puts(NFormat("(%4>d) %4>~d <- %4>~d * %s", diff[order[i]], histogram.Get(key, Null), old_histogram.Get(key, Null), key));
|
|
}
|
|
}
|
|
old_histogram = histogram;
|
|
}
|
|
|
|
void FileDump::RunCOFF()
|
|
{
|
|
const COFF_IMAGE_FILE_HEADER *hdr = (const COFF_IMAGE_FILE_HEADER *)&mapping[ne_offset + 4];
|
|
puts(NFormat("File: %s", filename));
|
|
puts(NFormat("File size: %d B", mapping.GetFileSize()));
|
|
const MachineInfo *mach = COFFMachineList();
|
|
while(mach->name && mach->code != hdr->Machine)
|
|
mach++;
|
|
puts(NFormat("Machine: 0x%04x (%s)", hdr->Machine, mach->name));
|
|
puts(NFormat("NumberOfSections: %d", hdr->NumberOfSections));
|
|
time_t stamp = hdr->TimeDateStamp;
|
|
puts(NFormat("TimeDateStamp: 0x%08x, (%s)", (int)hdr->TimeDateStamp, asctime(localtime(&stamp))));
|
|
puts(NFormat("PointerToSymbolTable: 0x%08x", (int)hdr->PointerToSymbolTable));
|
|
puts(NFormat("NumberOfSymbols: %d", (int)hdr->NumberOfSymbols));
|
|
puts(NFormat("SizeOfOptionalHeader: %d", hdr->SizeOfOptionalHeader));
|
|
puts(NFormat("Characteristics: 0x%08x", hdr->Characteristics));
|
|
if(hdr->SizeOfOptionalHeader < sizeof(COFF_IMAGE_OPTIONAL_HEADER32))
|
|
return;
|
|
|
|
const COFF_IMAGE_OPTIONAL_HEADER32 *opthdr = (const COFF_IMAGE_OPTIONAL_HEADER32 *)
|
|
&mapping[ne_offset + 4 + sizeof(COFF_IMAGE_FILE_HEADER)];
|
|
|
|
puts(NFormat("Magic: 0x%08x", opthdr->Magic));
|
|
puts(NFormat("MajorLinkerVersion: %d", opthdr->MajorLinkerVersion));
|
|
puts(NFormat("MinorLinkerVersion: %d", opthdr->MinorLinkerVersion));
|
|
puts(NFormat("SizeOfCode: 0x%08x", (int)opthdr->SizeOfCode));
|
|
puts(NFormat("SizeOfInitializedData: 0x%08x", (int)opthdr->SizeOfInitializedData));
|
|
puts(NFormat("SizeOfUninitializedData: 0x%08x", (int)opthdr->SizeOfUninitializedData));
|
|
puts(NFormat("AddressOfEntryPoint: 0x%08x", (int)opthdr->AddressOfEntryPoint));
|
|
puts(NFormat("BaseOfCode: 0x%08x", (int)opthdr->BaseOfCode));
|
|
puts(NFormat("BaseOfData: 0x%08x", (int)opthdr->BaseOfData));
|
|
puts(NFormat("ImageBase: 0x%08x", (int)opthdr->ImageBase));
|
|
puts(NFormat("SectionAlignment: 0x%08x", (int)opthdr->SectionAlignment));
|
|
puts(NFormat("FileAlignment: 0x%08x", (int)opthdr->FileAlignment));
|
|
puts(NFormat("MajorOperatingSystemVersion: %d", opthdr->MajorOperatingSystemVersion));
|
|
puts(NFormat("MinorOperatingSystemVersion: %d", opthdr->MinorOperatingSystemVersion));
|
|
puts(NFormat("MajorImageVersion: %d", opthdr->MajorImageVersion));
|
|
puts(NFormat("MinorImageVersion: %d", opthdr->MinorImageVersion));
|
|
puts(NFormat("MajorSubsystemVersion: %d", opthdr->MajorSubsystemVersion));
|
|
puts(NFormat("MinorSubsystemVersion: %d", opthdr->MinorSubsystemVersion));
|
|
puts(NFormat("Win32VersionValue: %d", (int)opthdr->Win32VersionValue));
|
|
puts(NFormat("SizeOfImage: 0x%08x", (int)opthdr->SizeOfImage));
|
|
puts(NFormat("SizeOfHeaders: 0x%08x", (int)opthdr->SizeOfHeaders));
|
|
puts(NFormat("CheckSum: 0x%08x", (int)opthdr->CheckSum));
|
|
puts(NFormat("Subsystem: %d", opthdr->Subsystem));
|
|
puts(NFormat("DllCharacteristics: 0x%08x", opthdr->DllCharacteristics));
|
|
puts(NFormat("SizeOfStackReserve: 0x%08x", (int)opthdr->SizeOfStackReserve));
|
|
puts(NFormat("SizeOfStackCommit: 0x%08x", (int)opthdr->SizeOfStackCommit));
|
|
puts(NFormat("SizeOfHeapReserve: 0x%08x", (int)opthdr->SizeOfHeapReserve));
|
|
puts(NFormat("SizeOfHeapCommit: 0x%08x", (int)opthdr->SizeOfHeapCommit));
|
|
puts(NFormat("LoaderFlags: 0x%08x", (int)opthdr->LoaderFlags));
|
|
puts(NFormat("NumberOfRvaAndSizes: %d", (int)opthdr->NumberOfRvaAndSizes));
|
|
const COFF_IMAGE_DATA_DIRECTORY *dir = opthdr->DataDirectory;
|
|
puts("Index RVA Size");
|
|
int i;
|
|
for(i = 0; i < (int)opthdr->NumberOfRvaAndSizes; i++, dir++)
|
|
if(dir->VirtualAddress || dir->Size)
|
|
puts(NFormat("0x%02x 0x%08x 0x%08x", i, (int)dir->VirtualAddress, (int)dir->Size));
|
|
const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)dir;
|
|
puts("# Section RVA RFA Size PtrData PtrReloc NumReloc PtrLineNo NumLineNo Char");
|
|
int stab_rfa = 0, stabstr_rfa = 0, stab_len = 0, stabstr_len;
|
|
for(i = 0; i < hdr->NumberOfSections; i++, sechdr++)
|
|
{
|
|
char temp[9];
|
|
temp[8] = 0;
|
|
memcpy(temp, sechdr->Name, COFF_IMAGE_SIZEOF_SHORT_NAME);
|
|
if(!strcmp(temp, ".stab"))
|
|
{
|
|
stab_rfa = sechdr->PointerToRawData;
|
|
stab_len = sechdr->Misc.VirtualSize;
|
|
}
|
|
else if(!strcmp(temp, ".stabstr"))
|
|
{
|
|
stabstr_rfa = sechdr->PointerToRawData;
|
|
stabstr_len = sechdr->Misc.VirtualSize;
|
|
}
|
|
String line;
|
|
line
|
|
<< NFormat("%2<d %8<s 0x%08x 0x%08x 0x%08x ",
|
|
i + 1,
|
|
temp,
|
|
(int)sechdr->VirtualAddress,
|
|
(int)sechdr->PointerToRawData,
|
|
(int)sechdr->Misc.VirtualSize)
|
|
<< NFormat("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
|
|
(int)sechdr->PointerToRawData,
|
|
(int)sechdr->PointerToRelocations, (int)sechdr->NumberOfRelocations,
|
|
(int)sechdr->PointerToLinenumbers, (int)sechdr->NumberOfLinenumbers,
|
|
(int)sechdr->Characteristics);
|
|
puts(line);
|
|
}
|
|
if(dump_globals && hdr->PointerToSymbolTable)
|
|
RunSymbols(hdr->PointerToSymbolTable, hdr->NumberOfSymbols);
|
|
if(dump_stabs && stab_rfa > 0 && stabstr_rfa > 0)
|
|
RunStab(stab_rfa, stab_len, stabstr_rfa, stabstr_len);
|
|
}
|
|
|
|
void FileDump::Run(const char *fn)
|
|
{
|
|
for(;;)
|
|
if(!memicmp(fn, "stab;", 5))
|
|
{
|
|
fn += 5;
|
|
dump_stabs = true;
|
|
}
|
|
else if(!memicmp(fn, "global;", 7))
|
|
{
|
|
fn += 7;
|
|
dump_globals = true;
|
|
}
|
|
else
|
|
break;
|
|
filename = fn;
|
|
if(!mapping.Open(filename = fn))
|
|
throw Exc("file failed to open");
|
|
if(mapping.GetCount() >= 0x40 && mapping[0] == 'M' && mapping[1] == 'Z'
|
|
&& (ne_offset = PeekIL(&mapping[0x3C])) >= 0x40 && ne_offset < mapping.GetFileSize()
|
|
&& PeekIL(&mapping[ne_offset]) == 'P' + 256 * 'E')
|
|
{
|
|
RunCOFF();
|
|
return;
|
|
}
|
|
throw Exc("unknown file format");
|
|
}
|
|
|
|
void DumpFile(String fn)
|
|
{
|
|
try
|
|
{
|
|
FileDump().Run(fn);
|
|
}
|
|
catch(Exc e)
|
|
{
|
|
throw Exc(NFormat("%s: %s", fn, e));
|
|
}
|
|
}
|