os/kernelhwsrv/kernel/eka/memmodel/epoc/pcodeseg.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\memmodel\epoc\pcodeseg.cpp
    15 // 
    16 //
    17 
    18 #include "plat_priv.h"
    19 #include <e32uid.h>
    20 
    21 TLinAddr DCodeSeg::ExceptionDescriptor()
    22 	{
    23 	DEpocCodeSeg* s = (DEpocCodeSeg*)this;
    24 	if (s->iXIP)
    25 		return s->RomInfo().iExceptionDescriptor;
    26 	return s->RamInfo().iExceptionDescriptor;
    27 	}
    28 
    29 DEpocCodeSeg::~DEpocCodeSeg()
    30 	{
    31 	if (!iXIP && iMemory)
    32 		{
    33 		iMemory->iCodeSeg = 0;
    34 		iMemory->Close();
    35 		iMemory = NULL;
    36 		}
    37 	}
    38 
    39 void DEpocCodeSeg::Destruct()
    40 	{
    41 	DCodeSeg::Wait();
    42 	
    43 	if (iLoaderCookie!=NULL)
    44 		{
    45 		if ((TInt) iLoaderCookie&1) // Not set fully loaded
    46 			{
    47 			iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) & ~1);
    48 			delete iLoaderCookie;
    49 			iLoaderCookie=NULL;
    50 			}
    51 		else
    52 			{
    53 			// Notify reaper of destruction
    54 			NKern::LockSystem();
    55 			if (DestructNotifyRequest->IsReady())
    56 				{
    57 				DThread* t = DestructNotifyThread;
    58 				DestructNotifyThread = NULL;				
    59 				Kern::QueueRequestComplete(t, DestructNotifyRequest,KErrNone);
    60 				}
    61 			NKern::UnlockSystem();
    62 	
    63 			iLoaderCookie->iNext=DestructNotifyList;
    64 			DestructNotifyList=iLoaderCookie;
    65 			iLoaderCookie=NULL;
    66 			}
    67 		}
    68 
    69 	DCodeSeg::Signal();
    70 	DCodeSeg::Destruct();
    71 	}
    72 
    73 void DEpocCodeSeg::Info(TCodeSegCreateInfo& aInfo)
    74 	{
    75 	CHECK_PAGING_SAFE;
    76 	if (iXIP)
    77 		{
    78 		const TRomImageHeader& rih=RomInfo();
    79 		aInfo.iCodeSize=rih.iCodeSize;
    80 		aInfo.iTextSize=rih.iTextSize;
    81 		aInfo.iDataSize=rih.iDataSize;
    82 		aInfo.iBssSize=rih.iBssSize;
    83 		aInfo.iTotalDataSize=rih.iTotalDataSize;
    84 		aInfo.iExportDir=rih.iExportDir;
    85 		aInfo.iExportDirCount=rih.iExportDirCount;
    86 		aInfo.iCodeLoadAddress=rih.iCodeAddress;
    87 		aInfo.iCodeRunAddress=rih.iCodeAddress;
    88 		aInfo.iDataLoadAddress=rih.iDataAddress;
    89 		aInfo.iDataRunAddress=rih.iDataBssLinearBase;
    90 		aInfo.iExceptionDescriptor = rih.iExceptionDescriptor;
    91 		}
    92 	else
    93 		{
    94 		const SRamCodeInfo& ri=RamInfo();
    95 		aInfo.iCodeSize=ri.iCodeSize;
    96 		aInfo.iTextSize=ri.iTextSize;
    97 		aInfo.iDataSize=ri.iDataSize;
    98 		aInfo.iBssSize=ri.iBssSize;
    99 		aInfo.iTotalDataSize=ri.iDataSize+ri.iBssSize;
   100 		aInfo.iExportDir=ri.iExportDir;
   101 		aInfo.iExportDirCount=ri.iExportDirCount;
   102 		aInfo.iCodeLoadAddress=ri.iCodeLoadAddr;
   103 		aInfo.iCodeRunAddress=ri.iCodeRunAddr;
   104 		aInfo.iDataLoadAddress=ri.iDataLoadAddr;
   105 		aInfo.iDataRunAddress=ri.iDataRunAddr;
   106 		aInfo.iExceptionDescriptor = ri.iExceptionDescriptor;
   107 		}
   108 	DCodeSeg::Info(aInfo);
   109 	}
   110 
   111 void DEpocCodeSeg::GetDataSizeAndBase(TInt& aTotalDataSizeOut, TLinAddr& aDataBaseOut)
   112 	{
   113 	if (iXIP)
   114 		{
   115 		aTotalDataSizeOut=RomInfo().iTotalDataSize;
   116 		aDataBaseOut=RomInfo().iDataBssLinearBase;
   117 		}
   118 	else
   119 		{
   120 		aTotalDataSizeOut=RamInfo().iDataSize+RamInfo().iBssSize;
   121 		aDataBaseOut=RamInfo().iDataRunAddr;
   122 		}	
   123 	}
   124 
   125 TLibraryFunction DEpocCodeSeg::Lookup(TInt aOrdinal)
   126 	{
   127 	CHECK_PAGING_SAFE;
   128 	// return NULL for -ve ordinal or 0th ordinal when not stddll/stdexe
   129 	if (aOrdinal<0 || (aOrdinal==0 && !(iAttr&ECodeSegAttNmdExpData)))
   130 		return NULL;
   131 	TInt xdc;
   132 	TLinAddr* xd;	// points to the 0th ordinal of export table
   133 	if (iXIP)
   134 		{
   135 		const TRomImageHeader& rih=RomInfo();
   136 		xdc=rih.iExportDirCount;
   137 		xd=(TLinAddr*)rih.iExportDir - 1;
   138 		}
   139 	else
   140 		{
   141 		SRamCodeInfo& ri=RamInfo();
   142 		xdc=ri.iExportDirCount;
   143 		xd=(TLinAddr*)ri.iExportDir - 1;
   144 		}
   145 	if (aOrdinal <= xdc)
   146 		{
   147 		UNLOCK_USER_MEMORY();
   148 		TLibraryFunction f=(TLibraryFunction)xd[aOrdinal];
   149 		LOCK_USER_MEMORY();
   150 		if ((TLinAddr)f == iFileEntryPoint)
   151 			f = NULL;
   152 		__KTRACE_OPT(KDLL,Kern::Printf("Lookup(%d)->%08x",aOrdinal,f));
   153 		return f;
   154 		}
   155 	__KTRACE_OPT(KDLL,Kern::Printf("Lookup(%d)->NULL",aOrdinal));
   156 	return NULL;
   157 	}
   158 
   159 TInt DEpocCodeSeg::GetMemoryInfo(TModuleMemoryInfo& aInfo, DProcess*)
   160 	{
   161 	CHECK_PAGING_SAFE;
   162 	if (iXIP)
   163 		{
   164 		const TRomImageHeader& rih		= RomInfo();
   165 		aInfo.iCodeBase					= rih.iCodeAddress;
   166 		aInfo.iCodeSize					= rih.iTextSize;
   167 		aInfo.iConstDataSize			= rih.iCodeSize - aInfo.iCodeSize;
   168 		aInfo.iConstDataBase			= (aInfo.iConstDataSize > 0) ? (aInfo.iCodeBase + aInfo.iCodeSize) : 0;
   169 		aInfo.iInitialisedDataBase		= rih.iDataBssLinearBase;
   170 		aInfo.iInitialisedDataSize		= rih.iDataSize;
   171 		aInfo.iUninitialisedDataSize	= rih.iBssSize;
   172 		aInfo.iUninitialisedDataBase	= aInfo.iInitialisedDataBase+aInfo.iInitialisedDataSize;
   173 		}
   174 	else
   175 		{
   176 		const SRamCodeInfo& ri			= RamInfo();
   177 		aInfo.iCodeBase					= ri.iCodeRunAddr;
   178 		aInfo.iCodeSize					= ri.iTextSize;
   179 		aInfo.iConstDataSize			= ri.iCodeSize - aInfo.iCodeSize;
   180 		aInfo.iConstDataBase			= (aInfo.iConstDataSize > 0) ? (aInfo.iCodeBase + aInfo.iCodeSize) : 0;
   181 		aInfo.iInitialisedDataBase		= ri.iDataRunAddr;
   182 		aInfo.iInitialisedDataSize		= ri.iDataSize;
   183 		aInfo.iUninitialisedDataSize	= ri.iBssSize;
   184 		aInfo.iUninitialisedDataBase	= aInfo.iInitialisedDataBase + aInfo.iInitialisedDataSize;
   185 		}
   186 	return KErrNone;
   187 	}
   188 
   189 //const TUint32 KRomImageFlagsAlwaysLoaded=KRomImageFlagPrimary|KRomImageFlagVariant|KRomImageFlagExtension;
   190 const TUint32 KRomImageDataFlags=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent);
   191 TInt DEpocCodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
   192 	{
   193 	__KTRACE_OPT(KDLL,Kern::Printf(">DEpocCodeSeg::DoCreate code_addr=%08x",aInfo.iCodeLoadAddress));
   194 	CHECK_PAGING_SAFE;
   195 	TInt r=KErrNone;
   196 	TBool exeSeg=(iExeCodeSeg==this);
   197 	TBool kp=exeSeg && (aProcess->iAttributes&DProcess::ESupervisor);
   198 	TBool user_proc=exeSeg && !kp;
   199 	if (aInfo.iCodeLoadAddress)
   200 		{
   201 		iXIP=ETrue;
   202 		iInfo=(const TAny*)aInfo.iCodeLoadAddress;
   203 		}
   204 	if (user_proc)
   205 		{
   206 		r=aProcess->CreateDataBssStackArea((TProcessCreateInfo&)aInfo);
   207 		if (r!=KErrNone)
   208 			return r;
   209 		}
   210 	if (iXIP)
   211 		{
   212 		const TRomImageHeader& rih=RomInfo();
   213 		iXIP=ETrue;
   214 		if ( (rih.iFlags & (KRomImageFlagExeInTree|KRomImageFlagDll)) == (KRomImageFlagExeInTree|KRomImageFlagDll))
   215 			{
   216 			const TRomImageHeader* exeRIH=rih.iDllRefTable->iEntry[0];	// EXE is always first entry
   217 			if (aProcess)
   218 				{
   219 				DEpocCodeSeg* pS=(DEpocCodeSeg*)aProcess->CodeSeg();
   220 				if (!pS->iXIP || &pS->RomInfo()!=exeRIH)
   221 					return KErrNotSupported;
   222 				iExeCodeSeg=pS;
   223 				}
   224 			}
   225 
   226 		iMark |= (rih.iFlags & KRomImageDataFlags);
   227 		iMark |= EMarkRecursiveFlagsValid;
   228 		__KTRACE_OPT(KDLL,Kern::Printf("ROM Code Seg: mark %08x attr=%02x",iMark,iAttr));
   229 		aInfo.iFileEntryPoint=rih.iEntryPoint;
   230 		aInfo.iExportDir=rih.iExportDir;
   231 		aInfo.iCodeLoadAddress=rih.iCodeAddress;
   232 		aInfo.iCodeRunAddress=rih.iCodeAddress;
   233 		iRunAddress = rih.iCodeAddress;
   234 		iSize = rih.iCodeSize;
   235 		aInfo.iDataLoadAddress=rih.iDataAddress;
   236 		if (aInfo.iTotalDataSize && user_proc && aProcess->iDataBssRunAddress!=rih.iDataBssLinearBase)
   237 			K::Fault(K::EProcessDataAddressInvalid);
   238 		aInfo.iDataRunAddress=rih.iDataBssLinearBase;
   239 		aInfo.iExceptionDescriptor = rih.iExceptionDescriptor;
   240 		r=DoCreateXIP(aProcess);
   241 		return r;
   242 		}
   243 	iMemory = DEpocCodeSegMemory::New(this);
   244 	if (!iMemory)
   245 		return KErrNoMemory;
   246 	iInfo = &iMemory->iRamInfo;
   247 
   248 	if (aInfo.iUseCodePaging)
   249 		{
   250 		if ((aInfo.iCodeBlockMapEntries==NULL) || (aInfo.iCodeBlockMapCommon.iLocalDriveNumber<0) ||
   251 		(((TInt64) (aInfo.iFileClamp.iCookie[0] | aInfo.iFileClamp.iCookie[1]))==0))
   252 				return KErrArgument;
   253 			
   254 		iLoaderCookie = new TCodeSegLoaderCookieList();
   255 		if (!iLoaderCookie)
   256 			return KErrNoMemory;
   257 				
   258 		SBlockMapInfoBase* cbm = &aInfo.iCodeBlockMapCommon;
   259 
   260 		TUint startBlock;
   261 		kumemget32(&startBlock, &aInfo.iCodeBlockMapEntries->iStartBlock, sizeof(TUint));
   262 
   263 		iLoaderCookie->iCookie.iDriveNumber = cbm->iLocalDriveNumber;
   264 		iLoaderCookie->iCookie.iStartAddress =	cbm->iStartBlockAddress +
   265 												startBlock *
   266 												cbm->iBlockGranularity +
   267 												cbm->iBlockStartOffset;
   268 		iLoaderCookie->iCookie.iFileClamp = aInfo.iFileClamp;
   269 		// Mark cookie not to be closed yet
   270 		iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) | 1);
   271 		}
   272 		
   273 	SRamCodeInfo& ri=RamInfo();
   274 	ri.iCodeSize=aInfo.iCodeSize;
   275 	ri.iTextSize=aInfo.iTextSize;
   276 	ri.iDataSize=aInfo.iDataSize;
   277 	ri.iBssSize=aInfo.iBssSize;
   278 	TInt total_data_size=ri.iDataSize+ri.iBssSize;
   279 	ri.iExportDirCount=aInfo.iExportDirCount;
   280 	if (total_data_size!=0)
   281 		{
   282 		iMark|=(EMarkData|EMarkDataPresent);
   283 		if (!exeSeg)
   284 			iMark|=EMarkDataInit;
   285 		}
   286 	// if this DLL/EXE doesn't have data, don't set valid bit since we don't yet know about its dependencies
   287 
   288 	if (exeSeg)
   289 		ri.iDataRunAddr=aProcess->iDataBssRunAddress;
   290 	r=DoCreateRam(aInfo, aProcess);
   291 	if (r==KErrNone)
   292 		{
   293 		aInfo.iFileEntryPoint+=ri.iCodeRunAddr;
   294 		aInfo.iExportDir+=ri.iCodeRunAddr;
   295 		ri.iExportDir=aInfo.iExportDir;
   296 		aInfo.iCodeLoadAddress=ri.iCodeLoadAddr;
   297 		aInfo.iCodeRunAddress=ri.iCodeRunAddr;
   298 		aInfo.iDataLoadAddress=ri.iDataLoadAddr;
   299 		aInfo.iDataRunAddress=ri.iDataRunAddr;
   300 		TUint32 xd = aInfo.iExceptionDescriptor;
   301 		ri.iExceptionDescriptor = xd ? (xd + ri.iCodeRunAddr) : 0;
   302 		aInfo.iExceptionDescriptor = ri.iExceptionDescriptor;
   303 		iRunAddress = ri.iCodeRunAddr;
   304 		}
   305 	__KTRACE_OPT(KDLL,Kern::Printf("RAM Code Seg: mark %08x attr=%02x xd=%08x",iMark,iAttr,ri.iExceptionDescriptor));
   306 	__KTRACE_OPT(KDLL,Kern::Printf("<DEpocCodeSeg::DoCreate %d",r));
   307 	return r;
   308 	}
   309 
   310 void DEpocCodeSeg::InitData()
   311 	{
   312 	__KTRACE_OPT(KDLL,Kern::Printf("DEpocCodeSeg::InitData %C", this));
   313 	CHECK_PAGING_SAFE;
   314 	TInt bss_size=0;
   315 	TInt data_size=0;
   316 	TUint8* data_run_ptr=0;
   317 	const TUint8* data_load_ptr=0;
   318 	if (iXIP)
   319 		{
   320 		const TRomImageHeader& rih=RomInfo();
   321 		bss_size=rih.iBssSize;
   322 		data_size=rih.iDataSize;
   323 		data_run_ptr=(TUint8*)rih.iDataBssLinearBase;
   324 		data_load_ptr=(const TUint8*)rih.iDataAddress;
   325 		}
   326 	else
   327 		{
   328 		SRamCodeInfo& ri=RamInfo();
   329 		bss_size=ri.iBssSize;
   330 		data_size=ri.iDataSize;
   331 		data_run_ptr=(TUint8*)ri.iDataRunAddr;
   332 		data_load_ptr=(const TUint8*)ri.iDataLoadAddr;
   333 		}
   334 	UNLOCK_USER_MEMORY();
   335 	if (data_size)
   336 		memcpy(data_run_ptr, data_load_ptr, data_size);
   337 	if (bss_size)
   338 		memclr(data_run_ptr+data_size, bss_size);
   339 	LOCK_USER_MEMORY();
   340 	}
   341 
   342 DCodeSeg* DCodeSeg::FindRomCode(const TAny* aRomImgHdr)
   343 	{
   344 	CHECK_PAGING_SAFE;
   345 	const TRomImageHeader& rih = *(const TRomImageHeader*)aRomImgHdr;
   346 	TLinAddr ca = rih.iCodeAddress;
   347 	return CodeSegsByAddress.Find(ca);
   348 	}
   349 
   350 void P::NormalizeExecutableFileName(TDes& /*aFileName*/)
   351 	{
   352 	}
   353 	
   354 TInt DEpocCodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
   355 	{
   356 	iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) & ~1);
   357 	return DCodeSeg::Loaded(aInfo);
   358 	}
   359 
   360 
   361 //
   362 // DEpocCodeSegMemory
   363 //
   364 
   365 DEpocCodeSegMemory::DEpocCodeSegMemory(DEpocCodeSeg* aCodeSeg)
   366 	: iAccessCount(1), iCodeSeg(aCodeSeg)
   367 	{
   368 	}
   369 
   370 
   371 TInt DEpocCodeSegMemory::Open()
   372 	{
   373 	return __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0) ? KErrNone : KErrGeneral;
   374 	}
   375 
   376 
   377 TInt DEpocCodeSegMemory::Close()
   378 	{
   379 	if (__e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0) == 1)
   380 		{
   381 		AsyncDelete();
   382 		return DObject::EObjectDeleted;
   383 		}
   384 	return 0;
   385 	}
   386 
   387