ultimatepp/uppsrc/coff/uld/dump.cpp
mdelfede 263ff5f895 changed svn layout
git-svn-id: svn://ultimatepp.org/upp/trunk@281 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-06-07 22:31:27 +00:00

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));
}
}