bintools/petools/pe_dump/pe_dump.cpp
changeset 629 541af5ee3ed9
parent 600 6d08f4a05d93
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/petools/pe_dump/pe_dump.cpp	Wed Aug 18 17:23:33 2010 +0300
@@ -0,0 +1,460 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32err.h>
+
+#include "h_ver.h"
+#include "pe_defs.h"
+#include <sys/stat.h>
+
+#if defined(__MSVCDOTNET__) || defined (__TOOLS2__)
+ #include <iostream>
+ #include <iomanip>
+ #include <fstream>
+ #include <string>
+ using namespace std;
+#else //__MSVCDOTNET__
+ #include <iostream.h>
+ #include <iomanip.h>
+ #include <fstream.h>
+ #include <string.h>
+#endif //__MSVCDOTNET__
+
+#include <stdio.h>
+
+const int KDiffIdentical=0;
+const int KDiffDifferent=2;
+
+class PeFile
+	{
+public:
+	PeFile();
+	~PeFile();
+	int Open(char *aFileName);
+	void Close();
+	PIMAGE_DOS_HEADER DosHeader();
+	PIMAGE_NT_HEADERS Headers();
+	PIMAGE_SECTION_HEADER SectionHeaders();
+	char *LoadSection(PIMAGE_SECTION_HEADER aSectionHeader);
+	int NumberOfSections();
+	char *LoadExtraData(int aOffsetToExtraData, TUint aFileSize);
+	
+	int Errno();  // Should be invoked only if previous call of PeFile's 
+	              // member function returns incorrectly
+	int Errno(int aErrno);  // Assign error number for special purpose.
+public:
+	fstream iFile;
+	PIMAGE_DOS_HEADER iDosHeader;
+	PIMAGE_NT_HEADERS iHeaders;
+	PIMAGE_SECTION_HEADER iSectionHeaders;
+private:
+	int errnumber;
+	};
+
+PeFile::PeFile()
+	//: iDosHeader(NULL), iHeaders(NULL), iSectionHeaders(NULL), errno(KErrNone)
+	//commented out as SBSv2 reports error: anachronistic old-style base class initializer
+{
+	iDosHeader      = NULL    ;
+	iHeaders        = NULL    ;
+	iSectionHeaders = NULL    ;
+	errnumber           = KErrNone;
+
+	return;
+}
+
+PeFile::~PeFile()
+	{
+	delete iDosHeader;
+	delete iHeaders;
+	delete [] iSectionHeaders;
+	}
+
+int PeFile::Open(char *aFileName)
+{
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
+	iFile.open(aFileName, ios::in | ios::binary);
+#else //!__MSVCDOTNET__
+	iFile.open(aFileName, ios::in | ios::binary | ios::nocreate);
+#endif //__MSVCDOTNET__
+	if (!iFile.is_open())
+	{
+		errnumber = KErrNotFound;
+		return KErrNotFound;
+	}
+	return KErrNone;
+}
+
+void PeFile::Close()
+	{
+	iFile.close();
+	}
+
+
+PIMAGE_DOS_HEADER PeFile::DosHeader()
+	{
+	if (iDosHeader)
+		return iDosHeader;
+
+	iDosHeader=new IMAGE_DOS_HEADER;
+	if (!iDosHeader) {
+		errnumber = KErrNoMemory;
+		return NULL;
+	}
+
+	memset(iDosHeader, 0, sizeof(IMAGE_DOS_HEADER));
+
+	iFile.seekg(0);
+	iFile.read((char *)iDosHeader, sizeof(IMAGE_DOS_HEADER));
+	if (iDosHeader->e_magic!=IMAGE_DOS_SIGNATURE) {
+		errnumber = KErrCorrupt;
+		return NULL;
+	}
+	return iDosHeader;
+	}
+
+PIMAGE_NT_HEADERS PeFile::Headers()
+	{
+	if (iHeaders)
+		return iHeaders;
+	PIMAGE_DOS_HEADER d=DosHeader();
+	if (d==NULL)
+		return NULL;
+
+	iHeaders=new IMAGE_NT_HEADERS;
+	if (!iHeaders) {
+		errnumber = KErrNoMemory;
+		return NULL;
+	}
+
+	memset(iHeaders, 0, sizeof(IMAGE_NT_HEADERS));
+
+	iFile.seekg(d->e_lfanew);
+	if (iFile.eof()) {
+		errnumber = KErrCorrupt;  // File size is too small.
+		return NULL;
+	}
+
+	iFile.read((char *)iHeaders, sizeof(IMAGE_NT_HEADERS));
+	return iHeaders;
+	}
+
+PIMAGE_SECTION_HEADER PeFile::SectionHeaders()
+	{
+	if (iSectionHeaders)
+		return iSectionHeaders;
+	PIMAGE_NT_HEADERS h=Headers();
+	if (h==NULL) {
+		errnumber = KErrNoMemory;
+		return NULL;
+	}
+
+	int numSec;
+	if ((numSec = NumberOfSections()) < 0) {
+		return NULL;
+	}
+	else {
+		iSectionHeaders=new IMAGE_SECTION_HEADER [numSec];
+		if (!iSectionHeaders) {
+			errnumber = KErrNoMemory;
+			return NULL;
+		}
+	}
+
+	iFile.seekg(DosHeader()->e_lfanew+sizeof(IMAGE_NT_HEADERS));
+	int i=sizeof(IMAGE_SECTION_HEADER)*numSec;
+	iFile.read((char *)iSectionHeaders, i);
+	if (iFile.gcount() != i) {  // The size of header is incorrect.
+		printf("Error: Cannot load section headers in offset: 0x%x \n", 
+			(int) (DosHeader()->e_lfanew + sizeof(IMAGE_NT_HEADERS)));
+		errnumber = KErrCorrupt;
+		return NULL;
+	}
+
+	return iSectionHeaders;
+	}
+
+int PeFile::NumberOfSections()
+	{
+	if (Headers()) 
+		return iHeaders->FileHeader.NumberOfSections;
+	else
+		return -1;
+	}
+
+char *PeFile::LoadSection(PIMAGE_SECTION_HEADER h)
+	{
+	char *section=new char [h->SizeOfRawData];
+	if (section==NULL){
+		errnumber = KErrNoMemory;
+		return NULL;
+	}
+
+	try
+	{
+	memset(section, 0, h->SizeOfRawData);
+	}
+	catch(...)
+	{
+	}
+
+	iFile.seekg(h->PointerToRawData);
+	iFile.read(section, h->SizeOfRawData);
+	
+	// Guarantee we have loaded the section correctly.
+	unsigned int actNum = iFile.gcount();
+	if (actNum != h->SizeOfRawData) { // The size of section is incorrect.
+		printf("Error: Cannot load section in offset: 0x%x \n", 
+			(int)h->PointerToRawData);
+		errnumber = KErrCorrupt;
+		return NULL;
+	}
+
+	return section;
+	}
+
+char* PeFile::LoadExtraData(int aOffset, TUint aFileSize)
+	{
+	TUint sizeOfExtraData = 0;
+	if(aFileSize >= (TUint)aOffset)
+		sizeOfExtraData=aFileSize-aOffset;
+	if(sizeOfExtraData>0){
+		char* buffer=new char [sizeOfExtraData];
+		if (!buffer) {
+			errnumber = KErrNoMemory;
+			return NULL;
+		}
+
+		memset(buffer, 0, sizeOfExtraData);
+		iFile.seekg(aOffset);
+		iFile.read(buffer, sizeOfExtraData); // Should be OK if the file size is correct.
+
+		// Guarantee we have loaded the data correctly.
+		unsigned int actNum = iFile.gcount();
+		if (actNum != sizeOfExtraData){ // Shouldn't be here is the file size is correct.
+			printf("Error: Cannot load extra section in offset: 0x%x \n", aOffset);
+			errnumber = KErrCorrupt;
+			return NULL;
+		}
+
+		return buffer;
+	}
+	else {
+		errnumber = KErrCorrupt;
+		return NULL;
+	}
+		
+}
+
+int PeFile::Errno() {
+	return errnumber;
+}
+
+int PeFile::Errno(int aErrno) {
+	return (errnumber = aErrno);
+}
+
+
+void dump(TUint *aData, TInt aLength)
+	{
+	TUint *p=aData;
+	TInt i=0;
+	char line[256];
+	unsigned char *cp=(unsigned char*)aData;
+	TInt j=0;
+	memset(line,' ',sizeof(line));
+	while (i<aLength)
+		{
+		TInt ccount=0;
+		char* linep=&line[8*9+2];
+		printf("%06x:", i);
+		while (i<aLength && ccount<8)
+			{
+			printf(" %08x", *p++);
+			i+=4;
+			ccount++;
+			for (j=0; j<4; j++)
+				{
+				unsigned char c=*cp++;
+				if (c<32 || c>127)
+					{
+					c = '.';
+					}
+				*linep++ = c;
+				}
+			}
+		*linep='\0';
+		printf("%s\n", line+(ccount*9));
+		}
+	}
+
+int pecmp(char *aFileName)
+	{
+
+	PeFile peFile;
+	if (peFile.Open(aFileName)!=KErrNone)
+		{
+		cout << "Cannot open file '"<<aFileName<<"' for input.\n";
+		return KErrNotFound;
+		}
+
+	PIMAGE_DOS_HEADER dosHeader=peFile.DosHeader();
+	if (dosHeader==NULL)
+	{
+		switch(peFile.Errno()){
+		case KErrNoMemory:
+			cout << "Error:  Out of memory\n";
+			return KErrNoMemory;
+		default:
+			cout << aFileName << " does not have a valid DOS header.\n";
+		}
+		return KErrGeneral;
+	}
+
+	PIMAGE_NT_HEADERS headers=peFile.Headers();
+	if (headers==NULL)
+	{
+		switch(peFile.Errno()){
+		case KErrNoMemory:
+			cout << "Error:  Out of memory\n";
+			return KErrNoMemory;
+		default:
+			cout << aFileName << " is too small to be a PE file.\n";
+		}
+		return KErrGeneral;
+	}
+
+	headers->FileHeader.TimeDateStamp=0;
+	headers->OptionalHeader.CheckSum = 0; // Fix for TOOLS2 
+
+	printf("NT Headers:\n");
+	dump((TUint*)headers, sizeof(IMAGE_NT_HEADERS));
+
+	int numberofsections=peFile.NumberOfSections();
+	if (numberofsections==-1)
+		{
+		cout << "Not a valid PE file.\n";
+		return KErrGeneral;
+		}
+
+	PIMAGE_SECTION_HEADER sectionheaders=peFile.SectionHeaders();
+
+	printf("Section Headers:\n");
+	dump((TUint*)sectionheaders, sizeof(IMAGE_SECTION_HEADER)*peFile.NumberOfSections());
+
+	TUint exportDirVa=headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+	TUint debugDirVa=headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+	int SizeOfHeaders=headers->OptionalHeader.SizeOfHeaders;
+	int offsetToExtraData=0;
+	int i;
+	for (i=0; i<numberofsections; i++)
+		{
+		PIMAGE_SECTION_HEADER h=&sectionheaders[i];
+		if(h->SizeOfRawData == 0)
+		{
+			continue;
+		}
+		char *section=peFile.LoadSection(h);
+		if (section==NULL)
+		{
+			switch(peFile.Errno()){
+			case KErrNoMemory:
+				cout << "Error:  Out of memory\n";
+				return KErrNoMemory;
+			default:
+				cout << "Not a valid PE file.\n";
+			}
+			return KErrGeneral;
+		}
+		char name[9];
+		for (int j=0; j<9; j++)
+			name[j]=h->Name[j];
+		name[8]=0;
+
+		if (debugDirVa>=h->VirtualAddress && debugDirVa<h->VirtualAddress+h->SizeOfRawData)
+			{
+			// Debug data in this section
+			PIMAGE_DEBUG_DIRECTORY dd=(PIMAGE_DEBUG_DIRECTORY)(section+debugDirVa-h->VirtualAddress);
+			TInt debugDirSize=headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+			while (debugDirSize>0)
+				{
+				dd->TimeDateStamp=0;
+				// size & location in file of debug data is not significant
+				// unless it's also mapped (AddressOfRawData != 0). If that's
+				// true, then the data will be visible in one of the sections
+				// anyway...
+				dd->SizeOfData=0;
+				dd->PointerToRawData=0;
+				dd++;
+				debugDirSize-=sizeof(IMAGE_DEBUG_DIRECTORY);
+				}
+			}
+		if (exportDirVa>=h->VirtualAddress && exportDirVa<h->VirtualAddress+h->SizeOfRawData)
+			{
+			// Export directory in this section
+			PIMAGE_EXPORT_DIRECTORY ed=(PIMAGE_EXPORT_DIRECTORY)(section+exportDirVa-h->VirtualAddress);
+			ed->TimeDateStamp=0;
+			}
+		if (strcmp(".rsrc",name)==0)
+			{
+			int *t=(int *)(section+4);
+			*t=0;
+			}
+
+		offsetToExtraData=offsetToExtraData+h->SizeOfRawData;
+		printf("Raw data:\n");
+		dump((TUint*)section, h->SizeOfRawData);
+
+		delete section;
+		}
+	struct stat buf;
+	stat (aFileName,&buf);
+	TUint fileSize=buf.st_size;
+	offsetToExtraData=offsetToExtraData+SizeOfHeaders;
+	TUint sizeOfExtraData = 0;
+	if(buf.st_size >= offsetToExtraData)
+		sizeOfExtraData=buf.st_size-offsetToExtraData;
+	char* extraData=peFile.LoadExtraData(offsetToExtraData, fileSize);
+	if(sizeOfExtraData>0){
+		char* nsisSign;
+		nsisSign=extraData+8;
+		if(strncmp (nsisSign,"NullsoftInst",12) == 0){
+			printf("\n\n Extra Data:\n");
+			dump((TUint*)extraData, sizeOfExtraData);
+		}
+	}
+	peFile.Close();
+	return KErrNone;
+	}
+
+int main(int argc, char *argv[])
+	{
+	int r=KErrArgument;
+	if (argc==2)
+		{
+		r=pecmp(argv[1]);
+		}
+	if (r==KErrArgument)
+		{
+		cout << "\nPE_DUMP - PE file dumper V";
+		cout << MajorVersion << '.' << setfill('0') << setw(2) << MinorVersion;
+		cout << '(' << setw(3) << Build << ")\n";
+		cout << Copyright;
+		cout << "Syntax: "<<argv[0]<<" pefile\n";
+		}
+	return r;
+	}