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