epoc32/include/f32image.h
branchSymbian3
changeset 4 837f303aceeb
parent 3 e1b950c65cb4
equal deleted inserted replaced
3:e1b950c65cb4 4:837f303aceeb
     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__