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