epoc32/include/f32image.h
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     1 // Copyright (c) 1996-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 the License "Symbian Foundation License v1.0" to Symbian Foundation members and "Symbian Foundation End User License Agreement v1.0" to non-members
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.symbianfoundation.org/legal/licencesv10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // f32\inc\f32image.h
    15 // 
    16 //
    17 
    18 
    19 
    20 /**
    21  @file f32\inc\f32image.h
    22  @internalTechnology
    23 */
    24 
    25 #ifndef __F32IMAGE_H__
    26 #define __F32IMAGE_H__
    27 #include <e32cmn.h>
    28 
    29 /**
    30 Value used for E32ImageHeader::iCpuIdentifier.
    31 */
    32 enum TCpu
    33 	{
    34 	ECpuUnknown=0, ECpuX86=0x1000, ECpuArmV4=0x2000, ECpuArmV5=0x2001, ECpuArmV6=0x2002, ECpuMCore=0x4000
    35 	};
    36 
    37 /**
    38 Ordinal value of the first entry in an executables export directory.
    39 @see E32ImageHeader::iExportDirOffset.
    40 */
    41 const TInt KOrdinalBase=1;
    42 
    43 /**
    44 Value used to initialise E32ImageHeader::iHeaderCrc prior to CRC generation.
    45 */
    46 const TUint32 KImageCrcInitialiser	= 0xc90fdaa2u;
    47 
    48 
    49 /**
    50 Byte offset from an executable's entrypoint to the code segment ID storage location.
    51 */
    52 const TUint KCodeSegIdOffset = 12;
    53 
    54 //
    55 // Flags fields for E32ImageHeader::iFlags
    56 //
    57 
    58 const TUint KImageDll				= 0x00000001u;	///< Flag set if executable is a DLL, clear if an EXE.
    59 
    60 const TUint KImageNoCallEntryPoint	= 0x00000002u;	///< Obsolete flag ignored since Symbian OS version 8.1b.
    61 
    62 const TUint KImageFixedAddressExe	= 0x00000004u;	///< Executable's data should not move when running on the moving memory model.
    63 
    64 const TUint KImageABIMask			= 0x00000018u;	///< Bitmask for ABI value.
    65 const TInt	KImageABIShift			= 3;			///< Bit shift count for ABI value.
    66 const TUint	KImageABI_GCC98r2		= 0x00000000u;	///< Obsolete ABI for ARM targets.
    67 const TUint	KImageABI_EABI			= 0x00000008u;	///< ARM EABI
    68 
    69 const TUint KImageEptMask			= 0x000000e0u;	///< Bitmask for Entrypoint value.
    70 const TInt	KImageEptShift			= 5;			///< Bit shift count for Entrypoint value
    71 const TUint KImageEpt_Eka1			= 0x00000000u;	///< @removed Obsolete format not used since Symbian OS version 8.1b.
    72 const TUint KImageEpt_Eka2			= 0x00000020u;	///< Standard entrypoint for ARM executable.
    73 
    74 const TUint KImageUnpaged			= 0x00000100u;	///< Executable image should not be demand paged. Exclusive with KImagePaged,
    75 const TUint KImagePaged				= 0x00000200u;	///< Executable image should be demand paged. Exclusive with KImageUnpaged,
    76 
    77 const TUint KImageNmdExpData		= 0x00000400u;	///< Flag to indicate when named symbol export data present in image
    78 
    79 const TUint KImageDebuggable		= 0x00000800u;	///< Flag to indicate image is debuggable
    80 
    81 const TUint KImageHWFloatMask		= 0x00f00000u;	///< Bitmask for Floating Point type.
    82 const TInt	KImageHWFloatShift		= 20;			///< Bit shift count for Floating Point type.
    83 const TUint	KImageHWFloat_None		= EFpTypeNone << KImageHWFloatShift;	///< No hardware floating point used.
    84 const TUint KImageHWFloat_VFPv2		= EFpTypeVFPv2 << KImageHWFloatShift;	///< ARM VFPv2 floating point used.
    85 
    86 const TUint KImageHdrFmtMask		= 0x0f000000u;	///< Bitmask for header format type.
    87 const TInt	KImageHdrFmtShift		= 24;			///< Bit shift count for header format type.
    88 const TUint KImageHdrFmt_Original	= 0x00000000u;	///< @removed Obsolete format not used since Symbian OS version 8.1b.
    89 const TUint KImageHdrFmt_J			= 0x01000000u;	///< @removed Obsolete format not used since Symbian OS version 8.1b.
    90 const TUint KImageHdrFmt_V			= 0x02000000u;	///< Header has format given by class E32ImageHeaderV.
    91 
    92 const TUint KImageImpFmtMask		= 0xf0000000u;	///< Bitmask for import section format type.
    93 const TInt	KImageImpFmtShift		= 28;			///< Bit shift count for import section format type.
    94 const TUint KImageImpFmt_PE			= 0x00000000u;	///< PE-derived imports.
    95 const TUint KImageImpFmt_ELF		= 0x10000000u;	///< ELF-derived imports.
    96 const TUint KImageImpFmt_PE2		= 0x20000000u;	///< PE-derived imports without redundant copy of import ordinals.
    97 
    98 
    99 
   100 
   101 // forward references...
   102 class RFile;
   103 class E32RelocSection;
   104 
   105 
   106 /**
   107 Structure for an executable image's header.
   108 This is extended by E32ImageHeaderComp and E32ImageHeaderV.
   109 All executables since Symbian OS version 8.1b have an header given by class E32ImageHeaderV.
   110 
   111 Summary of an executable image structure...
   112 
   113 - Header,			0..iCodeOffset-1
   114 - Code part,		iCodeOffset..iCodeOffset+iCodeSize-1
   115 	- .text section,				0 + iTextSize
   116 	- Import Address Table (IAT),	iText + ?
   117 	- Export Directory,				iExportDirOffset + iExportDirCount*4 (in .text Section)
   118 - Rest of data,		iCodeOffset+iCodeSize..EOF
   119 	- .data section,				iDataOffset + iDataSize
   120 	- Import section, 				iImportOffset + sizeof(E32ImportSection)+?
   121 	- Code relocation section,		iCodeRelocOffset + sizeof(E32RelocSection)+?
   122 	- Data relocation section,		iDataRelocOffset + sizeof(E32RelocSection)+?
   123 */
   124 class E32ImageHeader
   125 	{
   126 public:
   127 	static TInt New(E32ImageHeader*& aHdr, RFile& aFile);
   128 	static TInt New(E32ImageHeader*& aHdr, TUint8* aFileData, TUint32 aFileSize);
   129 	TInt ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const;
   130 
   131 	inline static TUint ABIFromFlags(TUint aFlags);
   132 	inline static TUint EptFromFlags(TUint aFlags);
   133 	inline static TUint HdrFmtFromFlags(TUint aFlags);
   134 	inline static TUint ImpFmtFromFlags(TUint aFlags);
   135 
   136 	inline TUint ABI() const;
   137 	inline TUint EntryPointFormat() const;
   138 	inline TUint HeaderFormat() const;
   139 	inline TUint ImportFormat() const;
   140 
   141 	inline TUint32 CompressionType() const;
   142 	inline TUint32 ModuleVersion() const;
   143 	inline TInt TotalSize() const;
   144 	inline TInt UncompressedFileSize() const;
   145 	inline void GetSecurityInfo(SSecurityInfo& aInfo) const;
   146 	inline TCpu CpuIdentifier() const;
   147 	inline TProcessPriority ProcessPriority() const;
   148 	inline TUint32 ExceptionDescriptor() const;
   149 public:
   150 	TUint32	iUid1;				///< KDynamicLibraryUidValue or KExecutableImageUidValue
   151 	TUint32	iUid2;				///< Second UID for executable.
   152 	TUint32	iUid3;				///< Third UID for executable.
   153 	TUint32 iUidChecksum;		///< Checksum for iUid1, iUid2 and iUid3.
   154 	TUint iSignature;			///< Contains 'EPOC'.
   155 	TUint32	iHeaderCrc;			///< CRC-32 of entire header. @see #KImageCrcInitialiser.
   156 	TUint32 iModuleVersion;		///< Version number for this executable (used in link resolution).
   157 	TUint32 iCompressionType;	///< Type of compression used for file contents located after the header. (UID or 0 for none).
   158 	TVersion iToolsVersion;		///< Version number of tools which generated this file.
   159 	TUint32 iTimeLo;			///< Least significant 32 bits of the time of image creation, in milliseconds since since midnight Jan 1st, 2000.
   160 	TUint32 iTimeHi;			///< Most significant 32 bits of the time of image creation, in milliseconds since since midnight Jan 1st, 2000.
   161 	TUint iFlags;				///< Contains various bit-fields of attributes for the image.
   162 	TInt iCodeSize;				///< Size of executables code. Includes import address table, constant data and export directory.
   163 	TInt iDataSize;				///< Size of executables initialised data.
   164 	TInt iHeapSizeMin;			///< Minimum size for an EXEs runtime heap memory.
   165 	TInt iHeapSizeMax;			///< Maximum size for an EXEs runtime heap memory.
   166 	TInt iStackSize;			///< Size for stack required by an EXEs initial thread.
   167 	TInt iBssSize;				///< Size of executables uninitialised data.
   168 	TUint iEntryPoint;			///< Offset into code of the entry point.
   169 	TUint iCodeBase;			///< Virtual address that the executables code is linked for.
   170 	TUint iDataBase;			///< Virtual address that the executables data is linked for.
   171 	TInt iDllRefTableCount;		///< Number of executable against which this executable is linked. The number of files mention in the import section at iImportOffset.
   172 	TUint iExportDirOffset;		///< Byte offset into file of the export directory.
   173 	TInt iExportDirCount;		///< Number of entries in the export directory.
   174 	TInt iTextSize;				///< Size of just the text section, also doubles as the offset for the Import Address Table w.r.t. the code section.
   175 	TUint iCodeOffset;			///< Offset into file of the code section. Also doubles the as header size.
   176 	TUint iDataOffset;			///< Offset into file of the data section.
   177 	TUint iImportOffset;		///< Offset into file of the import section (E32ImportSection).
   178 	TUint iCodeRelocOffset;		///< Offset into file of the code relocation section (E32RelocSection).
   179 	TUint iDataRelocOffset;		///< Offset into file of the data relocation section (E32RelocSection).
   180 	TUint16 iProcessPriority;	///< Initial runtime process priorty for an EXE. (Value from enum TProcessPriority.)
   181 	TUint16 iCpuIdentifier;		///< Value from enum TCpu which indicates the CPU architecture for which the image was created
   182 	};
   183 
   184 
   185 /**
   186 Extends E32ImageHeader.
   187 */
   188 class E32ImageHeaderComp : public E32ImageHeader
   189 	{
   190 public:
   191 	TUint32 iUncompressedSize;	///< Uncompressed size of file data after the header, or zero if file not compressed.
   192 	};
   193 
   194 
   195 /**
   196 Extends E32ImageHeaderComp.
   197 All Symbian OS executable files have a header in this format since OS version 8.1b.
   198 */
   199 class E32ImageHeaderV : public E32ImageHeaderComp
   200 	{
   201 public:
   202 	SSecurityInfo iS;				///< Platform Security information of executable.
   203 	TUint32 iExceptionDescriptor;   ///< Offset in bytes from start of code section to Exception Descriptor, bit 0 set if valid.
   204 	TUint32 iSpare2;				///< Reserved for future use. Set to zero.
   205 	TUint16	iExportDescSize;		///< Size of export description stored in iExportDesc.
   206 	TUint8	iExportDescType;		///< Type of description of holes in export table
   207 	TUint8	iExportDesc[1];			///< Description of holes in export table, size given by iExportDescSize..
   208 public:
   209 	TInt ValidateWholeImage(TAny* aBufferStart, TUint aBufferSize) const;
   210 	TInt ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const;
   211 	TInt ValidateExportDescription() const;
   212 	TInt ValidateRelocations(TAny* aBufferStart, TUint aBufferSize, TUint aRelocationInfoOffset, TUint aRelocatedSectionSize, E32RelocSection*& aRelocationSection) const;
   213 	TInt ValidateImports(TAny* aBufferStart, TUint aBufferSize, TUint& aBiggestImportCount) const;
   214 	TInt ValidateAndAdjust(TUint32 aFileSize);
   215 	};
   216 
   217 // export description type E32ImageHeaderV::iExportDescType
   218 const TUint	KImageHdr_ExpD_NoHoles			=0x00;	///< No holes, all exports present.
   219 const TUint	KImageHdr_ExpD_FullBitmap		=0x01;	///< Full bitmap present at E32ImageHeaderV::iExportDesc
   220 const TUint	KImageHdr_ExpD_SparseBitmap8	=0x02;	///< Sparse bitmap present at E32ImageHeaderV::iExportDesc, granularity 8
   221 const TUint	KImageHdr_ExpD_Xip				=0xff;	///< XIP file
   222 
   223 
   224 //
   225 // inline getters for E32ImageHeader
   226 //
   227 
   228 /**
   229 Extract ABI type from aFlags.
   230 */
   231 inline TUint E32ImageHeader::ABIFromFlags(TUint aFlags)
   232 	{
   233 	return aFlags & KImageABIMask;
   234 	}
   235 
   236 /**
   237 Extract ABI type from #iFlags.
   238 */
   239 inline TUint E32ImageHeader::ABI() const
   240 	{
   241 	return ABIFromFlags(iFlags);
   242 	}
   243 
   244 /**
   245 Extract entrypoint format from aFlags.
   246 */
   247 inline TUint E32ImageHeader::EptFromFlags(TUint aFlags)
   248 	{
   249 	return aFlags & KImageEptMask;
   250 	}
   251 
   252 /**
   253 Extract entrypoint format from #iFlags.
   254 */
   255 inline TUint E32ImageHeader::EntryPointFormat() const
   256 	{
   257 	return EptFromFlags(iFlags);
   258 	}
   259 
   260 /**
   261 Extract header format from aFlags.
   262 */
   263 inline TUint E32ImageHeader::HdrFmtFromFlags(TUint aFlags)
   264 	{
   265 	return aFlags & KImageHdrFmtMask;
   266 	}
   267 
   268 /**
   269 Extract header format from #iFlags.
   270 */
   271 inline TUint E32ImageHeader::HeaderFormat() const
   272 	{
   273 	return HdrFmtFromFlags(iFlags);
   274 	}
   275 
   276 /**
   277 Extract import format from aFlags.
   278 */
   279 inline TUint E32ImageHeader::ImpFmtFromFlags(TUint aFlags)
   280 	{
   281 	return aFlags & KImageImpFmtMask;
   282 	}
   283 
   284 /**
   285 Extract import format from #iFlags.
   286 */
   287 inline TUint E32ImageHeader::ImportFormat() const
   288 	{
   289 	return ImpFmtFromFlags(iFlags);
   290 	}
   291 
   292 /**
   293 Return #iCompressionType.
   294 */
   295 inline TUint32 E32ImageHeader::CompressionType() const
   296 	{
   297 	return iCompressionType;
   298 	}
   299 
   300 /**
   301 Return #iModuleVersion.
   302 */
   303 inline TUint32 E32ImageHeader::ModuleVersion() const
   304 	{
   305 	return iModuleVersion;
   306 	}
   307 
   308 /**
   309 Return size of this header.
   310 */
   311 inline TInt E32ImageHeader::TotalSize() const
   312 	{
   313 	return iCodeOffset;
   314 	}
   315 
   316 /**
   317 Return total size of file after decompression, or -1 if file not compressed.
   318 */
   319 inline TInt E32ImageHeader::UncompressedFileSize() const
   320 	{
   321 	if(iCompressionType==0)
   322 		return -1;			// not compressed
   323 	else
   324 		return ((E32ImageHeaderComp*)this)->iUncompressedSize + TotalSize();
   325 	}
   326 
   327 /**
   328 Return copy of security info, #E32ImageHeaderV::iS.
   329 */
   330 inline void E32ImageHeader::GetSecurityInfo(SSecurityInfo& aInfo) const
   331 	{
   332 	aInfo = ((E32ImageHeaderV*)this)->iS;
   333 	}
   334 
   335 /**
   336 Return #iCpuIdentifier.
   337 */
   338 inline TCpu E32ImageHeader::CpuIdentifier() const
   339 	{
   340 	return (TCpu)iCpuIdentifier;
   341 	}
   342 
   343 /**
   344 Return #iProcessPriority.
   345 */
   346 inline TProcessPriority E32ImageHeader::ProcessPriority() const
   347 	{
   348 	return (TProcessPriority)iProcessPriority;
   349 	}
   350 
   351 /**
   352 Return fffset in bytes from start of code section for the Exception Descriptor.
   353 Or zero if not present.
   354 */
   355 inline TUint32 E32ImageHeader::ExceptionDescriptor() const
   356 	{
   357 	TUint32 xd = ((E32ImageHeaderV*)this)->iExceptionDescriptor;
   358 
   359 	if((xd & 1) && (xd != 0xffffffffu))
   360 		return (xd & ~1);
   361 
   362 	return 0;
   363 	}
   364 
   365 
   366 /**
   367 A block of imports from a single executable.
   368 These structures are conatined in a images Import Section (E32ImportSection).
   369 */
   370 class E32ImportBlock
   371 	{
   372 public:
   373 	inline const E32ImportBlock* NextBlock(TUint aImpFmt) const;
   374 	inline TInt Size(TUint aImpFmt) const;
   375 	inline const TUint* Imports() const;	// import list if present
   376 public:
   377 	TUint32	iOffsetOfDllName;			///< Offset from start of import section for a NUL terminated executable (DLL or EXE) name.
   378 	TInt	iNumberOfImports;			///< Number of imports from this executable.
   379 //	TUint	iImport[iNumberOfImports];	///< For ELF-derived executes: list of code section offsets. For PE, list of imported ordinals. Omitted in PE2 import format
   380 	};
   381 
   382 /**
   383 Return size of this import block.
   384 @param aImpFmt Import format as obtained from image header.
   385 */
   386 inline TInt E32ImportBlock::Size(TUint aImpFmt) const
   387 	{
   388 	TInt r = sizeof(E32ImportBlock);
   389 	if(aImpFmt!=KImageImpFmt_PE2)
   390 		r += iNumberOfImports * sizeof(TUint);
   391 	return r;
   392 	}
   393 
   394 /**
   395 Return pointer to import block which immediately follows this one.
   396 @param aImpFmt Import format as obtained from image header.
   397 */
   398 inline const E32ImportBlock* E32ImportBlock::NextBlock(TUint aImpFmt) const
   399 	{
   400 	const E32ImportBlock* next = this + 1;
   401 	if(aImpFmt!=KImageImpFmt_PE2)
   402 		next = (const E32ImportBlock*)( (TUint8*)next + iNumberOfImports * sizeof(TUint) );
   403 	return next;
   404 	}
   405 
   406 /**
   407 Return address of first import in this block.
   408 For import format KImageImpFmt_ELF, imports are list of code section offsets.
   409 For import format KImageImpFmt_PE, imports are a list of imported ordinals.
   410 For import format KImageImpFmt_PE2, the import list is not present and should not be accessed.
   411 */
   412 inline const TUint* E32ImportBlock::Imports() const
   413 	{
   414 	return (const TUint*)(this + 1);
   415 	}
   416 
   417 
   418 /**
   419 Header for the Import Section in an image, as referenced by E32ImageHeader::iImportOffset.
   420 Immediately following this structure are an array of E32ImportBlock structures.
   421 The number of these is given by E32ImageHeader::iDllRefTableCount.
   422 */
   423 class E32ImportSection
   424 	{
   425 public:
   426 	TInt iSize;		///< Size of this section excluding 'this' structure
   427 //	E32ImportBlock iImportBlock[iDllRefTableCount];
   428 	};
   429 
   430 
   431 /**
   432 A block of relocations for a single page (4kB) of code/data.
   433 
   434 Immediately following this structure are an array of TUint16 values
   435 each representing a single value in the page which is to be relocated.
   436 The lower 12 bits of each entry is the offset, in bytes, from start of this page.
   437 The Upper 4 bits are the relocation type to be applied to the 32-bit value located
   438 at that offset.
   439 	- 1 means relocate relative to code section.
   440 	- 2 means relocate relative to data section.
   441 	- 3 means relocate relative to code or data section; calculate which.
   442 
   443 A value of all zeros (0x0000) is ignored. (Used for padding structure to 4 byte alignment).
   444 */
   445 class E32RelocBlock
   446 	{
   447 public:
   448 	TUint32 iPageOffset;	///< Offset, in bytes, for the page being relocated; relative to the section start. Always a multiple of the page size: 4096 bytes.
   449 	TUint32 iBlockSize;		///< Size, in bytes, for this block structure. Always a multiple of 4.
   450 //	TUint16 iEntry[]
   451 	};
   452 
   453 
   454 /**
   455 Header for a Relocation Section in an image, as referenced by E32ImageHeader::iCodeRelocOffset
   456 or E32ImageHeader::iDataRelocOffset.
   457 
   458 Immediately following this structure are an array of E32RelocBlock structures.
   459 */
   460 class E32RelocSection
   461 	{
   462 public:
   463 	TInt iSize;				///< Size of this relocation section including 'this' structure. Always a multiple of 4.
   464 	TInt iNumberOfRelocs;	///< Number of relocations in this section.
   465 //	E32RelocBlock iRelockBlock[];
   466 	};
   467 
   468 
   469 /**
   470 Structure contained in the export directory in text section of the stdexe/stddll.
   471 It contains information on the names of symbols exported by this stdexe/stddll and
   472 pointers to a E32EpocExpSymInfoHdr structure of any stddlls that are dependencies of
   473 this stdexe/stddll.
   474 
   475 This is not used for emulator images see E32EmulExpSymInfoHdr below.
   476 @see E32EmulExpSymInfoHdr
   477 */
   478 class E32EpocExpSymInfoHdr
   479 	{
   480 public:
   481 	TInt	iSize;						// size of this Table
   482 	TInt16	iFlags; 
   483 	TInt16	iSymCount;					// number of symbols
   484 	TInt	iSymbolTblOffset;			// start of the symbol table - offset from byte 0 of this header
   485 	TInt	iStringTableSz;				// size of the string table
   486 	TInt	iStringTableOffset;			// start of the string table having names of the symbols - offset from byte 0 of this header
   487 	TInt	iDllCount;					// Number of dependent DLLs
   488 	TInt	iDepDllZeroOrdTableOffset;	// offset of the DLL dependency table - offset from byte 0 of this header.
   489 	};
   490 
   491 
   492 /**
   493 Header of the structure contained in the 'KWin32SectionName_NmdExpData' 
   494 segment of emulator stdexe & stddll images.
   495 The segment contains addresses of symbols and NULL 
   496 terminated ASCII strings of the names of static dependencies.
   497 For a stdexe, this segment contains the following:
   498 	a) symbol count (iSymCount) and static dependency count (iDllCount)
   499 	b) iSymCount * symbol addresses
   500 	c) iSymCount * symbol names
   501 	d) iDllCount * dependency names
   502 	
   503 For a stddll, this segment contains the following:
   504 	a) symbol count (iSymCout) is always 0
   505 	b) static dependency count (iDllCount)
   506 	c) iDllCount * dependency names
   507 The symbol addresses and names are not required for a stddll as the Windows API,
   508 GetProcAddress may be used to get the addresses for symbol names.
   509 Since this API works only on DLL handles, we explicitly list them for stdexes.
   510 This is used for emulator images only.
   511 */
   512 class E32EmulExpSymInfoHdr
   513 	{
   514 public:
   515 	TInt32	iSymCount;		// Number of symbols
   516 	TInt32	iDllCount;		// Number of static dependency DLLs
   517 	};
   518 
   519 
   520 
   521 #ifdef INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
   522 
   523 // include code which implements validation functions...
   524 
   525 #ifndef RETURN_FAILURE
   526 #define RETURN_FAILURE(_r) return (_r)
   527 #endif
   528 
   529 #ifndef E32IMAGEHEADER_TRACE
   530 #define E32IMAGEHEADER_TRACE(_t) ((void)0)
   531 #endif
   532 
   533 
   534 #include <e32uid.h>
   535 
   536 
   537 /**
   538 Validate this image header.
   539 
   540 After successful validation the following are true:
   541 	- File size is big enough to contain the entire header.
   542 	- Values #iUidChecksum, #iSignature and #iHeaderCrc are correct.
   543 	- CPU type (#iCpuIdentifier), ABI type (#iFlags&#KImageABIMask) and
   544 	  entrypoint type (#iFlags&#KImageEptMask) are valid for this system.
   545 	- Code part of file as specified by #iCodeOffset and #iCodeSize is fully within the file.
   546 	- Text section size (#iTextSize) is within code part.
   547 	- Entrypoint value (#iEntryPoint) lies within the code part and is aligned correctly.
   548 	- Export directory as specified by #iExportDirCount and #iExportDirOffset is fully
   549 	  within code part and is aligned correctly.
   550 	- Exception description (E32ImageHeaderV::iExceptionDescriptor), if present,
   551 	  lies within the code part.
   552 	- Data part of file as specified by #iDataOffset and #iDataSize is fully within the file.
   553 	  Or data is not present (#iDataOffset==#iDataSize==0).
   554 	- Import section (class E32ImportSection at #iImportOffset) is within 'rest of data'
   555 	  and aligned correctly. Data following the E32ImportSection header is NOT validated or
   556 	  checked if it is fully contained within the file.
   557 	- Code relocations (class E32RelocSection at #iCodeRelocOffset) is within 'rest of data'
   558 	  and aligned correctly. Data following the E32RelocSection header is NOT validated or
   559 	  checked if it is fully contained within the file.
   560 	- Data relocations (class E32RelocSection at #iDataRelocOffset) is within 'rest of data'
   561 	  and aligned correctly. Data following the E32RelocSection header is NOT validated or
   562 	  checked if it is fully contained within the file.
   563 	- Export description is validated by E32ImageHeaderV::ValidateExportDescription().
   564 	- #iUid1 is consistant with #iFlags&#KImageDll. I.e. if flaged as a DLL, #iUid1 is
   565 	  KDynamicLibraryUidValue, otherwise it is KExecutableImageUidValue.
   566 	- Version number (#iModuleVersion) is valid. (Major and minor versions are <32768).
   567 	- File compression type (#iCompressionType) is supported.
   568 	- #iHeapSizeMax>=#iHeapSizeMin
   569 	- All signed values in header are not negative.
   570 
   571 @param		aFileSize			Total size of the file from which this header was created.
   572 @param[out] aUncompressedSize	Returns the total size that the file data would be once decompressed.
   573 
   574 @return KErrNone if no errors detected;
   575 		KErrCorrupt if errors found;
   576 		KErrNotSupported if image format not supported on this platform.
   577 */
   578 TInt E32ImageHeader::ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const
   579 	{
   580 	// check file is big enough for any header...
   581 	if(TUint(aFileSize)<sizeof(*this))
   582 		return KErrCorrupt;
   583 
   584 	TUint hdrfmt = HeaderFormat();
   585 	if(hdrfmt==KImageHdrFmt_V)
   586 		return ((E32ImageHeaderV*)this)->ValidateHeader(aFileSize,aUncompressedSize);
   587 
   588 	return KErrNotSupported; // header format unrecognised
   589 	}
   590 
   591 /**
   592 Validate this image header.
   593 
   594 @param aFileSize				Total size of the file from which this header was created.
   595 @param[out] aUncompressedSize	Returns the total size that the file data would be once decompressed.
   596 
   597 @return KErrNone if no errors detected;
   598 		KErrCorrupt if errors found;
   599 		KErrNotSupported if image format not supported on this platform.
   600 */
   601 TInt E32ImageHeaderV::ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const
   602 	{
   603 	const TUint KMaxDesSize = 0x0fffffffu; // maximum size of descriptor
   604 	if(aFileSize==-1)
   605 		{
   606 		// file size unknown, set to maximum valid so rest of validation works...
   607 		aFileSize = KMaxDesSize;
   608 		}
   609 	if(TUint(aFileSize)>KMaxDesSize)
   610 		RETURN_FAILURE(KErrCorrupt); // file size negative or too big
   611 
   612 	aUncompressedSize = 0;
   613 
   614 	// check file is big enough to contain this header...
   615 	if(aFileSize<(TInt)sizeof(*this))
   616 		RETURN_FAILURE(KErrCorrupt);
   617 
   618 	// check header format version...
   619 	if((iFlags&KImageHdrFmtMask)!=KImageHdrFmt_V)
   620 		RETURN_FAILURE(KErrNotSupported);
   621 
   622 	// check header size...
   623 	TUint headerSize = iCodeOffset;
   624 	if(headerSize>TUint(aFileSize))
   625 		RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because Loader will fail earlier when reading header from file
   626 
   627 	// check iCpuIdentifier...
   628 	TCpu cpu = (TCpu)iCpuIdentifier;
   629 	TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
   630 #if defined(__CPU_ARM)
   631 	if(!isARM)
   632 		RETURN_FAILURE(KErrNotSupported);
   633 #elif defined(__CPU_X86)
   634 	if(cpu!=ECpuX86)
   635 		RETURN_FAILURE(KErrNotSupported);
   636 #endif
   637 	TUint32 pointerAlignMask = isARM ? 3 : 0;	// mask of bits which must be zero for aligned pointers/offsets
   638 
   639 	// check iUid1,iUid2,iUid3,iUidChecksum...
   640 	TUidType uids = *(const TUidType*)&iUid1;
   641 	TCheckedUid chkuid(uids);
   642 	const TUint32* pChkUid = (const TUint32*)&chkuid; // need hackery to verify the UID checksum since everything is private
   643 	if(pChkUid[3]!=iUidChecksum)
   644 		RETURN_FAILURE(KErrCorrupt);
   645 
   646 	// check iSignature...
   647 	if(iSignature!=0x434f5045) // 'EPOC'
   648 		RETURN_FAILURE(KErrCorrupt);
   649 
   650 	// check iHeaderCrc...
   651 	TUint32 supplied_crc = iHeaderCrc;
   652 	((E32ImageHeaderV*)this)->iHeaderCrc = KImageCrcInitialiser;
   653 	TUint32 crc = 0;
   654 	Mem::Crc32(crc, this, headerSize);
   655 	((E32ImageHeaderV*)this)->iHeaderCrc = supplied_crc;
   656 	if(crc!=supplied_crc)
   657 		RETURN_FAILURE(KErrCorrupt);
   658 
   659 	// check iModuleVersion...
   660 	TUint32 mv = iModuleVersion;
   661 	if(mv>=0x80000000u || (mv&0x0000ffffu)>0x8000u)
   662 		RETURN_FAILURE(KErrNotSupported);
   663 
   664 	// check iCompressionType and get uncompressed size...
   665 	TUint compression = iCompressionType;
   666 	TUint uncompressedSize = aFileSize;
   667 	if(compression!=KFormatNotCompressed)
   668 		{
   669 		if(compression!=KUidCompressionDeflate && compression!=KUidCompressionBytePair)
   670 	        RETURN_FAILURE(KErrNotSupported);  // unknown compression method
   671 		uncompressedSize = headerSize+iUncompressedSize;
   672 		if(uncompressedSize<headerSize)
   673 			RETURN_FAILURE(KErrCorrupt); // size overflowed 32 bits
   674 		}
   675 
   676 	// check sizes won't overflow the limit for a descriptor (many Loader uses won't like that).
   677 	if(uncompressedSize>KMaxDesSize)
   678 		RETURN_FAILURE(KErrCorrupt);
   679 
   680 	// check KImageDll in iFlags...
   681 	if(iFlags&KImageDll)
   682 		{
   683 		if(iUid1!=TUint32(KDynamicLibraryUidValue))
   684 			RETURN_FAILURE(KErrNotSupported);
   685 		}
   686 	else if(iUid1!=TUint32(KExecutableImageUidValue))
   687 		RETURN_FAILURE(KErrNotSupported);
   688 
   689 	// check iFlags for ABI and entry point types...
   690 	if(isARM)
   691 		{
   692 		if((iFlags&KImageEptMask)!=KImageEpt_Eka2)
   693 			RETURN_FAILURE(KErrNotSupported);
   694 		#if defined(__EABI__)
   695 			if((iFlags&KImageABIMask)!=KImageABI_EABI)
   696 				RETURN_FAILURE(KErrNotSupported);
   697 		#elif defined(__GCC32__)
   698 			if((iFlags&KImageABIMask)!=KImageABI_GCC98r2)
   699 				RETURN_FAILURE(KErrNotSupported);
   700 		#endif
   701 		}
   702 	else
   703 		{
   704 		if(iFlags&KImageEptMask)
   705 			RETURN_FAILURE(KErrNotSupported); // no special entry point type allowed on non-ARM targets
   706 		if(iFlags&KImageABIMask)
   707 			RETURN_FAILURE(KErrNotSupported);
   708 		}
   709 
   710 	// check iFlags for import format...
   711 	if((iFlags&KImageImpFmtMask)>KImageImpFmt_PE2)
   712 		RETURN_FAILURE(KErrNotSupported);
   713 
   714 	// check iHeapSizeMin...
   715 	if(iHeapSizeMin<0)
   716 		RETURN_FAILURE(KErrCorrupt);
   717 
   718 	// check iHeapSizeMax...
   719 	if(iHeapSizeMax<iHeapSizeMin)
   720 		RETURN_FAILURE(KErrCorrupt);
   721 
   722 	// check iStackSize...
   723 	if(iStackSize<0)
   724 		RETURN_FAILURE(KErrCorrupt);
   725 
   726 	// check iBssSize...
   727 	if(iBssSize<0)
   728 		RETURN_FAILURE(KErrCorrupt);
   729 
   730 	// check iEntryPoint...
   731 	if(iEntryPoint>=TUint(iCodeSize))
   732 		RETURN_FAILURE(KErrCorrupt);
   733 	if(iEntryPoint+KCodeSegIdOffset+sizeof(TUint32)>TUint(iCodeSize))
   734 		RETURN_FAILURE(KErrCorrupt);
   735 	if(iEntryPoint&pointerAlignMask)
   736 		RETURN_FAILURE(KErrCorrupt); // not aligned
   737 
   738 	// check iCodeBase...
   739 	if(iCodeBase&3)
   740 		RETURN_FAILURE(KErrCorrupt); // not aligned
   741 
   742 	// check iDataBase...
   743 	if(iDataBase&3)
   744 		RETURN_FAILURE(KErrCorrupt); // not aligned
   745 
   746 	// check iDllRefTableCount...
   747 	if(iDllRefTableCount<0)
   748 		RETURN_FAILURE(KErrCorrupt);
   749 	if(iDllRefTableCount)
   750 		{
   751 		if(!iImportOffset)
   752 			RETURN_FAILURE(KErrCorrupt); // we link to DLLs but have no import data
   753 		}
   754 
   755 	// check iCodeOffset and iCodeSize specify region in file...
   756 	TUint codeStart = iCodeOffset;
   757 	TUint codeEnd = codeStart+iCodeSize;
   758 	if(codeEnd<codeStart)
   759 		RETURN_FAILURE(KErrCorrupt);
   760 //	if(codeStart<headerSize)
   761 //		RETURN_FAILURE(KErrCorrupt); // can't happen because headerSize is defined as iCodeOffset (codeStart)
   762 	if(codeEnd>uncompressedSize)
   763 		RETURN_FAILURE(KErrCorrupt);
   764 
   765 	// check iDataOffset and iDataSize specify region in file...
   766 	TUint dataStart = iDataOffset;
   767 	TUint dataEnd = dataStart+iDataSize;
   768 	if(dataEnd<dataStart)
   769 		RETURN_FAILURE(KErrCorrupt);
   770 	if(!dataStart)
   771 		{
   772 		// no data...
   773 		if(dataEnd)
   774 			RETURN_FAILURE(KErrCorrupt);
   775 		}
   776 	else
   777 		{
   778 		if(dataStart<codeEnd)
   779 			RETURN_FAILURE(KErrCorrupt);
   780 		if(dataEnd>uncompressedSize)
   781 			RETURN_FAILURE(KErrCorrupt);
   782 		if((dataStart-codeStart)&pointerAlignMask)
   783 			RETURN_FAILURE(KErrCorrupt); // data not aligned with respect to code
   784 		}
   785 
   786 
   787 	// check total data size isn't too bit...
   788 	TUint totalDataSize = iDataSize+iBssSize;
   789 	if(totalDataSize>0x7fff0000)
   790 		RETURN_FAILURE(KErrNoMemory);
   791 
   792 	// check iExportDirOffset and iExportDirCount specify region in code part...
   793 	if(TUint(iExportDirCount)>65535)
   794 		RETURN_FAILURE(KErrCorrupt); // too many exports
   795 	if(iExportDirCount)
   796 		{
   797 		TUint exportsStart = iExportDirOffset;
   798 		TUint exportsEnd = exportsStart+iExportDirCount*sizeof(TUint32);
   799 		if(iFlags&KImageNmdExpData)
   800 			exportsStart -= sizeof(TUint32); // allow for 0th ordinal
   801 		if(exportsEnd<exportsStart)
   802 			RETURN_FAILURE(KErrCorrupt);
   803 		if(exportsStart<codeStart)
   804 			RETURN_FAILURE(KErrCorrupt);
   805 		if(exportsEnd>codeEnd)
   806 			RETURN_FAILURE(KErrCorrupt);
   807 		if((exportsStart-codeStart)&pointerAlignMask)
   808 			RETURN_FAILURE(KErrCorrupt); // not aligned within code section
   809 		}
   810 
   811 	// check iTextSize...
   812 	if(TUint(iTextSize)>TUint(iCodeSize))
   813 		RETURN_FAILURE(KErrCorrupt);
   814 
   815 	// check iImportOffset...
   816 	TUint start = iImportOffset;
   817 	if(start)
   818 		{
   819 		TUint end = start+sizeof(E32ImportSection); // minimum valid size
   820 		if(end<start)
   821 			RETURN_FAILURE(KErrCorrupt);
   822 		if(start<codeEnd)
   823 			RETURN_FAILURE(KErrCorrupt);
   824 		if(end>uncompressedSize)
   825 			RETURN_FAILURE(KErrCorrupt);
   826 		if((start-codeEnd)&pointerAlignMask)
   827 			RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
   828 		}
   829 
   830 	// check iCodeRelocOffset...
   831 	start = iCodeRelocOffset;
   832 	if(start)
   833 		{
   834 		TUint end = start+sizeof(E32RelocSection); // minimum valid size
   835 		if(end<start)
   836 			RETURN_FAILURE(KErrCorrupt);
   837 		if(start<codeEnd)
   838 			RETURN_FAILURE(KErrCorrupt);
   839 		if(end>uncompressedSize)
   840 			RETURN_FAILURE(KErrCorrupt);
   841 		if((start-codeEnd)&pointerAlignMask)
   842 			RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
   843 		}
   844 
   845 	// check iDataRelocOffset...
   846 	start = iDataRelocOffset;
   847 	if(start)
   848 		{
   849 		TUint end = start+sizeof(E32RelocSection); // minimum valid size
   850 		if(end<start)
   851 			RETURN_FAILURE(KErrCorrupt);
   852 		if(start<codeEnd)
   853 			RETURN_FAILURE(KErrCorrupt);
   854 		if(end>uncompressedSize)
   855 			RETURN_FAILURE(KErrCorrupt);
   856 		if((start-codeEnd)&pointerAlignMask)
   857 			RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
   858 		}
   859 
   860 	// check exception descriptor...
   861 	if(iExceptionDescriptor&1) // if valid...
   862 		if(iExceptionDescriptor>=TUint(iCodeSize))
   863 			RETURN_FAILURE(KErrCorrupt);
   864 
   865 	TInt r = ValidateExportDescription();
   866 	if(r!=KErrNone)
   867 		RETURN_FAILURE(r);
   868 
   869 	// done...
   870 	aUncompressedSize = uncompressedSize;
   871 	return KErrNone;
   872 	}
   873 
   874 
   875 /**
   876 Valdate that the export description is valid.
   877 */
   878 TInt E32ImageHeaderV::ValidateExportDescription() const
   879 	{
   880 	TUint headerSize = iCodeOffset;
   881 
   882 	// check export description...
   883 	TUint edSize = iExportDescSize + sizeof(iExportDescSize) + sizeof(iExportDescType);
   884 	edSize = (edSize+3)&~3;
   885 	TUint edEnd = _FOFF(E32ImageHeaderV,iExportDescSize)+edSize;
   886 	if(edEnd!=headerSize)
   887 		RETURN_FAILURE(KErrCorrupt);
   888 
   889 	// size of bitmap of exports...
   890 	TUint bitmapSize = (iExportDirCount+7) >> 3;
   891 
   892 	// check export description bitmap...
   893 	switch(iExportDescType)
   894 		{
   895 	case KImageHdr_ExpD_NoHoles:
   896 		// no bitmap to check...
   897 		E32IMAGEHEADER_TRACE(("ValidateExportDescription NoHoles"));
   898 		return KErrNone;
   899 
   900 	case KImageHdr_ExpD_FullBitmap:
   901 		// full bitmap present...
   902 		E32IMAGEHEADER_TRACE(("ValidateExportDescription FullBitmap"));
   903 		if(bitmapSize!=iExportDescSize)
   904 			RETURN_FAILURE(KErrCorrupt);
   905 		return KErrNone;
   906 
   907 	case KImageHdr_ExpD_SparseBitmap8:
   908 		{
   909 		// sparse bitmap present...
   910 		E32IMAGEHEADER_TRACE(("ValidateExportDescription SparseBitmap8"));
   911 
   912 		// get size of meta-bitmap...
   913 		TUint metaBitmapSize = (bitmapSize+7) >> 3;
   914 		if(metaBitmapSize>iExportDescSize)
   915 			RETURN_FAILURE(KErrCorrupt); // doesn't fit
   916 
   917 		TUint totalSize = metaBitmapSize;
   918 
   919 		// scan meta-bitmap counting extra bytes which should be present...
   920 		const TUint8* metaBitmap = iExportDesc;
   921 		const TUint8* metaBitmapEnd = metaBitmap + metaBitmapSize;
   922 		while(metaBitmap<metaBitmapEnd)
   923 			{
   924 			TUint bits = *metaBitmap++;
   925 			do
   926 				{
   927 				if(bits&1)
   928 					++totalSize; // another byte is present in bitmap
   929 				}
   930 			while(bits>>=1);
   931 			}
   932 
   933 		if(totalSize!=iExportDescSize)
   934 			RETURN_FAILURE(KErrCorrupt);
   935 		}
   936 		return KErrNone;
   937 
   938 	default:
   939 		E32IMAGEHEADER_TRACE(("ValidateExportDescription ?"));
   940 		RETURN_FAILURE(KErrNotSupported);
   941 		}
   942 	}
   943 
   944 
   945 /**
   946 Validate a relocation section.
   947 
   948 @param aBufferStart				Start of buffer containing the data after the code part in the image file.
   949 @param aBufferSize				Size of data at aBufferStart.
   950 @param aRelocationInfoOffset	File offset for relocation section. (#iCodeRelocOffset or #iDataRelocOffset.)
   951 @param aRelocatedSectionSize	Size of section being relocated. (#iCodeSize or #iDataSize.)
   952 @param[out] aRelocationSection	Set to the start of the relocation section in the given buffer.
   953 
   954 @return KErrNone if relocation section is valid, else KErrCorrupt.
   955 */
   956 TInt E32ImageHeaderV::ValidateRelocations(TAny* aBufferStart, TUint aBufferSize, TUint aRelocationInfoOffset, TUint aRelocatedSectionSize, E32RelocSection*& aRelocationSection) const
   957 	{
   958 	aRelocationSection = 0;
   959 	if(!aRelocationInfoOffset)
   960 		return KErrNone; // no relocations
   961 
   962 	// get alignment requirements...
   963 	TCpu cpu = (TCpu)iCpuIdentifier;
   964 	TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
   965 	TUint32 pointerAlignMask = isARM ? 3 : 0;	// mask of bits which must be zero for aligned pointers/offsets
   966 
   967 	// buffer pointer to read relocation from...
   968 	TUint8* bufferStart = (TUint8*)aBufferStart;
   969 	TUint8* bufferEnd = bufferStart+aBufferSize;
   970 	TUint baseOffset = iCodeOffset+iCodeSize; // file offset for aBufferStart
   971 	TUint8* sectionStart = (bufferStart+aRelocationInfoOffset-baseOffset);
   972 	TUint8* p = sectionStart;
   973 
   974 	// read section header (ValidateHeader has alread checked this is OK)...
   975 	E32RelocSection* sectionHeader = (E32RelocSection*)p;
   976 	TUint size = sectionHeader->iSize;
   977 	TUint relocsRemaining = sectionHeader->iNumberOfRelocs;
   978 	E32IMAGEHEADER_TRACE(("E32RelocSection 0x%x %d",size,relocsRemaining));
   979 	if(size&3)
   980 		RETURN_FAILURE(KErrCorrupt); // not multiple of word size
   981 
   982 	// calculate buffer range for block data...
   983 	p = (TUint8*)(sectionHeader+1);  // start of first block
   984 	TUint8* sectionEnd = p+size;
   985 	if(sectionEnd<p)
   986 		RETURN_FAILURE(KErrCorrupt); // math overflow
   987 	if(sectionEnd>bufferEnd)
   988 		RETURN_FAILURE(KErrCorrupt); // overflows buffer
   989 
   990 	// process each block...
   991 	while(p!=sectionEnd)
   992 		{
   993 		E32RelocBlock* block = (E32RelocBlock*)p;
   994 
   995 		// get address of first entry in this block...
   996 		TUint16* entryPtr = (TUint16*)(block+1);
   997 		if((TUint8*)entryPtr<(TUint8*)block || (TUint8*)entryPtr>sectionEnd)
   998 			RETURN_FAILURE(KErrCorrupt);  // overflows relocation section
   999 
  1000 		// read block header...
  1001 		TUint pageOffset = block->iPageOffset;
  1002 		TUint blockSize = block->iBlockSize;
  1003 		E32IMAGEHEADER_TRACE(("E32RelocSection block 0x%x 0x%x",pageOffset,blockSize));
  1004 		if(pageOffset&0xfff)
  1005 			RETURN_FAILURE(KErrCorrupt); // not page aligned
  1006 		if(blockSize<sizeof(E32RelocBlock))
  1007 			RETURN_FAILURE(KErrCorrupt); // blockSize must be at least that of the header just read
  1008 		if(blockSize&3)
  1009 			RETURN_FAILURE(KErrCorrupt); // not word aligned
  1010 
  1011 		// caculate end of entries in this block...
  1012 		TUint16* entryEnd = (TUint16*)(p+blockSize);
  1013 		if(entryEnd<entryPtr)
  1014 			RETURN_FAILURE(KErrCorrupt); // math overflow
  1015 		if(entryEnd>(TUint16*)sectionEnd)
  1016 			RETURN_FAILURE(KErrCorrupt); // overflows relocation section
  1017 
  1018 		// process each entry in this block...
  1019 		while(entryPtr<entryEnd)
  1020 			{
  1021 			TUint entry = *entryPtr++;
  1022 			E32IMAGEHEADER_TRACE(("E32RelocSection entry 0x%04x",entry));
  1023 			if(!entry)
  1024 				continue;
  1025 
  1026 			// check relocation type...
  1027 			TUint entryType = entry&0xf000;
  1028 			if(entryType!=KTextRelocType && entryType!=KDataRelocType && entryType!=KInferredRelocType)
  1029 				RETURN_FAILURE(KErrCorrupt);
  1030 
  1031 			// check relocation is within section being relocated...
  1032 			TUint offset = pageOffset+(entry&0x0fff);
  1033 			if(offset>=aRelocatedSectionSize || offset+4>aRelocatedSectionSize)
  1034 				RETURN_FAILURE(KErrCorrupt); // not within section
  1035 			if(offset&pointerAlignMask)
  1036 				RETURN_FAILURE(KErrCorrupt); // not aligned correctly
  1037 
  1038 			// count each relocation processed...
  1039 			--relocsRemaining;
  1040 			}
  1041 
  1042 		// next sub block...
  1043 		p = (TUint8*)entryEnd;
  1044 		}
  1045 
  1046 	// check number of relocations in section header is correct...
  1047 	E32IMAGEHEADER_TRACE(("E32RelocSection relocsRemaining=%d",relocsRemaining));
  1048 	if(relocsRemaining)
  1049 		RETURN_FAILURE(KErrCorrupt); // incorrect number of entries
  1050 
  1051 	aRelocationSection = sectionHeader;
  1052 	return KErrNone;
  1053 	}
  1054 
  1055 
  1056 /**
  1057 Validate an import section.
  1058 
  1059 For PE format imports, this also verifies that the Import Address Table fits within the code
  1060 part of the image.
  1061 
  1062 @param aBufferStart				Start of buffer containing the data after the code part in the image file.
  1063 @param aBufferSize				Size of data at aBufferStart.
  1064 @param[out] aBiggestImportCount	Largest number of imports the image has from any single dependency.
  1065 
  1066 @return KErrNone if section is valid (or absent), else KErrCorrupt.
  1067 */
  1068 TInt E32ImageHeaderV::ValidateImports(TAny* aBufferStart, TUint aBufferSize, TUint& aBiggestImportCount) const
  1069 	{
  1070 	if(!iImportOffset)
  1071 		{
  1072 		aBiggestImportCount = 0;
  1073 		return KErrNone; // no imports
  1074 		}
  1075 
  1076 	// get alignment requirements...
  1077 	TCpu cpu = (TCpu)iCpuIdentifier;
  1078 	TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
  1079 	TUint32 pointerAlignMask = isARM ? 3 : 0;	// mask of bits which must be zero for aligned pointers/offsets
  1080 
  1081 	// buffer pointer to read imports from...
  1082 	TUint8* bufferStart = (TUint8*)aBufferStart;
  1083 	TUint8* bufferEnd = bufferStart+aBufferSize;
  1084 	TUint baseOffset = iCodeOffset+iCodeSize; // file offset for aBufferStart
  1085 	TUint8* sectionStart = (bufferStart+iImportOffset-baseOffset);
  1086 	TUint8* p = sectionStart;
  1087 
  1088 	// read section header (ValidateHeader has alread checked this is OK)...
  1089 	E32ImportSection* sectionHeader = (E32ImportSection*)p;
  1090 	TUint size = sectionHeader->iSize;
  1091 	E32IMAGEHEADER_TRACE(("E32ImportSection 0x%x",size));
  1092 
  1093 	// check section lies within buffer...
  1094 	p = (TUint8*)(sectionHeader+1);  // start of first import block
  1095 	TUint8* sectionEnd = sectionStart+size;
  1096 	if(sectionEnd<p)
  1097 		RETURN_FAILURE(KErrCorrupt); // math overflow or not big enough to contain header
  1098 	if(sectionEnd>bufferEnd)
  1099 		RETURN_FAILURE(KErrCorrupt); // overflows buffer
  1100 
  1101 	// process each import block...
  1102 	TUint numDeps = iDllRefTableCount;
  1103 	TUint biggestImportCount = 0;
  1104 	TUint totalImports = 0;
  1105 	TUint importFormat = iFlags&KImageImpFmtMask;
  1106 	while(numDeps--)
  1107 		{
  1108 		// get block header...
  1109 		E32ImportBlock* block = (E32ImportBlock*)p;
  1110 		p = (TUint8*)(block+1);
  1111 		if(p<(TUint8*)block || p>sectionEnd)
  1112 			RETURN_FAILURE(KErrCorrupt); // overflows buffer
  1113 
  1114 		E32IMAGEHEADER_TRACE(("E32ImportBlock 0x%x %d",block->iOffsetOfDllName,block->iNumberOfImports));
  1115 
  1116 		// check import dll name is within section...
  1117 		TUint8* name = sectionStart+block->iOffsetOfDllName;
  1118 		if(name<sectionStart || name>=sectionEnd)
  1119 			RETURN_FAILURE(KErrCorrupt); // not within import section
  1120 		while(*name++ && name<sectionEnd)
  1121 			{}
  1122 		if(name[-1])
  1123 			RETURN_FAILURE(KErrCorrupt); // name overflows section
  1124 		E32IMAGEHEADER_TRACE(("E32ImportBlock %s",sectionStart+block->iOffsetOfDllName));
  1125 
  1126 		// process import count...
  1127 		TUint numberOfImports = block->iNumberOfImports;
  1128 		if(numberOfImports>=0x80000000u/sizeof(TUint32))
  1129 			RETURN_FAILURE(KErrCorrupt); // size doesn't fit into a signed integer
  1130 		if(numberOfImports>biggestImportCount)
  1131 			biggestImportCount = numberOfImports;
  1132 		totalImports += numberOfImports;
  1133 
  1134 		// process import data...
  1135 
  1136 		// PE2 doesn't have any more data...
  1137 		if(importFormat==KImageImpFmt_PE2)
  1138 			continue;
  1139 
  1140 		// get import data range...
  1141 		TUint32* imports = (TUint32*)p;
  1142 		TUint32* importsEnd = imports+numberOfImports;
  1143 		if(importsEnd<imports)
  1144 			RETURN_FAILURE(KErrCorrupt); // math overflow. Fuzzer can't trigger this because needs aBufferStart to be in to be >0x80000000
  1145 		if(importsEnd>(TUint32*)sectionEnd)
  1146 			RETURN_FAILURE(KErrCorrupt); // overflows buffer
  1147 
  1148 		// move pointer on to next block...
  1149 		p = (TUint8*)importsEnd;
  1150 
  1151 		if(importFormat==KImageImpFmt_ELF)
  1152 			{
  1153 			// check imports are in code section...
  1154 			TUint32 limit = iCodeSize-sizeof(TUint32);
  1155 			while(imports<importsEnd)
  1156 				{
  1157 				TUint32 i = *imports++;
  1158 				if(i>limit)
  1159 					RETURN_FAILURE(KErrCorrupt);
  1160 				if(i&pointerAlignMask)
  1161 					RETURN_FAILURE(KErrCorrupt); // not word aligned
  1162 				}
  1163 			}
  1164 		else if(importFormat==KImageImpFmt_PE)
  1165 			{
  1166 			// import data is not used, so don't bother checking it
  1167 			}
  1168 		else
  1169 			{
  1170 			RETURN_FAILURE(KErrCorrupt); // bad import format, Fuzzer can't trigger this because import format checked by header validation
  1171 			}
  1172 
  1173 		// next block...
  1174 		p = (TUint8*)block->NextBlock(importFormat);
  1175 		}
  1176 
  1177 	// done processing imports; for PE derived files now check import address table (IAT)...
  1178 	if(importFormat==KImageImpFmt_PE || importFormat==KImageImpFmt_PE2)
  1179 		{
  1180 		if(totalImports>=0x80000000u/sizeof(TUint32))
  1181 			RETURN_FAILURE(KErrCorrupt); // size doesn't fit into a signed integer
  1182 		TUint importAddressTable = iTextSize; // offset for IAT
  1183 		if(importAddressTable&pointerAlignMask)
  1184 			RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because PE imports are for X86 which doesn't have alignment restrictions
  1185 		TUint importAddressTableEnd = importAddressTable+sizeof(TUint32)*totalImports;
  1186 		if(importAddressTableEnd<importAddressTable || importAddressTableEnd>TUint(iCodeSize))
  1187 			RETURN_FAILURE(KErrCorrupt); // import address table overflows code part of file
  1188 		E32IMAGEHEADER_TRACE(("E32ImportSection IAT offsets 0x%x..0x%x",importAddressTable,importAddressTableEnd));
  1189 		}
  1190 
  1191 	aBiggestImportCount = biggestImportCount;
  1192 	return KErrNone;
  1193 	}
  1194 
  1195 
  1196 
  1197 
  1198 /**
  1199 Validate a whole executable image.
  1200 
  1201 This runs all of the other validation methods in turn.
  1202 
  1203 @param aBufferStart	Start of buffer containing the data after the header part of an image file.
  1204 @param aBufferSize	Size of data at aBufferStart.
  1205 
  1206 @return KErrNone if image is valid, else KErrCorrupt or KErrNotSupported.
  1207 */
  1208 TInt E32ImageHeaderV::ValidateWholeImage(TAny* aBufferStart, TUint aBufferSize) const
  1209 	{
  1210 	TUint32 dummyUncompressedSize;
  1211 	TInt r = ValidateHeader(TotalSize()+aBufferSize,dummyUncompressedSize);
  1212 	if(r!=KErrNone)
  1213 		return r;
  1214 
  1215 	TInt endOfCodeOffset = iCodeSize;
  1216 	void* restOfFileData = ((TUint8*)aBufferStart)+endOfCodeOffset;
  1217 	TInt restOfFileSize = aBufferSize-endOfCodeOffset;
  1218 
  1219 	E32RelocSection* dummy;
  1220 	r = ValidateRelocations(restOfFileData,restOfFileSize,iCodeRelocOffset,iCodeSize,dummy);
  1221 	if(r!=KErrNone)
  1222 		return r;
  1223 	r = ValidateRelocations(restOfFileData,restOfFileSize,iDataRelocOffset,iDataSize,dummy);
  1224 	if(r!=KErrNone)
  1225 		return r;
  1226 
  1227 	TUint biggestImportCount; 
  1228 	r = ValidateImports(restOfFileData,restOfFileSize,biggestImportCount);
  1229 	if(r!=KErrNone)
  1230 		return r;
  1231 
  1232 	return r;
  1233 	}
  1234 
  1235 
  1236 #endif	// INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
  1237 
  1238 
  1239 #endif	// __F32IMAGE_H__