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