1.1 --- a/epoc32/include/f32image.h Wed Mar 31 12:27:01 2010 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1239 +0,0 @@
1.4 -// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 -// All rights reserved.
1.6 -// This component and the accompanying materials are made available
1.7 -// under the terms of the License "Symbian Foundation License v1.0" to Symbian Foundation members and "Symbian Foundation End User License Agreement v1.0" to non-members
1.8 -// which accompanies this distribution, and is available
1.9 -// at the URL "http://www.symbianfoundation.org/legal/licencesv10.html".
1.10 -//
1.11 -// Initial Contributors:
1.12 -// Nokia Corporation - initial contribution.
1.13 -//
1.14 -// Contributors:
1.15 -//
1.16 -// Description:
1.17 -// f32\inc\f32image.h
1.18 -//
1.19 -//
1.20 -
1.21 -
1.22 -
1.23 -/**
1.24 - @file f32\inc\f32image.h
1.25 - @internalTechnology
1.26 -*/
1.27 -
1.28 -#ifndef __F32IMAGE_H__
1.29 -#define __F32IMAGE_H__
1.30 -#include <e32cmn.h>
1.31 -
1.32 -/**
1.33 -Value used for E32ImageHeader::iCpuIdentifier.
1.34 -*/
1.35 -enum TCpu
1.36 - {
1.37 - ECpuUnknown=0, ECpuX86=0x1000, ECpuArmV4=0x2000, ECpuArmV5=0x2001, ECpuArmV6=0x2002, ECpuMCore=0x4000
1.38 - };
1.39 -
1.40 -/**
1.41 -Ordinal value of the first entry in an executables export directory.
1.42 -@see E32ImageHeader::iExportDirOffset.
1.43 -*/
1.44 -const TInt KOrdinalBase=1;
1.45 -
1.46 -/**
1.47 -Value used to initialise E32ImageHeader::iHeaderCrc prior to CRC generation.
1.48 -*/
1.49 -const TUint32 KImageCrcInitialiser = 0xc90fdaa2u;
1.50 -
1.51 -
1.52 -/**
1.53 -Byte offset from an executable's entrypoint to the code segment ID storage location.
1.54 -*/
1.55 -const TUint KCodeSegIdOffset = 12;
1.56 -
1.57 -//
1.58 -// Flags fields for E32ImageHeader::iFlags
1.59 -//
1.60 -
1.61 -const TUint KImageDll = 0x00000001u; ///< Flag set if executable is a DLL, clear if an EXE.
1.62 -
1.63 -const TUint KImageNoCallEntryPoint = 0x00000002u; ///< Obsolete flag ignored since Symbian OS version 8.1b.
1.64 -
1.65 -const TUint KImageFixedAddressExe = 0x00000004u; ///< Executable's data should not move when running on the moving memory model.
1.66 -
1.67 -const TUint KImageABIMask = 0x00000018u; ///< Bitmask for ABI value.
1.68 -const TInt KImageABIShift = 3; ///< Bit shift count for ABI value.
1.69 -const TUint KImageABI_GCC98r2 = 0x00000000u; ///< Obsolete ABI for ARM targets.
1.70 -const TUint KImageABI_EABI = 0x00000008u; ///< ARM EABI
1.71 -
1.72 -const TUint KImageEptMask = 0x000000e0u; ///< Bitmask for Entrypoint value.
1.73 -const TInt KImageEptShift = 5; ///< Bit shift count for Entrypoint value
1.74 -const TUint KImageEpt_Eka1 = 0x00000000u; ///< @removed Obsolete format not used since Symbian OS version 8.1b.
1.75 -const TUint KImageEpt_Eka2 = 0x00000020u; ///< Standard entrypoint for ARM executable.
1.76 -
1.77 -const TUint KImageUnpaged = 0x00000100u; ///< Executable image should not be demand paged. Exclusive with KImagePaged,
1.78 -const TUint KImagePaged = 0x00000200u; ///< Executable image should be demand paged. Exclusive with KImageUnpaged,
1.79 -
1.80 -const TUint KImageNmdExpData = 0x00000400u; ///< Flag to indicate when named symbol export data present in image
1.81 -
1.82 -const TUint KImageDebuggable = 0x00000800u; ///< Flag to indicate image is debuggable
1.83 -
1.84 -const TUint KImageHWFloatMask = 0x00f00000u; ///< Bitmask for Floating Point type.
1.85 -const TInt KImageHWFloatShift = 20; ///< Bit shift count for Floating Point type.
1.86 -const TUint KImageHWFloat_None = EFpTypeNone << KImageHWFloatShift; ///< No hardware floating point used.
1.87 -const TUint KImageHWFloat_VFPv2 = EFpTypeVFPv2 << KImageHWFloatShift; ///< ARM VFPv2 floating point used.
1.88 -
1.89 -const TUint KImageHdrFmtMask = 0x0f000000u; ///< Bitmask for header format type.
1.90 -const TInt KImageHdrFmtShift = 24; ///< Bit shift count for header format type.
1.91 -const TUint KImageHdrFmt_Original = 0x00000000u; ///< @removed Obsolete format not used since Symbian OS version 8.1b.
1.92 -const TUint KImageHdrFmt_J = 0x01000000u; ///< @removed Obsolete format not used since Symbian OS version 8.1b.
1.93 -const TUint KImageHdrFmt_V = 0x02000000u; ///< Header has format given by class E32ImageHeaderV.
1.94 -
1.95 -const TUint KImageImpFmtMask = 0xf0000000u; ///< Bitmask for import section format type.
1.96 -const TInt KImageImpFmtShift = 28; ///< Bit shift count for import section format type.
1.97 -const TUint KImageImpFmt_PE = 0x00000000u; ///< PE-derived imports.
1.98 -const TUint KImageImpFmt_ELF = 0x10000000u; ///< ELF-derived imports.
1.99 -const TUint KImageImpFmt_PE2 = 0x20000000u; ///< PE-derived imports without redundant copy of import ordinals.
1.100 -
1.101 -
1.102 -
1.103 -
1.104 -// forward references...
1.105 -class RFile;
1.106 -class E32RelocSection;
1.107 -
1.108 -
1.109 -/**
1.110 -Structure for an executable image's header.
1.111 -This is extended by E32ImageHeaderComp and E32ImageHeaderV.
1.112 -All executables since Symbian OS version 8.1b have an header given by class E32ImageHeaderV.
1.113 -
1.114 -Summary of an executable image structure...
1.115 -
1.116 -- Header, 0..iCodeOffset-1
1.117 -- Code part, iCodeOffset..iCodeOffset+iCodeSize-1
1.118 - - .text section, 0 + iTextSize
1.119 - - Import Address Table (IAT), iText + ?
1.120 - - Export Directory, iExportDirOffset + iExportDirCount*4 (in .text Section)
1.121 -- Rest of data, iCodeOffset+iCodeSize..EOF
1.122 - - .data section, iDataOffset + iDataSize
1.123 - - Import section, iImportOffset + sizeof(E32ImportSection)+?
1.124 - - Code relocation section, iCodeRelocOffset + sizeof(E32RelocSection)+?
1.125 - - Data relocation section, iDataRelocOffset + sizeof(E32RelocSection)+?
1.126 -*/
1.127 -class E32ImageHeader
1.128 - {
1.129 -public:
1.130 - static TInt New(E32ImageHeader*& aHdr, RFile& aFile);
1.131 - static TInt New(E32ImageHeader*& aHdr, TUint8* aFileData, TUint32 aFileSize);
1.132 - TInt ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const;
1.133 -
1.134 - inline static TUint ABIFromFlags(TUint aFlags);
1.135 - inline static TUint EptFromFlags(TUint aFlags);
1.136 - inline static TUint HdrFmtFromFlags(TUint aFlags);
1.137 - inline static TUint ImpFmtFromFlags(TUint aFlags);
1.138 -
1.139 - inline TUint ABI() const;
1.140 - inline TUint EntryPointFormat() const;
1.141 - inline TUint HeaderFormat() const;
1.142 - inline TUint ImportFormat() const;
1.143 -
1.144 - inline TUint32 CompressionType() const;
1.145 - inline TUint32 ModuleVersion() const;
1.146 - inline TInt TotalSize() const;
1.147 - inline TInt UncompressedFileSize() const;
1.148 - inline void GetSecurityInfo(SSecurityInfo& aInfo) const;
1.149 - inline TCpu CpuIdentifier() const;
1.150 - inline TProcessPriority ProcessPriority() const;
1.151 - inline TUint32 ExceptionDescriptor() const;
1.152 -public:
1.153 - TUint32 iUid1; ///< KDynamicLibraryUidValue or KExecutableImageUidValue
1.154 - TUint32 iUid2; ///< Second UID for executable.
1.155 - TUint32 iUid3; ///< Third UID for executable.
1.156 - TUint32 iUidChecksum; ///< Checksum for iUid1, iUid2 and iUid3.
1.157 - TUint iSignature; ///< Contains 'EPOC'.
1.158 - TUint32 iHeaderCrc; ///< CRC-32 of entire header. @see #KImageCrcInitialiser.
1.159 - TUint32 iModuleVersion; ///< Version number for this executable (used in link resolution).
1.160 - TUint32 iCompressionType; ///< Type of compression used for file contents located after the header. (UID or 0 for none).
1.161 - TVersion iToolsVersion; ///< Version number of tools which generated this file.
1.162 - TUint32 iTimeLo; ///< Least significant 32 bits of the time of image creation, in milliseconds since since midnight Jan 1st, 2000.
1.163 - TUint32 iTimeHi; ///< Most significant 32 bits of the time of image creation, in milliseconds since since midnight Jan 1st, 2000.
1.164 - TUint iFlags; ///< Contains various bit-fields of attributes for the image.
1.165 - TInt iCodeSize; ///< Size of executables code. Includes import address table, constant data and export directory.
1.166 - TInt iDataSize; ///< Size of executables initialised data.
1.167 - TInt iHeapSizeMin; ///< Minimum size for an EXEs runtime heap memory.
1.168 - TInt iHeapSizeMax; ///< Maximum size for an EXEs runtime heap memory.
1.169 - TInt iStackSize; ///< Size for stack required by an EXEs initial thread.
1.170 - TInt iBssSize; ///< Size of executables uninitialised data.
1.171 - TUint iEntryPoint; ///< Offset into code of the entry point.
1.172 - TUint iCodeBase; ///< Virtual address that the executables code is linked for.
1.173 - TUint iDataBase; ///< Virtual address that the executables data is linked for.
1.174 - TInt iDllRefTableCount; ///< Number of executable against which this executable is linked. The number of files mention in the import section at iImportOffset.
1.175 - TUint iExportDirOffset; ///< Byte offset into file of the export directory.
1.176 - TInt iExportDirCount; ///< Number of entries in the export directory.
1.177 - TInt iTextSize; ///< Size of just the text section, also doubles as the offset for the Import Address Table w.r.t. the code section.
1.178 - TUint iCodeOffset; ///< Offset into file of the code section. Also doubles the as header size.
1.179 - TUint iDataOffset; ///< Offset into file of the data section.
1.180 - TUint iImportOffset; ///< Offset into file of the import section (E32ImportSection).
1.181 - TUint iCodeRelocOffset; ///< Offset into file of the code relocation section (E32RelocSection).
1.182 - TUint iDataRelocOffset; ///< Offset into file of the data relocation section (E32RelocSection).
1.183 - TUint16 iProcessPriority; ///< Initial runtime process priorty for an EXE. (Value from enum TProcessPriority.)
1.184 - TUint16 iCpuIdentifier; ///< Value from enum TCpu which indicates the CPU architecture for which the image was created
1.185 - };
1.186 -
1.187 -
1.188 -/**
1.189 -Extends E32ImageHeader.
1.190 -*/
1.191 -class E32ImageHeaderComp : public E32ImageHeader
1.192 - {
1.193 -public:
1.194 - TUint32 iUncompressedSize; ///< Uncompressed size of file data after the header, or zero if file not compressed.
1.195 - };
1.196 -
1.197 -
1.198 -/**
1.199 -Extends E32ImageHeaderComp.
1.200 -All Symbian OS executable files have a header in this format since OS version 8.1b.
1.201 -*/
1.202 -class E32ImageHeaderV : public E32ImageHeaderComp
1.203 - {
1.204 -public:
1.205 - SSecurityInfo iS; ///< Platform Security information of executable.
1.206 - TUint32 iExceptionDescriptor; ///< Offset in bytes from start of code section to Exception Descriptor, bit 0 set if valid.
1.207 - TUint32 iSpare2; ///< Reserved for future use. Set to zero.
1.208 - TUint16 iExportDescSize; ///< Size of export description stored in iExportDesc.
1.209 - TUint8 iExportDescType; ///< Type of description of holes in export table
1.210 - TUint8 iExportDesc[1]; ///< Description of holes in export table, size given by iExportDescSize..
1.211 -public:
1.212 - TInt ValidateWholeImage(TAny* aBufferStart, TUint aBufferSize) const;
1.213 - TInt ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const;
1.214 - TInt ValidateExportDescription() const;
1.215 - TInt ValidateRelocations(TAny* aBufferStart, TUint aBufferSize, TUint aRelocationInfoOffset, TUint aRelocatedSectionSize, E32RelocSection*& aRelocationSection) const;
1.216 - TInt ValidateImports(TAny* aBufferStart, TUint aBufferSize, TUint& aBiggestImportCount) const;
1.217 - TInt ValidateAndAdjust(TUint32 aFileSize);
1.218 - };
1.219 -
1.220 -// export description type E32ImageHeaderV::iExportDescType
1.221 -const TUint KImageHdr_ExpD_NoHoles =0x00; ///< No holes, all exports present.
1.222 -const TUint KImageHdr_ExpD_FullBitmap =0x01; ///< Full bitmap present at E32ImageHeaderV::iExportDesc
1.223 -const TUint KImageHdr_ExpD_SparseBitmap8 =0x02; ///< Sparse bitmap present at E32ImageHeaderV::iExportDesc, granularity 8
1.224 -const TUint KImageHdr_ExpD_Xip =0xff; ///< XIP file
1.225 -
1.226 -
1.227 -//
1.228 -// inline getters for E32ImageHeader
1.229 -//
1.230 -
1.231 -/**
1.232 -Extract ABI type from aFlags.
1.233 -*/
1.234 -inline TUint E32ImageHeader::ABIFromFlags(TUint aFlags)
1.235 - {
1.236 - return aFlags & KImageABIMask;
1.237 - }
1.238 -
1.239 -/**
1.240 -Extract ABI type from #iFlags.
1.241 -*/
1.242 -inline TUint E32ImageHeader::ABI() const
1.243 - {
1.244 - return ABIFromFlags(iFlags);
1.245 - }
1.246 -
1.247 -/**
1.248 -Extract entrypoint format from aFlags.
1.249 -*/
1.250 -inline TUint E32ImageHeader::EptFromFlags(TUint aFlags)
1.251 - {
1.252 - return aFlags & KImageEptMask;
1.253 - }
1.254 -
1.255 -/**
1.256 -Extract entrypoint format from #iFlags.
1.257 -*/
1.258 -inline TUint E32ImageHeader::EntryPointFormat() const
1.259 - {
1.260 - return EptFromFlags(iFlags);
1.261 - }
1.262 -
1.263 -/**
1.264 -Extract header format from aFlags.
1.265 -*/
1.266 -inline TUint E32ImageHeader::HdrFmtFromFlags(TUint aFlags)
1.267 - {
1.268 - return aFlags & KImageHdrFmtMask;
1.269 - }
1.270 -
1.271 -/**
1.272 -Extract header format from #iFlags.
1.273 -*/
1.274 -inline TUint E32ImageHeader::HeaderFormat() const
1.275 - {
1.276 - return HdrFmtFromFlags(iFlags);
1.277 - }
1.278 -
1.279 -/**
1.280 -Extract import format from aFlags.
1.281 -*/
1.282 -inline TUint E32ImageHeader::ImpFmtFromFlags(TUint aFlags)
1.283 - {
1.284 - return aFlags & KImageImpFmtMask;
1.285 - }
1.286 -
1.287 -/**
1.288 -Extract import format from #iFlags.
1.289 -*/
1.290 -inline TUint E32ImageHeader::ImportFormat() const
1.291 - {
1.292 - return ImpFmtFromFlags(iFlags);
1.293 - }
1.294 -
1.295 -/**
1.296 -Return #iCompressionType.
1.297 -*/
1.298 -inline TUint32 E32ImageHeader::CompressionType() const
1.299 - {
1.300 - return iCompressionType;
1.301 - }
1.302 -
1.303 -/**
1.304 -Return #iModuleVersion.
1.305 -*/
1.306 -inline TUint32 E32ImageHeader::ModuleVersion() const
1.307 - {
1.308 - return iModuleVersion;
1.309 - }
1.310 -
1.311 -/**
1.312 -Return size of this header.
1.313 -*/
1.314 -inline TInt E32ImageHeader::TotalSize() const
1.315 - {
1.316 - return iCodeOffset;
1.317 - }
1.318 -
1.319 -/**
1.320 -Return total size of file after decompression, or -1 if file not compressed.
1.321 -*/
1.322 -inline TInt E32ImageHeader::UncompressedFileSize() const
1.323 - {
1.324 - if(iCompressionType==0)
1.325 - return -1; // not compressed
1.326 - else
1.327 - return ((E32ImageHeaderComp*)this)->iUncompressedSize + TotalSize();
1.328 - }
1.329 -
1.330 -/**
1.331 -Return copy of security info, #E32ImageHeaderV::iS.
1.332 -*/
1.333 -inline void E32ImageHeader::GetSecurityInfo(SSecurityInfo& aInfo) const
1.334 - {
1.335 - aInfo = ((E32ImageHeaderV*)this)->iS;
1.336 - }
1.337 -
1.338 -/**
1.339 -Return #iCpuIdentifier.
1.340 -*/
1.341 -inline TCpu E32ImageHeader::CpuIdentifier() const
1.342 - {
1.343 - return (TCpu)iCpuIdentifier;
1.344 - }
1.345 -
1.346 -/**
1.347 -Return #iProcessPriority.
1.348 -*/
1.349 -inline TProcessPriority E32ImageHeader::ProcessPriority() const
1.350 - {
1.351 - return (TProcessPriority)iProcessPriority;
1.352 - }
1.353 -
1.354 -/**
1.355 -Return fffset in bytes from start of code section for the Exception Descriptor.
1.356 -Or zero if not present.
1.357 -*/
1.358 -inline TUint32 E32ImageHeader::ExceptionDescriptor() const
1.359 - {
1.360 - TUint32 xd = ((E32ImageHeaderV*)this)->iExceptionDescriptor;
1.361 -
1.362 - if((xd & 1) && (xd != 0xffffffffu))
1.363 - return (xd & ~1);
1.364 -
1.365 - return 0;
1.366 - }
1.367 -
1.368 -
1.369 -/**
1.370 -A block of imports from a single executable.
1.371 -These structures are conatined in a images Import Section (E32ImportSection).
1.372 -*/
1.373 -class E32ImportBlock
1.374 - {
1.375 -public:
1.376 - inline const E32ImportBlock* NextBlock(TUint aImpFmt) const;
1.377 - inline TInt Size(TUint aImpFmt) const;
1.378 - inline const TUint* Imports() const; // import list if present
1.379 -public:
1.380 - TUint32 iOffsetOfDllName; ///< Offset from start of import section for a NUL terminated executable (DLL or EXE) name.
1.381 - TInt iNumberOfImports; ///< Number of imports from this executable.
1.382 -// TUint iImport[iNumberOfImports]; ///< For ELF-derived executes: list of code section offsets. For PE, list of imported ordinals. Omitted in PE2 import format
1.383 - };
1.384 -
1.385 -/**
1.386 -Return size of this import block.
1.387 -@param aImpFmt Import format as obtained from image header.
1.388 -*/
1.389 -inline TInt E32ImportBlock::Size(TUint aImpFmt) const
1.390 - {
1.391 - TInt r = sizeof(E32ImportBlock);
1.392 - if(aImpFmt!=KImageImpFmt_PE2)
1.393 - r += iNumberOfImports * sizeof(TUint);
1.394 - return r;
1.395 - }
1.396 -
1.397 -/**
1.398 -Return pointer to import block which immediately follows this one.
1.399 -@param aImpFmt Import format as obtained from image header.
1.400 -*/
1.401 -inline const E32ImportBlock* E32ImportBlock::NextBlock(TUint aImpFmt) const
1.402 - {
1.403 - const E32ImportBlock* next = this + 1;
1.404 - if(aImpFmt!=KImageImpFmt_PE2)
1.405 - next = (const E32ImportBlock*)( (TUint8*)next + iNumberOfImports * sizeof(TUint) );
1.406 - return next;
1.407 - }
1.408 -
1.409 -/**
1.410 -Return address of first import in this block.
1.411 -For import format KImageImpFmt_ELF, imports are list of code section offsets.
1.412 -For import format KImageImpFmt_PE, imports are a list of imported ordinals.
1.413 -For import format KImageImpFmt_PE2, the import list is not present and should not be accessed.
1.414 -*/
1.415 -inline const TUint* E32ImportBlock::Imports() const
1.416 - {
1.417 - return (const TUint*)(this + 1);
1.418 - }
1.419 -
1.420 -
1.421 -/**
1.422 -Header for the Import Section in an image, as referenced by E32ImageHeader::iImportOffset.
1.423 -Immediately following this structure are an array of E32ImportBlock structures.
1.424 -The number of these is given by E32ImageHeader::iDllRefTableCount.
1.425 -*/
1.426 -class E32ImportSection
1.427 - {
1.428 -public:
1.429 - TInt iSize; ///< Size of this section excluding 'this' structure
1.430 -// E32ImportBlock iImportBlock[iDllRefTableCount];
1.431 - };
1.432 -
1.433 -
1.434 -/**
1.435 -A block of relocations for a single page (4kB) of code/data.
1.436 -
1.437 -Immediately following this structure are an array of TUint16 values
1.438 -each representing a single value in the page which is to be relocated.
1.439 -The lower 12 bits of each entry is the offset, in bytes, from start of this page.
1.440 -The Upper 4 bits are the relocation type to be applied to the 32-bit value located
1.441 -at that offset.
1.442 - - 1 means relocate relative to code section.
1.443 - - 2 means relocate relative to data section.
1.444 - - 3 means relocate relative to code or data section; calculate which.
1.445 -
1.446 -A value of all zeros (0x0000) is ignored. (Used for padding structure to 4 byte alignment).
1.447 -*/
1.448 -class E32RelocBlock
1.449 - {
1.450 -public:
1.451 - TUint32 iPageOffset; ///< Offset, in bytes, for the page being relocated; relative to the section start. Always a multiple of the page size: 4096 bytes.
1.452 - TUint32 iBlockSize; ///< Size, in bytes, for this block structure. Always a multiple of 4.
1.453 -// TUint16 iEntry[]
1.454 - };
1.455 -
1.456 -
1.457 -/**
1.458 -Header for a Relocation Section in an image, as referenced by E32ImageHeader::iCodeRelocOffset
1.459 -or E32ImageHeader::iDataRelocOffset.
1.460 -
1.461 -Immediately following this structure are an array of E32RelocBlock structures.
1.462 -*/
1.463 -class E32RelocSection
1.464 - {
1.465 -public:
1.466 - TInt iSize; ///< Size of this relocation section including 'this' structure. Always a multiple of 4.
1.467 - TInt iNumberOfRelocs; ///< Number of relocations in this section.
1.468 -// E32RelocBlock iRelockBlock[];
1.469 - };
1.470 -
1.471 -
1.472 -/**
1.473 -Structure contained in the export directory in text section of the stdexe/stddll.
1.474 -It contains information on the names of symbols exported by this stdexe/stddll and
1.475 -pointers to a E32EpocExpSymInfoHdr structure of any stddlls that are dependencies of
1.476 -this stdexe/stddll.
1.477 -
1.478 -This is not used for emulator images see E32EmulExpSymInfoHdr below.
1.479 -@see E32EmulExpSymInfoHdr
1.480 -*/
1.481 -class E32EpocExpSymInfoHdr
1.482 - {
1.483 -public:
1.484 - TInt iSize; // size of this Table
1.485 - TInt16 iFlags;
1.486 - TInt16 iSymCount; // number of symbols
1.487 - TInt iSymbolTblOffset; // start of the symbol table - offset from byte 0 of this header
1.488 - TInt iStringTableSz; // size of the string table
1.489 - TInt iStringTableOffset; // start of the string table having names of the symbols - offset from byte 0 of this header
1.490 - TInt iDllCount; // Number of dependent DLLs
1.491 - TInt iDepDllZeroOrdTableOffset; // offset of the DLL dependency table - offset from byte 0 of this header.
1.492 - };
1.493 -
1.494 -
1.495 -/**
1.496 -Header of the structure contained in the 'KWin32SectionName_NmdExpData'
1.497 -segment of emulator stdexe & stddll images.
1.498 -The segment contains addresses of symbols and NULL
1.499 -terminated ASCII strings of the names of static dependencies.
1.500 -For a stdexe, this segment contains the following:
1.501 - a) symbol count (iSymCount) and static dependency count (iDllCount)
1.502 - b) iSymCount * symbol addresses
1.503 - c) iSymCount * symbol names
1.504 - d) iDllCount * dependency names
1.505 -
1.506 -For a stddll, this segment contains the following:
1.507 - a) symbol count (iSymCout) is always 0
1.508 - b) static dependency count (iDllCount)
1.509 - c) iDllCount * dependency names
1.510 -The symbol addresses and names are not required for a stddll as the Windows API,
1.511 -GetProcAddress may be used to get the addresses for symbol names.
1.512 -Since this API works only on DLL handles, we explicitly list them for stdexes.
1.513 -This is used for emulator images only.
1.514 -*/
1.515 -class E32EmulExpSymInfoHdr
1.516 - {
1.517 -public:
1.518 - TInt32 iSymCount; // Number of symbols
1.519 - TInt32 iDllCount; // Number of static dependency DLLs
1.520 - };
1.521 -
1.522 -
1.523 -
1.524 -#ifdef INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
1.525 -
1.526 -// include code which implements validation functions...
1.527 -
1.528 -#ifndef RETURN_FAILURE
1.529 -#define RETURN_FAILURE(_r) return (_r)
1.530 -#endif
1.531 -
1.532 -#ifndef E32IMAGEHEADER_TRACE
1.533 -#define E32IMAGEHEADER_TRACE(_t) ((void)0)
1.534 -#endif
1.535 -
1.536 -
1.537 -#include <e32uid.h>
1.538 -
1.539 -
1.540 -/**
1.541 -Validate this image header.
1.542 -
1.543 -After successful validation the following are true:
1.544 - - File size is big enough to contain the entire header.
1.545 - - Values #iUidChecksum, #iSignature and #iHeaderCrc are correct.
1.546 - - CPU type (#iCpuIdentifier), ABI type (#iFlags&#KImageABIMask) and
1.547 - entrypoint type (#iFlags&#KImageEptMask) are valid for this system.
1.548 - - Code part of file as specified by #iCodeOffset and #iCodeSize is fully within the file.
1.549 - - Text section size (#iTextSize) is within code part.
1.550 - - Entrypoint value (#iEntryPoint) lies within the code part and is aligned correctly.
1.551 - - Export directory as specified by #iExportDirCount and #iExportDirOffset is fully
1.552 - within code part and is aligned correctly.
1.553 - - Exception description (E32ImageHeaderV::iExceptionDescriptor), if present,
1.554 - lies within the code part.
1.555 - - Data part of file as specified by #iDataOffset and #iDataSize is fully within the file.
1.556 - Or data is not present (#iDataOffset==#iDataSize==0).
1.557 - - Import section (class E32ImportSection at #iImportOffset) is within 'rest of data'
1.558 - and aligned correctly. Data following the E32ImportSection header is NOT validated or
1.559 - checked if it is fully contained within the file.
1.560 - - Code relocations (class E32RelocSection at #iCodeRelocOffset) is within 'rest of data'
1.561 - and aligned correctly. Data following the E32RelocSection header is NOT validated or
1.562 - checked if it is fully contained within the file.
1.563 - - Data relocations (class E32RelocSection at #iDataRelocOffset) is within 'rest of data'
1.564 - and aligned correctly. Data following the E32RelocSection header is NOT validated or
1.565 - checked if it is fully contained within the file.
1.566 - - Export description is validated by E32ImageHeaderV::ValidateExportDescription().
1.567 - - #iUid1 is consistant with #iFlags&#KImageDll. I.e. if flaged as a DLL, #iUid1 is
1.568 - KDynamicLibraryUidValue, otherwise it is KExecutableImageUidValue.
1.569 - - Version number (#iModuleVersion) is valid. (Major and minor versions are <32768).
1.570 - - File compression type (#iCompressionType) is supported.
1.571 - - #iHeapSizeMax>=#iHeapSizeMin
1.572 - - All signed values in header are not negative.
1.573 -
1.574 -@param aFileSize Total size of the file from which this header was created.
1.575 -@param[out] aUncompressedSize Returns the total size that the file data would be once decompressed.
1.576 -
1.577 -@return KErrNone if no errors detected;
1.578 - KErrCorrupt if errors found;
1.579 - KErrNotSupported if image format not supported on this platform.
1.580 -*/
1.581 -TInt E32ImageHeader::ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const
1.582 - {
1.583 - // check file is big enough for any header...
1.584 - if(TUint(aFileSize)<sizeof(*this))
1.585 - return KErrCorrupt;
1.586 -
1.587 - TUint hdrfmt = HeaderFormat();
1.588 - if(hdrfmt==KImageHdrFmt_V)
1.589 - return ((E32ImageHeaderV*)this)->ValidateHeader(aFileSize,aUncompressedSize);
1.590 -
1.591 - return KErrNotSupported; // header format unrecognised
1.592 - }
1.593 -
1.594 -/**
1.595 -Validate this image header.
1.596 -
1.597 -@param aFileSize Total size of the file from which this header was created.
1.598 -@param[out] aUncompressedSize Returns the total size that the file data would be once decompressed.
1.599 -
1.600 -@return KErrNone if no errors detected;
1.601 - KErrCorrupt if errors found;
1.602 - KErrNotSupported if image format not supported on this platform.
1.603 -*/
1.604 -TInt E32ImageHeaderV::ValidateHeader(TInt aFileSize, TUint32& aUncompressedSize) const
1.605 - {
1.606 - const TUint KMaxDesSize = 0x0fffffffu; // maximum size of descriptor
1.607 - if(aFileSize==-1)
1.608 - {
1.609 - // file size unknown, set to maximum valid so rest of validation works...
1.610 - aFileSize = KMaxDesSize;
1.611 - }
1.612 - if(TUint(aFileSize)>KMaxDesSize)
1.613 - RETURN_FAILURE(KErrCorrupt); // file size negative or too big
1.614 -
1.615 - aUncompressedSize = 0;
1.616 -
1.617 - // check file is big enough to contain this header...
1.618 - if(aFileSize<(TInt)sizeof(*this))
1.619 - RETURN_FAILURE(KErrCorrupt);
1.620 -
1.621 - // check header format version...
1.622 - if((iFlags&KImageHdrFmtMask)!=KImageHdrFmt_V)
1.623 - RETURN_FAILURE(KErrNotSupported);
1.624 -
1.625 - // check header size...
1.626 - TUint headerSize = iCodeOffset;
1.627 - if(headerSize>TUint(aFileSize))
1.628 - RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because Loader will fail earlier when reading header from file
1.629 -
1.630 - // check iCpuIdentifier...
1.631 - TCpu cpu = (TCpu)iCpuIdentifier;
1.632 - TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
1.633 -#if defined(__CPU_ARM)
1.634 - if(!isARM)
1.635 - RETURN_FAILURE(KErrNotSupported);
1.636 -#elif defined(__CPU_X86)
1.637 - if(cpu!=ECpuX86)
1.638 - RETURN_FAILURE(KErrNotSupported);
1.639 -#endif
1.640 - TUint32 pointerAlignMask = isARM ? 3 : 0; // mask of bits which must be zero for aligned pointers/offsets
1.641 -
1.642 - // check iUid1,iUid2,iUid3,iUidChecksum...
1.643 - TUidType uids = *(const TUidType*)&iUid1;
1.644 - TCheckedUid chkuid(uids);
1.645 - const TUint32* pChkUid = (const TUint32*)&chkuid; // need hackery to verify the UID checksum since everything is private
1.646 - if(pChkUid[3]!=iUidChecksum)
1.647 - RETURN_FAILURE(KErrCorrupt);
1.648 -
1.649 - // check iSignature...
1.650 - if(iSignature!=0x434f5045) // 'EPOC'
1.651 - RETURN_FAILURE(KErrCorrupt);
1.652 -
1.653 - // check iHeaderCrc...
1.654 - TUint32 supplied_crc = iHeaderCrc;
1.655 - ((E32ImageHeaderV*)this)->iHeaderCrc = KImageCrcInitialiser;
1.656 - TUint32 crc = 0;
1.657 - Mem::Crc32(crc, this, headerSize);
1.658 - ((E32ImageHeaderV*)this)->iHeaderCrc = supplied_crc;
1.659 - if(crc!=supplied_crc)
1.660 - RETURN_FAILURE(KErrCorrupt);
1.661 -
1.662 - // check iModuleVersion...
1.663 - TUint32 mv = iModuleVersion;
1.664 - if(mv>=0x80000000u || (mv&0x0000ffffu)>0x8000u)
1.665 - RETURN_FAILURE(KErrNotSupported);
1.666 -
1.667 - // check iCompressionType and get uncompressed size...
1.668 - TUint compression = iCompressionType;
1.669 - TUint uncompressedSize = aFileSize;
1.670 - if(compression!=KFormatNotCompressed)
1.671 - {
1.672 - if(compression!=KUidCompressionDeflate && compression!=KUidCompressionBytePair)
1.673 - RETURN_FAILURE(KErrNotSupported); // unknown compression method
1.674 - uncompressedSize = headerSize+iUncompressedSize;
1.675 - if(uncompressedSize<headerSize)
1.676 - RETURN_FAILURE(KErrCorrupt); // size overflowed 32 bits
1.677 - }
1.678 -
1.679 - // check sizes won't overflow the limit for a descriptor (many Loader uses won't like that).
1.680 - if(uncompressedSize>KMaxDesSize)
1.681 - RETURN_FAILURE(KErrCorrupt);
1.682 -
1.683 - // check KImageDll in iFlags...
1.684 - if(iFlags&KImageDll)
1.685 - {
1.686 - if(iUid1!=TUint32(KDynamicLibraryUidValue))
1.687 - RETURN_FAILURE(KErrNotSupported);
1.688 - }
1.689 - else if(iUid1!=TUint32(KExecutableImageUidValue))
1.690 - RETURN_FAILURE(KErrNotSupported);
1.691 -
1.692 - // check iFlags for ABI and entry point types...
1.693 - if(isARM)
1.694 - {
1.695 - if((iFlags&KImageEptMask)!=KImageEpt_Eka2)
1.696 - RETURN_FAILURE(KErrNotSupported);
1.697 - #if defined(__EABI__)
1.698 - if((iFlags&KImageABIMask)!=KImageABI_EABI)
1.699 - RETURN_FAILURE(KErrNotSupported);
1.700 - #elif defined(__GCC32__)
1.701 - if((iFlags&KImageABIMask)!=KImageABI_GCC98r2)
1.702 - RETURN_FAILURE(KErrNotSupported);
1.703 - #endif
1.704 - }
1.705 - else
1.706 - {
1.707 - if(iFlags&KImageEptMask)
1.708 - RETURN_FAILURE(KErrNotSupported); // no special entry point type allowed on non-ARM targets
1.709 - if(iFlags&KImageABIMask)
1.710 - RETURN_FAILURE(KErrNotSupported);
1.711 - }
1.712 -
1.713 - // check iFlags for import format...
1.714 - if((iFlags&KImageImpFmtMask)>KImageImpFmt_PE2)
1.715 - RETURN_FAILURE(KErrNotSupported);
1.716 -
1.717 - // check iHeapSizeMin...
1.718 - if(iHeapSizeMin<0)
1.719 - RETURN_FAILURE(KErrCorrupt);
1.720 -
1.721 - // check iHeapSizeMax...
1.722 - if(iHeapSizeMax<iHeapSizeMin)
1.723 - RETURN_FAILURE(KErrCorrupt);
1.724 -
1.725 - // check iStackSize...
1.726 - if(iStackSize<0)
1.727 - RETURN_FAILURE(KErrCorrupt);
1.728 -
1.729 - // check iBssSize...
1.730 - if(iBssSize<0)
1.731 - RETURN_FAILURE(KErrCorrupt);
1.732 -
1.733 - // check iEntryPoint...
1.734 - if(iEntryPoint>=TUint(iCodeSize))
1.735 - RETURN_FAILURE(KErrCorrupt);
1.736 - if(iEntryPoint+KCodeSegIdOffset+sizeof(TUint32)>TUint(iCodeSize))
1.737 - RETURN_FAILURE(KErrCorrupt);
1.738 - if(iEntryPoint&pointerAlignMask)
1.739 - RETURN_FAILURE(KErrCorrupt); // not aligned
1.740 -
1.741 - // check iCodeBase...
1.742 - if(iCodeBase&3)
1.743 - RETURN_FAILURE(KErrCorrupt); // not aligned
1.744 -
1.745 - // check iDataBase...
1.746 - if(iDataBase&3)
1.747 - RETURN_FAILURE(KErrCorrupt); // not aligned
1.748 -
1.749 - // check iDllRefTableCount...
1.750 - if(iDllRefTableCount<0)
1.751 - RETURN_FAILURE(KErrCorrupt);
1.752 - if(iDllRefTableCount)
1.753 - {
1.754 - if(!iImportOffset)
1.755 - RETURN_FAILURE(KErrCorrupt); // we link to DLLs but have no import data
1.756 - }
1.757 -
1.758 - // check iCodeOffset and iCodeSize specify region in file...
1.759 - TUint codeStart = iCodeOffset;
1.760 - TUint codeEnd = codeStart+iCodeSize;
1.761 - if(codeEnd<codeStart)
1.762 - RETURN_FAILURE(KErrCorrupt);
1.763 -// if(codeStart<headerSize)
1.764 -// RETURN_FAILURE(KErrCorrupt); // can't happen because headerSize is defined as iCodeOffset (codeStart)
1.765 - if(codeEnd>uncompressedSize)
1.766 - RETURN_FAILURE(KErrCorrupt);
1.767 -
1.768 - // check iDataOffset and iDataSize specify region in file...
1.769 - TUint dataStart = iDataOffset;
1.770 - TUint dataEnd = dataStart+iDataSize;
1.771 - if(dataEnd<dataStart)
1.772 - RETURN_FAILURE(KErrCorrupt);
1.773 - if(!dataStart)
1.774 - {
1.775 - // no data...
1.776 - if(dataEnd)
1.777 - RETURN_FAILURE(KErrCorrupt);
1.778 - }
1.779 - else
1.780 - {
1.781 - if(dataStart<codeEnd)
1.782 - RETURN_FAILURE(KErrCorrupt);
1.783 - if(dataEnd>uncompressedSize)
1.784 - RETURN_FAILURE(KErrCorrupt);
1.785 - if((dataStart-codeStart)&pointerAlignMask)
1.786 - RETURN_FAILURE(KErrCorrupt); // data not aligned with respect to code
1.787 - }
1.788 -
1.789 -
1.790 - // check total data size isn't too bit...
1.791 - TUint totalDataSize = iDataSize+iBssSize;
1.792 - if(totalDataSize>0x7fff0000)
1.793 - RETURN_FAILURE(KErrNoMemory);
1.794 -
1.795 - // check iExportDirOffset and iExportDirCount specify region in code part...
1.796 - if(TUint(iExportDirCount)>65535)
1.797 - RETURN_FAILURE(KErrCorrupt); // too many exports
1.798 - if(iExportDirCount)
1.799 - {
1.800 - TUint exportsStart = iExportDirOffset;
1.801 - TUint exportsEnd = exportsStart+iExportDirCount*sizeof(TUint32);
1.802 - if(iFlags&KImageNmdExpData)
1.803 - exportsStart -= sizeof(TUint32); // allow for 0th ordinal
1.804 - if(exportsEnd<exportsStart)
1.805 - RETURN_FAILURE(KErrCorrupt);
1.806 - if(exportsStart<codeStart)
1.807 - RETURN_FAILURE(KErrCorrupt);
1.808 - if(exportsEnd>codeEnd)
1.809 - RETURN_FAILURE(KErrCorrupt);
1.810 - if((exportsStart-codeStart)&pointerAlignMask)
1.811 - RETURN_FAILURE(KErrCorrupt); // not aligned within code section
1.812 - }
1.813 -
1.814 - // check iTextSize...
1.815 - if(TUint(iTextSize)>TUint(iCodeSize))
1.816 - RETURN_FAILURE(KErrCorrupt);
1.817 -
1.818 - // check iImportOffset...
1.819 - TUint start = iImportOffset;
1.820 - if(start)
1.821 - {
1.822 - TUint end = start+sizeof(E32ImportSection); // minimum valid size
1.823 - if(end<start)
1.824 - RETURN_FAILURE(KErrCorrupt);
1.825 - if(start<codeEnd)
1.826 - RETURN_FAILURE(KErrCorrupt);
1.827 - if(end>uncompressedSize)
1.828 - RETURN_FAILURE(KErrCorrupt);
1.829 - if((start-codeEnd)&pointerAlignMask)
1.830 - RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
1.831 - }
1.832 -
1.833 - // check iCodeRelocOffset...
1.834 - start = iCodeRelocOffset;
1.835 - if(start)
1.836 - {
1.837 - TUint end = start+sizeof(E32RelocSection); // minimum valid size
1.838 - if(end<start)
1.839 - RETURN_FAILURE(KErrCorrupt);
1.840 - if(start<codeEnd)
1.841 - RETURN_FAILURE(KErrCorrupt);
1.842 - if(end>uncompressedSize)
1.843 - RETURN_FAILURE(KErrCorrupt);
1.844 - if((start-codeEnd)&pointerAlignMask)
1.845 - RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
1.846 - }
1.847 -
1.848 - // check iDataRelocOffset...
1.849 - start = iDataRelocOffset;
1.850 - if(start)
1.851 - {
1.852 - TUint end = start+sizeof(E32RelocSection); // minimum valid size
1.853 - if(end<start)
1.854 - RETURN_FAILURE(KErrCorrupt);
1.855 - if(start<codeEnd)
1.856 - RETURN_FAILURE(KErrCorrupt);
1.857 - if(end>uncompressedSize)
1.858 - RETURN_FAILURE(KErrCorrupt);
1.859 - if((start-codeEnd)&pointerAlignMask)
1.860 - RETURN_FAILURE(KErrCorrupt); // not aligned within 'rest of data'
1.861 - }
1.862 -
1.863 - // check exception descriptor...
1.864 - if(iExceptionDescriptor&1) // if valid...
1.865 - if(iExceptionDescriptor>=TUint(iCodeSize))
1.866 - RETURN_FAILURE(KErrCorrupt);
1.867 -
1.868 - TInt r = ValidateExportDescription();
1.869 - if(r!=KErrNone)
1.870 - RETURN_FAILURE(r);
1.871 -
1.872 - // done...
1.873 - aUncompressedSize = uncompressedSize;
1.874 - return KErrNone;
1.875 - }
1.876 -
1.877 -
1.878 -/**
1.879 -Valdate that the export description is valid.
1.880 -*/
1.881 -TInt E32ImageHeaderV::ValidateExportDescription() const
1.882 - {
1.883 - TUint headerSize = iCodeOffset;
1.884 -
1.885 - // check export description...
1.886 - TUint edSize = iExportDescSize + sizeof(iExportDescSize) + sizeof(iExportDescType);
1.887 - edSize = (edSize+3)&~3;
1.888 - TUint edEnd = _FOFF(E32ImageHeaderV,iExportDescSize)+edSize;
1.889 - if(edEnd!=headerSize)
1.890 - RETURN_FAILURE(KErrCorrupt);
1.891 -
1.892 - // size of bitmap of exports...
1.893 - TUint bitmapSize = (iExportDirCount+7) >> 3;
1.894 -
1.895 - // check export description bitmap...
1.896 - switch(iExportDescType)
1.897 - {
1.898 - case KImageHdr_ExpD_NoHoles:
1.899 - // no bitmap to check...
1.900 - E32IMAGEHEADER_TRACE(("ValidateExportDescription NoHoles"));
1.901 - return KErrNone;
1.902 -
1.903 - case KImageHdr_ExpD_FullBitmap:
1.904 - // full bitmap present...
1.905 - E32IMAGEHEADER_TRACE(("ValidateExportDescription FullBitmap"));
1.906 - if(bitmapSize!=iExportDescSize)
1.907 - RETURN_FAILURE(KErrCorrupt);
1.908 - return KErrNone;
1.909 -
1.910 - case KImageHdr_ExpD_SparseBitmap8:
1.911 - {
1.912 - // sparse bitmap present...
1.913 - E32IMAGEHEADER_TRACE(("ValidateExportDescription SparseBitmap8"));
1.914 -
1.915 - // get size of meta-bitmap...
1.916 - TUint metaBitmapSize = (bitmapSize+7) >> 3;
1.917 - if(metaBitmapSize>iExportDescSize)
1.918 - RETURN_FAILURE(KErrCorrupt); // doesn't fit
1.919 -
1.920 - TUint totalSize = metaBitmapSize;
1.921 -
1.922 - // scan meta-bitmap counting extra bytes which should be present...
1.923 - const TUint8* metaBitmap = iExportDesc;
1.924 - const TUint8* metaBitmapEnd = metaBitmap + metaBitmapSize;
1.925 - while(metaBitmap<metaBitmapEnd)
1.926 - {
1.927 - TUint bits = *metaBitmap++;
1.928 - do
1.929 - {
1.930 - if(bits&1)
1.931 - ++totalSize; // another byte is present in bitmap
1.932 - }
1.933 - while(bits>>=1);
1.934 - }
1.935 -
1.936 - if(totalSize!=iExportDescSize)
1.937 - RETURN_FAILURE(KErrCorrupt);
1.938 - }
1.939 - return KErrNone;
1.940 -
1.941 - default:
1.942 - E32IMAGEHEADER_TRACE(("ValidateExportDescription ?"));
1.943 - RETURN_FAILURE(KErrNotSupported);
1.944 - }
1.945 - }
1.946 -
1.947 -
1.948 -/**
1.949 -Validate a relocation section.
1.950 -
1.951 -@param aBufferStart Start of buffer containing the data after the code part in the image file.
1.952 -@param aBufferSize Size of data at aBufferStart.
1.953 -@param aRelocationInfoOffset File offset for relocation section. (#iCodeRelocOffset or #iDataRelocOffset.)
1.954 -@param aRelocatedSectionSize Size of section being relocated. (#iCodeSize or #iDataSize.)
1.955 -@param[out] aRelocationSection Set to the start of the relocation section in the given buffer.
1.956 -
1.957 -@return KErrNone if relocation section is valid, else KErrCorrupt.
1.958 -*/
1.959 -TInt E32ImageHeaderV::ValidateRelocations(TAny* aBufferStart, TUint aBufferSize, TUint aRelocationInfoOffset, TUint aRelocatedSectionSize, E32RelocSection*& aRelocationSection) const
1.960 - {
1.961 - aRelocationSection = 0;
1.962 - if(!aRelocationInfoOffset)
1.963 - return KErrNone; // no relocations
1.964 -
1.965 - // get alignment requirements...
1.966 - TCpu cpu = (TCpu)iCpuIdentifier;
1.967 - TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
1.968 - TUint32 pointerAlignMask = isARM ? 3 : 0; // mask of bits which must be zero for aligned pointers/offsets
1.969 -
1.970 - // buffer pointer to read relocation from...
1.971 - TUint8* bufferStart = (TUint8*)aBufferStart;
1.972 - TUint8* bufferEnd = bufferStart+aBufferSize;
1.973 - TUint baseOffset = iCodeOffset+iCodeSize; // file offset for aBufferStart
1.974 - TUint8* sectionStart = (bufferStart+aRelocationInfoOffset-baseOffset);
1.975 - TUint8* p = sectionStart;
1.976 -
1.977 - // read section header (ValidateHeader has alread checked this is OK)...
1.978 - E32RelocSection* sectionHeader = (E32RelocSection*)p;
1.979 - TUint size = sectionHeader->iSize;
1.980 - TUint relocsRemaining = sectionHeader->iNumberOfRelocs;
1.981 - E32IMAGEHEADER_TRACE(("E32RelocSection 0x%x %d",size,relocsRemaining));
1.982 - if(size&3)
1.983 - RETURN_FAILURE(KErrCorrupt); // not multiple of word size
1.984 -
1.985 - // calculate buffer range for block data...
1.986 - p = (TUint8*)(sectionHeader+1); // start of first block
1.987 - TUint8* sectionEnd = p+size;
1.988 - if(sectionEnd<p)
1.989 - RETURN_FAILURE(KErrCorrupt); // math overflow
1.990 - if(sectionEnd>bufferEnd)
1.991 - RETURN_FAILURE(KErrCorrupt); // overflows buffer
1.992 -
1.993 - // process each block...
1.994 - while(p!=sectionEnd)
1.995 - {
1.996 - E32RelocBlock* block = (E32RelocBlock*)p;
1.997 -
1.998 - // get address of first entry in this block...
1.999 - TUint16* entryPtr = (TUint16*)(block+1);
1.1000 - if((TUint8*)entryPtr<(TUint8*)block || (TUint8*)entryPtr>sectionEnd)
1.1001 - RETURN_FAILURE(KErrCorrupt); // overflows relocation section
1.1002 -
1.1003 - // read block header...
1.1004 - TUint pageOffset = block->iPageOffset;
1.1005 - TUint blockSize = block->iBlockSize;
1.1006 - E32IMAGEHEADER_TRACE(("E32RelocSection block 0x%x 0x%x",pageOffset,blockSize));
1.1007 - if(pageOffset&0xfff)
1.1008 - RETURN_FAILURE(KErrCorrupt); // not page aligned
1.1009 - if(blockSize<sizeof(E32RelocBlock))
1.1010 - RETURN_FAILURE(KErrCorrupt); // blockSize must be at least that of the header just read
1.1011 - if(blockSize&3)
1.1012 - RETURN_FAILURE(KErrCorrupt); // not word aligned
1.1013 -
1.1014 - // caculate end of entries in this block...
1.1015 - TUint16* entryEnd = (TUint16*)(p+blockSize);
1.1016 - if(entryEnd<entryPtr)
1.1017 - RETURN_FAILURE(KErrCorrupt); // math overflow
1.1018 - if(entryEnd>(TUint16*)sectionEnd)
1.1019 - RETURN_FAILURE(KErrCorrupt); // overflows relocation section
1.1020 -
1.1021 - // process each entry in this block...
1.1022 - while(entryPtr<entryEnd)
1.1023 - {
1.1024 - TUint entry = *entryPtr++;
1.1025 - E32IMAGEHEADER_TRACE(("E32RelocSection entry 0x%04x",entry));
1.1026 - if(!entry)
1.1027 - continue;
1.1028 -
1.1029 - // check relocation type...
1.1030 - TUint entryType = entry&0xf000;
1.1031 - if(entryType!=KTextRelocType && entryType!=KDataRelocType && entryType!=KInferredRelocType)
1.1032 - RETURN_FAILURE(KErrCorrupt);
1.1033 -
1.1034 - // check relocation is within section being relocated...
1.1035 - TUint offset = pageOffset+(entry&0x0fff);
1.1036 - if(offset>=aRelocatedSectionSize || offset+4>aRelocatedSectionSize)
1.1037 - RETURN_FAILURE(KErrCorrupt); // not within section
1.1038 - if(offset&pointerAlignMask)
1.1039 - RETURN_FAILURE(KErrCorrupt); // not aligned correctly
1.1040 -
1.1041 - // count each relocation processed...
1.1042 - --relocsRemaining;
1.1043 - }
1.1044 -
1.1045 - // next sub block...
1.1046 - p = (TUint8*)entryEnd;
1.1047 - }
1.1048 -
1.1049 - // check number of relocations in section header is correct...
1.1050 - E32IMAGEHEADER_TRACE(("E32RelocSection relocsRemaining=%d",relocsRemaining));
1.1051 - if(relocsRemaining)
1.1052 - RETURN_FAILURE(KErrCorrupt); // incorrect number of entries
1.1053 -
1.1054 - aRelocationSection = sectionHeader;
1.1055 - return KErrNone;
1.1056 - }
1.1057 -
1.1058 -
1.1059 -/**
1.1060 -Validate an import section.
1.1061 -
1.1062 -For PE format imports, this also verifies that the Import Address Table fits within the code
1.1063 -part of the image.
1.1064 -
1.1065 -@param aBufferStart Start of buffer containing the data after the code part in the image file.
1.1066 -@param aBufferSize Size of data at aBufferStart.
1.1067 -@param[out] aBiggestImportCount Largest number of imports the image has from any single dependency.
1.1068 -
1.1069 -@return KErrNone if section is valid (or absent), else KErrCorrupt.
1.1070 -*/
1.1071 -TInt E32ImageHeaderV::ValidateImports(TAny* aBufferStart, TUint aBufferSize, TUint& aBiggestImportCount) const
1.1072 - {
1.1073 - if(!iImportOffset)
1.1074 - {
1.1075 - aBiggestImportCount = 0;
1.1076 - return KErrNone; // no imports
1.1077 - }
1.1078 -
1.1079 - // get alignment requirements...
1.1080 - TCpu cpu = (TCpu)iCpuIdentifier;
1.1081 - TBool isARM = (cpu==ECpuArmV4 || cpu==ECpuArmV5 || cpu==ECpuArmV6);
1.1082 - TUint32 pointerAlignMask = isARM ? 3 : 0; // mask of bits which must be zero for aligned pointers/offsets
1.1083 -
1.1084 - // buffer pointer to read imports from...
1.1085 - TUint8* bufferStart = (TUint8*)aBufferStart;
1.1086 - TUint8* bufferEnd = bufferStart+aBufferSize;
1.1087 - TUint baseOffset = iCodeOffset+iCodeSize; // file offset for aBufferStart
1.1088 - TUint8* sectionStart = (bufferStart+iImportOffset-baseOffset);
1.1089 - TUint8* p = sectionStart;
1.1090 -
1.1091 - // read section header (ValidateHeader has alread checked this is OK)...
1.1092 - E32ImportSection* sectionHeader = (E32ImportSection*)p;
1.1093 - TUint size = sectionHeader->iSize;
1.1094 - E32IMAGEHEADER_TRACE(("E32ImportSection 0x%x",size));
1.1095 -
1.1096 - // check section lies within buffer...
1.1097 - p = (TUint8*)(sectionHeader+1); // start of first import block
1.1098 - TUint8* sectionEnd = sectionStart+size;
1.1099 - if(sectionEnd<p)
1.1100 - RETURN_FAILURE(KErrCorrupt); // math overflow or not big enough to contain header
1.1101 - if(sectionEnd>bufferEnd)
1.1102 - RETURN_FAILURE(KErrCorrupt); // overflows buffer
1.1103 -
1.1104 - // process each import block...
1.1105 - TUint numDeps = iDllRefTableCount;
1.1106 - TUint biggestImportCount = 0;
1.1107 - TUint totalImports = 0;
1.1108 - TUint importFormat = iFlags&KImageImpFmtMask;
1.1109 - while(numDeps--)
1.1110 - {
1.1111 - // get block header...
1.1112 - E32ImportBlock* block = (E32ImportBlock*)p;
1.1113 - p = (TUint8*)(block+1);
1.1114 - if(p<(TUint8*)block || p>sectionEnd)
1.1115 - RETURN_FAILURE(KErrCorrupt); // overflows buffer
1.1116 -
1.1117 - E32IMAGEHEADER_TRACE(("E32ImportBlock 0x%x %d",block->iOffsetOfDllName,block->iNumberOfImports));
1.1118 -
1.1119 - // check import dll name is within section...
1.1120 - TUint8* name = sectionStart+block->iOffsetOfDllName;
1.1121 - if(name<sectionStart || name>=sectionEnd)
1.1122 - RETURN_FAILURE(KErrCorrupt); // not within import section
1.1123 - while(*name++ && name<sectionEnd)
1.1124 - {}
1.1125 - if(name[-1])
1.1126 - RETURN_FAILURE(KErrCorrupt); // name overflows section
1.1127 - E32IMAGEHEADER_TRACE(("E32ImportBlock %s",sectionStart+block->iOffsetOfDllName));
1.1128 -
1.1129 - // process import count...
1.1130 - TUint numberOfImports = block->iNumberOfImports;
1.1131 - if(numberOfImports>=0x80000000u/sizeof(TUint32))
1.1132 - RETURN_FAILURE(KErrCorrupt); // size doesn't fit into a signed integer
1.1133 - if(numberOfImports>biggestImportCount)
1.1134 - biggestImportCount = numberOfImports;
1.1135 - totalImports += numberOfImports;
1.1136 -
1.1137 - // process import data...
1.1138 -
1.1139 - // PE2 doesn't have any more data...
1.1140 - if(importFormat==KImageImpFmt_PE2)
1.1141 - continue;
1.1142 -
1.1143 - // get import data range...
1.1144 - TUint32* imports = (TUint32*)p;
1.1145 - TUint32* importsEnd = imports+numberOfImports;
1.1146 - if(importsEnd<imports)
1.1147 - RETURN_FAILURE(KErrCorrupt); // math overflow. Fuzzer can't trigger this because needs aBufferStart to be in to be >0x80000000
1.1148 - if(importsEnd>(TUint32*)sectionEnd)
1.1149 - RETURN_FAILURE(KErrCorrupt); // overflows buffer
1.1150 -
1.1151 - // move pointer on to next block...
1.1152 - p = (TUint8*)importsEnd;
1.1153 -
1.1154 - if(importFormat==KImageImpFmt_ELF)
1.1155 - {
1.1156 - // check imports are in code section...
1.1157 - TUint32 limit = iCodeSize-sizeof(TUint32);
1.1158 - while(imports<importsEnd)
1.1159 - {
1.1160 - TUint32 i = *imports++;
1.1161 - if(i>limit)
1.1162 - RETURN_FAILURE(KErrCorrupt);
1.1163 - if(i&pointerAlignMask)
1.1164 - RETURN_FAILURE(KErrCorrupt); // not word aligned
1.1165 - }
1.1166 - }
1.1167 - else if(importFormat==KImageImpFmt_PE)
1.1168 - {
1.1169 - // import data is not used, so don't bother checking it
1.1170 - }
1.1171 - else
1.1172 - {
1.1173 - RETURN_FAILURE(KErrCorrupt); // bad import format, Fuzzer can't trigger this because import format checked by header validation
1.1174 - }
1.1175 -
1.1176 - // next block...
1.1177 - p = (TUint8*)block->NextBlock(importFormat);
1.1178 - }
1.1179 -
1.1180 - // done processing imports; for PE derived files now check import address table (IAT)...
1.1181 - if(importFormat==KImageImpFmt_PE || importFormat==KImageImpFmt_PE2)
1.1182 - {
1.1183 - if(totalImports>=0x80000000u/sizeof(TUint32))
1.1184 - RETURN_FAILURE(KErrCorrupt); // size doesn't fit into a signed integer
1.1185 - TUint importAddressTable = iTextSize; // offset for IAT
1.1186 - if(importAddressTable&pointerAlignMask)
1.1187 - RETURN_FAILURE(KErrCorrupt); // Fuzzer can't trigger this because PE imports are for X86 which doesn't have alignment restrictions
1.1188 - TUint importAddressTableEnd = importAddressTable+sizeof(TUint32)*totalImports;
1.1189 - if(importAddressTableEnd<importAddressTable || importAddressTableEnd>TUint(iCodeSize))
1.1190 - RETURN_FAILURE(KErrCorrupt); // import address table overflows code part of file
1.1191 - E32IMAGEHEADER_TRACE(("E32ImportSection IAT offsets 0x%x..0x%x",importAddressTable,importAddressTableEnd));
1.1192 - }
1.1193 -
1.1194 - aBiggestImportCount = biggestImportCount;
1.1195 - return KErrNone;
1.1196 - }
1.1197 -
1.1198 -
1.1199 -
1.1200 -
1.1201 -/**
1.1202 -Validate a whole executable image.
1.1203 -
1.1204 -This runs all of the other validation methods in turn.
1.1205 -
1.1206 -@param aBufferStart Start of buffer containing the data after the header part of an image file.
1.1207 -@param aBufferSize Size of data at aBufferStart.
1.1208 -
1.1209 -@return KErrNone if image is valid, else KErrCorrupt or KErrNotSupported.
1.1210 -*/
1.1211 -TInt E32ImageHeaderV::ValidateWholeImage(TAny* aBufferStart, TUint aBufferSize) const
1.1212 - {
1.1213 - TUint32 dummyUncompressedSize;
1.1214 - TInt r = ValidateHeader(TotalSize()+aBufferSize,dummyUncompressedSize);
1.1215 - if(r!=KErrNone)
1.1216 - return r;
1.1217 -
1.1218 - TInt endOfCodeOffset = iCodeSize;
1.1219 - void* restOfFileData = ((TUint8*)aBufferStart)+endOfCodeOffset;
1.1220 - TInt restOfFileSize = aBufferSize-endOfCodeOffset;
1.1221 -
1.1222 - E32RelocSection* dummy;
1.1223 - r = ValidateRelocations(restOfFileData,restOfFileSize,iCodeRelocOffset,iCodeSize,dummy);
1.1224 - if(r!=KErrNone)
1.1225 - return r;
1.1226 - r = ValidateRelocations(restOfFileData,restOfFileSize,iDataRelocOffset,iDataSize,dummy);
1.1227 - if(r!=KErrNone)
1.1228 - return r;
1.1229 -
1.1230 - TUint biggestImportCount;
1.1231 - r = ValidateImports(restOfFileData,restOfFileSize,biggestImportCount);
1.1232 - if(r!=KErrNone)
1.1233 - return r;
1.1234 -
1.1235 - return r;
1.1236 - }
1.1237 -
1.1238 -
1.1239 -#endif // INCLUDE_E32IMAGEHEADER_IMPLEMENTATION
1.1240 -
1.1241 -
1.1242 -#endif // __F32IMAGE_H__