diff -r 819e59dfc032 -r 2d9cac8919d3 utilityapps/launcher/engine/src/e32image.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utilityapps/launcher/engine/src/e32image.cpp Mon Oct 18 16:30:05 2010 +0300 @@ -0,0 +1,846 @@ +/* +* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + +#include "e32image.h" +#include "e32imageheaders.h" +#include "launchertraces.h" + + +const TInt KMaxHeaderSize = sizeof(E32ImageHeaderV) + 65536/8; + +SCapabilitySet AllCapabilities; +SCapabilitySet DisabledCapabilities; + +// --------------------------------------------------------------------------- + +E32ImageReader* E32ImageReader::NewLC() + { + E32ImageReader* self = new(ELeave) E32ImageReader; + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- + +E32ImageReader::E32ImageReader() + { + } + +// --------------------------------------------------------------------------- + +void E32ImageReader::ConstructL() + { + LOGSTRING("Launcher: E32ImageReader::ConstructL"); + + iEnv = CEikonEnv::Static(); + } + +// --------------------------------------------------------------------------- + +CDesCArray* E32ImageReader::ListOfDLLsL(const TDesC& aFullPathToE32Image) + { + LOGSTRING("Launcher: E32ImageReader::ListOfDLLsL"); + + // open the file for reading + User::LeaveIfError( iFile.Open(iEnv->FsSession(), aFullPathToE32Image, EFileRead) ); + CleanupClosePushL(iFile); + + // get local copies of capability sets + TCapabilitySet caps; + caps.SetAllSupported(); + AllCapabilities=*(SCapabilitySet*)∩︀ + caps.SetDisabled(); + DisabledCapabilities=*(SCapabilitySet*)∩︀ + + // read the header of the image + User::LeaveIfError( E32ImageHeader::New(iHeader, iFile) ); + + // set stuff + iHeapSizeMin = iHeader->iHeapSizeMin; + iHeapSizeMax = iHeader->iHeapSizeMax; + iStackSize = iHeader->iStackSize; + iPriority = iHeader->ProcessPriority(); + iDepCount = iHeader->iDllRefTableCount; + iExportDirCount = iHeader->iExportDirCount; + iExportDir = iHeader->iExportDirOffset-iHeader->iCodeOffset; + iTextSize = iHeader->iTextSize; + iCodeSize = iHeader->iCodeSize; + iDataSize = iHeader->iDataSize; + iBssSize = iHeader->iBssSize; + iTotalDataSize = iDataSize+iBssSize; + iFileEntryPoint = iHeader->iEntryPoint; + iEntryPtVeneer = 0; + iExceptionDescriptor = iHeader->ExceptionDescriptor(); + if (iHeader->iExportDirOffset) + iExportDirLoad=iExportDir; + + // allocate data for the code area + iCodeLoadAddress = (TUint32)User::Alloc(iCodeSize); + + // load data from the binary + User::LeaveIfError( LoadData() ); + + // create an array for the dll names from the import list + CDesCArray* dllArray = new(ELeave) CDesCArrayFlat(100); + CleanupStack::PushL(dllArray); + + // get the dll names from the import section + E32ImportSection* importSection = (E32ImportSection *)iImportData; + E32ImportBlock* block; + if(importSection) + block = (E32ImportBlock*)(importSection+1); + else + block = NULL; + iNextImportPos = 0; + + // loop through all import data blocks + for (TInt i=0; iiOffsetOfDllName); + TBuf8 rootname; + if (dllname.Length() > KMaxKernelName) + User::Leave( KErrNotSupported ); + + // parse the filename + TFileNameInfo fni; + User::LeaveIfError( fni.Set(dllname, TFileNameInfo::EAllowUid) ); + fni.GetName(rootname, TFileNameInfo::EIncludeBaseExt); + + // append the name to the dll name array + TFileName dllName16; + dllName16.Copy(rootname); + dllArray->AppendL(dllName16); + + // get the next block + TUint impfmt = iHeader->ImportFormat(); + block = (E32ImportBlock*)block->NextBlock(impfmt); + } + + CleanupStack::Pop(); //dllArray + CleanupStack::PopAndDestroy(); //iFile + + // free memory + delete iHeader; + iHeader = NULL; + delete iImportSection; + iImportSection = NULL; + delete iCodeRelocSection; + iCodeRelocSection = NULL; + delete iDataRelocSection; + iDataRelocSection = NULL; + + User::Free((TAny*)iCodeLoadAddress); + User::Free(iRestOfFileData); + User::Free(iCurrentImportList); + if (iExportDirLoadAllocated) + User::Free((TAny*)iExportDirLoad); + + return dllArray; + } + +// --------------------------------------------------------------------------- + +E32ImageReader::~E32ImageReader() + { + LOGSTRING("Launcher: E32ImageReader::~E32ImageReader"); + } + + +// --------------------------------------------------------------------------- + +TInt FileRead(RFile& aFile, TUint8* aDest, TInt aSize) + { + TPtr8 p(aDest,aSize,aSize); + return aFile.Read(p,aSize); + } + +// --------------------------------------------------------------------------- + +TInt E32ImageHeader::New(E32ImageHeader*& aHdr, RFile& aFile) + { + LOGSTRING("Launcher: E32ImageHeader::New"); + + E32ImageHeader* h = NULL; + TInt hdrsz = 0; + TInt filesize; + TInt r = aFile.Size(filesize); + if (r!=KErrNone) + return r; + E32ImageHeader bh; + r = FileRead(aFile, (TUint8*)&bh, sizeof(E32ImageHeader)); + if (r==KErrNone) + { + hdrsz = bh.TotalSize(); + if ( (TUint(hdrsz) > TUint(KMaxHeaderSize)) || (TUint(hdrsz) < TUint(sizeof(bh))) ) + return KErrCorrupt; + } + h = (E32ImageHeader*)User::Alloc(hdrsz); + if (!h) + return KErrNoMemory; + wordmove(h, &bh, sizeof(E32ImageHeader)); + if (hdrsz > (TInt)sizeof(E32ImageHeader)) + r = FileRead(aFile, (TUint8*)(h + 1), hdrsz - sizeof(E32ImageHeader)); + if (r==KErrNone) + r = h->IntegrityCheck(filesize); + if (r==KErrNone) + { + if (h->HeaderFormat() >= KImageHdrFmt_V) + { + // Overide capabilities in image + for(TInt i=0; iiS.iCaps[i] |= DisabledCapabilities[i]; + ((E32ImageHeaderV*)h)->iS.iCaps[i] &= AllCapabilities[i]; + } + } + aHdr = h; + } + else + { + delete h; + aHdr = NULL; + } + return r; + } + +// --------------------------------------------------------------------------- + +TInt E32ImageHeader::IntegrityCheck(TInt aFileSize) + { + LOGSTRING("Launcher: E32ImageHeader::IntegrityCheck"); + + TInt hdrsz = TotalSize(); + TUint hdrfmt = HeaderFormat(); + TUidType uids = *(const TUidType*)&iUid1; + E32ImageHeaderV* v = NULL; + TCheckedUid chkuid(uids); + const TUint32* pChkUid = (const TUint32*)&chkuid; + + if (pChkUid[3] != iUidChecksum) + return KErrCorrupt; + + if (hdrfmt == KImageHdrFmt_V) + { + TUint32 supplied_crc = iHeaderCrc; + iHeaderCrc = KImageCrcInitialiser; + TUint32 crc = 0; + Mem::Crc32(crc, this, hdrsz); + iHeaderCrc = supplied_crc; + if (crc != supplied_crc) + return KErrCorrupt; + v = (E32ImageHeaderV*)this; + TUint total_eds = v->iExportDescSize + sizeof(v->iExportDescSize) + sizeof(v->iExportDescType); + total_eds = (total_eds + 3) &~ 3; + if (total_eds + (TUint)_FOFF(E32ImageHeaderV, iExportDescSize) != (TUint)hdrsz) + return KErrCorrupt; + if (TUint(v->iExportDescType) > KImageHdr_ExpD_SparseBitmap8) + return KErrNotSupported; + } + else if (hdrfmt >= KImageHdrFmt_V) + return KErrNotSupported; + + TCpu cpu = CpuIdentifier(); + TUint abi = ABI(); + TUint impfmt = ImportFormat(); + TUint compression = CompressionType(); + + TUint uncompressed_size = compression ? UncompressedFileSize() : (TUint)aFileSize; + + if (iSignature != 0x434f5045) // 'EPOC' + return KErrCorrupt; + if (iCodeSize<0) + return KErrCorrupt; + if (iDataSize<0) + return KErrCorrupt; + if (iHeapSizeMin<0) + return KErrCorrupt; + if (iHeapSizeMax= uncompressed_size) + return KErrCorrupt; + if (TUint(iExportDirCount)>65535) + return KErrCorrupt; + if (iTextSize<0) + return KErrCorrupt; + if (iCodeSize= uncompressed_size) + return KErrCorrupt; + if (iDataOffset >= uncompressed_size) + return KErrCorrupt; + if (iImportOffset >= uncompressed_size) + return KErrCorrupt; + if (iCodeRelocOffset >= uncompressed_size) + return KErrCorrupt; + if (iDataRelocOffset >= uncompressed_size) + return KErrCorrupt; + if (TUint(iCodeSize+iDataSize) > uncompressed_size) + return KErrCorrupt; + + if (abi>KImageABI_EABI) + return KErrNotSupported; + if (impfmt>KImageImpFmt_PE2) + return KErrNotSupported; + if (iUid1 != (TUint32)KExecutableImageUidValue && iUid1 != (TUint32)KDynamicLibraryUidValue) + return KErrNotSupported; + TUint32 mv = ModuleVersion(); + if (mv >= 0x80000000u || (mv & 0x0000ffffu) > 0x8000u) + return KErrNotSupported; + + return KErrNone; + } +// --------------------------------------------------------------------------- + +TInt E32ImageReader::LoadData() + { + LOGSTRING("Launcher: E32ImageReader::LoadData"); + + TInt remainder; + iFile.Size(remainder); + + remainder -= iHeader->TotalSize(); + TUint32 compression = iHeader->CompressionType(); + if (compression != KMyFormatNotCompressed) + { + remainder = iHeader->UncompressedFileSize() - iHeader->iCodeOffset; + } + + remainder -= iHeader->iCodeSize; + + if (remainder > 0) + { + iRestOfFileData = (TUint8*)User::Alloc(remainder); + if (iRestOfFileData) + iRestOfFileSize=remainder; + else + return KErrNoMemory; + } + + iConversionOffset = iHeader->iCodeOffset + iHeader->iCodeSize; + + TInt r = LoadFile(compression); + if (r !=KErrNone) + return r; + + + TUint8* source=NULL; + if (iHeader->iImportOffset) + { + TUint bufferOffset=iHeader->iImportOffset-iConversionOffset; + + if(bufferOffset>iRestOfFileSize || bufferOffset+sizeof(E32ImportSection)>iRestOfFileSize) + return KErrCorrupt; + + source=iRestOfFileData+bufferOffset; + + iImportSection = new E32ImportSection; + + if (iImportSection) + Mem::Move((TText8*)iImportSection, source, sizeof(E32ImportSection)); + else + return KErrNoMemory; + } + + iCodeDelta = iCodeRunAddress-iHeader->iCodeBase; + iDataDelta = iDataRunAddress-iHeader->iDataBase; + + if (r==KErrNone) + r = ReadImportData(); + + return r; + } + +// --------------------------------------------------------------------------- + +TUint8* E32ImageReader::MemoryMove(TAny* aDestination, const TAny* aSource, TInt aNumberofBytes) + { + return Mem::Move(aDestination, aSource, aNumberofBytes); + } + +// --------------------------------------------------------------------------- + +GLDEF_C TInt svRelocateExports(TAny* aPtr) + { + E32ImageReader* pI=(E32ImageReader*)aPtr; + TUint32* destExport=(TUint32*)pI->iExportDirLoad; + TInt i=pI->iExportDirCount; + TUint32 codeBase=pI->iCodeRunAddress; + while (i-->0) + *destExport+++=codeBase; + return 0; + } + +// --------------------------------------------------------------------------- + +TInt E32ImageReader::LoadFile(TUint32 aCompression) + { + LOGSTRING("Launcher: E32ImageReader::LoadFile"); + + TInt r(KErrNone); + + if (aCompression == KMyFormatNotCompressed) + r=LoadFileNoCompress(); + + else if (aCompression == KMyUidCompressionDeflate) + { + TRAP(r, LoadFileInflateL()); + } + + else + r = KErrNotSupported; + + return r; + } + +// --------------------------------------------------------------------------- + +TInt E32ImageReader::LoadFileNoCompress() + { + LOGSTRING("Launcher: E32ImageReader::LoadFileNoCompress"); + + TInt r(KErrNone); + + if (iHeader->iCodeSize) + { + r = Read(iHeader->iCodeOffset, (TText8*)iCodeLoadAddress, iCodeSize); + } + + if (r != KErrNone) + { + return r; + } + + if (iRestOfFileSize) + { + r = Read(iConversionOffset, (TText8*)iRestOfFileData, iRestOfFileSize); + } + + return r; + } + +// --------------------------------------------------------------------------- + +void FileCleanup(TAny* aPtr) + { + TFileInput* f=(TFileInput*)aPtr; + f->Cancel(); + delete f; + } + +// --------------------------------------------------------------------------- + +void E32ImageReader::LoadFileInflateL() + { + LOGSTRING("Launcher: E32ImageReader::LoadFileInflateL"); + + TInt pos = iHeader->TotalSize(); + User::LeaveIfError(iFile.Seek(ESeekStart,pos)); + + TFileInput* file = new (ELeave) TFileInput(iFile); + CleanupStack::PushL(TCleanupItem(&FileCleanup,file)); + CInflater* inflater = CInflater::NewLC(*file); + + if (iHeader->iCodeSize) + { + TInt count = inflater->ReadL((TUint8*)iCodeLoadAddress, iCodeSize, &MemoryMove); + + if(count!=iCodeSize) + User::Leave(KErrCorrupt); + } + + if (iRestOfFileSize) + { + TUint32 count = inflater->ReadL(iRestOfFileData, iRestOfFileSize, &Mem::Move); + + if(count!=iRestOfFileSize) + User::Leave(KErrCorrupt); + } + + CleanupStack::PopAndDestroy(2,file); + } + +// --------------------------------------------------------------------------- + +TInt E32ImageReader::Read(TText8* aDest, TInt aSize) + { + TPtr8 p(aDest,aSize,aSize); + return iFile.Read(p,aSize); + } + +// --------------------------------------------------------------------------- + +TInt E32ImageReader::Read(TInt aPos, TText8* aDest, TInt aSize) + { + TPtr8 p(aDest,aSize,aSize); + if (aPos<0) + return KErrCorrupt; + return iFile.Read(aPos,p,aSize); + } + +// --------------------------------------------------------------------------- + +TInt E32ImageReader::ReadImportData() + { + LOGSTRING("Launcher: E32ImageReader::ReadImportData"); + + if (!iHeader->iImportOffset) + return KErrNone; + + TUint32 bufferOffset = iHeader->iImportOffset-iConversionOffset; + + if(bufferOffset>iRestOfFileSize || bufferOffset+iImportSection->iSize>iRestOfFileSize) + return KErrCorrupt; + + iImportData = (TUint32*)(iRestOfFileData+bufferOffset); + + E32ImportSection* s = (E32ImportSection*)iImportData; + E32ImportBlock* b = (E32ImportBlock*)(s + 1); + TUint impfmt = iHeader->ImportFormat(); + TInt i; + TInt n = 0; + + for (i=0; iiNumberOfImports > n) + n = b->iNumberOfImports; + b = (E32ImportBlock*)b->NextBlock(impfmt); + } + + iCurrentImportList = (TUint32*)User::Alloc(n * sizeof(TUint32)); + + if (!iCurrentImportList) + return KErrNoMemory; + + return KErrNone; + } + +// --------------------------------------------------------------------------- + +inline CInflater::CInflater(TBitInput& aInput) + :iBits(&aInput),iEncoding(0),iOut(0) + {} + +// --------------------------------------------------------------------------- + +void CInflater::ConstructL() + { + iEncoding=new(ELeave) TEncoding; + InitL(); + iLen=0; + iOut=new(ELeave) TUint8[KDeflateMaxDistance]; + iAvail=iLimit=iOut; + } + +// --------------------------------------------------------------------------- + +CInflater* CInflater::NewLC(TBitInput& aInput) + { + CInflater* self=new(ELeave) CInflater(aInput); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- + +CInflater::~CInflater() + { + delete iEncoding; + delete [] iOut; + } + +// --------------------------------------------------------------------------- + +TInt CInflater::ReadL(TUint8* aBuffer,TInt aLength, TMemoryMoveFunction aMemMovefn) + { + TInt tfr=0; + for (;;) + { + TInt len=Min(aLength,iLimit-iAvail); + if (len && aBuffer) + { + aMemMovefn(aBuffer,iAvail,len); + aBuffer+=len; + } + aLength-=len; + iAvail+=len; + tfr+=len; + if (aLength==0) + return tfr; + len=InflateL(); + if (len==0) + return tfr; + iAvail=iOut; + iLimit=iAvail+len; + } + } + +// --------------------------------------------------------------------------- + +TInt CInflater::SkipL(TInt aLength) + { + return ReadL(0,aLength,Mem::Move); + } + +// --------------------------------------------------------------------------- + +void CInflater::InitL() + { + Huffman::InternalizeL(*iBits,iEncoding->iLitLen,KDeflationCodes); + + if (!Huffman::IsValid(iEncoding->iLitLen,TEncoding::ELitLens) || + !Huffman::IsValid(iEncoding->iDistance,TEncoding::EDistances)) + User::Leave(KErrCorrupt); + + Huffman::Decoding(iEncoding->iLitLen,TEncoding::ELitLens,iEncoding->iLitLen); + Huffman::Decoding(iEncoding->iDistance,TEncoding::EDistances,iEncoding->iDistance,KDeflateDistCodeBase); + } + +// --------------------------------------------------------------------------- + +TInt CInflater::InflateL() + { + TUint8* out=iOut; + TUint8* const end=out+KDeflateMaxDistance; + const TUint32* tree=iEncoding->iLitLen; + if (iLen<0) // EOF + return 0; + if (iLen>0) + goto useHistory; + + while (outHuffmanL(tree)-TEncoding::ELiterals; + if (val<0) + { + *out++=TUint8(val); + continue; + } + if (val==TEncoding::EEos-TEncoding::ELiterals) + { + iLen=-1; + break; + } + + TInt code=val&0xff; + if (code>=8) + { + TInt xtra=(code>>2)-1; + code-=xtra<<2; + code<<=xtra; + code|=iBits->ReadL(xtra); + } + if (valiDistance; + continue; + } + + iRptr=out-(code+1); + if (iRptr+KDeflateMaxDistanceiLitLen; + }; + + return out-iOut; + } + +// --------------------------------------------------------------------------- + +TFileInput::TFileInput(RFile& aFile) + :iFile(aFile),iReadBuf(iBuf1),iPtr(iBuf1,KBufSize) + { + aFile.Read(iPtr,iStat); + } + +// --------------------------------------------------------------------------- + +void TFileInput::Cancel() + { + if (iReadBuf) + User::WaitForRequest(iStat); + } + +// --------------------------------------------------------------------------- + +void TFileInput::UnderflowL() + { + TUint8* b=iReadBuf; + ASSERT(b!=NULL); + User::WaitForRequest(iStat); + iReadBuf=0; + User::LeaveIfError(iStat.Int()); + if(iPtr.Length()==0) + User::Leave(KErrCorrupt); + Set(b,iPtr.Length()*8); + + b = b==iBuf1 ? iBuf2 : iBuf1; + iPtr.Set(b,0,KBufSize); + iFile.Read(iPtr,iStat); + iReadBuf=b; + } + +// --------------------------------------------------------------------------- + +TFileNameInfo::TFileNameInfo() + { + memclr(this, sizeof(TFileNameInfo)); + } + +// --------------------------------------------------------------------------- + +TInt TFileNameInfo::Set(const TDesC8& aFileName, TUint aFlags) + { + iUid = 0; + iVersion = 0; + iPathPos = 0; + iName = aFileName.Ptr(); + iLen = aFileName.Length(); + iExtPos = aFileName.LocateReverse('.'); + if (iExtPos<0) + iExtPos = iLen; + TInt osq = aFileName.LocateReverse('['); + TInt csq = aFileName.LocateReverse(']'); + if (!(aFlags & EAllowUid) && (osq>=0 || csq>=0)) + { + return KErrBadName; + } + if (osq>=iExtPos || csq>=iExtPos) + { + return KErrBadName; + } + TInt p = iExtPos; + if ((aFlags & EAllowUid) && p>=10 && iName[p-1]==']' && iName[p-10]=='[') + { + TPtrC8 uidstr(iName + p - 9, 8); + TLex8 uidlex(uidstr); + TUint32 uid = 0; + TInt r = uidlex.Val(uid, EHex); + if (r==KErrNone && uidlex.Eos()) + iUid = uid, p -= 10; + } + iUidPos = p; + TInt ob = aFileName.LocateReverse('{'); + TInt cb = aFileName.LocateReverse('}'); + if (ob>=iUidPos || cb>=iUidPos) + { + return KErrBadName; + } + if (ob>=0 && cb>=0 && p-1==cb) + { + TPtrC8 p8(iName, p); + TInt d = p8.LocateReverse('.'); + TPtrC8 verstr(iName+ob+1, p-ob-2); + TLex8 verlex(verstr); + if (ob==p-10 && dob && p-1>d && (aFlags & EAllowDecimalVersion)) + { + TUint32 maj = 0; + TUint32 min = 0; + TInt r = verlex.Val(maj, EDecimal); + TUint c = (TUint)verlex.Get(); + TInt r2 = verlex.Val(min, EDecimal); + if (r==KErrNone && c=='.' && r2==KErrNone && verlex.Eos() && maj<32768 && min<32768) + iVersion = (maj << 16) | min, p = ob; + } + } + iVerPos = p; + if (iLen>=2 && iName[1]==':') + { + TUint c = iName[0]; + if (c!='?' || !(aFlags & EAllowPlaceholder)) + { + c |= 0x20; + if (c<'a' || c>'z') + { + return KErrBadName; + } + } + iPathPos = 2; + } + TPtrC8 pathp(iName+iPathPos, iVerPos-iPathPos); + if (pathp.Locate('[')>=0 || pathp.Locate(']')>=0 || pathp.Locate('{')>=0 || pathp.Locate('}')>=0 || pathp.Locate(':')>=0) + { + return KErrBadName; + } + iBasePos = pathp.LocateReverse('\\') + 1 + iPathPos; + + return KErrNone; + } + +// --------------------------------------------------------------------------- + +void TFileNameInfo::GetName(TDes8& aName, TUint aFlags) const + { + if (aFlags & EIncludeDrive) + aName.Append(Drive()); + if (aFlags & EIncludePath) + { + if (PathLen() && iName[iPathPos]!='\\') + aName.Append('\\'); + aName.Append(Path()); + } + if (aFlags & EIncludeBase) + aName.Append(Base()); + if ((aFlags & EForceVer) || ((aFlags & EIncludeVer) && VerLen()) ) + { + aName.Append('{'); + aName.AppendNumFixedWidth(iVersion, EHex, 8); + aName.Append('}'); + } + if ((aFlags & EForceUid) || ((aFlags & EIncludeUid) && UidLen()) ) + { + aName.Append('['); + aName.AppendNumFixedWidth(iUid, EHex, 8); + aName.Append(']'); + } + if (aFlags & EIncludeExt) + aName.Append(Ext()); + } + +// ---------------------------------------------------------------------------