bintools/petools/pefile/pe_file.cpp
changeset 600 6d08f4a05d93
equal deleted inserted replaced
599:fa7a3cc6effd 600:6d08f4a05d93
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <string.h>
       
    18 #include <e32std.h>
       
    19 #include <e32std_private.h>
       
    20 #include <e32rom.h>
       
    21 #include "e32image.h"
       
    22 #include "pe_defs.h"
       
    23 #include "pe_file.h"
       
    24 #include "h_utl.h"
       
    25 
       
    26 TBool hadText, hadReloc = EFalse;
       
    27 TUint32 PEFile::iRomMemBase=0;
       
    28 TUint32 PEFile::iRomLinearBase=0;
       
    29 
       
    30 extern char* gX86imp;
       
    31 extern int gX86num_imp_dlls;
       
    32 
       
    33 PEFile::PEFile()
       
    34 	:iMemBase(0),iEntryPoint(0),iImageSize(0),iCodeSize(0),iDataSize(0),
       
    35 	iHeapReservedSize(0),iHeapCommittedSize(0),iStackReservedSize(0),iStackCommittedSize(0),
       
    36 	iBssSize(0),iBssOffset(0),iSectionAlign(0),iExpDirectoryOffset(0),iDataOffset(0),
       
    37 	iImageIsDll(EFalse),
       
    38 	iHeader(0),iExpDirectory(0),iImpDescriptor(0),iFileName(0),iFileHandle(0),
       
    39 	iLinkedBase(0),iStartOfHeaders(0),iSizeOfHeaders(0),iNumSections(0),
       
    40 	iRomRunAddr(0),iRamRunAddr(0),iRomDelta(0),iRamDelta(0),iHadDataSection(EFalse),
       
    41 	iBssSectionLinkedAddr(0),iBssSectionAddr(0),iBssSectionSize(0),
       
    42 	iDataSectionLinkedAddr(0),iDataSectionAddr(0),iDataSectionSize(0),
       
    43 	iCodeSectionAddr(0),iCodeSectionSize(0),
       
    44 	iRDataSectionAddr(0),iRDataSectionSize(0),
       
    45 	iCRTSectionAddr(0),iCRTSectionSize(0),
       
    46 	iExportDataDir(0)
       
    47 //
       
    48 // Constructor
       
    49 //
       
    50 	{
       
    51 
       
    52 	for (TInt i=0; i<KNumberOfSections; i++)
       
    53 		{
       
    54 		iSectionHeader[i]=NULL;
       
    55 		iSectionData[i]=NULL;
       
    56 		}
       
    57 	}
       
    58 
       
    59 
       
    60 PEFile::~PEFile()
       
    61 //
       
    62 // Destructor
       
    63 //
       
    64 	{
       
    65 
       
    66 	delete [] iFileName;
       
    67 	for (TInt i=0; i<KNumberOfSections; i++)
       
    68 		{
       
    69 		delete iSectionHeader[i];
       
    70 		delete iSectionData[i];
       
    71 		}
       
    72 	}
       
    73 
       
    74 
       
    75 TBool PEFile::Init(const char * const aFileName)
       
    76 //
       
    77 // Reads the PE headers to fill in lots of nice instance variables with info about the file
       
    78 //
       
    79  	{
       
    80 
       
    81  	delete [] iFileName;	
       
    82 	iFileName = new char[strlen((const char *)aFileName)+1];
       
    83 	strcpy ((char *)iFileName, (const char *)aFileName);
       
    84 
       
    85 	iHeader = (PIMAGE_NT_HEADERS)(HMem::Alloc(0,sizeof(IMAGE_DOS_HEADER)+sizeof(IMAGE_NT_HEADERS)));
       
    86 	if (!iHeader)
       
    87 		{
       
    88 		Print(EPeError,"Failed to allocate memory for headers.\n");
       
    89 		return EFalse;
       
    90 		}
       
    91 
       
    92 	TInt error = HFile::Open(iFileName, &iFileHandle);
       
    93 	if (error!=0)
       
    94 		return EFalse;
       
    95 
       
    96 	if (!HFile::Read(iFileHandle,iHeader,sizeof(IMAGE_DOS_HEADER)))
       
    97 		{
       
    98 		Print(EPeError,"Unable to read file %s.\n",iFileName);
       
    99 		HFile::Close(iFileHandle);
       
   100 		return EFalse;
       
   101 		}
       
   102 
       
   103 	if (IsValidDOSHeader((PIMAGE_DOS_HEADER)iHeader)) // read in the rest, overwriting the DOS header
       
   104 		iStartOfHeaders = ((PIMAGE_DOS_HEADER)iHeader)->e_lfanew;
       
   105 	else
       
   106 		iStartOfHeaders = 0;
       
   107 
       
   108 	if (!HFile::Seek(iFileHandle, iStartOfHeaders))
       
   109 		{
       
   110 		Print(EPeError,"File %s is not large enough to contain valid headers.\n",iFileName);
       
   111 		HFile::Close(iFileHandle);
       
   112 		return EFalse;
       
   113 		}
       
   114 
       
   115  	if (!HFile::Read(iFileHandle,iHeader,sizeof(IMAGE_NT_HEADERS)))
       
   116 		{
       
   117 		Print(EPeError,"Unable to read NT headers.\n");
       
   118 		HFile::Close(iFileHandle);
       
   119 		return EFalse;
       
   120 		}
       
   121 
       
   122 	if (!IsValidNTHeader(iHeader))
       
   123 		{
       
   124 		Print(EPeError,"Invalid NT header.\n");
       
   125 		HFile::Close(iFileHandle);
       
   126 		return EFalse;
       
   127 		}
       
   128 
       
   129 	if (!(IsValidFileHeader((PIMAGE_FILE_HEADER)&iHeader->FileHeader)))
       
   130 		{
       
   131 		Print(EPeError,"Invalid file header.\n");
       
   132 		HFile::Close(iFileHandle);
       
   133 		return EFalse;
       
   134 		}
       
   135 
       
   136 //	PIMAGE_NT_HEADERS pNTHeader = iHeader;
       
   137 	PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&iHeader->FileHeader;
       
   138 	PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&iHeader->OptionalHeader;
       
   139 //	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(iHeader+1);
       
   140 
       
   141 	iImageSize = pOptionalHeader->SizeOfImage;
       
   142 	iCodeSize = pOptionalHeader->SizeOfCode;
       
   143 	iDataSize = pOptionalHeader->SizeOfInitializedData;
       
   144 	iEntryPoint = pOptionalHeader->AddressOfEntryPoint;
       
   145 	iHeapReservedSize = pOptionalHeader->SizeOfHeapReserve;
       
   146 	iHeapCommittedSize = pOptionalHeader->SizeOfHeapCommit;
       
   147 	iStackReservedSize = 0x2000;
       
   148 	iStackCommittedSize = 0x2000;
       
   149 	iBssSize = pOptionalHeader->SizeOfUninitializedData;
       
   150     iSectionAlign =	pOptionalHeader->SectionAlignment;
       
   151  	if (pFileHeader->Characteristics & IMAGE_FILE_DLL)
       
   152 		iImageIsDll = ETrue;
       
   153 	else
       
   154 		iImageIsDll = EFalse;
       
   155  	iLinkedBase=pOptionalHeader->ImageBase;
       
   156 	iNumSections = pFileHeader->NumberOfSections;
       
   157 	iSizeOfHeaders = pOptionalHeader->SizeOfHeaders;
       
   158 	iExportDataDir=pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
       
   159 	iExportDirSize=pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
       
   160 //
       
   161 	iCpu=pFileHeader->Machine;
       
   162 	HMem::Free(iHeader);
       
   163 	iHeader=0;
       
   164 	return ETrue;
       
   165 	}
       
   166 
       
   167 void PEFile::Close()
       
   168 //
       
   169 // close the pe file
       
   170 //
       
   171 	{
       
   172 	HFile::Close(iFileHandle);
       
   173 	}
       
   174 
       
   175 TInt PEFile::ReadExportDirectory()
       
   176 //
       
   177 // Read in just the export directory
       
   178 //
       
   179 	{
       
   180 
       
   181 	if (iExportDataDir==0)
       
   182 		return KErrNotFound;
       
   183 	TInt r=ReadSectionHeaders();
       
   184 	if (r!=KErrNone)
       
   185 		return r;
       
   186 	iSectionData[KConstSection]=ReadSectionData(iSectionHeader[KConstSection]);
       
   187 	iExpDirectoryOffset=iSectionHeader[KConstSection]->VirtualAddress;
       
   188 	iExpDirectory=(PIMAGE_EXPORT_DIRECTORY)(iSectionData[KConstSection]+iExportDataDir-iExpDirectoryOffset);
       
   189 	return KErrNone;
       
   190 	}
       
   191 
       
   192 TInt PEFile::ReadSectionHeaders()
       
   193 //
       
   194 // Read in the section headers
       
   195 //
       
   196 	{
       
   197 	
       
   198 	TInt i;
       
   199 	for (i=0; i<KNumberOfSections; i++)
       
   200 		iSectionHeader[i]=NULL;
       
   201 	HFile::Seek(iFileHandle, iStartOfHeaders+sizeof(IMAGE_NT_HEADERS));
       
   202 	for (i=0; i<(TInt)iNumSections; i++)
       
   203 		{
       
   204 		PIMAGE_SECTION_HEADER header = new IMAGE_SECTION_HEADER;
       
   205 		if (!HFile::Read(iFileHandle, header, sizeof(IMAGE_SECTION_HEADER)))
       
   206 			return Print(EError, "Cannot read section header.\n");
       
   207 
       
   208 		if (CmpSectionName(header, ".text"))
       
   209 			iSectionHeader[KTextSection]=header;
       
   210 		else if (CmpSectionName(header, ".rdata"))
       
   211 			iSectionHeader[KConstSection]=header;
       
   212 		else if (CmpSectionName(header, ".edata"))
       
   213 			iSectionHeader[KExportSection]=header;
       
   214 		else if (CmpSectionName(header, ".data"))
       
   215 			iSectionHeader[KDataSection]=header;
       
   216 		else if (CmpSectionName(header, ".bss"))
       
   217 			iSectionHeader[KBssSection]=header;
       
   218 		else if (CmpSectionName(header, ".idata"))
       
   219 			iSectionHeader[KImportSection]=header;
       
   220 		else if (CmpSectionName(header, ".reloc"))
       
   221 			iSectionHeader[KRelocSection]=header;
       
   222 		else if (CmpSectionName(header, ".CRT"))
       
   223 			iSectionHeader[KCrtSection]=header;
       
   224 		else if (CmpSectionName(header, ".stab"))
       
   225 			delete header;
       
   226 		else if (CmpSectionName(header, ".stabstr"))
       
   227 			delete header;
       
   228 		else if (CmpSectionName(header,".E32_UID"))
       
   229 			delete header;
       
   230 		else if (CmpSectionName(header,".rsrc"))
       
   231 			delete header;
       
   232 		else
       
   233 			{
       
   234 			Print(EWarning, "Section '%.8s' removed.\n", header->Name);
       
   235 			delete header;
       
   236 			}
       
   237 		}
       
   238 	return KErrNone;
       
   239 	}
       
   240 
       
   241 char *PEFile::ReadSectionData(PIMAGE_SECTION_HEADER aPeHeader)
       
   242 //
       
   243 // Read in the data for this section
       
   244 //
       
   245 	{
       
   246 	char *section=NULL;
       
   247 	if (aPeHeader)
       
   248 		{
       
   249 		section=(char *)HMem::Alloc(NULL, aPeHeader->SizeOfRawData);
       
   250 		if (section==NULL)
       
   251 			return NULL;
       
   252 		HFile::Seek(iFileHandle, aPeHeader->PointerToRawData);
       
   253 		HFile::Read(iFileHandle, section, aPeHeader->SizeOfRawData);
       
   254 		}
       
   255 	return section;
       
   256 	}
       
   257 
       
   258 TInt PEFile::ReadData()
       
   259 //
       
   260 //
       
   261 //
       
   262 	{
       
   263 
       
   264 	TInt i;
       
   265 	for (i=0; i<KNumberOfSections; i++)
       
   266 		{
       
   267 		if (iSectionHeader[i])
       
   268 			{
       
   269 			iSectionData[i]=ReadSectionData(iSectionHeader[i]);
       
   270 			if (iSectionData[i]==NULL)
       
   271 				return Print(EError, "Cannot read %s section data.\n", iSectionHeader[i]->Name);
       
   272 			}
       
   273 		else
       
   274 			iSectionData[i]=NULL;
       
   275 		}
       
   276 	return KErrNone;
       
   277 	}
       
   278 
       
   279 TInt PEFile::NumberOfImports() const
       
   280 //
       
   281 // Count the total number of imports for this image
       
   282 //
       
   283 	{
       
   284 	
       
   285 //	if (gX86imp)
       
   286 //		return gX86num_imp_dlls;
       
   287 	char *importData=iSectionData[KImportSection];
       
   288 	PIMAGE_SECTION_HEADER importHeader=iSectionHeader[KImportSection];
       
   289 	if (importData==NULL)
       
   290 		return 0;
       
   291 	TInt n=0;
       
   292 	TUint *src=(TUint *)importData;
       
   293 	while (*src)
       
   294 		{
       
   295 		TUint vaoffset=src[4];
       
   296 		if (!gLittleEndian) ByteSwap(vaoffset);
       
   297 		TUint offset=vaoffset-importHeader->VirtualAddress; // find the offset into the section of import addr table
       
   298 		TUint *p=(TUint *)(importData+offset);
       
   299 		while (*p++)
       
   300 			n++;
       
   301 		src+=5; // sizeof pe import block/4
       
   302 		}
       
   303 	return n;
       
   304 	}
       
   305 
       
   306 TInt PEFile::NumberOfImportDlls() const
       
   307 //
       
   308 // Count the number of referenced Dlls
       
   309 //
       
   310 	{
       
   311 
       
   312 	char *importData=iSectionData[KImportSection];
       
   313 //	PIMAGE_SECTION_HEADER importHeader=iSectionHeader[KImportSection];
       
   314 	if (importData==NULL)
       
   315 		return 0;
       
   316 	TInt n=0;
       
   317 	while (*(TUint *)importData)
       
   318 		{
       
   319 		n++;
       
   320 		importData+=5*4; // size of pe import block
       
   321 		}
       
   322 	return n;
       
   323 	}
       
   324 
       
   325 TInt PEFile::NumberOfExports() const
       
   326 //
       
   327 // Count the number of exported symbols
       
   328 //
       
   329 	{
       
   330 
       
   331 	if (iExportDataDir==0)
       
   332 		return 0;
       
   333 	return ((PIMAGE_EXPORT_DIRECTORY)iSectionData[KExportSection])->NumberOfFunctions;
       
   334 	}
       
   335 
       
   336 TInt PEFile::NumberOfRelocs()
       
   337 //
       
   338 // Count the number of reloctions
       
   339 //
       
   340 	{
       
   341 
       
   342 	if (iSectionData[KRelocSection]==NULL)
       
   343 		return 0;
       
   344 	char *relocs=iSectionData[KRelocSection];
       
   345 	TInt n=0;
       
   346 	TInt dudrelocs=0;
       
   347 	TInt blocksize;
       
   348 	TUint page;
       
   349 	TInt size=iSectionHeader[KRelocSection]->Misc.VirtualSize;
       
   350 
       
   351 	TUint *rrelocs=(TUint *)relocs;
       
   352 	TUint ssize=size;
       
   353 	if (!gLittleEndian) ByteSwap(rrelocs, ssize);
       
   354 
       
   355 	while (size>0)
       
   356 		{
       
   357 		page=*(TUint *)relocs;
       
   358 		blocksize=*(TInt *)(relocs+4);
       
   359 		if (blocksize==0)
       
   360 			break;
       
   361 		size-=blocksize;
       
   362 		TUint16 *p=(TUint16 *)(relocs+8);
       
   363 		relocs+=blocksize;
       
   364 		blocksize-=8;
       
   365 		while (blocksize>0)
       
   366 			{
       
   367 			TInt rtype=(*p&0xf000)>>12;
       
   368 			if (rtype==IMAGE_REL_BASED_HIGHLOW)
       
   369 				{
       
   370 				TUint va=page+(*p&0xfff);
       
   371 
       
   372 				// va is the address requiring relocation, so it must be in a section and can't have been offset
       
   373 				TInt section=FindSectionByVa(va+iLinkedBase);
       
   374 				if (section==KTextSection || section==KConstSection || section==KDataSection || section==KCrtSection)
       
   375 					n++;
       
   376 				else
       
   377 					dudrelocs++;
       
   378 				}
       
   379 			else if (rtype!=IMAGE_REL_BASED_ABSOLUTE)	// used for padding
       
   380 				Print(EWarning, "Relocation type other than IMAGE_REL_BASED_HIGHLOW has been ignored.\n");
       
   381 			*p++;
       
   382 			blocksize-=2;
       
   383 			}
       
   384 		}
       
   385 #if defined(_DEBUG)
       
   386 	if (dudrelocs>0)
       
   387 		Print(EWarning, "Image '%s' has %d relocations pointing at uninitialised data.\n", iFileName, dudrelocs);
       
   388 #endif
       
   389 
       
   390 	if (!gLittleEndian) ByteSwap(rrelocs, ssize);
       
   391 	return n;
       
   392 	}
       
   393 
       
   394 void PEFile::GetRelocs(TUint *aReloc, TUint *aRelocSection, TInt /*aNumberOfRelocs*/)
       
   395 //
       
   396 // load the relocs from the reloc section into relocation and relocsection arrays
       
   397 //
       
   398 	{
       
   399 
       
   400 	TUint *relocation=aReloc;
       
   401 	TUint *relocsection=aRelocSection;
       
   402 	char *aRelocData=iSectionData[KRelocSection];
       
   403 
       
   404 	TUint16 *relocs=(TUint16 *)aRelocData;
       
   405 	TInt relocsize=iSectionHeader[KRelocSection]->Misc.VirtualSize;
       
   406 	TUint offset;
       
   407 	TUint page;
       
   408 	TInt i=0;
       
   409 
       
   410 	TUint *rrelocs=(TUint *)aRelocData;
       
   411 	TUint ssize=relocsize;
       
   412 	if (!gLittleEndian) ByteSwap(rrelocs, ssize);
       
   413 
       
   414 	while (relocsize>0)
       
   415 		{
       
   416 		page=*(TUint *)relocs;
       
   417 		relocs+=2;
       
   418 		TInt size=*(TUint *)relocs;
       
   419 		if (size==0)
       
   420 			break;
       
   421 		relocsize-=size;
       
   422 		relocs+=2;
       
   423 		size-=8;
       
   424 		while (size>0)
       
   425 			{
       
   426 			offset=*relocs++;
       
   427 			TInt type=offset&0xf000;
       
   428 			if (type==0x3000)
       
   429 				{
       
   430 				TUint va=page+(offset&0xfff);
       
   431 
       
   432 				// va is the address requiring relocation, so it must be in a section and can't have been offset
       
   433 				TInt section=FindSectionByVa(va+iLinkedBase);
       
   434 				if (section==KTextSection || section==KConstSection || section==KDataSection || section==KCrtSection)
       
   435 					{
       
   436 					relocsection[i]=section;
       
   437 					relocation[i++]=va;
       
   438 					}
       
   439 				}
       
   440 			size-=2;
       
   441 			}
       
   442 		}
       
   443 
       
   444 	if (!gLittleEndian) ByteSwap(rrelocs, ssize);
       
   445 	}
       
   446 
       
   447 TInt PEFile::Normalise()
       
   448 //
       
   449 // Remove the MSVC anomalies
       
   450 //
       
   451 	{
       
   452 
       
   453 	// MSVC puts export data in with .rdata
       
   454 	if (iExportDataDir && iSectionHeader[KExportSection]==NULL)
       
   455 		{
       
   456 		if (!PEFile::VirtualAddressInSection(iExportDataDir+iLinkedBase, iSectionHeader[KConstSection]))
       
   457 			return Print(EError, "Can't find exports in this PE file.\n");
       
   458 		else
       
   459 			{
       
   460 			iSectionHeader[KExportSection]=new IMAGE_SECTION_HEADER;
       
   461 			iSectionHeader[KExportSection]->VirtualAddress=iExportDataDir;
       
   462 			iSectionHeader[KExportSection]->Misc.VirtualSize=iExportDirSize;
       
   463 			iSectionHeader[KExportSection]->SizeOfRawData=iExportDirSize;
       
   464 			iSectionData[KExportSection]=new char [iExportDirSize];
       
   465 			if (iSectionData[KExportSection]==NULL)
       
   466 				return Print(EError, "Out of memory.\n");
       
   467 			memcpy(iSectionData[KExportSection], iSectionData[KConstSection]+iExportDataDir-iSectionHeader[KConstSection]->VirtualAddress, iExportDirSize);
       
   468 			// adjust .rdata so it does not include .edata
       
   469 			iSectionHeader[KConstSection]->Misc.VirtualSize-=iExportDirSize;
       
   470 			iSectionHeader[KConstSection]->SizeOfRawData-=iExportDirSize;
       
   471 			char *c=new char [iSectionHeader[KConstSection]->SizeOfRawData];
       
   472 			if (c==NULL)
       
   473 				return Print(EError, "Out of memory.\n");
       
   474 			memcpy(c, iSectionData[KConstSection], iSectionHeader[KConstSection]->SizeOfRawData);
       
   475 			delete iSectionData[KConstSection];
       
   476 			iSectionData[KConstSection]=c;
       
   477 			}
       
   478 		}
       
   479 	// Stupid compilers generate .idata sections even when there are no imports
       
   480 	if (iSectionHeader[KImportSection])
       
   481 		{
       
   482 		if (NumberOfImports()==0)
       
   483 			{
       
   484 			delete iSectionHeader[KImportSection];
       
   485 			delete iSectionData[KImportSection];
       
   486 			iSectionHeader[KImportSection]=NULL;
       
   487 			iSectionData[KImportSection]=NULL;
       
   488 			}
       
   489 		}
       
   490 	return KErrNone;
       
   491 	}
       
   492 
       
   493 
       
   494 TInt PEFile::HasInitialisedData(PIMAGE_SECTION_HEADER aHeader)
       
   495 //
       
   496 // Returns true if the pe file section contains any initialised data
       
   497 //
       
   498 	{
       
   499 
       
   500 	if (aHeader==NULL)
       
   501 		return FALSE;
       
   502 	if (aHeader->SizeOfRawData==0)
       
   503 		return FALSE;
       
   504 	return TRUE;
       
   505 	}
       
   506 
       
   507 void PEFile::CopySectionData(TAny *source, TAny *dest, TUint32 fileLength, TUint32 memLength)
       
   508 	{
       
   509 
       
   510 	if (fileLength <= memLength)
       
   511 		{
       
   512 		Print(EScreen,"   Copying %08x bytes from file at %08x to memory at %08x\n", fileLength, source, dest);
       
   513 		HMem::Copy(dest,source,fileLength);
       
   514 		dest = (TAny *)((TUint32)dest + fileLength);
       
   515 		TUint32 remainingSize = memLength - fileLength;
       
   516 		Print(EScreen,"   Zeroing remaining %08x bytes at %08x\n", remainingSize, dest);
       
   517 		HMem::Set(dest, 0, remainingSize);
       
   518 		}
       
   519 	else
       
   520 		{
       
   521 		Print(EScreen,"   Copying %08x bytes from file at %08x to memory at %08x\n", memLength, source, dest);
       
   522 		HMem::Copy(dest,source,memLength);
       
   523 		}
       
   524 	}		
       
   525 
       
   526 
       
   527 TBool PEFile::ProcessRelocData(TAny *relocData,TInt dataSize)
       
   528 	{
       
   529 
       
   530 	TBool hadBadRelocs=EFalse;
       
   531 	PIMAGE_BASE_RELOCATION pRelocData = (PIMAGE_BASE_RELOCATION)((TUint32)relocData);
       
   532 	Print(ELog,"   Info on .reloc section...\n");
       
   533 
       
   534 	while (pRelocData->SizeOfBlock != 0)
       
   535 		{
       
   536 		TUint16 relocType;
       
   537 		TUint32 relocOffset;
       
   538 		TUint32 *relocAddr;
       
   539 
       
   540 		Print(ELog,"      Virtual address: %08x  size: %08x\n",pRelocData->VirtualAddress, pRelocData->SizeOfBlock);
       
   541 			
       
   542 		TUint numEntries = (pRelocData->SizeOfBlock-sizeof(*pRelocData))/sizeof(TUint16);
       
   543 		TUint16 *pEntry = (TUint16 *)((TUint32)pRelocData+sizeof(*pRelocData));
       
   544 		
       
   545 		for (TUint i=0; i<numEntries; i++)
       
   546 			{
       
   547 			// Extract the top 4 bits of the relocation entry. This is the type
       
   548 			relocType = (TUint16)((*pEntry & 0xF000)>>12);
       
   549 			// The rest of the field is the offset
       
   550 			relocOffset = (*pEntry & 0x0FFF);
       
   551 			switch (relocType)
       
   552 				{
       
   553 				case 0: // Just padding
       
   554 					pEntry++;
       
   555 					break;
       
   556 
       
   557 				case 1:
       
   558 				case 2:
       
   559 				case 4:
       
   560 				case 5:
       
   561 					Print(EPeError,".reloc section, relocation type not handled.\n");
       
   562 					return EFalse;
       
   563 					break;
       
   564 
       
   565 				case 3:
       
   566 					{
       
   567 					if (pRelocData->VirtualAddress==0) // Defect in .reloc section of arm ekern.exe
       
   568 						{
       
   569 						pEntry++;
       
   570 						break;
       
   571 						}
       
   572 					TUint thisReloc=0;
       
   573 					relocAddr = (TUint32 *)((TUint32)iMemBase + (TUint32)pRelocData->VirtualAddress + relocOffset);
       
   574 					TUint32 reloc = *relocAddr;
       
   575 
       
   576 					if (IsInCode((TUint32)relocAddr) || IsInData((TUint32)relocAddr))
       
   577 						{
       
   578 						if (IsInDataReloc(reloc))
       
   579 					   		{
       
   580 							if (iImageIsDll)
       
   581 								{
       
   582 								Print(EPeError,"Dlls should have no RAM (data) relocations.\n");
       
   583 								return(EFalse);
       
   584 								}
       
   585 							thisReloc=reloc+iRamDelta;
       
   586 							}
       
   587 						else
       
   588 							thisReloc=reloc+iRomDelta;
       
   589 						*relocAddr = thisReloc; // this line here to enable breaking on values of thisReloc 
       
   590 						}
       
   591 					else
       
   592 						hadBadRelocs=ETrue;
       
   593 					pEntry++;
       
   594 					}
       
   595 					break;
       
   596 				default:
       
   597 					Print(EPeError,".reloc section, invalid relocation type.\n");
       
   598 					return(EFalse);
       
   599 				}
       
   600 			}
       
   601 		dataSize-=pRelocData->SizeOfBlock;
       
   602 		if(dataSize<=0)
       
   603 			break;
       
   604 		pRelocData = (PIMAGE_BASE_RELOCATION)((TUint32)pRelocData+pRelocData->SizeOfBlock);
       
   605 		}
       
   606 
       
   607 	if (hadBadRelocs)
       
   608 		Print(EPeError,"File %s has relocation in invalid section\n",iFileName);
       
   609 	return(ETrue);
       
   610 	}
       
   611 
       
   612 TBool PEFile::IsInCode(TUint32 anAddr)
       
   613 	{
       
   614 	if ((anAddr>=iCodeSectionAddr) && (anAddr<(iCodeSectionAddr+iCodeSectionSize)))
       
   615 		return(ETrue);
       
   616 	if ((anAddr>=iRDataSectionAddr) && (anAddr<(iRDataSectionAddr+iRDataSectionSize)))
       
   617 		return(ETrue);
       
   618 	if ((anAddr>=iCRTSectionAddr) && (anAddr<(iCRTSectionAddr+iCRTSectionSize)))
       
   619 		return(ETrue);
       
   620 	return(EFalse);
       
   621 	}
       
   622 
       
   623 TBool PEFile::IsInData(TUint32 anAddr)
       
   624 	{
       
   625 	if ((anAddr>=iDataSectionAddr) && (anAddr<(iDataSectionAddr+iDataSectionSize)))
       
   626 		return(ETrue);
       
   627 	if ((anAddr>=iBssSectionAddr) && (anAddr<(iBssSectionAddr+iBssSectionSize)))
       
   628 		return(ETrue);
       
   629 	return(EFalse);
       
   630 	}
       
   631 
       
   632 TBool PEFile::IsInDataReloc(TUint32 anAddr)
       
   633 	{
       
   634 	if ((anAddr>=iDataSectionLinkedAddr) && (anAddr<(iDataSectionLinkedAddr+iDataSectionSize)))
       
   635 		return(ETrue);
       
   636 	if ((anAddr>=iBssSectionLinkedAddr) && (anAddr<(iBssSectionLinkedAddr+iBssSectionSize)))
       
   637 		return(ETrue);
       
   638 	return(EFalse);
       
   639 	}
       
   640  
       
   641 
       
   642 TBool PEFile::IsValidDOSHeader(PIMAGE_DOS_HEADER aDOSHeader)
       
   643  	{
       
   644 	if (aDOSHeader->e_magic!=IMAGE_DOS_SIGNATURE)
       
   645 		{
       
   646 		Print(EPeError,"File does not have valid DOS MZ signature.\n");
       
   647 		return EFalse;
       
   648 		}
       
   649 	else
       
   650 		return ETrue;
       
   651 	}			  
       
   652 
       
   653 
       
   654 
       
   655 TBool PEFile::IsValidNTHeader(PIMAGE_NT_HEADERS aNTHeader)
       
   656  	{
       
   657  	if (aNTHeader->Signature != IMAGE_NT_SIGNATURE )
       
   658 		{
       
   659 		Print(EPeError,"File does not have valid NT PE signature.\n");
       
   660 		return EFalse;
       
   661 		}
       
   662 	else
       
   663 	 return ETrue;
       
   664 	}  
       
   665 
       
   666 
       
   667 TBool PEFile::IsValidFileHeader(PIMAGE_FILE_HEADER aFileHeader)
       
   668  	{
       
   669 	if ((aFileHeader->Machine != IMAGE_FILE_MACHINE_I386) 
       
   670 		&& (aFileHeader->Machine != 0xa00) 
       
   671 		&& (aFileHeader->Machine != 0xb00) 
       
   672 		&& (aFileHeader->Machine !=IMAGE_FILE_MACHINE_ALPHA))
       
   673 		{
       
   674 		Print(EPeError,"File is not a valid i386, ARM, M*Core or ALPHA executable.\n");
       
   675 		return EFalse;
       
   676 		}
       
   677 
       
   678 	if (aFileHeader->SizeOfOptionalHeader == 0)
       
   679 		{
       
   680 		Print(EPeError,"Optional header is 0 bytes in length - this is probably an object, not an executable\n");
       
   681 		return EFalse;
       
   682 		}
       
   683 
       
   684   	if (!(aFileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
       
   685 		{
       
   686 		Print(EPeError,"File is not a valid executable - probably linker error\n");
       
   687 		return EFalse;
       
   688 		}
       
   689 
       
   690 	return ETrue;
       
   691 	}
       
   692 
       
   693 
       
   694 // Get details of the next import to fix-up in the current file. Fill in the name of the dll 
       
   695 //it is imported from, the ordinal number and the address to write back to.
       
   696 #define ORDINAL_DONE 0x40000000
       
   697 
       
   698 TImportStat PEFile::GetNextImport(char * &aDllName, TUint16 &aOrdinal, TUint32 * &aThunk)
       
   699 	{
       
   700 	PIMAGE_THUNK_DATA pLookupTable = 0;
       
   701 	TUint32 *pThunk = 0;
       
   702 	TUint32 rawOrdinal = ORDINAL_DONE;
       
   703 	TImportStat res = EImpDone;
       
   704 	PIMAGE_IMPORT_DESCRIPTOR impDesc = iImpDescriptor;
       
   705 	char *expDllName = 0;
       
   706 
       
   707 	if (impDesc == 0)
       
   708 		return EImpDone; // This file imports nothing
       
   709 		
       
   710  	while ((rawOrdinal & ORDINAL_DONE) && ((impDesc->TimeDateStamp!=0 ) || (impDesc->Name!=0)))
       
   711 		{
       
   712 		expDllName = (char *)(iMemBase + impDesc->Name);
       
   713 		pLookupTable = (PIMAGE_THUNK_DATA)(iMemBase + impDesc->Characteristics);
       
   714  		pThunk = (TUint32 *)(iMemBase + (TUint32)impDesc->FirstThunk);
       
   715 		while ((rawOrdinal & ORDINAL_DONE) && (pLookupTable->u1.AddressOfData != 0))
       
   716  			{
       
   717  			if (pLookupTable->u1.Ordinal & IMAGE_ORDINAL_FLAG )
       
   718 				rawOrdinal = pLookupTable->u1.Ordinal;
       
   719 			else
       
   720 				{
       
   721 				Print(EPeError,"in file %s\n",iFileName);
       
   722 				Print(EPeError,"It is importing a symbol by name from %s\n",expDllName);
       
   723 				return EImpError;
       
   724 				}
       
   725 			pThunk++;
       
   726 			pLookupTable++;
       
   727 			}	
       
   728 		impDesc++;
       
   729 		}
       
   730 
       
   731 	if (!(rawOrdinal & ORDINAL_DONE))
       
   732 		{
       
   733 		pThunk--;
       
   734 		pLookupTable--;
       
   735 		res = EImpSuccess;
       
   736 		aDllName = expDllName;
       
   737 		aThunk = pThunk;
       
   738 		aOrdinal = (TUint16)(rawOrdinal & 0xFFFF);
       
   739 		pLookupTable->u1.Ordinal |= ORDINAL_DONE;
       
   740 		}
       
   741 
       
   742 	return res;
       
   743 	}
       
   744 
       
   745 TUint32 PEFile::GetFixUp(const TUint16 aOrdinal)
       
   746 //
       
   747 // Look through export directory to find fix-up for given ordinal
       
   748 //
       
   749 	{
       
   750 
       
   751 	TUint32 ordBase = iExpDirectory->Base;
       
   752 	TUint32 *functions = (TUint32 *)((TUint32)iExpDirectory->AddressOfFunctions + iMemBase);
       
   753 	TUint32 fixupAddr = functions[aOrdinal-ordBase] + iRomRunAddr;
       
   754 	return fixupAddr;
       
   755 	}
       
   756 
       
   757 TUint PEFile::GetNumberOfExportedFunctions()
       
   758 	{
       
   759 
       
   760 	return iExpDirectory->NumberOfFunctions;
       
   761 	}
       
   762 
       
   763 
       
   764 TUint PEFile::GetOrdinalBase()
       
   765 	{
       
   766 
       
   767 	return iExpDirectory->Base;
       
   768 	}
       
   769 
       
   770 
       
   771 TBool PEFile::ExportSectionExists()
       
   772 	{
       
   773 
       
   774 	if (iExpDirectory)
       
   775 		return ETrue;
       
   776 	else
       
   777 		return EFalse;
       
   778 	}
       
   779 
       
   780 
       
   781 TBool PEFile::ImportSectionExists()
       
   782 	{
       
   783 
       
   784 	if (iImpDescriptor)
       
   785 		return ETrue;
       
   786 	else
       
   787 		return EFalse;
       
   788 	}
       
   789 
       
   790 
       
   791 TUint PEFile::RoundToSectionSize(TUint aSize)
       
   792 //
       
   793 // Round to the nearest size in sections
       
   794 //
       
   795 	{
       
   796 	TUint sAlign = iSectionAlign;
       
   797 	return ((aSize+sAlign-1)/sAlign)*sAlign ;
       
   798 	}
       
   799 
       
   800 
       
   801 void PEFile::DumpPeHeaders()
       
   802 //
       
   803 // Print out loads of stuff from the PE header
       
   804 //
       
   805 	{
       
   806 	TInt err = HFile::Open(iFileName, &iFileHandle);
       
   807 	if (err!=0) 
       
   808 		return;
       
   809 
       
   810 	iHeader = (PIMAGE_NT_HEADERS)(HMem::Alloc(0,iSizeOfHeaders-iStartOfHeaders));
       
   811 	if (!iHeader)
       
   812 		return;
       
   813 
       
   814 	if (!HFile::Seek(iFileHandle, iStartOfHeaders))
       
   815 		return;
       
   816 
       
   817  	if (!HFile::Read(iFileHandle, iHeader, iSizeOfHeaders-iStartOfHeaders))
       
   818 		return;
       
   819 
       
   820 	PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&iHeader->FileHeader;
       
   821 	PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&iHeader->OptionalHeader;
       
   822 	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(iHeader+1);
       
   823 
       
   824  	printf("File header\n");
       
   825  	printf("-----------\n\n");
       
   826 	char *szMachine=0;
       
   827 	switch( pFileHeader->Machine )
       
   828 		{
       
   829 		case 0xa00:
       
   830 			szMachine = (char *)"ARM"; break;
       
   831 		case 0xb00:
       
   832 			szMachine = (char *)"M*Core"; break;
       
   833 		case IMAGE_FILE_MACHINE_I386:
       
   834 			szMachine = (char *)"i386"; break;
       
   835 		case IMAGE_FILE_MACHINE_I860:
       
   836 			szMachine = (char *)"i860"; break;
       
   837 		case IMAGE_FILE_MACHINE_R3000:
       
   838 			szMachine = (char *)"R3000"; break;
       
   839 		case IMAGE_FILE_MACHINE_R4000:
       
   840 			szMachine = (char *)"R4000"; break;
       
   841 		case IMAGE_FILE_MACHINE_ALPHA:
       
   842 			szMachine = (char *)"Alpha"; break;
       
   843 		case IMAGE_FILE_MACHINE_POWERPC:
       
   844 			szMachine = (char *)"IBM PowerPC"; break;
       
   845 		default:
       
   846 			printf ("ERROR - machine not specified.\n");
       
   847 			szMachine = (char *)"unknown";
       
   848 			break;
       
   849 		}
       
   850 
       
   851 	printf("\n    Machine: %s (Id=%04x)",szMachine, pFileHeader->Machine);
       
   852 	if ((pFileHeader->Machine != 0xa00)		// ARM
       
   853 		&& (pFileHeader->Machine != 0xb00))	// M*Core
       
   854 		printf("..........ERROR!!");
       
   855     printf("\n    Number of sections : %04x",pFileHeader->NumberOfSections);
       
   856     printf("\n    Time date stamp : %08lx",pFileHeader->TimeDateStamp);
       
   857 	if (pFileHeader->TimeDateStamp == 0)
       
   858 		printf("..........ERROR!!");
       
   859     printf("\n    Pointer to symbol table : %08lx",pFileHeader->PointerToSymbolTable);
       
   860     printf("\n    Number of symbols : %08lx",pFileHeader->NumberOfSymbols);
       
   861     printf("\n    Size of optional header : %08x",pFileHeader->SizeOfOptionalHeader);
       
   862 	if (pFileHeader->SizeOfOptionalHeader == 0)
       
   863 		printf("..........ERROR!!");
       
   864     printf("\n    Characteristics : %08x\n",pFileHeader->Characteristics);
       
   865 	if (pFileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
       
   866 		printf("\n      Relocations stripped..........ERROR!!");
       
   867 	if (pFileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
       
   868 		printf("\n      Executable image.");
       
   869 	else
       
   870 		printf("\n      Not executable image..........ERROR!!");
       
   871 	if (pFileHeader->Characteristics & IMAGE_FILE_CHAR_REVERSED_LO)
       
   872 		printf("\n      Bytes reversed lo..........ERROR!!");
       
   873  	if (pFileHeader->Characteristics & IMAGE_FILE_32BIT_MACHINE)
       
   874 		printf("\n      32bit image.");
       
   875 	else
       
   876 		printf("\n      Not 32bit image..........ERROR!!");
       
   877  	if (pFileHeader->Characteristics & IMAGE_FILE_SYSTEM)
       
   878 		printf("\n      System file.");
       
   879  	if (pFileHeader->Characteristics & IMAGE_FILE_DLL)
       
   880 		printf("\n      Dll file.");
       
   881 	if (pFileHeader->Characteristics & IMAGE_FILE_CHAR_REVERSED_HI)
       
   882 		printf("\n      Bytes reversed hi..........ERROR!!");
       
   883 
       
   884 
       
   885   	printf ("\n\n\nOptional Header\n");
       
   886   	printf ("------------------");
       
   887 
       
   888 	printf("\n    Magic = %04x", pOptionalHeader->Magic);
       
   889 	printf("\n    Major Linker Version = %02x", pOptionalHeader->MajorLinkerVersion);
       
   890 	printf("\n    Minor Linker Version = %02x", pOptionalHeader->MinorLinkerVersion);
       
   891 	printf("\n    Size of code (bytes) = %08lx", pOptionalHeader->SizeOfCode);
       
   892 	printf("\n    Size of initialized data (bytes) = %08lx", pOptionalHeader->SizeOfInitializedData);
       
   893 	printf("\n    Size of uninitialized data (bytes) = %08lx", pOptionalHeader->SizeOfUninitializedData);
       
   894 	printf("\n    Entrypoint RVA = %08lx", pOptionalHeader->AddressOfEntryPoint);
       
   895 	if (pOptionalHeader->AddressOfEntryPoint & 0x80000000)
       
   896 		printf("..........ERROR!!");
       
   897 	printf("\n    Base of code = %08lx", pOptionalHeader->BaseOfCode);
       
   898 	if (pOptionalHeader->BaseOfCode & 0x80000000)
       
   899 		printf("..........ERROR!!");
       
   900 	printf("\n    Base of data = %08lx", pOptionalHeader->BaseOfData);
       
   901 	if (pOptionalHeader->BaseOfData & 0x80000000)
       
   902 		printf("..........ERROR!!");
       
   903 	printf("\n    Image base = %08lx", pOptionalHeader->ImageBase);
       
   904 	if (pOptionalHeader->ImageBase & 0x80000000)
       
   905 		printf("..........ERROR!!");
       
   906 	printf("\n    Section alignment (bytes) = %08lx",pOptionalHeader->SectionAlignment);
       
   907 	if (pOptionalHeader->SectionAlignment & 0x80000000)
       
   908 		printf("..........ERROR!!\n");
       
   909 	printf("\n    File alignment (bytes) = %08lx", pOptionalHeader->FileAlignment);
       
   910 	if (pOptionalHeader->FileAlignment & 0x80000000)
       
   911 		printf("..........ERROR!!");
       
   912 	printf("\n    Major Operating System Version = %04x", pOptionalHeader->MajorOperatingSystemVersion);
       
   913 	printf("\n    Minor Operating System Version = %04x", pOptionalHeader->MinorOperatingSystemVersion);
       
   914 	printf("\n    Major Image Version = %04x", pOptionalHeader->MajorImageVersion);
       
   915 	printf("\n    Minor Image Version = %04x", pOptionalHeader->MinorImageVersion);
       
   916 	printf("\n    Major Subsystem Version = %04x", pOptionalHeader->MajorSubsystemVersion);
       
   917 	printf("\n    Minor Subsystem Version = %04x", pOptionalHeader->MinorSubsystemVersion);
       
   918 
       
   919 	printf("\n    Size of image (bytes) = %08lx", pOptionalHeader->SizeOfImage);
       
   920 	if (pOptionalHeader->SizeOfImage & 0x80000000)
       
   921 		printf("..........ERROR!!");
       
   922 	printf("\n    Size of headers (bytes) = %08lx",pOptionalHeader->SizeOfHeaders);
       
   923 	if (pOptionalHeader->SizeOfHeaders & 0x80000000)
       
   924 		printf("..........ERROR!!");
       
   925 	printf("\n    CheckSum = %04lx", pOptionalHeader->CheckSum);
       
   926 	printf("\n    Subsystem = %04x", pOptionalHeader->Subsystem);
       
   927 	printf("\n    Dll Characteristics = %04x", pOptionalHeader->DllCharacteristics);
       
   928 	printf("\n    Size Of Stack Reserve = %04lx", pOptionalHeader->SizeOfStackReserve);
       
   929 	printf("\n    Size Of Stack Commit = %04lx", pOptionalHeader->SizeOfStackCommit);
       
   930 	printf("\n    Size Of Heap Reserve = %04lx", pOptionalHeader->SizeOfHeapReserve);
       
   931 	printf("\n    Size Of Heap Commit = %04lx", pOptionalHeader->SizeOfHeapCommit);
       
   932 	printf("\n    Loader Flags = %04lx", pOptionalHeader->LoaderFlags);
       
   933 	printf("\n    Number Of Rva and Sizes = %04lx", pOptionalHeader->NumberOfRvaAndSizes);
       
   934 
       
   935 	printf("\n\n\nSection Headers\n");
       
   936  	printf("---------------\n\n");
       
   937 
       
   938  	for (TUint i=0;i<iNumSections;i++)
       
   939 		{
       
   940 		DumpNextSectionInFile(pSectionHeader);
       
   941 		pSectionHeader++;
       
   942 		}
       
   943 
       
   944 	if (!hadText)
       
   945  		printf("\nERROR - missing code section.");
       
   946 	if (!hadReloc)
       
   947  		printf("\nERROR - missing reloc section. (All images must be relocatable.)");
       
   948 	HMem::Free(iHeader);
       
   949  	}
       
   950 
       
   951 
       
   952 void PEFile::DumpNextSectionInFile(PIMAGE_SECTION_HEADER pSectionHeader)
       
   953 //
       
   954 // Print out loads of stuff from the section header
       
   955 //
       
   956 	{
       
   957 	printf("\nSection name %-8.8s\n",pSectionHeader->Name);
       
   958 	printf("\n    Virtual size            : %08lx", pSectionHeader->Misc.VirtualSize);
       
   959 	printf("\n    RVA of section data     : %08lx", pSectionHeader->VirtualAddress);
       
   960 	if (pSectionHeader->VirtualAddress & 0x80000000)
       
   961 		printf("..........ERROR!!");
       
   962 	printf("\n    Size of raw data        : %08lx", pSectionHeader->SizeOfRawData);
       
   963 	printf("\n    Pointer to raw data     : %08lx", pSectionHeader->PointerToRawData);
       
   964 	printf("\n    Characteristics: %08lx\n", pSectionHeader->Characteristics);
       
   965  	if (pSectionHeader->Characteristics & IMAGE_SCN_LNK_REMOVE)
       
   966 		printf("\nERROR - Section should have been removed by linker.\n");
       
   967 
       
   968 	// read the section in
       
   969 	TUint32 filePos = pSectionHeader->PointerToRawData;
       
   970  	TUint32 fileLength = pSectionHeader->SizeOfRawData;
       
   971 //	TUint32 memLength = pSectionHeader->Misc.VirtualSize;
       
   972 	TAny *sectionFile = HMem::Alloc((TAny *)0, fileLength); // get a buffer
       
   973 	HFile::Seek(iFileHandle, filePos);
       
   974 	HFile::Read(iFileHandle, sectionFile, fileLength); // and read the file into the buffer
       
   975 //	TAny *sectionMem = (TAny *)((TUint32)iMemBase + pSectionHeader->VirtualAddress);
       
   976 
       
   977 	if (strnicmp((const char *)pSectionHeader->Name, ".text", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
   978 		{
       
   979 		hadText = ETrue;
       
   980 		if (!(pSectionHeader->Characteristics & IMAGE_SCN_CNT_CODE))
       
   981 			printf("\nERROR - Code section has incorrect characteristics.\n");
       
   982 		else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE))
       
   983 			printf("\nERROR - Code section has incorrect characteristics.\n");
       
   984 		else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ))
       
   985 			printf("\nERROR - Code section has incorrect characteristics.\n");
       
   986 		}
       
   987 	else if (strnicmp((const char *)pSectionHeader->Name, ".data", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
   988 		{
       
   989 		if (iImageIsDll)
       
   990 			{
       
   991 			printf ("\nERROR - DLL has data section.\n");
       
   992 			}
       
   993 		else
       
   994 			{
       
   995 			if (!(pSectionHeader->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA))
       
   996 				printf("\nERROR - data section has incorrect characteristics.\n");
       
   997 			else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))
       
   998 				printf("\nERROR - data section has incorrect characteristics.\n");
       
   999 			else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ))
       
  1000 				printf("\nERROR - data section has incorrect characteristics.\n");
       
  1001 			}
       
  1002 		}
       
  1003 	else if (strnicmp((const char *)pSectionHeader->Name, ".rdata", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
  1004 		{
       
  1005 		}							
       
  1006 	else if (strnicmp((const char *)pSectionHeader->Name, ".bss", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
  1007 		{
       
  1008 		if (iImageIsDll)
       
  1009 			{
       
  1010 			printf ("\nERROR - DLL has bss section.\n");
       
  1011 			}
       
  1012 		else
       
  1013 			{
       
  1014 			if (!(pSectionHeader->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
       
  1015 				printf("\nERROR - BSS section has incorrect characteristics.\n");
       
  1016 			else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))
       
  1017 				printf("\nERROR - BSS section has incorrect characteristics.\n");
       
  1018 			else if (!(pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ))
       
  1019 				printf("\nERROR - BSS section has incorrect characteristics.\n");
       
  1020 			}
       
  1021 		}
       
  1022  	else if (strnicmp((const char *)pSectionHeader->Name, ".reloc", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
  1023 		{
       
  1024 		hadReloc = ETrue;
       
  1025 		}
       
  1026 	else if (strnicmp((const char *)pSectionHeader->Name, ".idata", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
  1027 		{
       
  1028 		}
       
  1029 	else if (strnicmp((const char *)pSectionHeader->Name, ".edata", IMAGE_SIZEOF_SHORT_NAME) == 0)
       
  1030 		{
       
  1031 		iExpDirectory = (PIMAGE_EXPORT_DIRECTORY)(sectionFile);
       
  1032 		if (iImageIsDll)
       
  1033 			{
       
  1034 			printf("\n      Ordinal base = %08lx", iExpDirectory->Base);
       
  1035 			printf("\n      Number of functions = %08lx", iExpDirectory->NumberOfFunctions);
       
  1036 			printf("\n      Number of names = %08lx", iExpDirectory->NumberOfNames);
       
  1037 			printf("\n      Export address table RVA = %08lx", (TUint32)iExpDirectory->AddressOfFunctions);
       
  1038 			printf("\n      Name pointer RVA = %08lx", (TUint32)iExpDirectory->AddressOfNames);
       
  1039 			printf("\n      Ordinal table RVA = %08lx", (TUint32)iExpDirectory->AddressOfNameOrdinals);
       
  1040 			}
       
  1041 		else
       
  1042 			{
       
  1043 			printf("\nERROR - non-DLL with export section.");
       
  1044 			}
       
  1045  		}
       
  1046 	else
       
  1047 		{
       
  1048 		printf("\nERROR - unexpected section.");
       
  1049 		}
       
  1050 
       
  1051 	HMem::Free(sectionFile);
       
  1052 	return;
       
  1053 	}
       
  1054