kernel/eka/memmodel/epoc/pcodeseg.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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