kernel/eka/memmodel/epoc/pcodeseg.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/memmodel/epoc/pcodeseg.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,387 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32\memmodel\epoc\pcodeseg.cpp
+// 
+//
+
+#include "plat_priv.h"
+#include <e32uid.h>
+
+TLinAddr DCodeSeg::ExceptionDescriptor()
+	{
+	DEpocCodeSeg* s = (DEpocCodeSeg*)this;
+	if (s->iXIP)
+		return s->RomInfo().iExceptionDescriptor;
+	return s->RamInfo().iExceptionDescriptor;
+	}
+
+DEpocCodeSeg::~DEpocCodeSeg()
+	{
+	if (!iXIP && iMemory)
+		{
+		iMemory->iCodeSeg = 0;
+		iMemory->Close();
+		iMemory = NULL;
+		}
+	}
+
+void DEpocCodeSeg::Destruct()
+	{
+	DCodeSeg::Wait();
+	
+	if (iLoaderCookie!=NULL)
+		{
+		if ((TInt) iLoaderCookie&1) // Not set fully loaded
+			{
+			iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) & ~1);
+			delete iLoaderCookie;
+			iLoaderCookie=NULL;
+			}
+		else
+			{
+			// Notify reaper of destruction
+			NKern::LockSystem();
+			if (DestructNotifyRequest->IsReady())
+				{
+				DThread* t = DestructNotifyThread;
+				DestructNotifyThread = NULL;				
+				Kern::QueueRequestComplete(t, DestructNotifyRequest,KErrNone);
+				}
+			NKern::UnlockSystem();
+	
+			iLoaderCookie->iNext=DestructNotifyList;
+			DestructNotifyList=iLoaderCookie;
+			iLoaderCookie=NULL;
+			}
+		}
+
+	DCodeSeg::Signal();
+	DCodeSeg::Destruct();
+	}
+
+void DEpocCodeSeg::Info(TCodeSegCreateInfo& aInfo)
+	{
+	CHECK_PAGING_SAFE;
+	if (iXIP)
+		{
+		const TRomImageHeader& rih=RomInfo();
+		aInfo.iCodeSize=rih.iCodeSize;
+		aInfo.iTextSize=rih.iTextSize;
+		aInfo.iDataSize=rih.iDataSize;
+		aInfo.iBssSize=rih.iBssSize;
+		aInfo.iTotalDataSize=rih.iTotalDataSize;
+		aInfo.iExportDir=rih.iExportDir;
+		aInfo.iExportDirCount=rih.iExportDirCount;
+		aInfo.iCodeLoadAddress=rih.iCodeAddress;
+		aInfo.iCodeRunAddress=rih.iCodeAddress;
+		aInfo.iDataLoadAddress=rih.iDataAddress;
+		aInfo.iDataRunAddress=rih.iDataBssLinearBase;
+		aInfo.iExceptionDescriptor = rih.iExceptionDescriptor;
+		}
+	else
+		{
+		const SRamCodeInfo& ri=RamInfo();
+		aInfo.iCodeSize=ri.iCodeSize;
+		aInfo.iTextSize=ri.iTextSize;
+		aInfo.iDataSize=ri.iDataSize;
+		aInfo.iBssSize=ri.iBssSize;
+		aInfo.iTotalDataSize=ri.iDataSize+ri.iBssSize;
+		aInfo.iExportDir=ri.iExportDir;
+		aInfo.iExportDirCount=ri.iExportDirCount;
+		aInfo.iCodeLoadAddress=ri.iCodeLoadAddr;
+		aInfo.iCodeRunAddress=ri.iCodeRunAddr;
+		aInfo.iDataLoadAddress=ri.iDataLoadAddr;
+		aInfo.iDataRunAddress=ri.iDataRunAddr;
+		aInfo.iExceptionDescriptor = ri.iExceptionDescriptor;
+		}
+	DCodeSeg::Info(aInfo);
+	}
+
+void DEpocCodeSeg::GetDataSizeAndBase(TInt& aTotalDataSizeOut, TLinAddr& aDataBaseOut)
+	{
+	if (iXIP)
+		{
+		aTotalDataSizeOut=RomInfo().iTotalDataSize;
+		aDataBaseOut=RomInfo().iDataBssLinearBase;
+		}
+	else
+		{
+		aTotalDataSizeOut=RamInfo().iDataSize+RamInfo().iBssSize;
+		aDataBaseOut=RamInfo().iDataRunAddr;
+		}	
+	}
+
+TLibraryFunction DEpocCodeSeg::Lookup(TInt aOrdinal)
+	{
+	CHECK_PAGING_SAFE;
+	// return NULL for -ve ordinal or 0th ordinal when not stddll/stdexe
+	if (aOrdinal<0 || (aOrdinal==0 && !(iAttr&ECodeSegAttNmdExpData)))
+		return NULL;
+	TInt xdc;
+	TLinAddr* xd;	// points to the 0th ordinal of export table
+	if (iXIP)
+		{
+		const TRomImageHeader& rih=RomInfo();
+		xdc=rih.iExportDirCount;
+		xd=(TLinAddr*)rih.iExportDir - 1;
+		}
+	else
+		{
+		SRamCodeInfo& ri=RamInfo();
+		xdc=ri.iExportDirCount;
+		xd=(TLinAddr*)ri.iExportDir - 1;
+		}
+	if (aOrdinal <= xdc)
+		{
+		UNLOCK_USER_MEMORY();
+		TLibraryFunction f=(TLibraryFunction)xd[aOrdinal];
+		LOCK_USER_MEMORY();
+		if ((TLinAddr)f == iFileEntryPoint)
+			f = NULL;
+		__KTRACE_OPT(KDLL,Kern::Printf("Lookup(%d)->%08x",aOrdinal,f));
+		return f;
+		}
+	__KTRACE_OPT(KDLL,Kern::Printf("Lookup(%d)->NULL",aOrdinal));
+	return NULL;
+	}
+
+TInt DEpocCodeSeg::GetMemoryInfo(TModuleMemoryInfo& aInfo, DProcess*)
+	{
+	CHECK_PAGING_SAFE;
+	if (iXIP)
+		{
+		const TRomImageHeader& rih		= RomInfo();
+		aInfo.iCodeBase					= rih.iCodeAddress;
+		aInfo.iCodeSize					= rih.iTextSize;
+		aInfo.iConstDataSize			= rih.iCodeSize - aInfo.iCodeSize;
+		aInfo.iConstDataBase			= (aInfo.iConstDataSize > 0) ? (aInfo.iCodeBase + aInfo.iCodeSize) : 0;
+		aInfo.iInitialisedDataBase		= rih.iDataBssLinearBase;
+		aInfo.iInitialisedDataSize		= rih.iDataSize;
+		aInfo.iUninitialisedDataSize	= rih.iBssSize;
+		aInfo.iUninitialisedDataBase	= aInfo.iInitialisedDataBase+aInfo.iInitialisedDataSize;
+		}
+	else
+		{
+		const SRamCodeInfo& ri			= RamInfo();
+		aInfo.iCodeBase					= ri.iCodeRunAddr;
+		aInfo.iCodeSize					= ri.iTextSize;
+		aInfo.iConstDataSize			= ri.iCodeSize - aInfo.iCodeSize;
+		aInfo.iConstDataBase			= (aInfo.iConstDataSize > 0) ? (aInfo.iCodeBase + aInfo.iCodeSize) : 0;
+		aInfo.iInitialisedDataBase		= ri.iDataRunAddr;
+		aInfo.iInitialisedDataSize		= ri.iDataSize;
+		aInfo.iUninitialisedDataSize	= ri.iBssSize;
+		aInfo.iUninitialisedDataBase	= aInfo.iInitialisedDataBase + aInfo.iInitialisedDataSize;
+		}
+	return KErrNone;
+	}
+
+//const TUint32 KRomImageFlagsAlwaysLoaded=KRomImageFlagPrimary|KRomImageFlagVariant|KRomImageFlagExtension;
+const TUint32 KRomImageDataFlags=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent);
+TInt DEpocCodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
+	{
+	__KTRACE_OPT(KDLL,Kern::Printf(">DEpocCodeSeg::DoCreate code_addr=%08x",aInfo.iCodeLoadAddress));
+	CHECK_PAGING_SAFE;
+	TInt r=KErrNone;
+	TBool exeSeg=(iExeCodeSeg==this);
+	TBool kp=exeSeg && (aProcess->iAttributes&DProcess::ESupervisor);
+	TBool user_proc=exeSeg && !kp;
+	if (aInfo.iCodeLoadAddress)
+		{
+		iXIP=ETrue;
+		iInfo=(const TAny*)aInfo.iCodeLoadAddress;
+		}
+	if (user_proc)
+		{
+		r=aProcess->CreateDataBssStackArea((TProcessCreateInfo&)aInfo);
+		if (r!=KErrNone)
+			return r;
+		}
+	if (iXIP)
+		{
+		const TRomImageHeader& rih=RomInfo();
+		iXIP=ETrue;
+		if ( (rih.iFlags & (KRomImageFlagExeInTree|KRomImageFlagDll)) == (KRomImageFlagExeInTree|KRomImageFlagDll))
+			{
+			const TRomImageHeader* exeRIH=rih.iDllRefTable->iEntry[0];	// EXE is always first entry
+			if (aProcess)
+				{
+				DEpocCodeSeg* pS=(DEpocCodeSeg*)aProcess->CodeSeg();
+				if (!pS->iXIP || &pS->RomInfo()!=exeRIH)
+					return KErrNotSupported;
+				iExeCodeSeg=pS;
+				}
+			}
+
+		iMark |= (rih.iFlags & KRomImageDataFlags);
+		iMark |= EMarkRecursiveFlagsValid;
+		__KTRACE_OPT(KDLL,Kern::Printf("ROM Code Seg: mark %08x attr=%02x",iMark,iAttr));
+		aInfo.iFileEntryPoint=rih.iEntryPoint;
+		aInfo.iExportDir=rih.iExportDir;
+		aInfo.iCodeLoadAddress=rih.iCodeAddress;
+		aInfo.iCodeRunAddress=rih.iCodeAddress;
+		iRunAddress = rih.iCodeAddress;
+		iSize = rih.iCodeSize;
+		aInfo.iDataLoadAddress=rih.iDataAddress;
+		if (aInfo.iTotalDataSize && user_proc && aProcess->iDataBssRunAddress!=rih.iDataBssLinearBase)
+			K::Fault(K::EProcessDataAddressInvalid);
+		aInfo.iDataRunAddress=rih.iDataBssLinearBase;
+		aInfo.iExceptionDescriptor = rih.iExceptionDescriptor;
+		r=DoCreateXIP(aProcess);
+		return r;
+		}
+	iMemory = DEpocCodeSegMemory::New(this);
+	if (!iMemory)
+		return KErrNoMemory;
+	iInfo = &iMemory->iRamInfo;
+
+	if (aInfo.iUseCodePaging)
+		{
+		if ((aInfo.iCodeBlockMapEntries==NULL) || (aInfo.iCodeBlockMapCommon.iLocalDriveNumber<0) ||
+		(((TInt64) (aInfo.iFileClamp.iCookie[0] | aInfo.iFileClamp.iCookie[1]))==0))
+				return KErrArgument;
+			
+		iLoaderCookie = new TCodeSegLoaderCookieList();
+		if (!iLoaderCookie)
+			return KErrNoMemory;
+				
+		SBlockMapInfoBase* cbm = &aInfo.iCodeBlockMapCommon;
+
+		TUint startBlock;
+		kumemget32(&startBlock, &aInfo.iCodeBlockMapEntries->iStartBlock, sizeof(TUint));
+
+		iLoaderCookie->iCookie.iDriveNumber = cbm->iLocalDriveNumber;
+		iLoaderCookie->iCookie.iStartAddress =	cbm->iStartBlockAddress +
+												startBlock *
+												cbm->iBlockGranularity +
+												cbm->iBlockStartOffset;
+		iLoaderCookie->iCookie.iFileClamp = aInfo.iFileClamp;
+		// Mark cookie not to be closed yet
+		iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) | 1);
+		}
+		
+	SRamCodeInfo& ri=RamInfo();
+	ri.iCodeSize=aInfo.iCodeSize;
+	ri.iTextSize=aInfo.iTextSize;
+	ri.iDataSize=aInfo.iDataSize;
+	ri.iBssSize=aInfo.iBssSize;
+	TInt total_data_size=ri.iDataSize+ri.iBssSize;
+	ri.iExportDirCount=aInfo.iExportDirCount;
+	if (total_data_size!=0)
+		{
+		iMark|=(EMarkData|EMarkDataPresent);
+		if (!exeSeg)
+			iMark|=EMarkDataInit;
+		}
+	// if this DLL/EXE doesn't have data, don't set valid bit since we don't yet know about its dependencies
+
+	if (exeSeg)
+		ri.iDataRunAddr=aProcess->iDataBssRunAddress;
+	r=DoCreateRam(aInfo, aProcess);
+	if (r==KErrNone)
+		{
+		aInfo.iFileEntryPoint+=ri.iCodeRunAddr;
+		aInfo.iExportDir+=ri.iCodeRunAddr;
+		ri.iExportDir=aInfo.iExportDir;
+		aInfo.iCodeLoadAddress=ri.iCodeLoadAddr;
+		aInfo.iCodeRunAddress=ri.iCodeRunAddr;
+		aInfo.iDataLoadAddress=ri.iDataLoadAddr;
+		aInfo.iDataRunAddress=ri.iDataRunAddr;
+		TUint32 xd = aInfo.iExceptionDescriptor;
+		ri.iExceptionDescriptor = xd ? (xd + ri.iCodeRunAddr) : 0;
+		aInfo.iExceptionDescriptor = ri.iExceptionDescriptor;
+		iRunAddress = ri.iCodeRunAddr;
+		}
+	__KTRACE_OPT(KDLL,Kern::Printf("RAM Code Seg: mark %08x attr=%02x xd=%08x",iMark,iAttr,ri.iExceptionDescriptor));
+	__KTRACE_OPT(KDLL,Kern::Printf("<DEpocCodeSeg::DoCreate %d",r));
+	return r;
+	}
+
+void DEpocCodeSeg::InitData()
+	{
+	__KTRACE_OPT(KDLL,Kern::Printf("DEpocCodeSeg::InitData %C", this));
+	CHECK_PAGING_SAFE;
+	TInt bss_size=0;
+	TInt data_size=0;
+	TUint8* data_run_ptr=0;
+	const TUint8* data_load_ptr=0;
+	if (iXIP)
+		{
+		const TRomImageHeader& rih=RomInfo();
+		bss_size=rih.iBssSize;
+		data_size=rih.iDataSize;
+		data_run_ptr=(TUint8*)rih.iDataBssLinearBase;
+		data_load_ptr=(const TUint8*)rih.iDataAddress;
+		}
+	else
+		{
+		SRamCodeInfo& ri=RamInfo();
+		bss_size=ri.iBssSize;
+		data_size=ri.iDataSize;
+		data_run_ptr=(TUint8*)ri.iDataRunAddr;
+		data_load_ptr=(const TUint8*)ri.iDataLoadAddr;
+		}
+	UNLOCK_USER_MEMORY();
+	if (data_size)
+		memcpy(data_run_ptr, data_load_ptr, data_size);
+	if (bss_size)
+		memclr(data_run_ptr+data_size, bss_size);
+	LOCK_USER_MEMORY();
+	}
+
+DCodeSeg* DCodeSeg::FindRomCode(const TAny* aRomImgHdr)
+	{
+	CHECK_PAGING_SAFE;
+	const TRomImageHeader& rih = *(const TRomImageHeader*)aRomImgHdr;
+	TLinAddr ca = rih.iCodeAddress;
+	return CodeSegsByAddress.Find(ca);
+	}
+
+void P::NormalizeExecutableFileName(TDes& /*aFileName*/)
+	{
+	}
+	
+TInt DEpocCodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
+	{
+	iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) & ~1);
+	return DCodeSeg::Loaded(aInfo);
+	}
+
+
+//
+// DEpocCodeSegMemory
+//
+
+DEpocCodeSegMemory::DEpocCodeSegMemory(DEpocCodeSeg* aCodeSeg)
+	: iAccessCount(1), iCodeSeg(aCodeSeg)
+	{
+	}
+
+
+TInt DEpocCodeSegMemory::Open()
+	{
+	return __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0) ? KErrNone : KErrGeneral;
+	}
+
+
+TInt DEpocCodeSegMemory::Close()
+	{
+	if (__e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0) == 1)
+		{
+		AsyncDelete();
+		return DObject::EObjectDeleted;
+		}
+	return 0;
+	}
+
+