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