diff -r 000000000000 -r 83f4b4db085c toolsandutils/e32tools/pefile/pe_file.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/pefile/pe_file.cpp Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,1054 @@ +// Copyright (c) 1995-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 +#include +#include +#include +#include "e32image.h" +#include "pe_defs.h" +#include "pe_file.h" +#include "h_utl.h" + +TBool hadText, hadReloc = EFalse; +TUint32 PEFile::iRomMemBase=0; +TUint32 PEFile::iRomLinearBase=0; + +extern char* gX86imp; +extern int gX86num_imp_dlls; + +PEFile::PEFile() + :iMemBase(0),iEntryPoint(0),iImageSize(0),iCodeSize(0),iDataSize(0), + iHeapReservedSize(0),iHeapCommittedSize(0),iStackReservedSize(0),iStackCommittedSize(0), + iBssSize(0),iBssOffset(0),iSectionAlign(0),iExpDirectoryOffset(0),iDataOffset(0), + iImageIsDll(EFalse), + iHeader(0),iExpDirectory(0),iImpDescriptor(0),iFileName(0),iFileHandle(0), + iLinkedBase(0),iStartOfHeaders(0),iSizeOfHeaders(0),iNumSections(0), + iRomRunAddr(0),iRamRunAddr(0),iRomDelta(0),iRamDelta(0),iHadDataSection(EFalse), + iBssSectionLinkedAddr(0),iBssSectionAddr(0),iBssSectionSize(0), + iDataSectionLinkedAddr(0),iDataSectionAddr(0),iDataSectionSize(0), + iCodeSectionAddr(0),iCodeSectionSize(0), + iRDataSectionAddr(0),iRDataSectionSize(0), + iCRTSectionAddr(0),iCRTSectionSize(0), + iExportDataDir(0) +// +// Constructor +// + { + + for (TInt i=0; ie_lfanew; + else + iStartOfHeaders = 0; + + if (!HFile::Seek(iFileHandle, iStartOfHeaders)) + { + Print(EPeError,"File %s is not large enough to contain valid headers.\n",iFileName); + HFile::Close(iFileHandle); + return EFalse; + } + + if (!HFile::Read(iFileHandle,iHeader,sizeof(IMAGE_NT_HEADERS))) + { + Print(EPeError,"Unable to read NT headers.\n"); + HFile::Close(iFileHandle); + return EFalse; + } + + if (!IsValidNTHeader(iHeader)) + { + Print(EPeError,"Invalid NT header.\n"); + HFile::Close(iFileHandle); + return EFalse; + } + + if (!(IsValidFileHeader((PIMAGE_FILE_HEADER)&iHeader->FileHeader))) + { + Print(EPeError,"Invalid file header.\n"); + HFile::Close(iFileHandle); + return EFalse; + } + +// PIMAGE_NT_HEADERS pNTHeader = iHeader; + PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&iHeader->FileHeader; + PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&iHeader->OptionalHeader; +// PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(iHeader+1); + + iImageSize = pOptionalHeader->SizeOfImage; + iCodeSize = pOptionalHeader->SizeOfCode; + iDataSize = pOptionalHeader->SizeOfInitializedData; + iEntryPoint = pOptionalHeader->AddressOfEntryPoint; + iHeapReservedSize = pOptionalHeader->SizeOfHeapReserve; + iHeapCommittedSize = pOptionalHeader->SizeOfHeapCommit; + iStackReservedSize = 0x2000; + iStackCommittedSize = 0x2000; + iBssSize = pOptionalHeader->SizeOfUninitializedData; + iSectionAlign = pOptionalHeader->SectionAlignment; + if (pFileHeader->Characteristics & IMAGE_FILE_DLL) + iImageIsDll = ETrue; + else + iImageIsDll = EFalse; + iLinkedBase=pOptionalHeader->ImageBase; + iNumSections = pFileHeader->NumberOfSections; + iSizeOfHeaders = pOptionalHeader->SizeOfHeaders; + iExportDataDir=pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + iExportDirSize=pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; +// + iCpu=pFileHeader->Machine; + HMem::Free(iHeader); + iHeader=0; + return ETrue; + } + +void PEFile::Close() +// +// close the pe file +// + { + HFile::Close(iFileHandle); + } + +TInt PEFile::ReadExportDirectory() +// +// Read in just the export directory +// + { + + if (iExportDataDir==0) + return KErrNotFound; + TInt r=ReadSectionHeaders(); + if (r!=KErrNone) + return r; + iSectionData[KConstSection]=ReadSectionData(iSectionHeader[KConstSection]); + iExpDirectoryOffset=iSectionHeader[KConstSection]->VirtualAddress; + iExpDirectory=(PIMAGE_EXPORT_DIRECTORY)(iSectionData[KConstSection]+iExportDataDir-iExpDirectoryOffset); + return KErrNone; + } + +TInt PEFile::ReadSectionHeaders() +// +// Read in the section headers +// + { + + TInt i; + for (i=0; iName); + delete header; + } + } + return KErrNone; + } + +char *PEFile::ReadSectionData(PIMAGE_SECTION_HEADER aPeHeader) +// +// Read in the data for this section +// + { + char *section=NULL; + if (aPeHeader) + { + section=(char *)HMem::Alloc(NULL, aPeHeader->SizeOfRawData); + if (section==NULL) + return NULL; + HFile::Seek(iFileHandle, aPeHeader->PointerToRawData); + HFile::Read(iFileHandle, section, aPeHeader->SizeOfRawData); + } + return section; + } + +TInt PEFile::ReadData() +// +// +// + { + + TInt i; + for (i=0; iName); + } + else + iSectionData[i]=NULL; + } + return KErrNone; + } + +TInt PEFile::NumberOfImports() const +// +// Count the total number of imports for this image +// + { + +// if (gX86imp) +// return gX86num_imp_dlls; + char *importData=iSectionData[KImportSection]; + PIMAGE_SECTION_HEADER importHeader=iSectionHeader[KImportSection]; + if (importData==NULL) + return 0; + TInt n=0; + TUint *src=(TUint *)importData; + while (*src) + { + TUint vaoffset=src[4]; + if (!gLittleEndian) ByteSwap(vaoffset); + TUint offset=vaoffset-importHeader->VirtualAddress; // find the offset into the section of import addr table + TUint *p=(TUint *)(importData+offset); + while (*p++) + n++; + src+=5; // sizeof pe import block/4 + } + return n; + } + +TInt PEFile::NumberOfImportDlls() const +// +// Count the number of referenced Dlls +// + { + + char *importData=iSectionData[KImportSection]; +// PIMAGE_SECTION_HEADER importHeader=iSectionHeader[KImportSection]; + if (importData==NULL) + return 0; + TInt n=0; + while (*(TUint *)importData) + { + n++; + importData+=5*4; // size of pe import block + } + return n; + } + +TInt PEFile::NumberOfExports() const +// +// Count the number of exported symbols +// + { + + if (iExportDataDir==0) + return 0; + return ((PIMAGE_EXPORT_DIRECTORY)iSectionData[KExportSection])->NumberOfFunctions; + } + +TInt PEFile::NumberOfRelocs() +// +// Count the number of reloctions +// + { + + if (iSectionData[KRelocSection]==NULL) + return 0; + char *relocs=iSectionData[KRelocSection]; + TInt n=0; + TInt dudrelocs=0; + TInt blocksize; + TUint page; + TInt size=iSectionHeader[KRelocSection]->Misc.VirtualSize; + + TUint *rrelocs=(TUint *)relocs; + TUint ssize=size; + if (!gLittleEndian) ByteSwap(rrelocs, ssize); + + while (size>0) + { + page=*(TUint *)relocs; + blocksize=*(TInt *)(relocs+4); + if (blocksize==0) + break; + size-=blocksize; + TUint16 *p=(TUint16 *)(relocs+8); + relocs+=blocksize; + blocksize-=8; + while (blocksize>0) + { + TInt rtype=(*p&0xf000)>>12; + if (rtype==IMAGE_REL_BASED_HIGHLOW) + { + TUint va=page+(*p&0xfff); + + // va is the address requiring relocation, so it must be in a section and can't have been offset + TInt section=FindSectionByVa(va+iLinkedBase); + if (section==KTextSection || section==KConstSection || section==KDataSection || section==KCrtSection) + n++; + else + dudrelocs++; + } + else if (rtype!=IMAGE_REL_BASED_ABSOLUTE) // used for padding + Print(EWarning, "Relocation type other than IMAGE_REL_BASED_HIGHLOW has been ignored.\n"); + *p++; + blocksize-=2; + } + } +#if defined(_DEBUG) + if (dudrelocs>0) + Print(EWarning, "Image '%s' has %d relocations pointing at uninitialised data.\n", iFileName, dudrelocs); +#endif + + if (!gLittleEndian) ByteSwap(rrelocs, ssize); + return n; + } + +void PEFile::GetRelocs(TUint *aReloc, TUint *aRelocSection, TInt /*aNumberOfRelocs*/) +// +// load the relocs from the reloc section into relocation and relocsection arrays +// + { + + TUint *relocation=aReloc; + TUint *relocsection=aRelocSection; + char *aRelocData=iSectionData[KRelocSection]; + + TUint16 *relocs=(TUint16 *)aRelocData; + TInt relocsize=iSectionHeader[KRelocSection]->Misc.VirtualSize; + TUint offset; + TUint page; + TInt i=0; + + TUint *rrelocs=(TUint *)aRelocData; + TUint ssize=relocsize; + if (!gLittleEndian) ByteSwap(rrelocs, ssize); + + while (relocsize>0) + { + page=*(TUint *)relocs; + relocs+=2; + TInt size=*(TUint *)relocs; + if (size==0) + break; + relocsize-=size; + relocs+=2; + size-=8; + while (size>0) + { + offset=*relocs++; + TInt type=offset&0xf000; + if (type==0x3000) + { + TUint va=page+(offset&0xfff); + + // va is the address requiring relocation, so it must be in a section and can't have been offset + TInt section=FindSectionByVa(va+iLinkedBase); + if (section==KTextSection || section==KConstSection || section==KDataSection || section==KCrtSection) + { + relocsection[i]=section; + relocation[i++]=va; + } + } + size-=2; + } + } + + if (!gLittleEndian) ByteSwap(rrelocs, ssize); + } + +TInt PEFile::Normalise() +// +// Remove the MSVC anomalies +// + { + + // MSVC puts export data in with .rdata + if (iExportDataDir && iSectionHeader[KExportSection]==NULL) + { + if (!PEFile::VirtualAddressInSection(iExportDataDir+iLinkedBase, iSectionHeader[KConstSection])) + return Print(EError, "Can't find exports in this PE file.\n"); + else + { + iSectionHeader[KExportSection]=new IMAGE_SECTION_HEADER; + iSectionHeader[KExportSection]->VirtualAddress=iExportDataDir; + iSectionHeader[KExportSection]->Misc.VirtualSize=iExportDirSize; + iSectionHeader[KExportSection]->SizeOfRawData=iExportDirSize; + iSectionData[KExportSection]=new char [iExportDirSize]; + if (iSectionData[KExportSection]==NULL) + return Print(EError, "Out of memory.\n"); + memcpy(iSectionData[KExportSection], iSectionData[KConstSection]+iExportDataDir-iSectionHeader[KConstSection]->VirtualAddress, iExportDirSize); + // adjust .rdata so it does not include .edata + iSectionHeader[KConstSection]->Misc.VirtualSize-=iExportDirSize; + iSectionHeader[KConstSection]->SizeOfRawData-=iExportDirSize; + char *c=new char [iSectionHeader[KConstSection]->SizeOfRawData]; + if (c==NULL) + return Print(EError, "Out of memory.\n"); + memcpy(c, iSectionData[KConstSection], iSectionHeader[KConstSection]->SizeOfRawData); + delete iSectionData[KConstSection]; + iSectionData[KConstSection]=c; + } + } + // Stupid compilers generate .idata sections even when there are no imports + if (iSectionHeader[KImportSection]) + { + if (NumberOfImports()==0) + { + delete iSectionHeader[KImportSection]; + delete iSectionData[KImportSection]; + iSectionHeader[KImportSection]=NULL; + iSectionData[KImportSection]=NULL; + } + } + return KErrNone; + } + + +TInt PEFile::HasInitialisedData(PIMAGE_SECTION_HEADER aHeader) +// +// Returns true if the pe file section contains any initialised data +// + { + + if (aHeader==NULL) + return FALSE; + if (aHeader->SizeOfRawData==0) + return FALSE; + return TRUE; + } + +void PEFile::CopySectionData(TAny *source, TAny *dest, TUint32 fileLength, TUint32 memLength) + { + + if (fileLength <= memLength) + { + Print(EScreen," Copying %08x bytes from file at %08x to memory at %08x\n", fileLength, source, dest); + HMem::Copy(dest,source,fileLength); + dest = (TAny *)((TUint32)dest + fileLength); + TUint32 remainingSize = memLength - fileLength; + Print(EScreen," Zeroing remaining %08x bytes at %08x\n", remainingSize, dest); + HMem::Set(dest, 0, remainingSize); + } + else + { + Print(EScreen," Copying %08x bytes from file at %08x to memory at %08x\n", memLength, source, dest); + HMem::Copy(dest,source,memLength); + } + } + + +TBool PEFile::ProcessRelocData(TAny *relocData,TInt dataSize) + { + + TBool hadBadRelocs=EFalse; + PIMAGE_BASE_RELOCATION pRelocData = (PIMAGE_BASE_RELOCATION)((TUint32)relocData); + Print(ELog," Info on .reloc section...\n"); + + while (pRelocData->SizeOfBlock != 0) + { + TUint16 relocType; + TUint32 relocOffset; + TUint32 *relocAddr; + + Print(ELog," Virtual address: %08x size: %08x\n",pRelocData->VirtualAddress, pRelocData->SizeOfBlock); + + TUint numEntries = (pRelocData->SizeOfBlock-sizeof(*pRelocData))/sizeof(TUint16); + TUint16 *pEntry = (TUint16 *)((TUint32)pRelocData+sizeof(*pRelocData)); + + for (TUint i=0; i>12); + // The rest of the field is the offset + relocOffset = (*pEntry & 0x0FFF); + switch (relocType) + { + case 0: // Just padding + pEntry++; + break; + + case 1: + case 2: + case 4: + case 5: + Print(EPeError,".reloc section, relocation type not handled.\n"); + return EFalse; + break; + + case 3: + { + if (pRelocData->VirtualAddress==0) // Defect in .reloc section of arm ekern.exe + { + pEntry++; + break; + } + TUint thisReloc=0; + relocAddr = (TUint32 *)((TUint32)iMemBase + (TUint32)pRelocData->VirtualAddress + relocOffset); + TUint32 reloc = *relocAddr; + + if (IsInCode((TUint32)relocAddr) || IsInData((TUint32)relocAddr)) + { + if (IsInDataReloc(reloc)) + { + if (iImageIsDll) + { + Print(EPeError,"Dlls should have no RAM (data) relocations.\n"); + return(EFalse); + } + thisReloc=reloc+iRamDelta; + } + else + thisReloc=reloc+iRomDelta; + *relocAddr = thisReloc; // this line here to enable breaking on values of thisReloc + } + else + hadBadRelocs=ETrue; + pEntry++; + } + break; + default: + Print(EPeError,".reloc section, invalid relocation type.\n"); + return(EFalse); + } + } + dataSize-=pRelocData->SizeOfBlock; + if(dataSize<=0) + break; + pRelocData = (PIMAGE_BASE_RELOCATION)((TUint32)pRelocData+pRelocData->SizeOfBlock); + } + + if (hadBadRelocs) + Print(EPeError,"File %s has relocation in invalid section\n",iFileName); + return(ETrue); + } + +TBool PEFile::IsInCode(TUint32 anAddr) + { + if ((anAddr>=iCodeSectionAddr) && (anAddr<(iCodeSectionAddr+iCodeSectionSize))) + return(ETrue); + if ((anAddr>=iRDataSectionAddr) && (anAddr<(iRDataSectionAddr+iRDataSectionSize))) + return(ETrue); + if ((anAddr>=iCRTSectionAddr) && (anAddr<(iCRTSectionAddr+iCRTSectionSize))) + return(ETrue); + return(EFalse); + } + +TBool PEFile::IsInData(TUint32 anAddr) + { + if ((anAddr>=iDataSectionAddr) && (anAddr<(iDataSectionAddr+iDataSectionSize))) + return(ETrue); + if ((anAddr>=iBssSectionAddr) && (anAddr<(iBssSectionAddr+iBssSectionSize))) + return(ETrue); + return(EFalse); + } + +TBool PEFile::IsInDataReloc(TUint32 anAddr) + { + if ((anAddr>=iDataSectionLinkedAddr) && (anAddr<(iDataSectionLinkedAddr+iDataSectionSize))) + return(ETrue); + if ((anAddr>=iBssSectionLinkedAddr) && (anAddr<(iBssSectionLinkedAddr+iBssSectionSize))) + return(ETrue); + return(EFalse); + } + + +TBool PEFile::IsValidDOSHeader(PIMAGE_DOS_HEADER aDOSHeader) + { + if (aDOSHeader->e_magic!=IMAGE_DOS_SIGNATURE) + { + Print(EPeError,"File does not have valid DOS MZ signature.\n"); + return EFalse; + } + else + return ETrue; + } + + + +TBool PEFile::IsValidNTHeader(PIMAGE_NT_HEADERS aNTHeader) + { + if (aNTHeader->Signature != IMAGE_NT_SIGNATURE ) + { + Print(EPeError,"File does not have valid NT PE signature.\n"); + return EFalse; + } + else + return ETrue; + } + + +TBool PEFile::IsValidFileHeader(PIMAGE_FILE_HEADER aFileHeader) + { + if ((aFileHeader->Machine != IMAGE_FILE_MACHINE_I386) + && (aFileHeader->Machine != 0xa00) + && (aFileHeader->Machine != 0xb00) + && (aFileHeader->Machine !=IMAGE_FILE_MACHINE_ALPHA)) + { + Print(EPeError,"File is not a valid i386, ARM, M*Core or ALPHA executable.\n"); + return EFalse; + } + + if (aFileHeader->SizeOfOptionalHeader == 0) + { + Print(EPeError,"Optional header is 0 bytes in length - this is probably an object, not an executable\n"); + return EFalse; + } + + if (!(aFileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) + { + Print(EPeError,"File is not a valid executable - probably linker error\n"); + return EFalse; + } + + return ETrue; + } + + +// Get details of the next import to fix-up in the current file. Fill in the name of the dll +//it is imported from, the ordinal number and the address to write back to. +#define ORDINAL_DONE 0x40000000 + +TImportStat PEFile::GetNextImport(TText * &aDllName, TUint16 &aOrdinal, TUint32 * &aThunk) + { + PIMAGE_THUNK_DATA pLookupTable = 0; + TUint32 *pThunk = 0; + TUint32 rawOrdinal = ORDINAL_DONE; + TImportStat res = EImpDone; + PIMAGE_IMPORT_DESCRIPTOR impDesc = iImpDescriptor; + TText *expDllName = 0; + + if (impDesc == 0) + return EImpDone; // This file imports nothing + + while ((rawOrdinal & ORDINAL_DONE) && ((impDesc->TimeDateStamp!=0 ) || (impDesc->Name!=0))) + { + expDllName = (TText *)(iMemBase + impDesc->Name); + pLookupTable = (PIMAGE_THUNK_DATA)(iMemBase + impDesc->Characteristics); + pThunk = (TUint32 *)(iMemBase + (TUint32)impDesc->FirstThunk); + while ((rawOrdinal & ORDINAL_DONE) && (pLookupTable->u1.AddressOfData != 0)) + { + if (pLookupTable->u1.Ordinal & IMAGE_ORDINAL_FLAG ) + rawOrdinal = pLookupTable->u1.Ordinal; + else + { + Print(EPeError,"in file %s\n",iFileName); + Print(EPeError,"It is importing a symbol by name from %s\n",expDllName); + return EImpError; + } + pThunk++; + pLookupTable++; + } + impDesc++; + } + + if (!(rawOrdinal & ORDINAL_DONE)) + { + pThunk--; + pLookupTable--; + res = EImpSuccess; + aDllName = expDllName; + aThunk = pThunk; + aOrdinal = (TUint16)(rawOrdinal & 0xFFFF); + pLookupTable->u1.Ordinal |= ORDINAL_DONE; + } + + return res; + } + +TUint32 PEFile::GetFixUp(const TUint16 aOrdinal) +// +// Look through export directory to find fix-up for given ordinal +// + { + + TUint32 ordBase = iExpDirectory->Base; + TUint32 *functions = (TUint32 *)((TUint32)iExpDirectory->AddressOfFunctions + iMemBase); + TUint32 fixupAddr = functions[aOrdinal-ordBase] + iRomRunAddr; + return fixupAddr; + } + +TUint PEFile::GetNumberOfExportedFunctions() + { + + return iExpDirectory->NumberOfFunctions; + } + + +TUint PEFile::GetOrdinalBase() + { + + return iExpDirectory->Base; + } + + +TBool PEFile::ExportSectionExists() + { + + if (iExpDirectory) + return ETrue; + else + return EFalse; + } + + +TBool PEFile::ImportSectionExists() + { + + if (iImpDescriptor) + return ETrue; + else + return EFalse; + } + + +TUint PEFile::RoundToSectionSize(TUint aSize) +// +// Round to the nearest size in sections +// + { + TUint sAlign = iSectionAlign; + return ((aSize+sAlign-1)/sAlign)*sAlign ; + } + + +void PEFile::DumpPeHeaders() +// +// Print out loads of stuff from the PE header +// + { + TInt err = HFile::Open(iFileName, &iFileHandle); + if (err!=0) + return; + + iHeader = (PIMAGE_NT_HEADERS)(HMem::Alloc(0,iSizeOfHeaders-iStartOfHeaders)); + if (!iHeader) + return; + + if (!HFile::Seek(iFileHandle, iStartOfHeaders)) + return; + + if (!HFile::Read(iFileHandle, iHeader, iSizeOfHeaders-iStartOfHeaders)) + return; + + PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&iHeader->FileHeader; + PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&iHeader->OptionalHeader; + PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(iHeader+1); + + printf("File header\n"); + printf("-----------\n\n"); + TText *szMachine=0; + switch( pFileHeader->Machine ) + { + case 0xa00: + szMachine = (TText *)"ARM"; break; + case 0xb00: + szMachine = (TText *)"M*Core"; break; + case IMAGE_FILE_MACHINE_I386: + szMachine = (TText *)"i386"; break; + case IMAGE_FILE_MACHINE_I860: + szMachine = (TText *)"i860"; break; + case IMAGE_FILE_MACHINE_R3000: + szMachine = (TText *)"R3000"; break; + case IMAGE_FILE_MACHINE_R4000: + szMachine = (TText *)"R4000"; break; + case IMAGE_FILE_MACHINE_ALPHA: + szMachine = (TText *)"Alpha"; break; + case IMAGE_FILE_MACHINE_POWERPC: + szMachine = (TText *)"IBM PowerPC"; break; + default: + printf ("ERROR - machine not specified.\n"); + szMachine = (TText *)"unknown"; + break; + } + + printf("\n Machine: %s (Id=%04x)",szMachine, pFileHeader->Machine); + if ((pFileHeader->Machine != 0xa00) // ARM + && (pFileHeader->Machine != 0xb00)) // M*Core + printf("..........ERROR!!"); + printf("\n Number of sections : %04x",pFileHeader->NumberOfSections); + printf("\n Time date stamp : %08lx",pFileHeader->TimeDateStamp); + if (pFileHeader->TimeDateStamp == 0) + printf("..........ERROR!!"); + printf("\n Pointer to symbol table : %08lx",pFileHeader->PointerToSymbolTable); + printf("\n Number of symbols : %08lx",pFileHeader->NumberOfSymbols); + printf("\n Size of optional header : %08x",pFileHeader->SizeOfOptionalHeader); + if (pFileHeader->SizeOfOptionalHeader == 0) + printf("..........ERROR!!"); + printf("\n Characteristics : %08x\n",pFileHeader->Characteristics); + if (pFileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) + printf("\n Relocations stripped..........ERROR!!"); + if (pFileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) + printf("\n Executable image."); + else + printf("\n Not executable image..........ERROR!!"); + if (pFileHeader->Characteristics & IMAGE_FILE_CHAR_REVERSED_LO) + printf("\n Bytes reversed lo..........ERROR!!"); + if (pFileHeader->Characteristics & IMAGE_FILE_32BIT_MACHINE) + printf("\n 32bit image."); + else + printf("\n Not 32bit image..........ERROR!!"); + if (pFileHeader->Characteristics & IMAGE_FILE_SYSTEM) + printf("\n System file."); + if (pFileHeader->Characteristics & IMAGE_FILE_DLL) + printf("\n Dll file."); + if (pFileHeader->Characteristics & IMAGE_FILE_CHAR_REVERSED_HI) + printf("\n Bytes reversed hi..........ERROR!!"); + + + printf ("\n\n\nOptional Header\n"); + printf ("------------------"); + + printf("\n Magic = %04x", pOptionalHeader->Magic); + printf("\n Major Linker Version = %02x", pOptionalHeader->MajorLinkerVersion); + printf("\n Minor Linker Version = %02x", pOptionalHeader->MinorLinkerVersion); + printf("\n Size of code (bytes) = %08lx", pOptionalHeader->SizeOfCode); + printf("\n Size of initialized data (bytes) = %08lx", pOptionalHeader->SizeOfInitializedData); + printf("\n Size of uninitialized data (bytes) = %08lx", pOptionalHeader->SizeOfUninitializedData); + printf("\n Entrypoint RVA = %08lx", pOptionalHeader->AddressOfEntryPoint); + if (pOptionalHeader->AddressOfEntryPoint & 0x80000000) + printf("..........ERROR!!"); + printf("\n Base of code = %08lx", pOptionalHeader->BaseOfCode); + if (pOptionalHeader->BaseOfCode & 0x80000000) + printf("..........ERROR!!"); + printf("\n Base of data = %08lx", pOptionalHeader->BaseOfData); + if (pOptionalHeader->BaseOfData & 0x80000000) + printf("..........ERROR!!"); + printf("\n Image base = %08lx", pOptionalHeader->ImageBase); + if (pOptionalHeader->ImageBase & 0x80000000) + printf("..........ERROR!!"); + printf("\n Section alignment (bytes) = %08lx",pOptionalHeader->SectionAlignment); + if (pOptionalHeader->SectionAlignment & 0x80000000) + printf("..........ERROR!!\n"); + printf("\n File alignment (bytes) = %08lx", pOptionalHeader->FileAlignment); + if (pOptionalHeader->FileAlignment & 0x80000000) + printf("..........ERROR!!"); + printf("\n Major Operating System Version = %04x", pOptionalHeader->MajorOperatingSystemVersion); + printf("\n Minor Operating System Version = %04x", pOptionalHeader->MinorOperatingSystemVersion); + printf("\n Major Image Version = %04x", pOptionalHeader->MajorImageVersion); + printf("\n Minor Image Version = %04x", pOptionalHeader->MinorImageVersion); + printf("\n Major Subsystem Version = %04x", pOptionalHeader->MajorSubsystemVersion); + printf("\n Minor Subsystem Version = %04x", pOptionalHeader->MinorSubsystemVersion); + + printf("\n Size of image (bytes) = %08lx", pOptionalHeader->SizeOfImage); + if (pOptionalHeader->SizeOfImage & 0x80000000) + printf("..........ERROR!!"); + printf("\n Size of headers (bytes) = %08lx",pOptionalHeader->SizeOfHeaders); + if (pOptionalHeader->SizeOfHeaders & 0x80000000) + printf("..........ERROR!!"); + printf("\n CheckSum = %04lx", pOptionalHeader->CheckSum); + printf("\n Subsystem = %04x", pOptionalHeader->Subsystem); + printf("\n Dll Characteristics = %04x", pOptionalHeader->DllCharacteristics); + printf("\n Size Of Stack Reserve = %04lx", pOptionalHeader->SizeOfStackReserve); + printf("\n Size Of Stack Commit = %04lx", pOptionalHeader->SizeOfStackCommit); + printf("\n Size Of Heap Reserve = %04lx", pOptionalHeader->SizeOfHeapReserve); + printf("\n Size Of Heap Commit = %04lx", pOptionalHeader->SizeOfHeapCommit); + printf("\n Loader Flags = %04lx", pOptionalHeader->LoaderFlags); + printf("\n Number Of Rva and Sizes = %04lx", pOptionalHeader->NumberOfRvaAndSizes); + + printf("\n\n\nSection Headers\n"); + printf("---------------\n\n"); + + for (TUint i=0;iName); + printf("\n Virtual size : %08lx", pSectionHeader->Misc.VirtualSize); + printf("\n RVA of section data : %08lx", pSectionHeader->VirtualAddress); + if (pSectionHeader->VirtualAddress & 0x80000000) + printf("..........ERROR!!"); + printf("\n Size of raw data : %08lx", pSectionHeader->SizeOfRawData); + printf("\n Pointer to raw data : %08lx", pSectionHeader->PointerToRawData); + printf("\n Characteristics: %08lx\n", pSectionHeader->Characteristics); + if (pSectionHeader->Characteristics & IMAGE_SCN_LNK_REMOVE) + printf("\nERROR - Section should have been removed by linker.\n"); + + // read the section in + TUint32 filePos = pSectionHeader->PointerToRawData; + TUint32 fileLength = pSectionHeader->SizeOfRawData; +// TUint32 memLength = pSectionHeader->Misc.VirtualSize; + TAny *sectionFile = HMem::Alloc((TAny *)0, fileLength); // get a buffer + HFile::Seek(iFileHandle, filePos); + HFile::Read(iFileHandle, sectionFile, fileLength); // and read the file into the buffer +// TAny *sectionMem = (TAny *)((TUint32)iMemBase + pSectionHeader->VirtualAddress); + + if (strnicmp((const char *)pSectionHeader->Name, ".text", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + hadText = ETrue; + if (!(pSectionHeader->Characteristics & IMAGE_SCN_CNT_CODE)) + printf("\nERROR - Code section has incorrect characteristics.\n"); + else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE)) + printf("\nERROR - Code section has incorrect characteristics.\n"); + else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ)) + printf("\nERROR - Code section has incorrect characteristics.\n"); + } + else if (strnicmp((const char *)pSectionHeader->Name, ".data", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + if (iImageIsDll) + { + printf ("\nERROR - DLL has data section.\n"); + } + else + { + if (!(pSectionHeader->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)) + printf("\nERROR - data section has incorrect characteristics.\n"); + else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE)) + printf("\nERROR - data section has incorrect characteristics.\n"); + else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ)) + printf("\nERROR - data section has incorrect characteristics.\n"); + } + } + else if (strnicmp((const char *)pSectionHeader->Name, ".rdata", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + } + else if (strnicmp((const char *)pSectionHeader->Name, ".bss", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + if (iImageIsDll) + { + printf ("\nERROR - DLL has bss section.\n"); + } + else + { + if (!(pSectionHeader->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) + printf("\nERROR - BSS section has incorrect characteristics.\n"); + else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE)) + printf("\nERROR - BSS section has incorrect characteristics.\n"); + else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ)) + printf("\nERROR - BSS section has incorrect characteristics.\n"); + } + } + else if (strnicmp((const char *)pSectionHeader->Name, ".reloc", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + hadReloc = ETrue; + } + else if (strnicmp((const char *)pSectionHeader->Name, ".idata", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + } + else if (strnicmp((const char *)pSectionHeader->Name, ".edata", IMAGE_SIZEOF_SHORT_NAME) == 0) + { + iExpDirectory = (PIMAGE_EXPORT_DIRECTORY)(sectionFile); + if (iImageIsDll) + { + printf("\n Ordinal base = %08lx", iExpDirectory->Base); + printf("\n Number of functions = %08lx", iExpDirectory->NumberOfFunctions); + printf("\n Number of names = %08lx", iExpDirectory->NumberOfNames); + printf("\n Export address table RVA = %08lx", (TUint32)iExpDirectory->AddressOfFunctions); + printf("\n Name pointer RVA = %08lx", (TUint32)iExpDirectory->AddressOfNames); + printf("\n Ordinal table RVA = %08lx", (TUint32)iExpDirectory->AddressOfNameOrdinals); + } + else + { + printf("\nERROR - non-DLL with export section."); + } + } + else + { + printf("\nERROR - unexpected section."); + } + + HMem::Free(sectionFile); + return; + } +