sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include sl@0: #include "mmu/mm.h" sl@0: #include "mmboot.h" sl@0: #include "mmu/mcodepaging.h" sl@0: sl@0: #include "cache_maintenance.h" sl@0: sl@0: sl@0: DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&) sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg")); sl@0: return new DMemModelCodeSeg; sl@0: } sl@0: sl@0: sl@0: // sl@0: // DMemModelCodeSegMemory sl@0: // sl@0: sl@0: DEpocCodeSegMemory* DEpocCodeSegMemory::New(DEpocCodeSeg* aCodeSeg) sl@0: { sl@0: return new DMemModelCodeSegMemory(aCodeSeg); sl@0: } sl@0: sl@0: sl@0: DMemModelCodeSegMemory::DMemModelCodeSegMemory(DEpocCodeSeg* aCodeSeg) sl@0: : DEpocCodeSegMemory(aCodeSeg) sl@0: { sl@0: } sl@0: sl@0: sl@0: TInt DMemModelCodeSegMemory::Create(TCodeSegCreateInfo& aInfo, DMemModelProcess* aProcess) sl@0: { sl@0: TInt r; sl@0: sl@0: TUint codePageCount; sl@0: TUint dataPageCount; sl@0: TBool isDemandPaged; sl@0: if(!aInfo.iUseCodePaging) sl@0: { sl@0: isDemandPaged = 0; sl@0: codePageCount = MM::RoundToPageCount(iRamInfo.iCodeSize+iRamInfo.iDataSize); sl@0: dataPageCount = 0; sl@0: } sl@0: else sl@0: { sl@0: isDemandPaged = 1; sl@0: codePageCount = MM::RoundToPageCount(iRamInfo.iCodeSize); sl@0: dataPageCount = MM::RoundToPageCount(iRamInfo.iDataSize); sl@0: sl@0: iDataSectionMemory = Kern::Alloc(iRamInfo.iDataSize); sl@0: if(!iDataSectionMemory) sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: iCodeSeg->iSize = codePageCount<IsExe()) sl@0: {// Get the os asid without opening a reference on it as aProcess isn't fully sl@0: // created yet so won't free its os asid. sl@0: r = MM::VirtualAlloc(aProcess->OsAsid(),iRamInfo.iCodeRunAddr,codeSize,isDemandPaged); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: aProcess->iCodeVirtualAllocSize = codeSize; sl@0: aProcess->iCodeVirtualAllocAddress = iRamInfo.iCodeRunAddr; sl@0: iCodeSeg->iAttr |= ECodeSegAttAddrNotUnique; sl@0: } sl@0: else sl@0: { sl@0: r = MM::VirtualAllocCommon(iRamInfo.iCodeRunAddr,codeSize,isDemandPaged); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: iVirtualAllocCommonSize = codeSize; sl@0: } sl@0: sl@0: // create memory object for codeseg... sl@0: if(isDemandPaged) sl@0: { sl@0: // create memory object... sl@0: r = MM::PagedCodeNew(iCodeMemoryObject, codePageCount, iPagedCodeInfo); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: // get file blockmap for codeseg contents... sl@0: r = iPagedCodeInfo->ReadBlockMap(aInfo); sl@0: if (r != KErrNone) sl@0: return r; sl@0: } sl@0: else sl@0: { sl@0: // create memory object... sl@0: TMemoryCreateFlags flags = (TMemoryCreateFlags)(EMemoryCreateNoWipe | EMemoryCreateAllowExecution); sl@0: r = MM::MemoryNew(iCodeMemoryObject, EMemoryObjectMovable, codePageCount, flags); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: // commit memory... sl@0: r = MM::MemoryAlloc(iCodeMemoryObject,0,codePageCount); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: } sl@0: sl@0: // create a mapping of the memory for the loader... sl@0: // No need to open reference on os asid it is the current thread/process's. sl@0: DMemModelProcess* pP = (DMemModelProcess*)TheCurrentThread->iOwningProcess; sl@0: r = MM::MappingNew(iCodeLoadMapping,iCodeMemoryObject,EUserReadWrite,pP->OsAsid()); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: iRamInfo.iCodeLoadAddr = MM::MappingBase(iCodeLoadMapping); sl@0: sl@0: // work out where the loader is to put the loaded data section... sl@0: TInt loadSize = iRamInfo.iCodeSize; // size of memory filled by loader sl@0: if(iRamInfo.iDataSize) sl@0: { sl@0: if(!dataPageCount) sl@0: { sl@0: // data loaded immediately after code... sl@0: iRamInfo.iDataLoadAddr = iRamInfo.iCodeLoadAddr+iRamInfo.iCodeSize; sl@0: loadSize += iRamInfo.iDataSize; sl@0: } sl@0: else sl@0: { sl@0: // create memory object for data... sl@0: DMemoryObject* dataMemory; sl@0: r = MM::MemoryNew(dataMemory, EMemoryObjectMovable, dataPageCount, EMemoryCreateNoWipe); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: // commit memory... sl@0: r = MM::MemoryAlloc(dataMemory,0,dataPageCount); sl@0: if(r==KErrNone) sl@0: { sl@0: // create a mapping of the memory for the loader... sl@0: // No need to open reference on os asid it is the current thread/process's. sl@0: r = MM::MappingNew(iDataLoadMapping,dataMemory,EUserReadWrite,pP->OsAsid()); sl@0: } sl@0: sl@0: if(r!=KErrNone) sl@0: { sl@0: MM::MemoryDestroy(dataMemory); sl@0: return r; sl@0: } sl@0: sl@0: iRamInfo.iDataLoadAddr = MM::MappingBase(iDataLoadMapping); sl@0: } sl@0: } sl@0: sl@0: if(!isDemandPaged) sl@0: { sl@0: // wipe memory that the loader wont fill... sl@0: UNLOCK_USER_MEMORY(); sl@0: memset((TAny*)(iRamInfo.iCodeLoadAddr+loadSize), 0x03, codeSize-loadSize); sl@0: LOCK_USER_MEMORY(); sl@0: } sl@0: sl@0: // done... sl@0: iCreator = pP; sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt DMemModelCodeSegMemory::Loaded(TCodeSegCreateInfo& aInfo) sl@0: { sl@0: if(iPagedCodeInfo) sl@0: { sl@0: // get information needed to fixup code for it's run address... sl@0: TInt r = iPagedCodeInfo->ReadFixupTables(aInfo); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: MM::PagedCodeLoaded(iCodeMemoryObject, iRamInfo.iCodeLoadAddr); sl@0: } sl@0: else sl@0: { sl@0: // make code visible to instruction cache... sl@0: UNLOCK_USER_MEMORY(); sl@0: CacheMaintenance::CodeChanged(iRamInfo.iCodeLoadAddr, iRamInfo.iCodeSize); sl@0: LOCK_USER_MEMORY(); sl@0: } sl@0: sl@0: // adjust iDataLoadAddr to point to address contents for initial data section sl@0: // in running process... sl@0: if(iRamInfo.iDataLoadAddr) sl@0: { sl@0: TAny* dataSection = iDataSectionMemory; sl@0: if(dataSection) sl@0: { sl@0: // contents for initial data section to be stored in iDataSectionMemory... sl@0: UNLOCK_USER_MEMORY(); sl@0: memcpy(dataSection,(TAny*)iRamInfo.iDataLoadAddr,iRamInfo.iDataSize); sl@0: LOCK_USER_MEMORY(); sl@0: iRamInfo.iDataLoadAddr = (TLinAddr)dataSection; sl@0: } sl@0: else sl@0: { sl@0: // contents for initial data section stored after code... sl@0: __NK_ASSERT_DEBUG(iRamInfo.iDataLoadAddr==iRamInfo.iCodeLoadAddr+iRamInfo.iCodeSize); // check data loaded at end of code sl@0: iRamInfo.iDataLoadAddr = iRamInfo.iCodeRunAddr+iRamInfo.iCodeSize; sl@0: } sl@0: } sl@0: sl@0: // copy export directory (this will now have fixups applied)... sl@0: TInt exportDirSize = iRamInfo.iExportDirCount * sizeof(TLinAddr); sl@0: if(exportDirSize > 0 || (exportDirSize==0 && (iCodeSeg->iAttr&ECodeSegAttNmdExpData)) ) sl@0: { sl@0: exportDirSize += sizeof(TLinAddr); sl@0: TLinAddr* expDir = (TLinAddr*)Kern::Alloc(exportDirSize); sl@0: if(!expDir) sl@0: return KErrNoMemory; sl@0: iCopyOfExportDir = expDir; sl@0: TLinAddr expDirLoad = iRamInfo.iExportDir-iRamInfo.iCodeRunAddr+iRamInfo.iCodeLoadAddr; sl@0: UNLOCK_USER_MEMORY(); sl@0: memcpy(expDir,(TAny*)(expDirLoad-sizeof(TLinAddr)),exportDirSize); sl@0: LOCK_USER_MEMORY(); sl@0: } sl@0: sl@0: // unmap code from loading process... sl@0: DMemModelProcess* pP=(DMemModelProcess*)TheCurrentThread->iOwningProcess; sl@0: __ASSERT_ALWAYS(iCreator==pP, MM::Panic(MM::ECodeSegLoadedNotCreator)); sl@0: MM::MappingDestroy(iCodeLoadMapping); sl@0: MM::MappingAndMemoryDestroy(iDataLoadMapping); sl@0: iCreator=NULL; sl@0: sl@0: // Mark the code memory object read only to prevent malicious code modifying it. sl@0: TInt r = MM::MemorySetReadOnly(iCodeMemoryObject); sl@0: __ASSERT_ALWAYS(r == KErrNone, MM::Panic(MM::ECodeSegSetReadOnlyFailure)); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void DMemModelCodeSegMemory::Destroy() sl@0: { sl@0: MM::MappingDestroy(iCodeLoadMapping); sl@0: MM::MappingAndMemoryDestroy(iDataLoadMapping); sl@0: } sl@0: sl@0: sl@0: DMemModelCodeSegMemory::~DMemModelCodeSegMemory() sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSegMemory::~DMemModelCodeSegMemory %x", this)); sl@0: __NK_ASSERT_DEBUG(iAccessCount==0); sl@0: sl@0: MM::MappingDestroy(iCodeLoadMapping); sl@0: MM::MappingAndMemoryDestroy(iDataLoadMapping); sl@0: MM::MemoryDestroy(iCodeMemoryObject); sl@0: sl@0: if(iVirtualAllocCommonSize) sl@0: MM::VirtualFreeCommon(iRamInfo.iCodeRunAddr, iVirtualAllocCommonSize); sl@0: sl@0: Kern::Free(iCopyOfExportDir); sl@0: Kern::Free(iDataSectionMemory); sl@0: } sl@0: sl@0: sl@0: // sl@0: // DMemModelCodeSeg sl@0: // sl@0: sl@0: DMemModelCodeSeg::DMemModelCodeSeg() sl@0: { sl@0: } sl@0: sl@0: sl@0: DMemModelCodeSeg::~DMemModelCodeSeg() sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::Destruct %C", this)); sl@0: DCodeSeg::Wait(); sl@0: sl@0: MM::MappingDestroy(iCodeLoadMapping); sl@0: MM::MappingDestroy(iCodeGlobalMapping); sl@0: MM::MemoryDestroy(iCodeMemoryObject); sl@0: sl@0: if(Memory()) sl@0: Memory()->Destroy(); sl@0: sl@0: if(iDataAllocSize) sl@0: MM::VirtualFreeCommon(iDataAllocBase,iDataAllocSize); sl@0: sl@0: DCodeSeg::Signal(); sl@0: sl@0: Kern::Free(iKernelData); sl@0: sl@0: DEpocCodeSeg::Destruct(); sl@0: } sl@0: sl@0: sl@0: TInt DMemModelCodeSeg::DoCreateRam(TCodeSegCreateInfo& aInfo, DProcess* aProcess) sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::DoCreateRam %C", this)); sl@0: sl@0: SRamCodeInfo& ri = RamInfo(); sl@0: iSize = MM::RoundToPageSize(ri.iCodeSize+ri.iDataSize); sl@0: if (iSize==0) sl@0: return KErrCorrupt; sl@0: sl@0: TBool kernel = ( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel ); sl@0: // TBool user_global = ( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttGlobal ); sl@0: TBool user_local = ( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == 0 ); sl@0: sl@0: TUint total_data_size = ri.iDataSize+ri.iBssSize; sl@0: sl@0: if(user_local) sl@0: { sl@0: // setup paging attribute for code... sl@0: if(aInfo.iUseCodePaging) sl@0: iAttr |= ECodeSegAttCodePaged; sl@0: sl@0: if(total_data_size && !IsExe()) sl@0: { sl@0: // setup paging attribute for data section... sl@0: if(aInfo.iUseCodePaging) sl@0: if(K::MemModelAttributes & EMemModelAttrDataPaging) sl@0: iAttr |= ECodeSegAttDataPaged; sl@0: sl@0: // allocate virtual address for data section... sl@0: TInt r = MM::VirtualAllocCommon(iDataAllocBase,total_data_size,iAttr&ECodeSegAttDataPaged); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: iDataAllocSize = total_data_size; sl@0: ri.iDataRunAddr = iDataAllocBase; sl@0: } sl@0: sl@0: // create DCodeSegMemory for RAM loaded user local code... sl@0: TInt r = Memory()->Create(aInfo,(DMemModelProcess*)aProcess); sl@0: sl@0: #ifdef BTRACE_FLEXIBLE_MEM_MODEL sl@0: if (r == KErrNone) sl@0: { sl@0: BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsCodeSeg,Memory()->iCodeMemoryObject,this); sl@0: } sl@0: #endif sl@0: sl@0: return r; sl@0: } sl@0: sl@0: // kernel or user-global code... sl@0: sl@0: // create memory object for codeseg... sl@0: TMemoryCreateFlags flags = EMemoryCreateAllowExecution; sl@0: if(kernel) sl@0: { sl@0: flags = (TMemoryCreateFlags)(flags|EMemoryCreateNoWipe); sl@0: } sl@0: TInt r = MM::MemoryNew(iCodeMemoryObject, EMemoryObjectMovable, MM::BytesToPages(iSize), flags); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: // commit memory... sl@0: r = MM::MemoryAlloc(iCodeMemoryObject,0,MM::BytesToPages(iSize)); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: sl@0: // create a mapping of the memory for the loader... sl@0: // No need to open reference on os asid it is the current thread/process's. sl@0: DMemModelProcess* pP = (DMemModelProcess*)TheCurrentThread->iOwningProcess; sl@0: r = MM::MappingNew(iCodeLoadMapping,iCodeMemoryObject,EUserReadWrite,pP->OsAsid()); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: ri.iCodeLoadAddr = MM::MappingBase(iCodeLoadMapping); sl@0: sl@0: // create a global mapping of the memory for the codeseg to run at... sl@0: r = MM::MappingNew(iCodeGlobalMapping,iCodeMemoryObject,kernel?ESupervisorExecute:EUserExecute,KKernelOsAsid); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: ri.iCodeRunAddr = MM::MappingBase(iCodeGlobalMapping); sl@0: sl@0: if(kernel) sl@0: { sl@0: // setup data section memory... sl@0: if (ri.iDataSize) sl@0: ri.iDataLoadAddr = ri.iCodeLoadAddr+ri.iCodeSize; sl@0: if (total_data_size) sl@0: { sl@0: iKernelData = Kern::Alloc(total_data_size); sl@0: if (!iKernelData) sl@0: return KErrNoMemory; sl@0: ri.iDataRunAddr = (TLinAddr)iKernelData; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // we don't allow static data in global code... sl@0: ri.iDataLoadAddr = 0; sl@0: ri.iDataRunAddr = 0; sl@0: } sl@0: sl@0: #ifdef BTRACE_FLEXIBLE_MEM_MODEL sl@0: BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsCodeSeg,iCodeMemoryObject,this); sl@0: #endif sl@0: sl@0: // done... sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt DMemModelCodeSeg::DoCreateXIP(DProcess* aProcess) sl@0: { sl@0: // __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::DoCreateXIP %C proc %O", this, aProcess)); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt DMemModelCodeSeg::Loaded(TCodeSegCreateInfo& aInfo) sl@0: { sl@0: if(iXIP) sl@0: return DEpocCodeSeg::Loaded(aInfo); sl@0: sl@0: TBool kernel = ( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel ); sl@0: TBool user_global = ( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttGlobal ); sl@0: TBool user_local = ( (iAttr&(ECodeSegAttKernel|ECodeSegAttGlobal)) == 0 ); sl@0: if(user_local) sl@0: { sl@0: TInt r = Memory()->Loaded(aInfo); sl@0: if(r!=KErrNone) sl@0: return r; sl@0: } sl@0: else if((kernel && iExeCodeSeg!=this) || user_global) sl@0: { sl@0: // user-global or kernel code... sl@0: SRamCodeInfo& ri = RamInfo(); sl@0: UNLOCK_USER_MEMORY(); sl@0: CacheMaintenance::CodeChanged(ri.iCodeLoadAddr, ri.iCodeSize); sl@0: LOCK_USER_MEMORY(); sl@0: MM::MappingDestroy(iCodeLoadMapping); sl@0: // adjust iDataLoadAddr to point to address contents for initial data section sl@0: // in running process... sl@0: if(ri.iDataLoadAddr) sl@0: ri.iDataLoadAddr = ri.iCodeRunAddr+ri.iCodeSize; sl@0: sl@0: // Mark the code memory object read only to prevent malicious code modifying it. sl@0: TInt r = MM::MemorySetReadOnly(iCodeMemoryObject); sl@0: __ASSERT_ALWAYS(r == KErrNone, MM::Panic(MM::ECodeSegSetReadOnlyFailure)); sl@0: } sl@0: return DEpocCodeSeg::Loaded(aInfo); sl@0: } sl@0: sl@0: sl@0: void DMemModelCodeSeg::ReadExportDir(TUint32* aDest) sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DMemModelCodeSeg::ReadExportDir %C %08x",this, aDest)); sl@0: sl@0: if(!iXIP) sl@0: { sl@0: // This is not XIP code so the loader can't access the export directory. sl@0: if (Memory()->iCopyOfExportDir) sl@0: {// This must be local user side code. sl@0: __NK_ASSERT_DEBUG((iAttr & (ECodeSegAttKernel|ECodeSegAttGlobal)) == 0); sl@0: // Copy the kernel's copy of the export directory for this code seg to the loader's buffer. sl@0: SRamCodeInfo& ri = RamInfo(); sl@0: TInt size = (ri.iExportDirCount + 1) * sizeof(TLinAddr); sl@0: kumemput(aDest, Memory()->iCopyOfExportDir, size); sl@0: } sl@0: else sl@0: {// This must be kernel side code. sl@0: __NK_ASSERT_DEBUG((iAttr & (ECodeSegAttKernel|ECodeSegAttGlobal)) == ECodeSegAttKernel); sl@0: // Copy the export directory for this code seg to the loader's buffer. sl@0: SRamCodeInfo& ri = RamInfo(); sl@0: TInt size = (ri.iExportDirCount + 1) * sizeof(TLinAddr); sl@0: TAny* expDirLoad = (TAny*)(ri.iExportDir - sizeof(TLinAddr)); sl@0: kumemput(aDest, expDirLoad, size); sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: TBool DMemModelCodeSeg::OpenCheck(DProcess* aProcess) sl@0: { sl@0: return FindCheck(aProcess); sl@0: } sl@0: sl@0: sl@0: TBool DMemModelCodeSeg::FindCheck(DProcess* aProcess) sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess)); sl@0: if (aProcess) sl@0: { sl@0: DMemModelProcess& p=*(DMemModelProcess*)aProcess; sl@0: DCodeSeg* pPSeg=p.CodeSeg(); sl@0: if (iAttachProcess && iAttachProcess!=aProcess) sl@0: return EFalse; sl@0: if (iExeCodeSeg && iExeCodeSeg!=pPSeg) sl@0: return EFalse; sl@0: } sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: void DMemModelCodeSeg::BTracePrime(TInt aCategory) sl@0: { sl@0: DCodeSeg::BTracePrime(aCategory); sl@0: sl@0: #ifdef BTRACE_FLEXIBLE_MEM_MODEL sl@0: if (aCategory == BTrace::EFlexibleMemModel || aCategory == -1) sl@0: { sl@0: // code seg mutex is held here, so memory objects cannot be destroyed sl@0: DMemModelCodeSegMemory* codeSegMemory = Memory(); sl@0: if (codeSegMemory) sl@0: { sl@0: if (codeSegMemory->iCodeMemoryObject) sl@0: { sl@0: BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsCodeSeg,Memory()->iCodeMemoryObject,this); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (iCodeMemoryObject) sl@0: { sl@0: BTrace8(BTrace::EFlexibleMemModel,BTrace::EMemoryObjectIsCodeSeg,iCodeMemoryObject,this); sl@0: } sl@0: } sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: sl@0: // sl@0: // TPagedCodeInfo sl@0: // sl@0: sl@0: TPagedCodeInfo::~TPagedCodeInfo() sl@0: { sl@0: Kern::Free(iCodeRelocTable); sl@0: Kern::Free(iCodePageOffsets); sl@0: } sl@0: sl@0: sl@0: TInt TPagedCodeInfo::ReadBlockMap(const TCodeSegCreateInfo& aInfo) sl@0: { sl@0: if(aInfo.iCodeBlockMapEntriesSize <= 0) sl@0: return KErrArgument; // no block map provided sl@0: sl@0: // get compression data... sl@0: iCompressionType = aInfo.iCompressionType; sl@0: switch(iCompressionType) sl@0: { sl@0: case KFormatNotCompressed: sl@0: __ASSERT_COMPILE(KFormatNotCompressed==0); // Decompress() assumes this sl@0: break; sl@0: sl@0: case KUidCompressionBytePair: sl@0: { sl@0: if(!aInfo.iCodePageOffsets) sl@0: return KErrArgument; sl@0: sl@0: TInt pageCount = MM::RoundToPageCount(aInfo.iCodeSize); sl@0: sl@0: TInt size = sizeof(TInt32) * (pageCount + 1); sl@0: iCodePageOffsets = (TInt32*)Kern::Alloc(size); sl@0: if(!iCodePageOffsets) sl@0: return KErrNoMemory; sl@0: kumemget32(iCodePageOffsets, aInfo.iCodePageOffsets, size); sl@0: sl@0: #ifdef __DUMP_BLOCKMAP_INFO sl@0: Kern::Printf("CodePageOffsets:"); sl@0: for (TInt i = 0 ; i < pageCount + 1 ; ++i) sl@0: Kern::Printf(" %08x", iCodePageOffsets[i]); sl@0: #endif sl@0: sl@0: TInt last = 0; sl@0: for(TInt j=0; j (aInfo.iCodeLengthInFile + aInfo.iCodeStartInFile)) sl@0: { sl@0: __NK_ASSERT_DEBUG(0); sl@0: return KErrCorrupt; sl@0: } sl@0: last = iCodePageOffsets[j]; sl@0: } sl@0: } sl@0: break; sl@0: sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: // Copy block map data itself... sl@0: sl@0: #ifdef __DUMP_BLOCKMAP_INFO sl@0: Kern::Printf("Original block map"); sl@0: Kern::Printf(" block granularity: %d", aInfo.iCodeBlockMapCommon.iBlockGranularity); sl@0: Kern::Printf(" block start offset: %x", aInfo.iCodeBlockMapCommon.iBlockStartOffset); sl@0: Kern::Printf(" start block address: %016lx", aInfo.iCodeBlockMapCommon.iStartBlockAddress); sl@0: Kern::Printf(" local drive number: %d", aInfo.iCodeBlockMapCommon.iLocalDriveNumber); sl@0: Kern::Printf(" entry size: %d", aInfo.iCodeBlockMapEntriesSize); sl@0: #endif sl@0: sl@0: // Find relevant paging device sl@0: iCodeLocalDrive = aInfo.iCodeBlockMapCommon.iLocalDriveNumber; sl@0: if(TUint(iCodeLocalDrive) >= (TUint)KMaxLocalDrives) sl@0: { sl@0: __KTRACE_OPT(KPAGING,Kern::Printf("Bad local drive number")); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: DPagingDevice* device = CodePagingDevice(iCodeLocalDrive); sl@0: if(!device) sl@0: { sl@0: __KTRACE_OPT(KPAGING,Kern::Printf("No paging device installed for drive")); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: // Set code start offset sl@0: iCodeStartInFile = aInfo.iCodeStartInFile; sl@0: if(iCodeStartInFile < 0) sl@0: { sl@0: __KTRACE_OPT(KPAGING,Kern::Printf("Bad code start offset")); sl@0: return KErrArgument; sl@0: } sl@0: sl@0: // Allocate buffer for block map and copy from user-side sl@0: TBlockMapEntryBase* buffer = (TBlockMapEntryBase*)Kern::Alloc(aInfo.iCodeBlockMapEntriesSize); sl@0: if(!buffer) sl@0: return KErrNoMemory; sl@0: kumemget32(buffer, aInfo.iCodeBlockMapEntries, aInfo.iCodeBlockMapEntriesSize); sl@0: sl@0: #ifdef __DUMP_BLOCKMAP_INFO sl@0: Kern::Printf(" entries:"); sl@0: for (TInt k = 0 ; k < aInfo.iCodeBlockMapEntriesSize / sizeof(TBlockMapEntryBase) ; ++k) sl@0: Kern::Printf(" %d: %d blocks at %08x", k, buffer[k].iNumberOfBlocks, buffer[k].iStartBlock); sl@0: #endif sl@0: sl@0: // Initialise block map sl@0: TInt r = iBlockMap.Initialise(aInfo.iCodeBlockMapCommon, sl@0: buffer, sl@0: aInfo.iCodeBlockMapEntriesSize, sl@0: device->iReadUnitShift, sl@0: iCodeStartInFile + aInfo.iCodeLengthInFile); sl@0: if(r!=KErrNone) sl@0: { sl@0: Kern::Free(buffer); sl@0: return r; sl@0: } sl@0: sl@0: #if defined(__DUMP_BLOCKMAP_INFO) && defined(_DEBUG) sl@0: iBlockMap.Dump(); sl@0: #endif sl@0: sl@0: iCodeSize = aInfo.iCodeSize; sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Read code relocation table and import fixup table from user side. sl@0: */ sl@0: TInt TPagedCodeInfo::ReadFixupTables(const TCodeSegCreateInfo& aInfo) sl@0: { sl@0: iCodeRelocTableSize = aInfo.iCodeRelocTableSize; sl@0: iImportFixupTableSize = aInfo.iImportFixupTableSize; sl@0: iCodeDelta = aInfo.iCodeDelta; sl@0: iDataDelta = aInfo.iDataDelta; sl@0: sl@0: // round sizes up to four-byte boundaries... sl@0: TUint relocSize = (iCodeRelocTableSize + 3) & ~3; sl@0: TUint fixupSize = (iImportFixupTableSize + 3) & ~3; sl@0: sl@0: // copy relocs and fixups... sl@0: iCodeRelocTable = (TUint8*)Kern::Alloc(relocSize+fixupSize); sl@0: if (!iCodeRelocTable) sl@0: return KErrNoMemory; sl@0: iImportFixupTable = iCodeRelocTable + relocSize; sl@0: kumemget32(iCodeRelocTable, aInfo.iCodeRelocTable, relocSize); sl@0: kumemget32(iImportFixupTable, aInfo.iImportFixupTable, fixupSize); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void TPagedCodeInfo::ApplyFixups(TLinAddr aBuffer, TUint iIndex) sl@0: { sl@0: // START_PAGING_BENCHMARK; sl@0: sl@0: // relocate code... sl@0: if(iCodeRelocTableSize) sl@0: { sl@0: TUint8* codeRelocTable = iCodeRelocTable; sl@0: TUint startOffset = ((TUint32*)codeRelocTable)[iIndex]; sl@0: TUint endOffset = ((TUint32*)codeRelocTable)[iIndex+1]; sl@0: sl@0: __KTRACE_OPT(KPAGING, Kern::Printf("Performing code relocation: start == %x, end == %x", startOffset, endOffset)); sl@0: __ASSERT_ALWAYS(startOffset<=endOffset && endOffset<=iCodeRelocTableSize, K::Fault(K::ECodeSegBadFixupTables)); sl@0: sl@0: const TUint32 codeDelta = iCodeDelta; sl@0: const TUint32 dataDelta = iDataDelta; sl@0: sl@0: const TUint16* ptr = (const TUint16*)(codeRelocTable + startOffset); sl@0: const TUint16* end = (const TUint16*)(codeRelocTable + endOffset); sl@0: while(ptr