--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bintools/petools/pediff/pediff.cpp Wed Aug 18 17:23:33 2010 +0300
@@ -0,0 +1,388 @@
+// Copyright (c) 1996-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 "e32image.h"
+
+#include "h_ver.h"
+#include "h_utl.h"
+#include "pe_defs.h"
+
+#ifdef __MSVCDOTNET__
+ #include <fstream>
+ #include <iomanip>
+ #include <string>
+ using namespace std;
+#else //!__MSVCDOTNET__
+ #include <fstream.h>
+ #include <iomanip.h>
+ #include <string.h>
+#endif //__MSVCDOTNET__
+
+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();
+public:
+ fstream iFile;
+ PIMAGE_DOS_HEADER iDosHeader;
+ PIMAGE_NT_HEADERS iHeaders;
+ PIMAGE_SECTION_HEADER iSectionHeaders;
+ };
+
+PeFile::PeFile()
+ : iDosHeader(NULL), iHeaders(NULL), iSectionHeaders(NULL)
+ {}
+
+PeFile::~PeFile()
+ {
+
+ delete iDosHeader;
+ delete iHeaders;
+ delete [] iSectionHeaders;
+ }
+
+int PeFile::Open(char *aFileName)
+ {
+ iFile.open(aFileName, ios::in | ios::binary);
+ if (!iFile.is_open())
+ return KErrNotFound;
+ return KErrNone;
+ }
+
+void PeFile::Close()
+ {
+
+ iFile.close();
+ }
+
+
+PIMAGE_DOS_HEADER PeFile::DosHeader()
+ {
+ if (iDosHeader)
+ return iDosHeader;
+ iDosHeader=new IMAGE_DOS_HEADER;
+ iFile.seekg(0);
+ iFile.read((char *)iDosHeader, sizeof(IMAGE_DOS_HEADER));
+ if (iDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
+ 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;
+ iFile.seekg(d->e_lfanew);
+ if (iFile.eof())
+ 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)
+ return NULL;
+ iSectionHeaders=new IMAGE_SECTION_HEADER [NumberOfSections()];
+ iFile.seekg(DosHeader()->e_lfanew+sizeof(IMAGE_NT_HEADERS));
+ int i=sizeof(IMAGE_SECTION_HEADER)*NumberOfSections();
+ iFile.read((char *)iSectionHeaders, i);
+ 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];
+ memset(section, 0, h->SizeOfRawData);
+ if (section==NULL)
+ return NULL;
+ iFile.seekg(h->PointerToRawData);
+ iFile.read(section, h->SizeOfRawData);
+ return section;
+ }
+
+int pecmp(char *aFileName1, char *aFileName2)
+ {
+
+ PeFile file1, file2;
+ if (file1.Open(aFileName1)!=KErrNone)
+ {
+ cout << "Cannot open file '"<<aFileName1<<"' for input.\n";
+ return KErrNotFound;
+ }
+ if (file2.Open(aFileName2)!=KErrNone)
+ {
+ cout << "Cannot open file '"<<aFileName2<<"' for input.\n";
+ return KErrNotFound;
+ }
+
+ PIMAGE_DOS_HEADER dosheader1=file1.DosHeader();
+ if (dosheader1==NULL)
+ {
+ cout << aFileName1 << " does not have a valid DOS header.\n";
+ return KErrGeneral;
+ }
+ PIMAGE_DOS_HEADER dosheader2=file2.DosHeader();
+ if (dosheader2==NULL)
+ {
+ cout << aFileName2 << " does not have a valid DOS header.\n";
+ return KErrGeneral;
+ }
+
+ PIMAGE_NT_HEADERS headers1=file1.Headers();
+ if (headers1==NULL)
+ {
+ cout << aFileName1 << " is too small to be a PE file.\n";
+ return KErrGeneral;
+ }
+ PIMAGE_NT_HEADERS headers2=file2.Headers();
+ if (headers2==NULL)
+ {
+ cout << aFileName2 << " is too small to be a PE file.\n";
+ return KErrGeneral;
+ }
+
+ int sameTime=(headers1->FileHeader.TimeDateStamp==headers2->FileHeader.TimeDateStamp);
+ headers1->FileHeader.TimeDateStamp=0;
+ headers2->FileHeader.TimeDateStamp=0;
+
+ int r=memcmp(headers1, headers2, sizeof(IMAGE_NT_HEADERS));
+ if (r)
+ {
+ cout << "PE file headers are different.\n";
+ return KDiffDifferent;
+ }
+
+ PIMAGE_SECTION_HEADER sectionheaders1=file1.SectionHeaders();
+ PIMAGE_SECTION_HEADER sectionheaders2=file2.SectionHeaders();
+ // file one and two have the same number of sections
+ int numberofsections=file1.NumberOfSections();
+ if (numberofsections==-1)
+ {
+ cout << "Not a valid PE file.\n";
+ return KErrGeneral;
+ }
+ r=memcmp(sectionheaders1, sectionheaders2, sizeof(IMAGE_SECTION_HEADER)*file1.NumberOfSections());
+ if (r)
+ {
+ cout << "The files are different: PE section headers are different.\n";
+ return KDiffDifferent;
+ }
+
+ TUint exportDirVa=headers1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
+ TUint debugDirVa=headers1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+
+ int i;
+ for (i=0; i<numberofsections; i++)
+ {
+ PIMAGE_SECTION_HEADER h=§ionheaders1[i];
+ char *section1=file1.LoadSection(h);
+ char *section2=file2.LoadSection(h);
+ if ((section1==NULL) || (section2==NULL))
+ {
+ cout << "Error: Out of memory\n";
+ return KErrNoMemory;
+ }
+ 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 dd1=(PIMAGE_DEBUG_DIRECTORY)(section1+debugDirVa-h->VirtualAddress);
+ PIMAGE_DEBUG_DIRECTORY dd2=(PIMAGE_DEBUG_DIRECTORY)(section2+debugDirVa-h->VirtualAddress);
+ TInt debugDirSize=headers1->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ while (debugDirSize>0)
+ {
+ if (sameTime)
+ sameTime=(dd1->TimeDateStamp==dd2->TimeDateStamp);
+ dd1->TimeDateStamp=0;
+ dd2->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...
+ dd1->SizeOfData=0;
+ dd2->SizeOfData=0;
+ dd1->PointerToRawData=0;
+ dd2->PointerToRawData=0;
+ dd1++;
+ dd2++;
+ debugDirSize-=sizeof(IMAGE_DEBUG_DIRECTORY);
+ }
+ }
+ if (exportDirVa>=h->VirtualAddress && exportDirVa<h->VirtualAddress+h->SizeOfRawData)
+ {
+ // Export directory in this section
+ PIMAGE_EXPORT_DIRECTORY ed1=(PIMAGE_EXPORT_DIRECTORY)(section1+exportDirVa-h->VirtualAddress);
+ PIMAGE_EXPORT_DIRECTORY ed2=(PIMAGE_EXPORT_DIRECTORY)(section2+exportDirVa-h->VirtualAddress);
+ if (sameTime)
+ sameTime=(ed1->TimeDateStamp==ed2->TimeDateStamp);
+ ed1->TimeDateStamp=0;
+ ed2->TimeDateStamp=0;
+ }
+ if (strcmp(".rsrc",name)==0)
+ {
+ int *t1=(int *)(section1+4);
+ int *t2=(int *)(section2+4);
+ if (sameTime)
+ sameTime=(*t1==*t2);
+ *t1=0;
+ *t2=0;
+ }
+
+ r=memcmp(section1, section2, h->SizeOfRawData);
+ if (r)
+ {
+ cout << name << " sections are different.\n";
+ return KDiffDifferent;
+ }
+ delete section1;
+ delete section2;
+ }
+
+ if (sameTime)
+ cout << "PE files are identical (time/data stamps also identical).\n";
+ else
+ cout << "PE files are identical except for time/date stamps.\n";
+ file1.Close();
+ file2.Close();
+ return KDiffIdentical;
+ }
+
+int e32cmp(char *aFileName1, char *aFileName2)
+ {
+ char* f1 = NormaliseFileName(aFileName1);
+ char* f2 = NormaliseFileName(aFileName2);
+
+ E32ImageFile e32image1;
+ E32ImageFile e32image2;
+ TInt r = e32image1.Open(f1);
+ if (r != KErrNone)
+ {
+ if (r<0)
+ fprintf(stderr, "%s is not a valid E32Image file (error %d)\n", f1, r);
+ else
+ r = -1;
+ return r;
+ }
+ r = e32image2.Open(f2);
+ if (r != KErrNone)
+ {
+ if (r<0)
+ fprintf(stderr, "%s is not a valid E32Image file (error %d)\n", f2, r);
+ else
+ r = -1;
+ return r;
+ }
+
+
+
+ int sametime=(e32image1.iHdr->iTimeLo==e32image2.iHdr->iTimeLo)
+ &&(e32image1.iHdr->iTimeHi==e32image2.iHdr->iTimeHi);
+ e32image1.iHdr->iTimeLo=0;
+ e32image1.iHdr->iTimeHi=0;
+ e32image1.iOrigHdr->iTimeLo=0;
+ e32image1.iOrigHdr->iTimeHi=0;
+ e32image2.iHdr->iTimeLo=0;
+ e32image2.iHdr->iTimeHi=0;
+ e32image2.iOrigHdr->iTimeLo=0;
+ e32image2.iOrigHdr->iTimeHi=0;
+ e32image1.iHdr->iToolsVersion=e32image2.iHdr->iToolsVersion;
+ e32image1.iOrigHdr->iToolsVersion=e32image2.iOrigHdr->iToolsVersion;
+ e32image1.iHdr->iHeaderCrc=0;
+ e32image2.iHdr->iHeaderCrc=0;
+
+ int ohs1 = e32image1.iOrigHdr->TotalSize();
+ int ohs2 = e32image2.iOrigHdr->TotalSize();
+ int orighdrcmp = (ohs1==ohs2) ? memcmp(e32image1.iOrigHdr, e32image2.iOrigHdr, ohs1) : 1;
+
+ int hs1 = e32image1.iHdr->TotalSize();
+ int hs2 = e32image2.iHdr->TotalSize();
+ int hdrcmp = (hs1==hs2) ? memcmp(e32image1.iHdr, e32image2.iHdr, hs1) : 1;
+
+ int rs1 = e32image1.iSize - ohs1;
+ int rs2 = e32image2.iSize - ohs2;
+ int rcmp = (rs1==rs2) ? memcmp(e32image1.iData + ohs1, e32image2.iData + ohs2, rs1) : 1;
+
+ if (orighdrcmp==0 && rcmp==0)
+ {
+ if (sametime)
+ printf("E32 image files are identical\n");
+ else
+ printf("E32 image files are identical apart from timestamps and Header CRC \n");
+ return KDiffIdentical;
+ }
+ if (hdrcmp==0 && rcmp==0)
+ {
+ printf("E32 image files are functionally equivalent but have different headers\n");
+ return KDiffDifferent;
+ }
+ printf("E32 image files are different\n");
+ return KDiffDifferent;
+ }
+
+
+int main(int argc, char *argv[])
+ {
+ cout << "\nPEDIFF - PE file compare V";
+ cout << MajorVersion << '.' << setfill('0') << setw(2) << MinorVersion;
+ cout << '(' << setw(3) << Build << ")\n";
+ cout << Copyright;
+
+ int r=KErrArgument;
+ if ((argc==3) || (argc==4))
+ {
+ if (argc==3)
+ r=pecmp(argv[1], argv[2]);
+ else if (strcmp("-e32", argv[1])==0)
+ r=e32cmp(argv[2], argv[3]);
+ }
+ if (r==KErrArgument)
+ {
+ cout << "Syntax: "<<argv[0]<<" pefile pefile\n";
+ cout << " "<<argv[0]<<" -e32 e32imagefile e32imagefile\n";
+ }
+ return r;
+ }
+