Update contrib.
1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
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.
22 @file f32\inc\f32image.h
26 #ifndef __F32IMAGE_H__
27 #define __F32IMAGE_H__
30 #include <e32ldr_private.h>
33 Value used for E32ImageHeader::iCpuIdentifier.
37 ECpuUnknown=0, ECpuX86=0x1000, ECpuArmV4=0x2000, ECpuArmV5=0x2001, ECpuArmV6=0x2002, ECpuMCore=0x4000
41 Ordinal value of the first entry in an executables export directory.
42 @see E32ImageHeader::iExportDirOffset.
44 const TInt KOrdinalBase=1;
47 Value used to initialise E32ImageHeader::iHeaderCrc prior to CRC generation.
49 const TUint32 KImageCrcInitialiser = 0xc90fdaa2u;
53 Byte offset from an executable's entrypoint to the code segment ID storage location.
55 const TUint KCodeSegIdOffset = 12;
58 // Flags fields for E32ImageHeader::iFlags
61 const TUint KImageDll = 0x00000001u; ///< Flag set if executable is a DLL, clear if an EXE.
63 const TUint KImageNoCallEntryPoint = 0x00000002u; ///< Obsolete flag ignored since Symbian OS version 8.1b.
65 const TUint KImageFixedAddressExe = 0x00000004u; ///< Executable's data should not move when running on the moving memory model.
67 const TUint KImageABIMask = 0x00000018u; ///< Bitmask for ABI value.
68 const TInt KImageABIShift = 3; ///< Bit shift count for ABI value.
69 const TUint KImageABI_GCC98r2 = 0x00000000u; ///< Obsolete ABI for ARM targets.
70 const TUint KImageABI_EABI = 0x00000008u; ///< ARM EABI
72 const TUint KImageEptMask = 0x000000e0u; ///< Bitmask for Entrypoint value.
73 const TInt KImageEptShift = 5; ///< Bit shift count for Entrypoint value
74 const TUint KImageEpt_Eka1 = 0x00000000u; ///< @removed Obsolete format not used since Symbian OS version 8.1b.
75 const TUint KImageEpt_Eka2 = 0x00000020u; ///< Standard entrypoint for ARM executable.
77 const TUint KImageCodeUnpaged = 0x00000100u; ///< Executable image should not be demand paged. Exclusive with KImageCodePaged,
78 const TUint KImageCodePaged = 0x00000200u; ///< Executable image should be demand paged. Exclusive with KImageCodeUnpaged,
80 const TUint KImageNmdExpData = 0x00000400u; ///< Flag to indicate when named symbol export data present in image
82 const TUint KImageDebuggable = 0x00000800u; ///< Flag to indicate image is debuggable
84 const TUint KImageDataUnpaged = 0x00001000u; ///< Flag to indicate the image should not be data paged. Exclusive with KImageDataPaged.
85 const TUint KImageDataPaged = 0x00002000u; ///< Flag to indicate the image should be data paged. Exclusive with KImageDataUnpaged.
86 const TUint KImageDataPagingMask = KImageDataUnpaged | KImageDataPaged; ///< Mask for data paging flags.
88 const TUint KImageSMPSafe = 0x00004000u; ///< Flag to indicate image is SMP safe
90 const TUint KImageHWFloatMask = 0x00f00000u; ///< Bitmask for Floating Point type.
91 const TInt KImageHWFloatShift = 20; ///< Bit shift count for Floating Point type.
92 const TUint KImageHWFloat_None = EFpTypeNone << KImageHWFloatShift; ///< No hardware floating point used.
93 const TUint KImageHWFloat_VFPv2 = EFpTypeVFPv2 << KImageHWFloatShift; ///< ARM VFPv2 floating point used.
94 const TUint KImageHWFloat_VFPv3 = EFpTypeVFPv3 << KImageHWFloatShift; ///< ARM VFPv3 floating point used. This includes Advanced SIMD (NEON).
95 const TUint KImageHWFloat_VFPv3D16 = EFpTypeVFPv3D16 << KImageHWFloatShift; ///< ARM VFPv3-D16 floating point used. This does not include Advanced SIMD (NEON).
97 const TUint KImageHdrFmtMask = 0x0f000000u; ///< Bitmask for header format type.
98 const TInt KImageHdrFmtShift = 24; ///< Bit shift count for header format type.
99 const TUint KImageHdrFmt_Original = 0x00000000u; ///< @removed Obsolete format not used since Symbian OS version 8.1b.
100 const TUint KImageHdrFmt_J = 0x01000000u; ///< @removed Obsolete format not used since Symbian OS version 8.1b.
101 const TUint KImageHdrFmt_V = 0x02000000u; ///< Header has format given by class E32ImageHeaderV.
103 const TUint KImageImpFmtMask = 0xf0000000u; ///< Bitmask for import section format type.
104 const TInt KImageImpFmtShift = 28; ///< Bit shift count for import section format type.
105 const TUint KImageImpFmt_PE = 0x00000000u; ///< PE-derived imports.
106 const TUint KImageImpFmt_ELF = 0x10000000u; ///< ELF-derived imports.
107 const TUint KImageImpFmt_PE2 = 0x20000000u; ///< PE-derived imports without redundant copy of import ordinals.
112 // forward references...
114 class E32RelocSection;
118 Structure for an executable image's header.
119 This is extended by E32ImageHeaderComp and E32ImageHeaderV.
120 All executables since Symbian OS version 8.1b have an header given by class E32ImageHeaderV.
122 Summary of an executable image structure...
124 - Header, 0..iCodeOffset-1
125 - Code part, iCodeOffset..iCodeOffset+iCodeSize-1
126 - .text section, 0 + iTextSize
127 - Import Address Table (IAT), iText + ?
128 - Export Directory, iExportDirOffset + iExportDirCount*4 (in .text Section)
129 - Rest of data, iCodeOffset+iCodeSize..EOF
130 - .data section, iDataOffset + iDataSize
131 - Import section, iImportOffset + sizeof(E32ImportSection)+?
132 - Code relocation section, iCodeRelocOffset + sizeof(E32RelocSection)+?
133 - Data relocation section, iDataRelocOffset + sizeof(E32RelocSection)+?
138 static TInt New(E32ImageHeader*& aHdr, RFile& aFile);
139 static TInt New(E32ImageHeader*& aHdr, TUint8* aFileData, TUint32 aFileSize);
140 TInt ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const;
142 inline static TUint ABIFromFlags(TUint aFlags);
143 inline static TUint EptFromFlags(TUint aFlags);
144 inline static TUint HdrFmtFromFlags(TUint aFlags);
145 inline static TUint ImpFmtFromFlags(TUint aFlags);
147 inline TUint ABI() const;
148 inline TUint EntryPointFormat() const;
149 inline TUint HeaderFormat() const;
150 inline TUint ImportFormat() const;
152 inline TUint32 CompressionType() const;
153 inline TUint32 ModuleVersion() const;
154 inline TInt TotalSize() const;
155 inline TInt UncompressedFileSize() const;
156 inline void GetSecurityInfo(SSecurityInfo& aInfo) const;
157 inline TCpu CpuIdentifier() const;
158 inline TProcessPriority ProcessPriority() const;
159 inline TUint32 ExceptionDescriptor() const;
161 TUint32 iUid1; ///< KDynamicLibraryUidValue or KExecutableImageUidValue
162 TUint32 iUid2; ///< Second UID for executable.
163 TUint32 iUid3; ///< Third UID for executable.
164 TUint32 iUidChecksum; ///< Checksum for iUid1, iUid2 and iUid3.
165 TUint iSignature; ///< Contains 'EPOC'.
166 TUint32 iHeaderCrc; ///< CRC-32 of entire header. @see #KImageCrcInitialiser.
167 TUint32 iModuleVersion; ///< Version number for this executable (used in link resolution).
168 TUint32 iCompressionType; ///< Type of compression used for file contents located after the header. (UID or 0 for none).
169 TVersion iToolsVersion; ///< Version number of tools which generated this file.
170 TUint32 iTimeLo; ///< Least significant 32 bits of the time of image creation, in milliseconds since since midnight Jan 1st, 2000.
171 TUint32 iTimeHi; ///< Most significant 32 bits of the time of image creation, in milliseconds since since midnight Jan 1st, 2000.
172 TUint iFlags; ///< Contains various bit-fields of attributes for the image.
173 TInt iCodeSize; ///< Size of executables code. Includes import address table, constant data and export directory.
174 TInt iDataSize; ///< Size of executables initialised data.
175 TInt iHeapSizeMin; ///< Minimum size for an EXEs runtime heap memory.
176 TInt iHeapSizeMax; ///< Maximum size for an EXEs runtime heap memory.
177 TInt iStackSize; ///< Size for stack required by an EXEs initial thread.
178 TInt iBssSize; ///< Size of executables uninitialised data.
179 TUint iEntryPoint; ///< Offset into code of the entry point.
180 TUint iCodeBase; ///< Virtual address that the executables code is linked for.
181 TUint iDataBase; ///< Virtual address that the executables data is linked for.
182 TInt iDllRefTableCount; ///< Number of executable against which this executable is linked. The number of files mention in the import section at iImportOffset.
183 TUint iExportDirOffset; ///< Byte offset into file of the export directory.
184 TInt iExportDirCount; ///< Number of entries in the export directory.
185 TInt iTextSize; ///< Size of just the text section, also doubles as the offset for the Import Address Table w.r.t. the code section.
186 TUint iCodeOffset; ///< Offset into file of the code section. Also doubles the as header size.
187 TUint iDataOffset; ///< Offset into file of the data section.
188 TUint iImportOffset; ///< Offset into file of the import section (E32ImportSection).
189 TUint iCodeRelocOffset; ///< Offset into file of the code relocation section (E32RelocSection).
190 TUint iDataRelocOffset; ///< Offset into file of the data relocation section (E32RelocSection).
191 TUint16 iProcessPriority; ///< Initial runtime process priorty for an EXE. (Value from enum TProcessPriority.)
192 TUint16 iCpuIdentifier; ///< Value from enum TCpu which indicates the CPU architecture for which the image was created
197 Extends E32ImageHeader.
199 class E32ImageHeaderComp : public E32ImageHeader
202 TUint32 iUncompressedSize; ///< Uncompressed size of file data after the header, or zero if file not compressed.
207 Extends E32ImageHeaderComp.
208 All Symbian OS executable files have a header in this format since OS version 8.1b.
210 class E32ImageHeaderV : public E32ImageHeaderComp
213 SSecurityInfo iS; ///< Platform Security information of executable.
214 TUint32 iExceptionDescriptor; ///< Offset in bytes from start of code section to Exception Descriptor, bit 0 set if valid.
215 TUint32 iSpare2; ///< Reserved for future use. Set to zero.
216 TUint16 iExportDescSize; ///< Size of export description stored in iExportDesc.
217 TUint8 iExportDescType; ///< Type of description of holes in export table
218 TUint8 iExportDesc[1]; ///< Description of holes in export table, size given by iExportDescSize..
220 TInt ValidateWholeImage(TAny* aBufferStart, TUint aBufferSize) const;
221 TInt ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const;
222 TInt ValidateExportDescription() const;
223 TInt ValidateRelocations(TAny* aBufferStart, TUint aBufferSize, TUint aRelocationInfoOffset, TUint aRelocatedSectionSize, E32RelocSection*& aRelocationSection) const;
224 TInt ValidateImports(TAny* aBufferStart, TUint aBufferSize, TUint& aBiggestImportCount) const;
225 TInt ValidateAndAdjust(TUint32 aFileSize);
228 // export description type E32ImageHeaderV::iExportDescType
229 const TUint KImageHdr_ExpD_NoHoles =0x00; ///< No holes, all exports present.
230 const TUint KImageHdr_ExpD_FullBitmap =0x01; ///< Full bitmap present at E32ImageHeaderV::iExportDesc
231 const TUint KImageHdr_ExpD_SparseBitmap8 =0x02; ///< Sparse bitmap present at E32ImageHeaderV::iExportDesc, granularity 8
232 const TUint KImageHdr_ExpD_Xip =0xff; ///< XIP file
236 // inline getters for E32ImageHeader
240 Extract ABI type from aFlags.
242 inline TUint E32ImageHeader::ABIFromFlags(TUint aFlags)
244 return aFlags & KImageABIMask;
248 Extract ABI type from #iFlags.
250 inline TUint E32ImageHeader::ABI() const
252 return ABIFromFlags(iFlags);
256 Extract entrypoint format from aFlags.
258 inline TUint E32ImageHeader::EptFromFlags(TUint aFlags)
260 return aFlags & KImageEptMask;
264 Extract entrypoint format from #iFlags.
266 inline TUint E32ImageHeader::EntryPointFormat() const
268 return EptFromFlags(iFlags);
272 Extract header format from aFlags.
274 inline TUint E32ImageHeader::HdrFmtFromFlags(TUint aFlags)
276 return aFlags & KImageHdrFmtMask;
280 Extract header format from #iFlags.
282 inline TUint E32ImageHeader::HeaderFormat() const
284 return HdrFmtFromFlags(iFlags);
288 Extract import format from aFlags.
290 inline TUint E32ImageHeader::ImpFmtFromFlags(TUint aFlags)
292 return aFlags & KImageImpFmtMask;
296 Extract import format from #iFlags.
298 inline TUint E32ImageHeader::ImportFormat() const
300 return ImpFmtFromFlags(iFlags);
304 Return #iCompressionType.
306 inline TUint32 E32ImageHeader::CompressionType() const
308 return iCompressionType;
312 Return #iModuleVersion.
314 inline TUint32 E32ImageHeader::ModuleVersion() const
316 return iModuleVersion;
320 Return size of this header.
322 inline TInt E32ImageHeader::TotalSize() const
328 Return total size of file after decompression, or -1 if file not compressed.
330 inline TInt E32ImageHeader::UncompressedFileSize() const
332 if(iCompressionType==0)
333 return -1; // not compressed
335 return ((E32ImageHeaderComp*)this)->iUncompressedSize + TotalSize();
339 Return copy of security info, #E32ImageHeaderV::iS.
341 inline void E32ImageHeader::GetSecurityInfo(SSecurityInfo& aInfo) const
343 aInfo = ((E32ImageHeaderV*)this)->iS;
347 Return #iCpuIdentifier.
349 inline TCpu E32ImageHeader::CpuIdentifier() const
351 return (TCpu)iCpuIdentifier;
355 Return #iProcessPriority.
357 inline TProcessPriority E32ImageHeader::ProcessPriority() const
359 return (TProcessPriority)iProcessPriority;
363 Return fffset in bytes from start of code section for the Exception Descriptor.
364 Or zero if not present.
366 inline TUint32 E32ImageHeader::ExceptionDescriptor() const
368 TUint32 xd = ((E32ImageHeaderV*)this)->iExceptionDescriptor;
370 if((xd & 1) && (xd != 0xffffffffu))
378 A block of imports from a single executable.
379 These structures are conatined in a images Import Section (E32ImportSection).
384 inline const E32ImportBlock* NextBlock(TUint aImpFmt) const;
385 inline TInt Size(TUint aImpFmt) const;
386 inline const TUint* Imports() const; // import list if present
388 TUint32 iOffsetOfDllName; ///< Offset from start of import section for a NUL terminated executable (DLL or EXE) name.
389 TInt iNumberOfImports; ///< Number of imports from this executable.
390 // TUint iImport[iNumberOfImports]; ///< For ELF-derived executes: list of code section offsets. For PE, list of imported ordinals. Omitted in PE2 import format
394 Return size of this import block.
395 @param aImpFmt Import format as obtained from image header.
397 inline TInt E32ImportBlock::Size(TUint aImpFmt) const
399 TInt r = sizeof(E32ImportBlock);
400 if(aImpFmt!=KImageImpFmt_PE2)
401 r += iNumberOfImports * sizeof(TUint);
406 Return pointer to import block which immediately follows this one.
407 @param aImpFmt Import format as obtained from image header.
409 inline const E32ImportBlock* E32ImportBlock::NextBlock(TUint aImpFmt) const
411 const E32ImportBlock* next = this + 1;
412 if(aImpFmt!=KImageImpFmt_PE2)
413 next = (const E32ImportBlock*)( (TUint8*)next + iNumberOfImports * sizeof(TUint) );
418 Return address of first import in this block.
419 For import format KImageImpFmt_ELF, imports are list of code section offsets.
420 For import format KImageImpFmt_PE, imports are a list of imported ordinals.
421 For import format KImageImpFmt_PE2, the import list is not present and should not be accessed.
423 inline const TUint* E32ImportBlock::Imports() const
425 return (const TUint*)(this + 1);
430 Header for the Import Section in an image, as referenced by E32ImageHeader::iImportOffset.
431 Immediately following this structure are an array of E32ImportBlock structures.
432 The number of these is given by E32ImageHeader::iDllRefTableCount.
434 class E32ImportSection
437 TInt iSize; ///< Size of this section excluding 'this' structure
438 // E32ImportBlock iImportBlock[iDllRefTableCount];
443 A block of relocations for a single page (4kB) of code/data.
445 Immediately following this structure are an array of TUint16 values
446 each representing a single value in the page which is to be relocated.
447 The lower 12 bits of each entry is the offset, in bytes, from start of this page.
448 The Upper 4 bits are the relocation type to be applied to the 32-bit value located
450 - 1 means relocate relative to code section.
451 - 2 means relocate relative to data section.
452 - 3 means relocate relative to code or data section; calculate which.
454 A value of all zeros (0x0000) is ignored. (Used for padding structure to 4 byte alignment).
459 TUint32 iPageOffset; ///< Offset, in bytes, for the page being relocated; relative to the section start. Always a multiple of the page size: 4096 bytes.
460 TUint32 iBlockSize; ///< Size, in bytes, for this block structure. Always a multiple of 4.
466 Header for a Relocation Section in an image, as referenced by E32ImageHeader::iCodeRelocOffset
467 or E32ImageHeader::iDataRelocOffset.
469 Immediately following this structure are an array of E32RelocBlock structures.
471 class E32RelocSection
474 TInt iSize; ///< Size of this relocation section including 'this' structure. Always a multiple of 4.
475 TInt iNumberOfRelocs; ///< Number of relocations in this section.
476 // E32RelocBlock iRelockBlock[];
481 Structure contained in the export directory in text section of the stdexe/stddll.
482 It contains information on the names of symbols exported by this stdexe/stddll and
483 pointers to a E32EpocExpSymInfoHdr structure of any stddlls that are dependencies of
486 This is not used for emulator images see E32EmulExpSymInfoHdr below.
487 @see E32EmulExpSymInfoHdr
489 class E32EpocExpSymInfoHdr
492 TInt iSize; // size of this Table
494 TInt16 iSymCount; // number of symbols
495 TInt iSymbolTblOffset; // start of the symbol table - offset from byte 0 of this header
496 TInt iStringTableSz; // size of the string table
497 TInt iStringTableOffset; // start of the string table having names of the symbols - offset from byte 0 of this header
498 TInt iDllCount; // Number of dependent DLLs
499 TInt iDepDllZeroOrdTableOffset; // offset of the DLL dependency table - offset from byte 0 of this header.
504 Header of the structure contained in the 'KWin32SectionName_NmdExpData'
505 segment of emulator stdexe & stddll images.
506 The segment contains addresses of symbols and NULL
507 terminated ASCII strings of the names of static dependencies.
508 For a stdexe, this segment contains the following:
509 a) symbol count (iSymCount) and static dependency count (iDllCount)
510 b) iSymCount * symbol addresses
511 c) iSymCount * symbol names
512 d) iDllCount * dependency names
514 For a stddll, this segment contains the following:
515 a) symbol count (iSymCout) is always 0
516 b) static dependency count (iDllCount)
517 c) iDllCount * dependency names
518 The symbol addresses and names are not required for a stddll as the Windows API,
519 GetProcAddress may be used to get the addresses for symbol names.
520 Since this API works only on DLL handles, we explicitly list them for stdexes.
521 This is used for emulator images only.
523 class E32EmulExpSymInfoHdr
526 TInt32 iSymCount; // Number of symbols
527 TInt32 iDllCount; // Number of static dependency DLLs
532 #ifdef INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
534 // include code which implements validation functions...
536 #ifndef RETURN_FAILURE
537 #define RETURN_FAILURE(_r) return (_r)
540 #ifndef E32IMAGEHEADER_TRACE
541 #define E32IMAGEHEADER_TRACE(_t) ((void)0)
549 Validate this image header.
551 After successful validation the following are true:
552 - File size is big enough to contain the entire header.
553 - Values #iUidChecksum, #iSignature and #iHeaderCrc are correct.
554 - CPU type (#iCpuIdentifier), ABI type (#iFlags&#KImageABIMask) and
555 entrypoint type (#iFlags&#KImageEptMask) are valid for this system.
556 - Code part of file as specified by #iCodeOffset and #iCodeSize is fully within the file.
557 - Text section size (#iTextSize) is within code part.
558 - Entrypoint value (#iEntryPoint) lies within the code part and is aligned correctly.
559 - Export directory as specified by #iExportDirCount and #iExportDirOffset is fully
560 within code part and is aligned correctly.
561 - Exception description (E32ImageHeaderV::iExceptionDescriptor), if present,
562 lies within the code part.
563 - Data part of file as specified by #iDataOffset and #iDataSize is fully within the file.
564 Or data is not present (#iDataOffset==#iDataSize==0).
565 - Import section (class E32ImportSection at #iImportOffset) is within 'rest of data'
566 and aligned correctly. Data following the E32ImportSection header is NOT validated or
567 checked if it is fully contained within the file.
568 - Code relocations (class E32RelocSection at #iCodeRelocOffset) is within 'rest of data'
569 and aligned correctly. Data following the E32RelocSection header is NOT validated or
570 checked if it is fully contained within the file.
571 - Data relocations (class E32RelocSection at #iDataRelocOffset) is within 'rest of data'
572 and aligned correctly. Data following the E32RelocSection header is NOT validated or
573 checked if it is fully contained within the file.
574 - Export description is validated by E32ImageHeaderV::ValidateExportDescription().
575 - #iUid1 is consistant with #iFlags&#KImageDll. I.e. if flaged as a DLL, #iUid1 is
576 KDynamicLibraryUidValue, otherwise it is KExecutableImageUidValue.
577 - Version number (#iModuleVersion) is valid. (Major and minor versions are <32768).
578 - File compression type (#iCompressionType) is supported.
579 - #iHeapSizeMax>=#iHeapSizeMin
580 - All signed values in header are not negative.
582 @param aFileSize Total size of the file from which this header was created.
583 @param[out] aUncompressedSize Returns the total size that the file data would be once decompressed.
585 @return KErrNone if no errors detected;
586 KErrCorrupt if errors found;
587 KErrNotSupported if image format not supported on this platform.
589 TInt E32ImageHeader::ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const
591 // check file is big enough for any header...
592 if(TUint(aFileSize)<sizeof(*this))
595 TUint hdrfmt = HeaderFormat();
596 if(hdrfmt==KImageHdrFmt_V)
597 return ((E32ImageHeaderV*)this)->ValidateHeader(aFileSize,aUncompressedSize);
599 return KErrNotSupported; // header format unrecognised
603 Validate this image header.
605 @param aFileSize Total size of the file from which this header was created.
606 @param[out] aUncompressedSize Returns the total size that the file data would be once decompressed.
608 @return KErrNone if no errors detected;
609 KErrCorrupt if errors found;
610 KErrNotSupported if image format not supported on this platform.
612 TInt E32ImageHeaderV::ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const
614 const TUint KMaxDesSize = 0x0fffffffu; // maximum size of descriptor
617 // file size unknown, set to maximum valid so rest of validation works...
618 aFileSize = KMaxDesSize;
620 if(TUint(aFileSize)>KMaxDesSize)
621 RETURN_FAILURE(KErrCorrupt); // file size negative or too big
623 aUncompressedSize = 0;
625 // check file is big enough to contain this header...
626 if(aFileSize<(TInt)sizeof(*this))
627 RETURN_FAILURE(KErrCorrupt);
629 // check header format version...
630 if((iFlags&KImageHdrFmtMask)!=KImageHdrFmt_V)
631 RETURN_FAILURE(KErrNotSupported);
633 // check header size...
634 TUint headerSize = iCodeOffset;
635 if(headerSize>TUint(aFileSize))
636 RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because Loader will fail earlier when reading header from file
638 // check iCpuIdentifier...
639 TCpu cpu = (TCpu)iCpuIdentifier;
640 TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
641 #if defined(__CPU_ARM)
643 RETURN_FAILURE(KErrNotSupported);
644 #elif defined(__CPU_X86)
646 RETURN_FAILURE(KErrNotSupported);
648 TUint32 pointerAlignMask = isARM ? 3 : 0; // mask of bits which must be zero for aligned pointers/offsets
650 // check iUid1,iUid2,iUid3,iUidChecksum...
651 TUidType uids = *(const TUidType*)&iUid1;
652 TCheckedUid chkuid(uids);
653 const TUint32* pChkUid = (const TUint32*)&chkuid; // need hackery to verify the UID checksum since everything is private
654 if(pChkUid[3]!=iUidChecksum)
655 RETURN_FAILURE(KErrCorrupt);
657 // check iSignature...
658 if(iSignature!=0x434f5045) // 'EPOC'
659 RETURN_FAILURE(KErrCorrupt);
661 // check iHeaderCrc...
662 TUint32 supplied_crc = iHeaderCrc;
663 ((E32ImageHeaderV*)this)->iHeaderCrc = KImageCrcInitialiser;
665 Mem::Crc32(crc, this, headerSize);
666 ((E32ImageHeaderV*)this)->iHeaderCrc = supplied_crc;
667 if(crc!=supplied_crc)
668 RETURN_FAILURE(KErrCorrupt);
670 // check iModuleVersion...
671 TUint32 mv = iModuleVersion;
672 if(mv>=0x80000000u || (mv&0x0000ffffu)>0x8000u)
673 RETURN_FAILURE(KErrNotSupported);
675 // check iCompressionType and get uncompressed size...
676 TUint compression = iCompressionType;
677 TUint uncompressedSize = aFileSize;
678 if(compression!=KFormatNotCompressed)
680 if(compression!=KUidCompressionDeflate && compression!=KUidCompressionBytePair)
681 RETURN_FAILURE(KErrNotSupported); // unknown compression method
682 uncompressedSize = headerSize+iUncompressedSize;
683 if(uncompressedSize<headerSize)
684 RETURN_FAILURE(KErrCorrupt); // size overflowed 32 bits
687 // check sizes won't overflow the limit for a descriptor (many Loader uses won't like that).
688 if(uncompressedSize>KMaxDesSize)
689 RETURN_FAILURE(KErrCorrupt);
691 // check KImageDll in iFlags...
694 if(iUid1!=TUint32(KDynamicLibraryUidValue))
695 RETURN_FAILURE(KErrNotSupported);
697 else if(iUid1!=TUint32(KExecutableImageUidValue))
698 RETURN_FAILURE(KErrNotSupported);
700 // check iFlags for ABI and entry point types...
703 if((iFlags&KImageEptMask)!=KImageEpt_Eka2)
704 RETURN_FAILURE(KErrNotSupported);
705 #if defined(__EABI__)
706 if((iFlags&KImageABIMask)!=KImageABI_EABI)
707 RETURN_FAILURE(KErrNotSupported);
708 #elif defined(__GCC32__)
709 if((iFlags&KImageABIMask)!=KImageABI_GCC98r2)
710 RETURN_FAILURE(KErrNotSupported);
715 if(iFlags&KImageEptMask)
716 RETURN_FAILURE(KErrNotSupported); // no special entry point type allowed on non-ARM targets
717 if(iFlags&KImageABIMask)
718 RETURN_FAILURE(KErrNotSupported);
721 // check iFlags for import format...
722 if((iFlags&KImageImpFmtMask)>KImageImpFmt_PE2)
723 RETURN_FAILURE(KErrNotSupported);
725 // check iHeapSizeMin...
727 RETURN_FAILURE(KErrCorrupt);
729 // check iHeapSizeMax...
730 if(iHeapSizeMax<iHeapSizeMin)
731 RETURN_FAILURE(KErrCorrupt);
733 // check iStackSize...
735 RETURN_FAILURE(KErrCorrupt);
739 RETURN_FAILURE(KErrCorrupt);
741 // check iEntryPoint...
742 if(iEntryPoint>=TUint(iCodeSize))
743 RETURN_FAILURE(KErrCorrupt);
744 if(iEntryPoint+KCodeSegIdOffset+sizeof(TUint32)>TUint(iCodeSize))
745 RETURN_FAILURE(KErrCorrupt);
746 if(iEntryPoint&pointerAlignMask)
747 RETURN_FAILURE(KErrCorrupt); // not aligned
749 // check iCodeBase...
751 RETURN_FAILURE(KErrCorrupt); // not aligned
753 // check iDataBase...
755 RETURN_FAILURE(KErrCorrupt); // not aligned
757 // check iDllRefTableCount...
758 if(iDllRefTableCount<0)
759 RETURN_FAILURE(KErrCorrupt);
760 if(iDllRefTableCount)
763 RETURN_FAILURE(KErrCorrupt); // we link to DLLs but have no import data
766 // check iCodeOffset and iCodeSize specify region in file...
767 TUint codeStart = iCodeOffset;
768 TUint codeEnd = codeStart+iCodeSize;
769 if(codeEnd<codeStart)
770 RETURN_FAILURE(KErrCorrupt);
771 // if(codeStart<headerSize)
772 // RETURN_FAILURE(KErrCorrupt); // can't happen because headerSize is defined as iCodeOffset (codeStart)
773 if(codeEnd>uncompressedSize)
774 RETURN_FAILURE(KErrCorrupt);
776 // check iDataOffset and iDataSize specify region in file...
777 TUint dataStart = iDataOffset;
778 TUint dataEnd = dataStart+iDataSize;
779 if(dataEnd<dataStart)
780 RETURN_FAILURE(KErrCorrupt);
785 RETURN_FAILURE(KErrCorrupt);
789 if(dataStart<codeEnd)
790 RETURN_FAILURE(KErrCorrupt);
791 if(dataEnd>uncompressedSize)
792 RETURN_FAILURE(KErrCorrupt);
793 if((dataStart-codeStart)&pointerAlignMask)
794 RETURN_FAILURE(KErrCorrupt); // data not aligned with respect to code
798 // check total data size isn't too bit...
799 TUint totalDataSize = iDataSize+iBssSize;
800 if(totalDataSize>0x7fff0000)
801 RETURN_FAILURE(KErrNoMemory);
803 // check iExportDirOffset and iExportDirCount specify region in code part...
804 if(TUint(iExportDirCount)>65535)
805 RETURN_FAILURE(KErrCorrupt); // too many exports
808 TUint exportsStart = iExportDirOffset;
809 TUint exportsEnd = exportsStart+iExportDirCount*sizeof(TUint32);
810 if(iFlags&KImageNmdExpData)
811 exportsStart -= sizeof(TUint32); // allow for 0th ordinal
812 if(exportsEnd<exportsStart)
813 RETURN_FAILURE(KErrCorrupt);
814 if(exportsStart<codeStart)
815 RETURN_FAILURE(KErrCorrupt);
816 if(exportsEnd>codeEnd)
817 RETURN_FAILURE(KErrCorrupt);
818 if((exportsStart-codeStart)&pointerAlignMask)
819 RETURN_FAILURE(KErrCorrupt); // not aligned within code section
822 // check iTextSize...
823 if(TUint(iTextSize)>TUint(iCodeSize))
824 RETURN_FAILURE(KErrCorrupt);
826 // check iImportOffset...
827 TUint start = iImportOffset;
830 TUint end = start+sizeof(E32ImportSection); // minimum valid size
832 RETURN_FAILURE(KErrCorrupt);
834 RETURN_FAILURE(KErrCorrupt);
835 if(end>uncompressedSize)
836 RETURN_FAILURE(KErrCorrupt);
837 if((start-codeEnd)&pointerAlignMask)
838 RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
841 // check iCodeRelocOffset...
842 start = iCodeRelocOffset;
845 TUint end = start+sizeof(E32RelocSection); // minimum valid size
847 RETURN_FAILURE(KErrCorrupt);
849 RETURN_FAILURE(KErrCorrupt);
850 if(end>uncompressedSize)
851 RETURN_FAILURE(KErrCorrupt);
852 if((start-codeEnd)&pointerAlignMask)
853 RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
856 // check iDataRelocOffset...
857 start = iDataRelocOffset;
860 TUint end = start+sizeof(E32RelocSection); // minimum valid size
862 RETURN_FAILURE(KErrCorrupt);
864 RETURN_FAILURE(KErrCorrupt);
865 if(end>uncompressedSize)
866 RETURN_FAILURE(KErrCorrupt);
867 if((start-codeEnd)&pointerAlignMask)
868 RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
871 // check exception descriptor...
872 if(iExceptionDescriptor&1) // if valid...
873 if(iExceptionDescriptor>=TUint(iCodeSize))
874 RETURN_FAILURE(KErrCorrupt);
876 TInt r = ValidateExportDescription();
881 aUncompressedSize = uncompressedSize;
887 Valdate that the export description is valid.
889 TInt E32ImageHeaderV::ValidateExportDescription() const
891 TUint headerSize = iCodeOffset;
893 // check export description...
894 TUint edSize = iExportDescSize + sizeof(iExportDescSize) + sizeof(iExportDescType);
895 edSize = (edSize+3)&~3;
896 TUint edEnd = _FOFF(E32ImageHeaderV,iExportDescSize)+edSize;
897 if(edEnd!=headerSize)
898 RETURN_FAILURE(KErrCorrupt);
900 // size of bitmap of exports...
901 TUint bitmapSize = (iExportDirCount+7) >> 3;
903 // check export description bitmap...
904 switch(iExportDescType)
906 case KImageHdr_ExpD_NoHoles:
907 // no bitmap to check...
908 E32IMAGEHEADER_TRACE(("ValidateExportDescription NoHoles"));
911 case KImageHdr_ExpD_FullBitmap:
912 // full bitmap present...
913 E32IMAGEHEADER_TRACE(("ValidateExportDescription FullBitmap"));
914 if(bitmapSize!=iExportDescSize)
915 RETURN_FAILURE(KErrCorrupt);
918 case KImageHdr_ExpD_SparseBitmap8:
920 // sparse bitmap present...
921 E32IMAGEHEADER_TRACE(("ValidateExportDescription SparseBitmap8"));
923 // get size of meta-bitmap...
924 TUint metaBitmapSize = (bitmapSize+7) >> 3;
925 if(metaBitmapSize>iExportDescSize)
926 RETURN_FAILURE(KErrCorrupt); // doesn't fit
928 TUint totalSize = metaBitmapSize;
930 // scan meta-bitmap counting extra bytes which should be present...
931 const TUint8* metaBitmap = iExportDesc;
932 const TUint8* metaBitmapEnd = metaBitmap + metaBitmapSize;
933 while(metaBitmap<metaBitmapEnd)
935 TUint bits = *metaBitmap++;
939 ++totalSize; // another byte is present in bitmap
944 if(totalSize!=iExportDescSize)
945 RETURN_FAILURE(KErrCorrupt);
950 E32IMAGEHEADER_TRACE(("ValidateExportDescription ?"));
951 RETURN_FAILURE(KErrNotSupported);
957 Validate a relocation section.
959 @param aBufferStart Start of buffer containing the data after the code part in the image file.
960 @param aBufferSize Size of data at aBufferStart.
961 @param aRelocationInfoOffset File offset for relocation section. (#iCodeRelocOffset or #iDataRelocOffset.)
962 @param aRelocatedSectionSize Size of section being relocated. (#iCodeSize or #iDataSize.)
963 @param[out] aRelocationSection Set to the start of the relocation section in the given buffer.
965 @return KErrNone if relocation section is valid, else KErrCorrupt.
967 TInt E32ImageHeaderV::ValidateRelocations(TAny* aBufferStart, TUint aBufferSize, TUint aRelocationInfoOffset, TUint aRelocatedSectionSize, E32RelocSection*& aRelocationSection) const
969 aRelocationSection = 0;
970 if(!aRelocationInfoOffset)
971 return KErrNone; // no relocations
973 // get alignment requirements...
974 TCpu cpu = (TCpu)iCpuIdentifier;
975 TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
976 TUint32 pointerAlignMask = isARM ? 3 : 0; // mask of bits which must be zero for aligned pointers/offsets
978 // buffer pointer to read relocation from...
979 TUint8* bufferStart = (TUint8*)aBufferStart;
980 TUint8* bufferEnd = bufferStart+aBufferSize;
981 TUint baseOffset = iCodeOffset+iCodeSize; // file offset for aBufferStart
982 TUint8* sectionStart = (bufferStart+aRelocationInfoOffset-baseOffset);
983 TUint8* p = sectionStart;
985 // read section header (ValidateHeader has alread checked this is OK)...
986 E32RelocSection* sectionHeader = (E32RelocSection*)p;
987 TUint size = sectionHeader->iSize;
988 TUint relocsRemaining = sectionHeader->iNumberOfRelocs;
989 E32IMAGEHEADER_TRACE(("E32RelocSection 0x%x %d",size,relocsRemaining));
991 RETURN_FAILURE(KErrCorrupt); // not multiple of word size
993 // calculate buffer range for block data...
994 p = (TUint8*)(sectionHeader+1); // start of first block
995 TUint8* sectionEnd = p+size;
997 RETURN_FAILURE(KErrCorrupt); // math overflow
998 if(sectionEnd>bufferEnd)
999 RETURN_FAILURE(KErrCorrupt); // overflows buffer
1001 // process each block...
1002 while(p!=sectionEnd)
1004 E32RelocBlock* block = (E32RelocBlock*)p;
1006 // get address of first entry in this block...
1007 TUint16* entryPtr = (TUint16*)(block+1);
1008 if((TUint8*)entryPtr<(TUint8*)block || (TUint8*)entryPtr>sectionEnd)
1009 RETURN_FAILURE(KErrCorrupt); // overflows relocation section
1011 // read block header...
1012 TUint pageOffset = block->iPageOffset;
1013 TUint blockSize = block->iBlockSize;
1014 E32IMAGEHEADER_TRACE(("E32RelocSection block 0x%x 0x%x",pageOffset,blockSize));
1015 if(pageOffset&0xfff)
1016 RETURN_FAILURE(KErrCorrupt); // not page aligned
1017 if(blockSize<sizeof(E32RelocBlock))
1018 RETURN_FAILURE(KErrCorrupt); // blockSize must be at least that of the header just read
1020 RETURN_FAILURE(KErrCorrupt); // not word aligned
1022 // caculate end of entries in this block...
1023 TUint16* entryEnd = (TUint16*)(p+blockSize);
1024 if(entryEnd<entryPtr)
1025 RETURN_FAILURE(KErrCorrupt); // math overflow
1026 if(entryEnd>(TUint16*)sectionEnd)
1027 RETURN_FAILURE(KErrCorrupt); // overflows relocation section
1029 // process each entry in this block...
1030 while(entryPtr<entryEnd)
1032 TUint entry = *entryPtr++;
1033 E32IMAGEHEADER_TRACE(("E32RelocSection entry 0x%04x",entry));
1037 // check relocation type...
1038 TUint entryType = entry&0xf000;
1039 if(entryType!=KTextRelocType && entryType!=KDataRelocType && entryType!=KInferredRelocType)
1040 RETURN_FAILURE(KErrCorrupt);
1042 // check relocation is within section being relocated...
1043 TUint offset = pageOffset+(entry&0x0fff);
1044 if(offset>=aRelocatedSectionSize || offset+4>aRelocatedSectionSize)
1045 RETURN_FAILURE(KErrCorrupt); // not within section
1046 if(offset&pointerAlignMask)
1047 RETURN_FAILURE(KErrCorrupt); // not aligned correctly
1049 // count each relocation processed...
1053 // next sub block...
1054 p = (TUint8*)entryEnd;
1057 // check number of relocations in section header is correct...
1058 E32IMAGEHEADER_TRACE(("E32RelocSection relocsRemaining=%d",relocsRemaining));
1060 RETURN_FAILURE(KErrCorrupt); // incorrect number of entries
1062 aRelocationSection = sectionHeader;
1068 Validate an import section.
1070 For PE format imports, this also verifies that the Import Address Table fits within the code
1073 @param aBufferStart Start of buffer containing the data after the code part in the image file.
1074 @param aBufferSize Size of data at aBufferStart.
1075 @param[out] aBiggestImportCount Largest number of imports the image has from any single dependency.
1077 @return KErrNone if section is valid (or absent), else KErrCorrupt.
1079 TInt E32ImageHeaderV::ValidateImports(TAny* aBufferStart, TUint aBufferSize, TUint& aBiggestImportCount) const
1083 aBiggestImportCount = 0;
1084 return KErrNone; // no imports
1087 // get alignment requirements...
1088 TCpu cpu = (TCpu)iCpuIdentifier;
1089 TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
1090 TUint32 pointerAlignMask = isARM ? 3 : 0; // mask of bits which must be zero for aligned pointers/offsets
1092 // buffer pointer to read imports from...
1093 TUint8* bufferStart = (TUint8*)aBufferStart;
1094 TUint8* bufferEnd = bufferStart+aBufferSize;
1095 TUint baseOffset = iCodeOffset+iCodeSize; // file offset for aBufferStart
1096 TUint8* sectionStart = (bufferStart+iImportOffset-baseOffset);
1097 TUint8* p = sectionStart;
1099 // read section header (ValidateHeader has alread checked this is OK)...
1100 E32ImportSection* sectionHeader = (E32ImportSection*)p;
1101 TUint size = sectionHeader->iSize;
1102 E32IMAGEHEADER_TRACE(("E32ImportSection 0x%x",size));
1104 // check section lies within buffer...
1105 p = (TUint8*)(sectionHeader+1); // start of first import block
1106 TUint8* sectionEnd = sectionStart+size;
1108 RETURN_FAILURE(KErrCorrupt); // math overflow or not big enough to contain header
1109 if(sectionEnd>bufferEnd)
1110 RETURN_FAILURE(KErrCorrupt); // overflows buffer
1112 // process each import block...
1113 TUint numDeps = iDllRefTableCount;
1114 TUint biggestImportCount = 0;
1115 TUint totalImports = 0;
1116 TUint importFormat = iFlags&KImageImpFmtMask;
1119 // get block header...
1120 E32ImportBlock* block = (E32ImportBlock*)p;
1121 p = (TUint8*)(block+1);
1122 if(p<(TUint8*)block || p>sectionEnd)
1123 RETURN_FAILURE(KErrCorrupt); // overflows buffer
1125 E32IMAGEHEADER_TRACE(("E32ImportBlock 0x%x %d",block->iOffsetOfDllName,block->iNumberOfImports));
1127 // check import dll name is within section...
1128 TUint8* name = sectionStart+block->iOffsetOfDllName;
1129 if(name<sectionStart || name>=sectionEnd)
1130 RETURN_FAILURE(KErrCorrupt); // not within import section
1131 while(*name++ && name<sectionEnd)
1134 RETURN_FAILURE(KErrCorrupt); // name overflows section
1135 E32IMAGEHEADER_TRACE(("E32ImportBlock %s",sectionStart+block->iOffsetOfDllName));
1137 // process import count...
1138 TUint numberOfImports = block->iNumberOfImports;
1139 if(numberOfImports>=0x80000000u/sizeof(TUint32))
1140 RETURN_FAILURE(KErrCorrupt); // size doesn't fit into a signed integer
1141 if(numberOfImports>biggestImportCount)
1142 biggestImportCount = numberOfImports;
1143 totalImports += numberOfImports;
1145 // process import data...
1147 // PE2 doesn't have any more data...
1148 if(importFormat==KImageImpFmt_PE2)
1151 // get import data range...
1152 TUint32* imports = (TUint32*)p;
1153 TUint32* importsEnd = imports+numberOfImports;
1154 if(importsEnd<imports)
1155 RETURN_FAILURE(KErrCorrupt); // math overflow. Fuzzer can't trigger this because needs aBufferStart to be in to be >0x80000000
1156 if(importsEnd>(TUint32*)sectionEnd)
1157 RETURN_FAILURE(KErrCorrupt); // overflows buffer
1159 // move pointer on to next block...
1160 p = (TUint8*)importsEnd;
1162 if(importFormat==KImageImpFmt_ELF)
1164 // check imports are in code section...
1165 TUint32 limit = iCodeSize-sizeof(TUint32);
1166 while(imports<importsEnd)
1168 TUint32 i = *imports++;
1170 RETURN_FAILURE(KErrCorrupt);
1171 if(i&pointerAlignMask)
1172 RETURN_FAILURE(KErrCorrupt); // not word aligned
1175 else if(importFormat==KImageImpFmt_PE)
1177 // import data is not used, so don't bother checking it
1181 RETURN_FAILURE(KErrCorrupt); // bad import format, Fuzzer can't trigger this because import format checked by header validation
1185 p = (TUint8*)block->NextBlock(importFormat);
1188 // done processing imports; for PE derived files now check import address table (IAT)...
1189 if(importFormat==KImageImpFmt_PE || importFormat==KImageImpFmt_PE2)
1191 if(totalImports>=0x80000000u/sizeof(TUint32))
1192 RETURN_FAILURE(KErrCorrupt); // size doesn't fit into a signed integer
1193 TUint importAddressTable = iTextSize; // offset for IAT
1194 if(importAddressTable&pointerAlignMask)
1195 RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because PE imports are for X86 which doesn't have alignment restrictions
1196 TUint importAddressTableEnd = importAddressTable+sizeof(TUint32)*totalImports;
1197 if(importAddressTableEnd<importAddressTable || importAddressTableEnd>TUint(iCodeSize))
1198 RETURN_FAILURE(KErrCorrupt); // import address table overflows code part of file
1199 E32IMAGEHEADER_TRACE(("E32ImportSection IAT offsets 0x%x..0x%x",importAddressTable,importAddressTableEnd));
1202 aBiggestImportCount = biggestImportCount;
1210 Validate a whole executable image.
1212 This runs all of the other validation methods in turn.
1214 @param aBufferStart Start of buffer containing the data after the header part of an image file.
1215 @param aBufferSize Size of data at aBufferStart.
1217 @return KErrNone if image is valid, else KErrCorrupt or KErrNotSupported.
1219 TInt E32ImageHeaderV::ValidateWholeImage(TAny* aBufferStart, TUint aBufferSize) const
1221 TUint32 dummyUncompressedSize;
1222 TInt r = ValidateHeader(TotalSize()+aBufferSize,dummyUncompressedSize);
1226 TInt endOfCodeOffset = iCodeSize;
1227 void* restOfFileData = ((TUint8*)aBufferStart)+endOfCodeOffset;
1228 TInt restOfFileSize = aBufferSize-endOfCodeOffset;
1230 E32RelocSection* dummy;
1231 r = ValidateRelocations(restOfFileData,restOfFileSize,iCodeRelocOffset,iCodeSize,dummy);
1234 r = ValidateRelocations(restOfFileData,restOfFileSize,iDataRelocOffset,iDataSize,dummy);
1238 TUint biggestImportCount;
1239 r = ValidateImports(restOfFileData,restOfFileSize,biggestImportCount);
1247 #endif // INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
1250 #endif // __F32IMAGE_H__