1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/epoc/putils.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1189 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\memmodel\epoc\putils.cpp
1.18 +// EPOC implementation of the ROM related parts of the system
1.19 +//
1.20 +//
1.21 +
1.22 +#include "plat_priv.h"
1.23 +#include <e32uid.h>
1.24 +#include "execs.h"
1.25 +#include "cache_maintenance.h"
1.26 +
1.27 +_LIT(KKernelFullPathNameSysBin,"z:\\sys\\bin\\ekern.exe");
1.28 +
1.29 +#ifdef __MARM__
1.30 +#define CHECK_ROM_ENTRY_POINT(a) __ASSERT_ALWAYS( ((a).iFlags & KRomImageEptMask) == KRomImageEpt_Eka2, PP::Panic(PP::EUnsupportedOldBinary) )
1.31 +#else
1.32 +#define CHECK_ROM_ENTRY_POINT(a)
1.33 +#endif
1.34 +
1.35 +void PP::Panic(TPlatPanic aPanic)
1.36 + {
1.37 + Kern::Fault("PLAT",aPanic);
1.38 + }
1.39 +
1.40 +void PP::InitSuperPageFromRom(TLinAddr aRomHeader, TLinAddr aSuperPage)
1.41 + {
1.42 + RomHeaderAddress = aRomHeader;
1.43 + SuperPageAddress = aSuperPage;
1.44 +
1.45 + TInt j;
1.46 + for (j = 0; j < KNumTraceMaskWords; j++)
1.47 + TheSuperPage().iDebugMask[j] = TheRomHeader().iTraceMask[j];
1.48 +
1.49 + for (j = 0; j < 8; j++)
1.50 + TheSuperPage().iInitialBTraceFilter[j] = TheRomHeader().iInitialBTraceFilter[j];
1.51 +
1.52 + Kern::SuperPage().iInitialBTraceBuffer = TheRomHeader().iInitialBTraceBuffer;
1.53 + Kern::SuperPage().iInitialBTraceMode = TheRomHeader().iInitialBTraceMode;
1.54 +
1.55 + TheSuperPage().SetKernelConfigFlags(TheRomHeader().iKernelConfigFlags);
1.56 +
1.57 + memcpy(&TheSuperPage().iDisabledCapabilities, &TheRomHeader().iDisabledCapabilities, sizeof(TheRomHeader().iDisabledCapabilities));
1.58 + }
1.59 +
1.60 +TInt P::DefaultInitialTime()
1.61 + {
1.62 +//
1.63 +// Default implementation of the kernel hook for getting the initial system
1.64 +// time, can be overriden by variant.
1.65 +//
1.66 + TInt seconds;
1.67 + if (K::ColdStart || A::SystemTimeInSecondsFrom2000(seconds)!=KErrNone)
1.68 + return KErrCorrupt;
1.69 + else
1.70 + return seconds;
1.71 + }
1.72 +
1.73 +TInt P::InitSystemTime()
1.74 + {
1.75 +//
1.76 +// Initialise system time
1.77 +// Return the initial time in seconds from 00:00:00 01-01-2000
1.78 +//
1.79 +
1.80 + // Reset the UTC offset (I assume this gets loaded from storage at some point after F32 loads)
1.81 + TUint dummy;
1.82 + K::SetSystemTimeAndOffset(0, 0, 0, dummy, ETimeSetOffset | ETimeSetNoTimeUpdate);
1.83 +
1.84 + // Read the hardware clock value. If this is negative it means it couldnt be read.
1.85 + TInt seconds = K::InitialTimeHandler()();
1.86 +
1.87 + if (seconds >= 0)
1.88 + {
1.89 + K::SecureClockStatus |= ESecureClockPresent;
1.90 + __KTRACE_OPT(KBOOT,Kern::Printf("Read initial system time"));
1.91 + // now=Hardware RTC value
1.92 + }
1.93 + else
1.94 + {
1.95 + __KTRACE_OPT(KBOOT,Kern::Printf("Could not read initial system time - using ROM timestamp to set system time"));
1.96 + TTimeK rom_time=*(const TTimeK*)&TheRomHeader().iTime;
1.97 + rom_time -= TTimeK(K::HomeTimeOffsetSeconds)*1000000;
1.98 + TInt s;
1.99 + TInt r=K::SecondsFrom2000(rom_time,s);
1.100 + if (r!=KErrNone)
1.101 + PP::Panic(PP::EInitialSystemTimeInvalid);
1.102 + seconds=s;
1.103 +
1.104 + // write the ROM timestamp to the hardware RTC
1.105 + A::SetSystemTimeInSecondsFrom2000(seconds);
1.106 + }
1.107 + return seconds;
1.108 + }
1.109 +
1.110 +
1.111 +void FindRomRootDirectory()
1.112 + {
1.113 + TUint variant = TheSuperPage().iActiveVariant;
1.114 + TUint cpu = (variant >> 16) & 0xff;
1.115 + TUint asic = (variant >> 24);
1.116 + PP::RomRootDirAddress=0;
1.117 + TRomRootDirectoryList* pL=(TRomRootDirectoryList*)TheSuperPage().iRootDirList;
1.118 + if (!pL)
1.119 + pL=(TRomRootDirectoryList*)TheRomHeader().iRomRootDirectoryList;
1.120 + TInt i;
1.121 + for (i=0; i<pL->iNumRootDirs; i++)
1.122 + {
1.123 + if (THardwareVariant(pL->iRootDir[i].iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
1.124 + {
1.125 + __KTRACE_OPT(KBOOT,Kern::Printf("Found ROM root dir index %d addr %08x",
1.126 + i, pL->iRootDir[i].iAddressLin));
1.127 + PP::RomRootDirAddress=pL->iRootDir[i].iAddressLin;
1.128 + return;
1.129 + }
1.130 + }
1.131 + }
1.132 +
1.133 +typedef TInt (*TInitVarExtFn)(const TRomImageHeader&);
1.134 +
1.135 +#ifdef KBOOT
1.136 +void DumpRomFileInfo(const TRomEntry& aRomEntry)
1.137 + {
1.138 + TBuf8<128> name;
1.139 + TInt i;
1.140 + for (i=0; i<aRomEntry.iNameLength; ++i)
1.141 + {
1.142 + name.Append(TChar(aRomEntry.iName[i<<1]&0xff));
1.143 + }
1.144 + const TRomImageHeader& img = *(const TRomImageHeader*)aRomEntry.iAddressLin;
1.145 + __KTRACE_OPT(KBOOT,Kern::Printf("File %S[%08x]", &name, TUint(img.iHardwareVariant) ));
1.146 + }
1.147 +#endif
1.148 +
1.149 +void InitVarExt(TBool aVar, TInitVarExtFn aFn)
1.150 + {
1.151 + __KTRACE_OPT(KBOOT,Kern::Printf("InitVarExt var=%d, fn=%08x", aVar, aFn));
1.152 + TUint variant = TheSuperPage().iActiveVariant;
1.153 + TUint cpu = (variant >> 16) & 0xff;
1.154 + TUint asic = (variant >> 24);
1.155 + __KTRACE_OPT(KBOOT,Kern::Printf("cpu=%d, asic=%d, variant=%x", cpu, asic, variant));
1.156 + const TRomHeader& rh = TheRomHeader();
1.157 + TRomEntry* pE = aVar ? (TRomEntry*)rh.iVariantFile : (TRomEntry*)rh.iExtensionFile;
1.158 + while(pE)
1.159 + {
1.160 +#ifdef KBOOT
1.161 + DumpRomFileInfo(*pE);
1.162 +#endif
1.163 + const TRomImageHeader& img = *(const TRomImageHeader*)pE->iAddressLin;
1.164 + if (THardwareVariant(img.iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
1.165 + {
1.166 + __KTRACE_OPT(KBOOT,Kern::Printf("Processing"));
1.167 + (*aFn)(img);
1.168 + if (aVar)
1.169 + {
1.170 + __KTRACE_OPT(KBOOT,Kern::Printf("Variant installed"));
1.171 + return;
1.172 + }
1.173 + }
1.174 + pE=(TRomEntry*)img.iNextExtension;
1.175 + }
1.176 + if (aVar)
1.177 + Kern::Fault("NoVariant",0);
1.178 + }
1.179 +
1.180 +TInt InitData(const TRomImageHeader& a)
1.181 + {
1.182 + __KTRACE_OPT(KBOOT,Kern::Printf("InitData %08x+%x->%08x", a.iDataAddress, a.iDataSize, a.iDataBssLinearBase));
1.183 + CHECK_ROM_ENTRY_POINT(a);
1.184 + if (a.iDataSize)
1.185 + memcpy((TAny*)a.iDataBssLinearBase,(TAny*)a.iDataAddress,a.iDataSize);
1.186 + TLibraryEntry ep = (TLibraryEntry)a.iEntryPoint;
1.187 + __KTRACE_OPT(KBOOT,Kern::Printf("Calling entrypoint %08x(VariantInit0)", ep));
1.188 + TInt r = ep(KModuleEntryReasonVariantInit0);
1.189 + __KTRACE_OPT(KBOOT,Kern::Printf("Entrypoint returned %d",r));
1.190 + if(!(++K::ExtensionCount&0x7fffffff))
1.191 + K::Fault(K::ETooManyExtensions);
1.192 + return r;
1.193 + }
1.194 +
1.195 +TInt InitVariant(const TRomImageHeader& a)
1.196 + {
1.197 + TInt r = InitData(a);
1.198 + __KTRACE_OPT(KBOOT,Kern::Printf("InitVariant: entry point returns %08x", r));
1.199 + if (r<0)
1.200 + Kern::Fault("VariantEntry",r);
1.201 +
1.202 + // Initialise and create the variant object
1.203 + r = A::CreateVariant(&a, r);
1.204 + if (r<0)
1.205 + Kern::Fault("VariantInit",r);
1.206 + return r;
1.207 + }
1.208 +
1.209 +void P::CreateVariant()
1.210 + {
1.211 + __KTRACE_OPT(KBOOT,Kern::Printf("CreateVariant"));
1.212 + BTrace::Init0();
1.213 + InitVarExt(EFalse, &InitData); // initialise .data for all extensions
1.214 + InitVarExt(ETrue, &InitVariant); // find variant and initialise it
1.215 + FindRomRootDirectory();
1.216 + }
1.217 +
1.218 +struct SExtInit1EntryPoint
1.219 + {
1.220 + inline SExtInit1EntryPoint() : iEntryPoint(0),iReturnCode(0)
1.221 + {}
1.222 + inline SExtInit1EntryPoint(TLibraryEntry aEp, TInt aVal) : iEntryPoint(aEp),iReturnCode(aVal)
1.223 + {}
1.224 + TLibraryEntry iEntryPoint;
1.225 + TInt iReturnCode; // bits 7-0 used for extension startup priority order
1.226 + };
1.227 +
1.228 +// This ordering function when used in conjunction with RArray<>::InsertInOrderAllowRepeats
1.229 +// orders the array of extensions as follow:
1.230 +// highest priority -> lowest priority
1.231 +// if same priority -> first in, lowest index
1.232 +//
1.233 +TInt priorityOrder(const SExtInit1EntryPoint& aMatch, const SExtInit1EntryPoint& aEntry)
1.234 + {
1.235 + TUint8 l=(TUint8)aMatch.iReturnCode;
1.236 + TUint8 r=(TUint8)aEntry.iReturnCode;
1.237 + if(l>r)
1.238 + return -1;
1.239 + else if(l<r)
1.240 + return 1;
1.241 + else
1.242 + return 0;
1.243 + }
1.244 +
1.245 +TInt InitExt0(const TRomImageHeader& a)
1.246 + {
1.247 + CHECK_ROM_ENTRY_POINT(a);
1.248 + TLibraryEntry ep = (TLibraryEntry)a.iEntryPoint;
1.249 + __KTRACE_OPT(KBOOT,Kern::Printf("InitExt0 %08x ep=%08x", &a, ep));
1.250 + TInt r = (*ep)(KModuleEntryReasonExtensionInit0);
1.251 + if (r<KErrNone)
1.252 + {
1.253 + __KTRACE_OPT(KBOOT,Kern::Printf("Already started"));
1.254 + return r;
1.255 + }
1.256 + SExtInit1EntryPoint s(ep,r);
1.257 + TInt count=K::ExtensionArray->Count();
1.258 + if(count==K::ExtensionCount) // this function is only called if extensions exist, i.e. K::ExtensionCount>0
1.259 + K::Fault(K::EExtensionArrayOverflowed); // the first insertion will allocate space for K::ExtensionCount entries and that is the maximum number of entries allowed
1.260 + TLinearOrder<SExtInit1EntryPoint> PriorityOrder(priorityOrder);
1.261 + if(K::ExtensionArray->InsertInOrderAllowRepeats(s,PriorityOrder)!=KErrNone)
1.262 + K::Fault(K::EInsertExtensionFailed);
1.263 + __KTRACE_OPT(KBOOT,Kern::Printf("Inserted at index %d, priority %d, last index %d", K::ExtensionArray->SpecificFindInOrder(s,PriorityOrder,EArrayFindMode_Last)-1, (TUint8)r, count));
1.264 + return KErrNone;
1.265 + }
1.266 +
1.267 +void P::StartExtensions()
1.268 + {
1.269 + // start extensions...
1.270 + __KTRACE_OPT(KBOOT, Kern::Printf("Starting kernel extensions..."));
1.271 +
1.272 + K::ExtensionArray = new RArray<SExtInit1EntryPoint>(--K::ExtensionCount); // ordered array of extensions excluding Variant
1.273 + if(!K::ExtensionArray)
1.274 + K::Fault(K::EExtensionArrayAllocationFailed);
1.275 + __KTRACE_OPT(KBOOT, Kern::Printf("Entry point array at %08x, max size %d",K::ExtensionArray,K::ExtensionCount));
1.276 +
1.277 + InitVarExt(EFalse, &InitExt0); // populates the array of entry points in priority order
1.278 +
1.279 + for(TInt i=0; i<K::ExtensionArray->Count(); i++) // call entry points in combined priority and temporal orders
1.280 + {
1.281 + TLibraryEntry ep = (*K::ExtensionArray)[i].iEntryPoint;
1.282 + __KTRACE_OPT(KBOOT,Kern::Printf("InitExt1: calling entrypoint %08x", ep));
1.283 + TInt r = ep(KModuleEntryReasonExtensionInit1);
1.284 + __KTRACE_OPT(KBOOT,Kern::Printf("Entrypoint returned %d", r));
1.285 + if (r!=KErrNone)
1.286 + K::Fault(K::EStartExtensionsFailed);
1.287 + }
1.288 + // preserve array of extensions, it contains the returned codes from ExtInit0 which may be useful for future use
1.289 + //delete K::ExtensionArray;
1.290 + //K::ExtensionArray=NULL;
1.291 + }
1.292 +
1.293 +void P::KernelInfo(TProcessCreateInfo& aInfo, TAny*& aStack, TAny*& aHeap)
1.294 +//
1.295 +// Provide the initial supervisor data information from the ROM
1.296 +//
1.297 + {
1.298 + aInfo.iFileName=KKernelFullPathNameSysBin;
1.299 + aInfo.iRootNameOffset=11;
1.300 + aInfo.iRootNameLength=9;
1.301 + aInfo.iExtOffset = 16;
1.302 +
1.303 + aInfo.iAttr=ECodeSegAttKernel|ECodeSegAttFixed;
1.304 +
1.305 + const TRomHeader& romHdr=TheRomHeader();
1.306 + const TRomEntry* primaryEntry=(const TRomEntry*)TheSuperPage().iPrimaryEntry;
1.307 + const TRomImageHeader* primaryImageHeader=(const TRomImageHeader*)primaryEntry->iAddressLin;
1.308 + Epoc::RomProcessInfo(aInfo, *primaryImageHeader);
1.309 + aStack = (TAny*)(romHdr.iKernDataAddress + Kern::RoundToPageSize(romHdr.iTotalSvDataSize));
1.310 + aHeap = (TAny*)(TLinAddr(aStack) + Kern::RoundToPageSize(aInfo.iStackSize));
1.311 + aInfo.iTotalDataSize=romHdr.iTotalSvDataSize;
1.312 + aInfo.iHeapSizeMin=TheSuperPage().iInitialHeapSize;
1.313 + }
1.314 +
1.315 +EXPORT_C void Epoc::RomProcessInfo(TProcessCreateInfo& aInfo, const TRomImageHeader& a)
1.316 + {
1.317 + CHECK_PAGING_SAFE;
1.318 + aInfo.iUids=*(const TUidType*)&a.iUid1;
1.319 + aInfo.iCodeSize=a.iCodeSize;
1.320 + aInfo.iTextSize=a.iTextSize;
1.321 + aInfo.iDataSize=a.iDataSize;
1.322 + aInfo.iBssSize=a.iBssSize;
1.323 + aInfo.iTotalDataSize=a.iTotalDataSize;
1.324 + aInfo.iEntryPtVeneer=a.iEntryPoint;
1.325 + aInfo.iFileEntryPoint=a.iEntryPoint;
1.326 + aInfo.iDepCount=a.iDllRefTable ? a.iDllRefTable->iNumberOfEntries : 0;
1.327 + aInfo.iExportDir=a.iExportDir;
1.328 + aInfo.iExportDirCount=a.iExportDirCount;
1.329 + aInfo.iCodeLoadAddress=(TLinAddr)&a;//a.iCodeAddress;
1.330 + aInfo.iCodeRunAddress=a.iCodeAddress;
1.331 + aInfo.iDataLoadAddress=a.iDataAddress;
1.332 + aInfo.iDataRunAddress=a.iDataBssLinearBase;
1.333 + aInfo.iExceptionDescriptor = a.iExceptionDescriptor;
1.334 + aInfo.iHeapSizeMin=a.iHeapSizeMin;
1.335 + aInfo.iHeapSizeMax=a.iHeapSizeMax;
1.336 + aInfo.iStackSize=a.iStackSize;
1.337 + aInfo.iPriority=a.iPriority;
1.338 + aInfo.iHandle=NULL;
1.339 + aInfo.iS = a.iS;
1.340 + aInfo.iModuleVersion = a.iModuleVersion;
1.341 + if (a.iFlags&KRomImageFlagsKernelMask)
1.342 + aInfo.iAttr=ECodeSegAttKernel;
1.343 + else
1.344 + aInfo.iAttr=ECodeSegAttGlobal;
1.345 + if (a.iFlags&KRomImageFlagFixedAddressExe)
1.346 + aInfo.iAttr|=ECodeSegAttFixed;
1.347 + aInfo.iAttr &= ~ECodeSegAttABIMask;
1.348 + aInfo.iAttr |= (a.iFlags & KRomImageABIMask);
1.349 + if(a.iFlags&KRomImageSMPSafe)
1.350 + aInfo.iAttr |= ECodeSegAttSMPSafe;
1.351 + aInfo.iClientHandle = KCurrentThreadHandle;
1.352 + aInfo.iClientProcessHandle = 0;
1.353 + aInfo.iFinalHandle = 0;
1.354 + aInfo.iOwnerType = EOwnerProcess;
1.355 + aInfo.iFlags &= ~(TProcessCreateInfo::EDataPagingMask);
1.356 + if(a.iFlags&KRomImageFlagDataPaged)
1.357 + aInfo.iFlags |= TProcessCreateInfo::EDataPaged;
1.358 + if(a.iFlags&KRomImageFlagDataUnpaged)
1.359 + aInfo.iFlags |= TProcessCreateInfo::EDataUnpaged;
1.360 + CHECK_ROM_ENTRY_POINT(a);
1.361 + }
1.362 +
1.363 +EXPORT_C void Epoc::SetMonitorEntryPoint(TDfcFn aFn)
1.364 + {
1.365 + if (aFn)
1.366 + {
1.367 + TUint32 x=(TUint32)aFn;
1.368 + PP::MonitorEntryPoint[0]=x;
1.369 + PP::MonitorEntryPoint[1]=~x;
1.370 + PP::MonitorEntryPoint[2]=((x>>2)*~x);
1.371 + }
1.372 + else
1.373 + {
1.374 + PP::MonitorEntryPoint[0]=0;
1.375 + PP::MonitorEntryPoint[1]=0;
1.376 + PP::MonitorEntryPoint[2]=0;
1.377 + }
1.378 + }
1.379 +
1.380 +EXPORT_C void Epoc::SetMonitorExceptionHandler(TLinAddr aHandler)
1.381 + {
1.382 + TheScheduler.iMonitorExceptionHandler=aHandler;
1.383 + }
1.384 +
1.385 +EXPORT_C TAny* Epoc::ExceptionInfo()
1.386 + {
1.387 +#ifdef __SMP__
1.388 + return 0; // separate for each CPU
1.389 +#else
1.390 + return TheScheduler.i_ExcInfo;
1.391 +#endif
1.392 + }
1.393 +
1.394 +EXPORT_C const TRomHeader& Epoc::RomHeader()
1.395 + {
1.396 + return TheRomHeader();
1.397 + }
1.398 +
1.399 +TLinAddr ExecHandler::RomHeaderAddress()
1.400 + {
1.401 + return ::RomHeaderAddress;
1.402 + }
1.403 +
1.404 +TLinAddr ExecHandler::RomRootDirectoryAddress()
1.405 + {
1.406 + return PP::RomRootDirAddress;
1.407 + }
1.408 +
1.409 +TBool M::IsRomAddress(const TAny* aPtr)
1.410 + {
1.411 + TLinAddr start=::RomHeaderAddress;
1.412 + TLinAddr end=start+TheRomHeader().iUncompressedSize;
1.413 + return ((TLinAddr)aPtr>=start) && ((TLinAddr)aPtr<end);
1.414 + }
1.415 +
1.416 +void P::SetSuperPageSignature()
1.417 + {
1.418 + TUint32* sig = TheSuperPage().iSignature;
1.419 + const TUint32* time = (const TUint32*)&TheRomHeader().iTime;
1.420 + sig[0] = time[0] ^ 0xb504f333;
1.421 + sig[1] = time[1] ^ 0xf9de6484;
1.422 + }
1.423 +
1.424 +TBool P::CheckSuperPageSignature()
1.425 + {
1.426 + const TUint32* sig = TheSuperPage().iSignature;
1.427 + const TUint32* time = (const TUint32*)&TheRomHeader().iTime;
1.428 + return ( (sig[0]^time[0])==0xb504f333 && (sig[1]^time[1])==0xf9de6484 );
1.429 + }
1.430 +
1.431 +static const TUint32 KMapAttrType2 = 0x80000000;
1.432 +static const TUint32 KMapAttrTypeShift = 26;
1.433 +
1.434 +#if defined(__CPU_MEMORY_TYPE_REMAPPING)
1.435 +extern TUint32 PrimaryRegionRemapRegister();
1.436 +extern TUint32 NormalMemoryRemapRegister();
1.437 +#endif
1.438 +
1.439 +EXPORT_C TMappingAttributes2::TMappingAttributes2(TMemoryType aType,
1.440 + TBool aUserAccess,
1.441 + TBool aWritable,
1.442 + TBool aExecutable,
1.443 + TInt aShared,
1.444 + TInt aParity)
1.445 + {
1.446 + //Sort out default values:
1.447 + if (aShared<0)
1.448 + #if defined (__CPU_USE_SHARED_MEMORY)
1.449 + aShared = 1;
1.450 + #else
1.451 + aShared = 0;
1.452 + #endif
1.453 + if (aParity<0)
1.454 + aParity = 0;
1.455 +
1.456 + // KMapAttrType2 bit marks the object as of TMappingAttributes2 type (as opposed to TMappingAttributes bitmask).
1.457 + // We have to make sure that these two types can work together.
1.458 +
1.459 + iAttributes = KMapAttrType2 | // Mark it as TMappingAttributes2 object
1.460 + EMapAttrReadSup | // All memory is readable from Kernel (Supervisor) mode
1.461 + (aType <<KMapAttrTypeShift) |
1.462 + (aUserAccess ? EMapAttrReadUser : 0)|
1.463 + (aWritable ? EMapAttrWriteSup : 0)|
1.464 + ((aWritable&&aUserAccess)? EMapAttrWriteUser: 0)|
1.465 +#ifdef __MMU_USE_SYMMETRIC_ACCESS_PERMISSIONS
1.466 + (aExecutable ? EMapAttrExecSup : 0)|
1.467 + ((aExecutable&&aUserAccess)? EMapAttrExecUser: 0)|
1.468 +#else
1.469 + (aExecutable ? EMapAttrExecUser|EMapAttrExecSup : 0)|
1.470 +#endif
1.471 + (aShared ? EMapAttrShared : 0)|
1.472 + (aParity ? EMapAttrUseECC : 0);
1.473 +
1.474 + // Kernel relies on TMappingAttributes bitmask when dealing with various memory mappings.
1.475 + // Set cache attribute bits as they are in TMappingAttributes.
1.476 + iAttributes |= InternalCache::TypeToCachingAttributes(aType);
1.477 + }
1.478 +
1.479 +TMappingAttributes2::TMappingAttributes2(TUint aMapAttr):iAttributes(aMapAttr)
1.480 + {
1.481 + };
1.482 +
1.483 +TMemoryType TMappingAttributes2::Type()
1.484 + {
1.485 + if(iAttributes&KMapAttrType2)
1.486 + return (TMemoryType)(iAttributes>>KMapAttrTypeShift & 0x7); //three bits for memory type.
1.487 +
1.488 + switch(iAttributes&EMapAttrL1CacheMask)
1.489 + {
1.490 + case EMapAttrFullyBlocking:
1.491 + return EMemAttStronglyOrdered;
1.492 +
1.493 + case EMapAttrBufferedNC:
1.494 + return EMemAttDevice;
1.495 +
1.496 + case EMapAttrBufferedC:
1.497 + case EMapAttrL1Uncached:
1.498 + case EMapAttrCachedWTRA:
1.499 + case EMapAttrCachedWTWA:
1.500 + case EMapAttrAltCacheWTRA:
1.501 + case EMapAttrAltCacheWTWA:
1.502 + return EMemAttNormalUncached;
1.503 +
1.504 + case EMapAttrCachedWBRA:
1.505 + case EMapAttrCachedWBWA:
1.506 + case EMapAttrAltCacheWBRA:
1.507 + case EMapAttrAltCacheWBWA:
1.508 + case EMapAttrL1CachedMax:
1.509 + return EMemAttNormalCached;
1.510 +
1.511 + default:
1.512 + Panic(KErrArgument);
1.513 + return EMemAttNormalCached;
1.514 + }
1.515 + }
1.516 +
1.517 +TBool TMappingAttributes2::UserAccess() {return (iAttributes&EMapAttrUserRw ? (TBool)ETrue : (TBool)EFalse);}
1.518 +TBool TMappingAttributes2::Writable() {return (iAttributes&EMapAttrWriteMask? (TBool)ETrue : (TBool)EFalse);}
1.519 +#ifdef __MMU_USE_SYMMETRIC_ACCESS_PERMISSIONS
1.520 +TBool TMappingAttributes2::Executable() {return (iAttributes&EMapAttrExecMask ? (TBool)ETrue : (TBool)EFalse);}
1.521 +#else
1.522 +TBool TMappingAttributes2::Executable() {return (iAttributes&EMapAttrExecUser ? (TBool)ETrue : (TBool)EFalse);}
1.523 +#endif
1.524 +TBool TMappingAttributes2::Shared() {return (iAttributes&EMapAttrShared ? (TBool)ETrue : (TBool)EFalse);}
1.525 +TBool TMappingAttributes2::Parity() {return (iAttributes&EMapAttrUseECC ? (TBool)ETrue : (TBool)EFalse);}
1.526 +TBool TMappingAttributes2::ObjectType2(){return (iAttributes&KMapAttrType2 ? (TBool)ETrue : (TBool)EFalse);}
1.527 +void TMappingAttributes2::Panic(TInt aPanic) {Kern::Fault("TMappingAttributes2",aPanic);}
1.528 +
1.529 +
1.530 +#ifdef __DEBUGGER_SUPPORT__
1.531 + /**
1.532 + Initialises the breakpoint pool.
1.533 + There is only one breakpoint pool in the system. The breakpoint pool should be initialised only once - usually from
1.534 + the run-mode debugger device driver.
1.535 +
1.536 + @param aCapabilities On return this is set to a bitmask of values from enum DebugSupport::TType which represents the
1.537 + supported breakpoint types. At the moment only DebugSupport::EBreakpointGlobal type is supported.
1.538 + @param aMaxBreakpoints The number of breakpoints for which resources should be reserved. It represents
1.539 + the maximum number of the breakpoints at a time.
1.540 +
1.541 + @return KErrNoMemory, if not enough memory to reserve breakpoint resources.
1.542 + KErrInUse, if breakpoint pool already exists. Indicates that another debug tool might be using it at the moment.
1.543 + KErrNotSupported, if Kernel is not built with __DEBUGGER_SUPPORT__ option
1.544 + KErrNone, on success.
1.545 +
1.546 + @pre No fast mutex can be held.
1.547 + @pre Kernel must be unlocked.
1.548 + @pre Call in a thread context.
1.549 + @pre Interrupts must be enabled.
1.550 + */
1.551 +EXPORT_C TInt DebugSupport::InitialiseCodeModifier(TUint& aCapabilities, TInt aMaxBreakpoints)
1.552 + {
1.553 + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::InitialiseCodeModifier");
1.554 + TInt err;
1.555 + NKern::ThreadEnterCS();
1.556 + Kern::MutexWait(CodeModifier::Mutex());
1.557 +
1.558 + if ( KErrNone == (err =CodeModifier::CreateAndInitialise(aMaxBreakpoints)))
1.559 + aCapabilities = EBreakpointGlobal;
1.560 +
1.561 + Kern::MutexSignal(CodeModifier::Mutex());
1.562 + NKern::ThreadLeaveCS();
1.563 + return err;
1.564 + }
1.565 +
1.566 + /**
1.567 + Restore all breakpoints and free resources.
1.568 + Must not be called before Initialise().
1.569 +
1.570 + @panic CodeModifier 0 if called before InitialiseCodeModifier().
1.571 +
1.572 + @pre No fast mutex can be held.
1.573 + @pre Kernel must be unlocked.
1.574 + @pre Call in a thread context.
1.575 + @pre Interrupts must be enabled.
1.576 + */
1.577 +EXPORT_C void DebugSupport::CloseCodeModifier()
1.578 + {
1.579 + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::CloseCodeModifier");
1.580 + NKern::ThreadEnterCS();
1.581 + Kern::MutexWait(CodeModifier::Mutex());
1.582 +
1.583 + if (!TheCodeModifier)
1.584 + {
1.585 + Kern::MutexSignal(CodeModifier::Mutex());
1.586 + NKern::ThreadLeaveCS();
1.587 + CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
1.588 + }
1.589 + TheCodeModifier->Close();
1.590 +
1.591 + Kern::MutexSignal(CodeModifier::Mutex());
1.592 + NKern::ThreadLeaveCS();
1.593 + }
1.594 +
1.595 +/**
1.596 +Write a single breakpoint.
1.597 +I.e. store aValue at location aAddress in the address space of aThread.
1.598 +If the address resides in XIP code (ROM image), the memory page is shadowed before the content of the aAddress is altered.
1.599 +
1.600 +The breakpoint should be cleared/restored by DebugSupport::RestoreCode with matching aThread and aAddress.
1.601 +The breakpoints are owned by the corresponding process. Therefore:
1.602 +@code
1.603 +DebugSupport::ModifyCode(thread1, address, size, value, type);
1.604 +and
1.605 +DebugSupport::ModifyCode(thread2, address size, value, type);
1.606 +@endcode
1.607 +have the same effect if thread1 and thread2 belong to the same process.
1.608 +
1.609 +Breakpoints of the diferent type(size) cannot overlap each other. For example:
1.610 +@code
1.611 +DebugSupport::ModifyCode(thread, address, 4, value, type); //address is word aligned address
1.612 +DebugSupport::ModifyCode(thread, address, 2, value, type); //will return KErrAccessDenied
1.613 +DebugSupport::ModifyCode(thread, address+2, 2, value, type); //will return KErrAccessDenied
1.614 +DebugSupport::ModifyCode(thread, address+1, 1, value, type); //will return KErrAccessDenied
1.615 +@endcode
1.616 +
1.617 +After the content of aAddress is altered, instruction cache invalidation is performed on the cache line that aAddress
1.618 +belongs to. Therefore, the device driver doesn't have to call Cache::IMB_Range().
1.619 +
1.620 +If a code segment (which a valid breakpoint belongs to) is removed from the given process, the breakpoint will be
1.621 +automatically removed. This occures just before EEventRemoveCodeSeg event is issued with DProcess* matching
1.622 +the breakpoint's process. This also applies to the terminating/killed process, as all breakpoints belonging to it will be removed too.
1.623 +
1.624 +@param aThread The thread in who's address space the breakpoint is to be written.
1.625 +@param aAddress The linear address of the breakpoint. Must be a multiple of aSize.
1.626 +@param aSize The size, in bytes, of the breakpoint. Must be 1,2 or 4.
1.627 +@param aValue The value to be stored at aAddress. This value is trucated to the
1.628 + number of bits relevent to aSize.
1.629 +@param aType The breakpoint type required. This is a bitmask of values from enum TType.
1.630 + If this specifies more than one type, then the type with least scope
1.631 + (i.e. EBreakpointLocal) is used when this is supported.
1.632 +
1.633 + @return KErrNoMemory, if no resources are available.
1.634 + KErrAlreadyExists, if a breakpoint with the same address, size and the same owning process already exists in the pool.
1.635 + KErrAccessDenied, if an existing breakpoint of a different size and the same owning process overlaps the specified breakpoint.
1.636 + KErrNotSupported, if none of the breakpoints types specified are supported or if Kernel is not built with __DEBUGGER_SUPPORT__ option
1.637 + Otherwise, a positive value from enum TType which represents the type of breakpoint written.
1.638 +
1.639 + @panic CodeModifier 0 if called before InitialiseCodeModifier().
1.640 + @panic CodeModifier 1 if aSize value or aAdress alignement is invalid.
1.641 +
1.642 + @pre No fast mutex can be held.
1.643 + @pre Kernel must be unlocked.
1.644 + @pre Call in a thread context.
1.645 + @pre Interrupts must be enabled.
1.646 + */
1.647 +EXPORT_C TInt DebugSupport::ModifyCode(DThread* aThread, TLinAddr aAddress, TInt aSize, TUint aValue, TUint aType)
1.648 + {
1.649 + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::ModifyCode");
1.650 + switch(aSize) //Chack aSize and aValue
1.651 + {
1.652 + case CodeModifier::EByte:
1.653 + break;
1.654 + case CodeModifier::EHalfword:
1.655 + if ((TInt)aAddress & 1)
1.656 + CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
1.657 + break;
1.658 + case CodeModifier::EWord:
1.659 + if ((TInt)aAddress & 3)
1.660 + CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
1.661 + break;
1.662 + default:
1.663 + CodeModifier::Fault(CodeModifier::EPanicInvalidSizeOrAlignment);
1.664 + }
1.665 +
1.666 + if (aType != DebugSupport::EBreakpointGlobal)//Check breakpoint type
1.667 + return KErrNotSupported;
1.668 +
1.669 + NKern::ThreadEnterCS();
1.670 + Kern::MutexWait(CodeModifier::Mutex());
1.671 +
1.672 + if (!TheCodeModifier)
1.673 + {
1.674 + Kern::MutexSignal(CodeModifier::Mutex());
1.675 + NKern::ThreadLeaveCS();
1.676 + CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
1.677 + }
1.678 + TInt r = TheCodeModifier->Modify(aThread, aAddress, aSize, aValue);
1.679 +
1.680 + Kern::MutexSignal(CodeModifier::Mutex());
1.681 + NKern::ThreadLeaveCS();
1.682 +
1.683 + if (r)
1.684 + return r;
1.685 + return EBreakpointGlobal;
1.686 + }
1.687 +
1.688 + /**
1.689 + Restore a previousely written breakpoint.
1.690 + I.e. restore the value at location aAddress in the address space of aProcess.
1.691 +
1.692 + After the content of aAddress is altered, instruction cache invalidation is performed on the cache line
1.693 + that aAddress belongs to. Therefore, the device driver doesn't have to call Cache::IMB_Range().
1.694 +
1.695 + If the address resides in shadowed memory, the memory page will be un-shadowed if this is the last breakpoint
1.696 + in the page. However, if the page had been already shadowed before the first breakpoint in the page was applied,
1.697 + the page will remain shadowed.
1.698 +
1.699 + @param aProcess The process in who's address space aAddress lies.
1.700 + @param aAddress The linear address of an existing breakpoint.
1.701 +
1.702 + @return KErrNotFound, if the breakpoint hadn't been previously written. It is also returned if the breakpoint
1.703 + was previously removed from the list because the code segment (which the breakpoint belongs to) was
1.704 + unloaded/removed from the process associated with the breakpoint.
1.705 + KErrNotSupported, if Kernel is not built with __DEBUGGER_SUPPORT__ option
1.706 + KErrNone, on success.
1.707 +
1.708 + @panic CodeModifier 0 if called before InitialiseCodeModifier().
1.709 +
1.710 + @pre No fast mutex can be held.
1.711 + @pre Kernel must be unlocked.
1.712 + @pre Call in a thread context.
1.713 + @pre Interrupts must be enabled.
1.714 + */
1.715 +EXPORT_C TInt DebugSupport::RestoreCode(DThread* aThread, TLinAddr aAddress)
1.716 + {
1.717 + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::RestoreCode");
1.718 + NKern::ThreadEnterCS();
1.719 + Kern::MutexWait(CodeModifier::Mutex());
1.720 +
1.721 + if (!TheCodeModifier)
1.722 + {
1.723 + Kern::MutexSignal(CodeModifier::Mutex());
1.724 + NKern::ThreadLeaveCS();
1.725 + CodeModifier::Fault(CodeModifier::EPanicNotInitialised);
1.726 + }
1.727 + TInt r = TheCodeModifier->Restore(aThread, aAddress);
1.728 +
1.729 + Kern::MutexSignal(CodeModifier::Mutex());
1.730 + NKern::ThreadLeaveCS();
1.731 + return r;
1.732 + }
1.733 +
1.734 + /**
1.735 + Terminates a specified process on behalf of a debugger.
1.736 +
1.737 + @param aProcess The process in who's address space aAddress lies.
1.738 + @param aReason The reason code to supply when terminating a process
1.739 +
1.740 + @return N/A.
1.741 +
1.742 + @pre No fast mutex can be held.
1.743 + @pre Kernel must be unlocked.
1.744 + @pre Call in a thread context.
1.745 + @pre Interrupts must be enabled.
1.746 + */
1.747 +EXPORT_C void DebugSupport::TerminateProcess(DProcess* aProcess, const TInt aReason)
1.748 + {
1.749 + CHECK_PRECONDITIONS(MASK_THREAD_STANDARD,"DebugSupport::TerminateProcess");
1.750 + NKern::ThreadEnterCS();
1.751 + aProcess->Die(EExitTerminate,aReason,KNullDesC);
1.752 + NKern::ThreadLeaveCS();
1.753 + return;
1.754 + }
1.755 +
1.756 +/**
1.757 +Creates CodeModifier.
1.758 +@param aMaxBreakpoints The number of breakpoints to be allocated.
1.759 +@return KErrInUse if code modifier already exists.
1.760 + KErrNoMemory if out of memory
1.761 + KErrNone on success
1.762 +@pre Calling thread must be in the critical section
1.763 +@pre CodeSeg mutex held
1.764 +*/
1.765 +TInt CodeModifier::CreateAndInitialise(TInt aMaxBreakpoints)
1.766 + {
1.767 + if (TheCodeModifier)
1.768 + return KErrInUse;
1.769 +
1.770 + CodeModifier* modifier = new CodeModifier;
1.771 + if (!modifier)
1.772 + return KErrNoMemory;
1.773 +
1.774 + modifier->iBreakpoints = new TBreakpoint[aMaxBreakpoints];
1.775 + if (!modifier->iBreakpoints)
1.776 + {
1.777 + delete modifier;
1.778 + return KErrNoMemory;
1.779 + };
1.780 +
1.781 + modifier->iPages = new TPageInfo[aMaxBreakpoints];
1.782 + if (!modifier->iPages)
1.783 + {
1.784 + delete[] modifier->iBreakpoints;
1.785 + delete modifier;
1.786 + return KErrNoMemory;
1.787 + }
1.788 +
1.789 + modifier->iPoolSize = aMaxBreakpoints;
1.790 + modifier->iPageSize = Kern::RoundToPageSize(1);
1.791 + modifier->iPageMask = ~(modifier->iPageSize-1);
1.792 +
1.793 + TheCodeModifier = modifier;
1.794 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CreateAndInitialise() Size:%d created", aMaxBreakpoints));
1.795 + return KErrNone;
1.796 + }
1.797 +
1.798 +/**
1.799 +Sets breakpoint.
1.800 +@pre Calling thread must be in the critical section
1.801 +@pre CodeSeg mutex held
1.802 +*/
1.803 +TInt CodeModifier::Modify(DThread* aThread, TLinAddr aAddress, TInt aSize, TUint aValue)
1.804 + {
1.805 + TInt r;
1.806 + TUint oldValue;
1.807 + TBool overlap;
1.808 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Modify() T:%x Addr:%x, Size:%d Val:%x", aThread, aAddress, aSize, aValue));
1.809 +
1.810 + TBreakpoint* brk =FindBreakpoint(aThread, aAddress,aSize,overlap);
1.811 + if (overlap)
1.812 + return KErrAccessDenied;
1.813 + if (brk)
1.814 + return KErrAlreadyExists;
1.815 +
1.816 + if(NULL==(brk = FindEmptyBrk()))
1.817 + return KErrNoMemory;
1.818 +
1.819 + //Find the page (if exists). Shadow the page if necessery.
1.820 + TInt pageIndex = -1;
1.821 +
1.822 +#ifndef __DEMAND_PAGING__
1.823 + if (IsRom(aAddress)) // If no demand paging, only need to do this if the address is in rom
1.824 +#endif
1.825 + {
1.826 + pageIndex = FindPageInfo(aAddress);
1.827 + if (pageIndex < 0)
1.828 + {
1.829 + pageIndex = FindEmptyPageInfo();
1.830 + if (pageIndex < 0)
1.831 + return KErrNoMemory;
1.832 + TPageInfo& page = iPages[pageIndex];
1.833 + memclr(&page, sizeof(page));
1.834 + page.iAddress = aAddress & iPageMask;
1.835 +
1.836 + if (IsRom(aAddress))
1.837 + {
1.838 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Modify() - Shadowing Page"));
1.839 + r = Epoc::AllocShadowPage(aAddress & iPageMask);
1.840 + if (r==KErrAlreadyExists)
1.841 + page.iWasShadowed = ETrue;
1.842 + else if (r!=KErrNone)
1.843 + return r;
1.844 + }
1.845 +#ifdef __DEMAND_PAGING__
1.846 + else
1.847 + {
1.848 + DDemandPagingLock* lock = new DDemandPagingLock;
1.849 + if (lock == NULL)
1.850 + return KErrNoMemory;
1.851 + r = lock->Alloc(iPageSize);
1.852 + if (r != KErrNone)
1.853 + {
1.854 + delete lock;
1.855 + return r;
1.856 + }
1.857 + lock->Lock(aThread, aAddress & iPageMask, iPageSize);
1.858 + page.iPagingLock = lock;
1.859 + }
1.860 +#endif
1.861 + }
1.862 + iPages[pageIndex].iCounter++;
1.863 + }
1.864 +
1.865 + r = SafeWriteCode(aThread->iOwningProcess, aAddress, aSize, aValue, &oldValue);
1.866 + if (r != KErrNone)
1.867 + {//aAddress is invalid
1.868 + if (pageIndex >= 0)
1.869 + RestorePage(pageIndex);
1.870 + return r;
1.871 + }
1.872 +
1.873 + //All done. Update the internal structures.
1.874 + brk->iAddress = aAddress;
1.875 + brk->iProcessId = (aThread->iOwningProcess)->iId;
1.876 + brk->iOldValue = oldValue;
1.877 + brk->iSize = aSize;
1.878 + brk->iPageIndex = pageIndex;
1.879 + return KErrNone;
1.880 + }
1.881 +
1.882 +/**
1.883 +@pre Calling thread must be in the critical section
1.884 +@pre CodeSeg mutex held
1.885 +*/
1.886 +TInt CodeModifier::Restore(DThread* aThread, TLinAddr aAddress)
1.887 + {
1.888 + TUint oldValue;
1.889 + TBool overlaps;
1.890 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Restore() T:%x Addr:%x", aThread, aAddress));
1.891 + TInt r = KErrNone;;
1.892 + TBreakpoint* br = FindBreakpoint(aThread, aAddress, 0, overlaps);
1.893 + if (br==NULL)
1.894 + return KErrNotFound;
1.895 +
1.896 + r = SafeWriteCode(aThread->iOwningProcess, br->iAddress, br->iSize, br->iOldValue, &oldValue);
1.897 + if (r)
1.898 + r=KErrNotFound;
1.899 +
1.900 + br->iSize = (TUint)EEmpty;
1.901 +
1.902 + TInt pageIndex = br->iPageIndex;
1.903 + if (pageIndex>=0)
1.904 + RestorePage(pageIndex);
1.905 +
1.906 + return r;
1.907 + }
1.908 +
1.909 +/*
1.910 +@pre Calling thread must be in the critical section
1.911 +@pre CodeSeg mutex held
1.912 +*/
1.913 +void CodeModifier::Close()
1.914 + {
1.915 + TUint oldValue;
1.916 + TInt brkIndex;
1.917 +
1.918 + TheCodeModifier = NULL;
1.919 +
1.920 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Close()"));
1.921 +
1.922 + for (brkIndex=0; brkIndex<iPoolSize; brkIndex++)
1.923 + {
1.924 + if (iBreakpoints[brkIndex].iSize ==(TUint16)EEmpty)
1.925 + continue;
1.926 + DProcess* process = Process(iBreakpoints[brkIndex].iProcessId);
1.927 +
1.928 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Close() - Removing Brk:%x",iBreakpoints[brkIndex].iAddress));
1.929 +
1.930 + //Write back the original value
1.931 + if (process)
1.932 + SafeWriteCode(process, iBreakpoints[brkIndex].iAddress, iBreakpoints[brkIndex].iSize, iBreakpoints[brkIndex].iOldValue, &oldValue);
1.933 +
1.934 + iBreakpoints[brkIndex].iSize = (TUint)EEmpty;
1.935 + TInt pageIndex = iBreakpoints[brkIndex].iPageIndex;
1.936 + if (pageIndex>=0)
1.937 + RestorePage(pageIndex);
1.938 + }
1.939 +
1.940 + delete this;
1.941 + }
1.942 +
1.943 +/*
1.944 +Destructor. The object is deleted asynchroniously from Kernel Supervisor thread.
1.945 +*/
1.946 +CodeModifier::~CodeModifier()
1.947 + {
1.948 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::~CodeModifier()"));
1.949 + delete[] iPages;
1.950 + delete[] iBreakpoints;
1.951 + }
1.952 +
1.953 +/**
1.954 +This is executed when a code segment is about to be unmapped from the process. It corresponds to EEventRemoveCodeSeg Kernel event.
1.955 +Removes breakpoints that belong to the threads from aProcess. Also, removes shadow pages if there is no breakpoint left in them.
1.956 +
1.957 +@param aCodeSeg Code Segment that is removed from aProcess.
1.958 +@param aProcess Process from whom the code segment is removed.
1.959 +
1.960 +@pre Calling thread must be in the critical section
1.961 +@pre CodeSeg mutex held
1.962 +*/
1.963 +void CodeModifier::CodeSegRemoved(DCodeSeg* aCodeSeg, DProcess* aProcess)
1.964 + {
1.965 + if (!TheCodeModifier)
1.966 + return;
1.967 + TheCodeModifier->DoCodeSegRemoved(aCodeSeg, aProcess);
1.968 + }
1.969 +
1.970 +void CodeModifier::DoCodeSegRemoved(DCodeSeg* aCodeSeg, DProcess* aProcess)
1.971 + {
1.972 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CodeSegRemoved()"));
1.973 +
1.974 + TUint oldValue;
1.975 + TUint minAddr = aCodeSeg->iRunAddress;
1.976 + TUint maxAddr = aCodeSeg->iRunAddress + aCodeSeg->iSize;
1.977 +
1.978 + TBreakpoint* bp = iBreakpoints;
1.979 + TBreakpoint* bpEnd = bp+iPoolSize; //points right behind iBreakpoints
1.980 + for (; bp<bpEnd; ++bp)
1.981 + {
1.982 + if (bp->iSize == (TUint)EEmpty) continue;
1.983 +
1.984 + if (aProcess->iId == bp->iProcessId)
1.985 + {
1.986 + if (bp->iAddress >= minAddr && bp->iAddress < maxAddr)
1.987 + {
1.988 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::CodeSegRemoved()- a breakpoint"));
1.989 +
1.990 + //Remove breakpoint. Don't examine error code as there is nobody to report to.
1.991 + SafeWriteCode(aProcess, bp->iAddress, bp->iSize, bp->iOldValue, &oldValue);
1.992 +
1.993 + //Mark the slot as empty and decrease the counter of the shadow page slot (if there is any associated)
1.994 + bp->iSize = (TUint)EEmpty;
1.995 + if (bp->iPageIndex >= 0)
1.996 + RestorePage(bp->iPageIndex);
1.997 + }
1.998 + }
1.999 + }
1.1000 +
1.1001 + }
1.1002 +
1.1003 +/*
1.1004 +Finds DProcess that matches to processId
1.1005 +@param aProcessId ProcessId
1.1006 +@return Pointer to matching DProcess or NULL
1.1007 +*/
1.1008 +DProcess* CodeModifier::Process(TUint aProcessId)
1.1009 + {
1.1010 + TInt i;
1.1011 + DProcess* process = NULL;
1.1012 + DObjectCon* processCon = Kern::Containers()[EProcess];
1.1013 + processCon->Wait();
1.1014 +
1.1015 + for (i=0;i<processCon->Count();i++)
1.1016 + {
1.1017 + DProcess* pr = (DProcess*)(*processCon)[i];
1.1018 + if (pr->iId == aProcessId)
1.1019 + {
1.1020 + process=(DProcess*)pr;
1.1021 + break;
1.1022 + }
1.1023 + }
1.1024 +
1.1025 + processCon->Signal();
1.1026 + return process;
1.1027 + }
1.1028 +
1.1029 +/*
1.1030 +Returns eTrue if given virtual address belongs to rom image, EFalse otherwise
1.1031 +*/
1.1032 +TBool CodeModifier::IsRom(TLinAddr aAddress)
1.1033 + {
1.1034 + TRomHeader romHeader = Epoc::RomHeader();
1.1035 + if ( (aAddress >= romHeader.iRomBase ) && (aAddress < (romHeader.iRomBase + romHeader.iUncompressedSize)) )
1.1036 + return ETrue;
1.1037 + return EFalse;
1.1038 + }
1.1039 +
1.1040 +/*
1.1041 +Finds the first available(empty) breakpoint slot.
1.1042 +@return The pointer of the empty slot or NULL if all occupied.
1.1043 +*/
1.1044 +CodeModifier::TBreakpoint* CodeModifier::FindEmptyBrk()
1.1045 + {
1.1046 + TBreakpoint* bp = TheCodeModifier->iBreakpoints;
1.1047 + TBreakpoint* bpEnd = bp+TheCodeModifier->iPoolSize; //points right behind iBreakpoints
1.1048 + for (; bp<bpEnd; ++bp)
1.1049 + if (bp->iSize == (TInt16)EEmpty)
1.1050 + return bp;
1.1051 +
1.1052 + return NULL;
1.1053 + }
1.1054 +
1.1055 +/*
1.1056 +Finds matching breakpoint.
1.1057 +
1.1058 +@param aThread The thread who's process owns the breakpoint
1.1059 +@param aAddress Address of the breakpoint.
1.1060 +@param aSize The size of the breakpoint. Value 0, 1,2 or 4 is assumed. If 0, it doesn't check the size nor overlaps(used to remove breakpoint).
1.1061 +@param aOverlap On return, it is true if a breakpoint is found that doesn't match the size but overlaps with
1.1062 + the specified breakpoint(i.e. address and process are the same but the size is different).
1.1063 +
1.1064 +@return - The pointer to the breakpoint slot that matches the entry (adress, size and the owning process)
1.1065 + - NULL - if could't find the matching breakpoint.
1.1066 +*/
1.1067 +CodeModifier::TBreakpoint* CodeModifier::FindBreakpoint(DThread* aThread, TLinAddr aAddress, TInt aSize, TBool& aOverlap)
1.1068 + {
1.1069 + TInt bytes=0;
1.1070 + aOverlap = EFalse;
1.1071 + TUint processId = aThread->iOwningProcess->iId;//processId of the thread that owns aThread
1.1072 +
1.1073 + if (aSize) //if size==0, we do not check overlaps.
1.1074 + bytes = ((1<<aSize)-1)<<(aAddress&3); //bits[3-0] marks the bytes that are contained in the breakpoint:
1.1075 + // address: ...00b size: 1 => bytes=0001b
1.1076 + // address: ...01b size: 1 => bytes=0010b
1.1077 + // address: ...10b size: 1 => bytes=0100b
1.1078 + // address: ...11b size: 1 => bytes=1000b
1.1079 + // address: ...00b size: 2 => bytes=0011b
1.1080 + // address: ...10b size: 2 => bytes=1100b
1.1081 + // address: ...00b size: 4 => bytes=1111b
1.1082 +
1.1083 + TBreakpoint* bp = TheCodeModifier->iBreakpoints;
1.1084 + TBreakpoint* bpEnd = bp+TheCodeModifier->iPoolSize; //points right behind iBreakpoints
1.1085 + for (; bp<bpEnd; ++bp)
1.1086 + {
1.1087 + if (bp->iSize == (TInt16)EEmpty || bp->iProcessId != processId)
1.1088 + continue;//Either empty or not matchng process.
1.1089 +
1.1090 + if (!aSize)
1.1091 + { //Do not check the size. If the address does not match, do not check for overlap.
1.1092 + if (bp->iAddress == aAddress)
1.1093 + return bp;
1.1094 + else
1.1095 + continue;
1.1096 + }
1.1097 +
1.1098 + if (bp->iAddress == aAddress && bp->iSize == aSize)
1.1099 + return bp;//If we find a matching breakpoint, there cannot be another one that overlaps
1.1100 +
1.1101 + //Check if bp breakpoint overlaps with the specified one.
1.1102 + if ((bp->iAddress^aAddress)>>2)
1.1103 + continue;//Not in the same word
1.1104 +
1.1105 + if (((1<<bp->iSize)-1)<<(bp->iAddress&3)&bytes)
1.1106 + {//Two brakpoints are within the same word with some overlaping bytes.
1.1107 + aOverlap = ETrue;
1.1108 + return NULL; //If we find an overlaping breakpoint, there cannot be another one that matches exactly.
1.1109 + }
1.1110 + }
1.1111 + return NULL;
1.1112 + }
1.1113 +
1.1114 +/*
1.1115 +Finds the first available(empty) page info slot.
1.1116 +@return The index of the slot or KErrNotFound if all occupied.
1.1117 +*/
1.1118 +TInt CodeModifier::FindEmptyPageInfo()
1.1119 + {
1.1120 + TInt i;
1.1121 + for (i=0; i<iPoolSize; i++)
1.1122 + if (!iPages[i].iCounter)
1.1123 + return i;
1.1124 + return KErrNotFound;
1.1125 + }
1.1126 +
1.1127 +/*
1.1128 +Finds the page info structure that contains given virtual address
1.1129 +@return The index of the page info slot or KErrNotFound.
1.1130 +*/
1.1131 +TInt CodeModifier::FindPageInfo(TLinAddr aAddress)
1.1132 + {
1.1133 + TInt i;
1.1134 + aAddress &= iPageMask; //round down to the page base address
1.1135 + for (i=0; i<iPoolSize; i++)
1.1136 + if(iPages[i].iCounter)
1.1137 + if (iPages[i].iAddress == aAddress)
1.1138 + return i;
1.1139 + return KErrNotFound;
1.1140 + }
1.1141 +
1.1142 +/**
1.1143 +Decrement the count of breakpoints associated with this page, and restores page
1.1144 +to its original state if there are none remaining.
1.1145 +*/
1.1146 +void CodeModifier::RestorePage(TInt aPageIndex)
1.1147 + {
1.1148 + TPageInfo& page = iPages[aPageIndex];
1.1149 + if(--page.iCounter==0)
1.1150 + {
1.1151 + if (!page.iWasShadowed)
1.1152 + {
1.1153 + __KTRACE_OPT(KDEBUGGER,Kern::Printf("CodeModifier::Restore() - Freeing Shadow Page"));
1.1154 + Epoc::FreeShadowPage(page.iAddress);
1.1155 + }
1.1156 +#ifdef __DEMAND_PAGING__
1.1157 + if (page.iPagingLock)
1.1158 + {
1.1159 + // Release lock and free resources
1.1160 + delete page.iPagingLock;
1.1161 + page.iPagingLock = NULL;
1.1162 + }
1.1163 +#endif
1.1164 + }
1.1165 + }
1.1166 +
1.1167 +void CodeModifier::Fault(TPanic aPanic)
1.1168 + {
1.1169 + Kern::Fault("CodeModifier", aPanic);
1.1170 + }
1.1171 +
1.1172 +#else //__DEBUGGER_SUPPORT__
1.1173 +EXPORT_C TInt DebugSupport::InitialiseCodeModifier(TUint& /*aCapabilities*/, TInt /*aMinBreakpoints*/)
1.1174 + {
1.1175 + return KErrNotSupported;
1.1176 + }
1.1177 +EXPORT_C void DebugSupport::CloseCodeModifier()
1.1178 + {
1.1179 + }
1.1180 +EXPORT_C TInt DebugSupport::ModifyCode(DThread* /*aProcess*/, TLinAddr /*aAddress*/, TInt /*aSize*/, TUint /*aValue*/, TUint /*aType*/)
1.1181 + {
1.1182 + return KErrNotSupported;
1.1183 + }
1.1184 +EXPORT_C TInt DebugSupport::RestoreCode(DThread* /*aProcess*/, TLinAddr /*aAddress*/)
1.1185 + {
1.1186 + return KErrNotSupported;
1.1187 + }
1.1188 +EXPORT_C void DebugSupport::TerminateProcess(DProcess* /*aProcess*/, const TInt /*aReason*/)
1.1189 + {
1.1190 + }
1.1191 +#endif
1.1192 +