Catchup.
authorJoe Branton <joe.branton@accenture.com>
Thu, 29 Jul 2010 12:05:54 +1000
changeset 16 18a55d594fba
parent 15 6bb86f60191e (current diff)
parent 12 d0b16e01f384 (diff)
child 17 949c6f5096e4
Catchup.
--- a/commands/testexecute/testexecute.cif	Thu Jul 29 12:03:43 2010 +1000
+++ b/commands/testexecute/testexecute.cif	Thu Jul 29 12:05:54 2010 +1000
@@ -17,7 +17,9 @@
 
 ==long-description
 
-An fshell exe that wraps up a Test Execute script run and redirects its output to the fshell console.
+An fshell exe that wraps up a Test Execute script run and redirects its log output to the fshell console.
+
+Important note: Older versions of Test Execute do not support the C<-tci> and C<-txi> options. Therefore, C<--include> and C<--exclude> may have no effect.
 
 ==option bool d debug
 
@@ -47,7 +49,7 @@
 
 You can specify the test case IDs using all the three different ways listed above. For example, in the following testexecute command, the test cases list is a combination of comma-separated test case IDs, test case ID range and a .tcs file containing IDs of the test cases to be included during execution: 
 
- c:\>testexecute c:\tefintegrationtest\TEFIntegrationTest-regular.script -tci TEST-001,TEST-002,TEST-008:TEST-015,some.tcs
+    c:\>testexecute c:\tefintegrationtest\TEFIntegrationTest-regular.script -tci TEST-001,TEST-002,TEST-008:TEST-015,some.tcs
 
 ==option bool t ignore
 
--- a/core/builtins/date.cif	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/builtins/date.cif	Thu Jul 29 12:05:54 2010 +1000
@@ -67,7 +67,7 @@
 
 ==option bool j just-display
 
-Rather than going ahead and setting the specified time and date, do a dry run and just displays it in human readable form. Must be used in conjunction with C<--set>. In effect it is an option to check that the set string has been parsed correctly before actually making the change.
+Rather than going ahead and setting the specified time and date, do a dry run and just displays it in human readable form. Must be used in conjunction with C<--set> or <--raw-set>. In effect it is an option to check that the set string has been parsed correctly before actually making the change.
 
 ==option int64 R raw-set
 
@@ -77,6 +77,10 @@
 
 Display the date in timestamp format C<YYYYMMDD-HHMM.SS> suitable for use in a file name.
 
+==option bool k kern
+
+Only applicable with C<--raw> and/or C<--raw-set>. Instead of using 2000AD as the epoc, use 0AD nominal Gregorian, the kernel's internal native time format.
+
 ==copyright
 
 Copyright (c) 2006-2010 Accenture. All rights reserved.
--- a/core/builtins/kill.cpp	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/builtins/kill.cpp	Thu Jul 29 12:05:54 2010 +1000
@@ -123,13 +123,16 @@
 			PrintWarning(_L("Couldn't open %S (err=%d)"), &fullName);
 			}
 		}
-	if (numFound == 0)
+	if (!iAll)
 		{
-		LeaveIfErr(KErrNotFound, _L("No matches for pattern \"%S\", or all matches are zombies"), &aPattern);
-		}
-	else if (numFound > 1 && !iAll)
-		{
-		PrintWarning(_L("%d further matches for pattern \"%S\" found, be more specific or use --all option"), numFound-1, &aPattern);
+		if (numFound == 0)
+			{
+			LeaveIfErr(KErrNotFound, _L("No matches for pattern \"%S\", or all matches are zombies"), &aPattern);
+			}
+		else if (numFound > 1)
+			{
+			PrintWarning(_L("%d further matches for pattern \"%S\" found, be more specific or use --all option"), numFound-1, &aPattern);
+			}
 		}
 	}
 
--- a/core/builtins/ps.cif	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/builtins/ps.cif	Thu Jul 29 12:05:54 2010 +1000
@@ -96,6 +96,10 @@
 
 Print C<System>, C<Protected> and C<LoadedFromRam> flag values. Only available on EKA1.
 
+==option bool C codesegs
+
+Print the code segments loaded into the process.
+
 ==copyright
 
 Copyright (c) 2005-2010 Accenture. All rights reserved.
--- a/core/builtins/ps.cpp	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/builtins/ps.cpp	Thu Jul 29 12:05:54 2010 +1000
@@ -169,6 +169,11 @@
 
 	_LIT(KOptAddresses, "addresses");
 	aOptions.AppendBoolL(iAddresses, KOptAddresses);
+
+#ifdef FSHELL_MEMORY_ACCESS_SUPPORT
+	_LIT(KOptCodeSegs, "codesegs");
+	aOptions.AppendBoolL(iPrintCodesegs, KOptCodeSegs);
+#endif
 	}
 
 #if defined(__WINS__) && !defined(EKA2)
@@ -317,6 +322,10 @@
 			iFormatter->AppendFormatL(_L("\tAddress: 0x%08x\r\n"), objectInfo.iAddressOfKernelObject);
 			}
 		}
+	if (iPrintCodesegs && iMemoryAccess.Handle())
+		{
+		PrintCodeSegsL(aProcess);
+		}
 #endif // FSHELL_MEMORY_ACCESS_SUPPORT
 	
 	if (iHandleCount)
@@ -542,6 +551,30 @@
 		}
 	}
 
+void ReleaseCodesegMutex(TAny* aMemAccess)
+	{
+	static_cast<RMemoryAccess*>(aMemAccess)->ReleaseCodeSegMutex();
+	}
+
+void CCmdPs::PrintCodeSegsL(RProcess& aProcess)
+	{
+	TInt count = iMemoryAccess.AcquireCodeSegMutexAndFilterCodesegsForProcess(aProcess.Id());
+	LeaveIfErr(count, _L("Couldn't acquire codeseg mutex"));
+	CleanupStack::PushL(TCleanupItem(&ReleaseCodesegMutex, &iMemoryAccess));
+
+	iFormatter->AppendFormatL(_L("\t%d code segments:\r\n"), count);
+
+	TCodeSegKernelInfo codeSegInfo;
+	TPckg<TCodeSegKernelInfo> pkg(codeSegInfo);
+	while (iMemoryAccess.GetNextCodeSegInfo(pkg) == KErrNone)
+		{
+		// Reuse iChunkName, I'm sure it doesn't mind
+		iChunkName.Copy(codeSegInfo.iFileName);
+		iFormatter->AppendFormatL(_L("\t\t%S\r\n"), &iChunkName);
+		}
+	CleanupStack::PopAndDestroy(); // ReleaseCodesegMutex
+	}
+
 #ifdef EXE_BUILD
 EXE_BOILER_PLATE(CCmdPs)
 #endif
--- a/core/builtins/ps.h	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/builtins/ps.h	Thu Jul 29 12:05:54 2010 +1000
@@ -42,6 +42,7 @@
 	void PrintCpuTimeL(RThread& aThread, const TDesC& aThreadName);
 	void PrintChunkInfoL(const TDesC& aProcessName);
 	void PrintSizeL(const TDesC& aCaption, TInt aSize);
+	void PrintCodeSegsL(RProcess& aProcess);
 private:
 	TUint iProcessId;
 	HBufC* iMatch;
@@ -55,6 +56,7 @@
 	TBool iPrintCommandLine;
 	TBool iPrintFlags;
 	TBool iPrintMemoryInfo;
+	TBool iPrintCodesegs;
 	TBool iVerbose;
 	TBool iHuman;
 	TBool iExcludeDead;
--- a/core/src/commands.cpp	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/src/commands.cpp	Thu Jul 29 12:05:54 2010 +1000
@@ -2335,6 +2335,10 @@
 // CCmdDate.
 //
 
+// Appearently kernel reckons to 365.2485 days per year between 0AD (nominal gregorian) and 2000AD, which comes to 730497 days in total.
+// timeanddate.com agrees once you factor in Julian->Gregorian and assuming 0AD wasn't a leap year (it refuses to allow you to directly enter 0AD nominal Gregorian)
+const TInt64 KY2kInMicroSeconds = 730497 * 24 * 60 * (TInt64)(60 * 1000 * 1000);
+
 CCommandBase* CCmdDate::NewLC()
 	{
 	CCmdDate* self = new(ELeave) CCmdDate();
@@ -2356,7 +2360,9 @@
 	{
 	if (iRaw)
 		{
-		Printf(_L("%Ld\r\n"), aTime.Int64());
+		TInt64 time = aTime.Int64();
+		if (iUseKernelFormat) time += KY2kInMicroSeconds;
+		Printf(_L("%Ld\r\n"), time);
 		}
 	else if (iUseTimestampFormat)
 		{
@@ -2412,6 +2418,7 @@
 	else
 		{
 		_LIT(KSettingError, "Cannot set the time");
+		if (iUseKernelFormat) iRawTimeToSet -= KY2kInMicroSeconds;
 		TTime time(iRawTimeToSet);
 		if (iDateToSet)
 			{
@@ -2469,7 +2476,8 @@
 	_LIT(KCmdDateOptRaw, "raw");
 	_LIT(KCmdDateOptJustDisplay, "just-display");
 	_LIT(KCmdDateOptSetRaw, "raw-set");
-	_LIT(KCmdDataOptTimestamp, "timestamp");
+	_LIT(KCmdDateOptTimestamp, "timestamp");
+	_LIT(KCmdDateOptKern, "kern");
 
 	aOptions.AppendBoolL(iUniversalTime, KCmdDateOptUniversal);
 	aOptions.AppendStringL(iDateToSet, KCmdDateOptSet);
@@ -2480,7 +2488,8 @@
 	aOptions.AppendBoolL(iRaw, KCmdDateOptRaw);
 	aOptions.AppendBoolL(iJustDisplay, KCmdDateOptJustDisplay);
 	aOptions.AppendIntL(iRawTimeToSet, KCmdDateOptSetRaw);
-	aOptions.AppendBoolL(iUseTimestampFormat, KCmdDataOptTimestamp);
+	aOptions.AppendBoolL(iUseTimestampFormat, KCmdDateOptTimestamp);
+	aOptions.AppendBoolL(iUseKernelFormat, KCmdDateOptKern);
 	}
 
 
--- a/core/src/commands.h	Thu Jul 29 12:03:43 2010 +1000
+++ b/core/src/commands.h	Thu Jul 29 12:05:54 2010 +1000
@@ -555,6 +555,7 @@
 	TBool iJustDisplay;
 	TInt64 iRawTimeToSet;
 	TBool iUseTimestampFormat;
+	TBool iUseKernelFormat;
 	};
 
 
--- a/documentation/cif_syntax.pod	Thu Jul 29 12:03:43 2010 +1000
+++ b/documentation/cif_syntax.pod	Thu Jul 29 12:05:54 2010 +1000
@@ -16,7 +16,7 @@
 
 =head2 Introduction
 
-Command Info Files (CIFs) can be used to define the interface and documentation for fshell commands that are implemented using CCommandBase. Where previously details of arguments and options etc. were specified in C++ source code, the majority of this information can now be defined in a CIF, which is a plain text file. The format of CIFs is similar to POD (Perl's documentation source format), but with an additional set of key-words that relate to the specifics of command interfaces.
+Command Info Files (CIFs) can be used to define the interface and documentation for fshell commands that are implemented using CCommandBase. Where previously details of arguments and options etc. were specified in C++ source code, the majority of this information can now be defined in a CIF, which is a plain text file. The format of CIFs is similar to POD (Perl's documentation source format), but with an additional set of keywords that relate to the specifics of command interfaces.
 
 CIF files for fshell commands live in F<\resource\cif\fshell> and should be named I<commandname>.cif where I<commandname> is the same as what is returned by the command's Name() function.
 
@@ -72,7 +72,7 @@
 
 =item *
 
-Only the final argument is allowed to have the C<last> attribute. It indicates that further arguments are allowed without needing to quote them and will be merged into this argument. C<last> may not be combined with C<multiple>. If a string provided for a C<last> argument naturally (i.e. as a result of normal string quote and escape handling) forms a single argument and consumes the whole of the remainder of the command line, the resulting single argument will be used as is. Otherwise, the string will be used without any quote or escape handling. Here are some example (using fshell's 'time' command, which takes a single argument that uses the C<last> attribute):
+Only the final argument is allowed to have the C<last> attribute. It indicates that further arguments are allowed without needing to quote them and will be merged into this argument. C<last> may not be combined with C<multiple>. If a string provided for a C<last> argument naturally (i.e. as a result of normal string quote and escape handling) forms a single argument and consumes the whole of the remainder of the command line, the resulting single argument will be used as is. Otherwise, the string will be used without any quote or escape handling. Here are some examples (using fshell's 'time' command, which takes a single argument that uses the C<last> attribute):
 
       Input command-line            Argument receive by the 'time' command
 
@@ -167,7 +167,7 @@
     ...
     void CMyCommand::ArgumentsL(RCommandArgumentList& aArguments)
         {
-        aArguments.AppendEnum((TInt&)iOperation, _L("operation"));
+        aArguments.AppendEnumL((TInt&)iOperation, _L("operation"));
         }
 
 The CIF file would therefore contain:
--- a/documentation/common_mmh.pod	Thu Jul 29 12:03:43 2010 +1000
+++ b/documentation/common_mmh.pod	Thu Jul 29 12:05:54 2010 +1000
@@ -12,7 +12,7 @@
 
 =head1 common.mmh and platform.mmh Syntax
 
-The fshell build system uses a number of macros to control what should be built and how. These are defined in F<fshell/build/common/common.mmh> and F<fshell/platforms/E<lt>PLATFORME<gt>/platform.mmh>. Each platform defines the things it does and doesn't support in its platform.mmh. common.mmh takes these and defines some derived macros. This system allows fshell to be built in a large number of configurations, ranging from minimal base textshell on Symbian OS v9.1 to full GUI on the latest Symbian Foundation codeline.
+The fshell build system uses a number of macros to control what should be built and how. These are defined in F<fshell/build/common/common.mmh> and F<fshell/build/E<lt>PLATFORME<gt>/platform.mmh>. Each platform defines the things it does and doesn't support in its platform.mmh. common.mmh takes these and defines some derived macros. This system allows fshell to be built in a large number of configurations, ranging from minimal base textshell on Symbian OS v9.1 to full GUI on the latest Symbian Foundation codeline.
 
 Any code wishing to use the fshell conditional system should C<< #include <fshell/common.mmh> >> and use the macros below and/or the ones defined in common.mmh to decide how to behave. Below follows the complete list of things that the platform.mmh can define. This isn't the complete list of all the macros that can be I<used>, for that see common.mmh directly. common.mmh can be included anywhere that the preprocessor is used - eg in source code, MMP files, RSS files or bld.infs.
 
@@ -24,7 +24,7 @@
 
 =item FSHELL_[NO_]BTRACE_SUPPORT
 
-BTrace (including timestamp2) supported in kernel.
+BTrace (including timestamp2) supported in kernel. Everything except legacy v9.1-based platforms support btrace.
 
 =item FSHELL_[NO_]PIPS_SUPPORT
 
@@ -132,7 +132,7 @@
 
 =item FSHELL_CORE_SUPPORT_LICENSE
 
-Build platform specific license support into fshell. Note, the platform must export F<\epoc32\build\fshell\core\generated\license.cpp> that provides the implementation of the interface defined in F<\fshell\core\src\license.h>.
+Build platform specific license support into fshell. Note, the platform must export F<\epoc32\build\fshell\core\generated\license.cpp> that provides the implementation of the interface defined in F<\fshell\core\src\license.h>. Obsolete.
 
 =item FSHELL_[NO_]SAMPLINGPROFILER_SUPPORT
 
@@ -235,6 +235,7 @@
 An example platform.mmh is included below. This is for an imaginary platform based on the S^4 release, that is text-only but supports most other things. Generally the older and/or more restricted the platform is, the more C<FSHELL_NO_...> macros you have to define.
 
 	// platform.mmh for the imaginary Mythic platform
+	// This would belong in \fshell\build\mythic\platform.mmh
 
 	#ifndef FSHELL_PLATFORM_MMH
 	#define FSHELL_PLATFORM_MMH
--- a/libraries/memoryaccess/MemoryAccess.cpp	Thu Jul 29 12:03:43 2010 +1000
+++ b/libraries/memoryaccess/MemoryAccess.cpp	Thu Jul 29 12:05:54 2010 +1000
@@ -15,6 +15,10 @@
 #include <kernel.h>
 #include <kern_priv.h>
 
+#ifdef __EPOC32__
+#include <memmodel/epoc/plat_priv.h> // For DEpocCodeSeg
+#endif
+
 #include <fshell/common.mmh>
 
 #ifdef FSHELL_DOBJECTIX_SUPPORT
@@ -119,6 +123,7 @@
 	TInt GetObjectAddresses(TObjectType aObjectType, const TDesC8& aOwningProcess, TDes8* aKernelInfoBuf);
 	TInt GetChunkAddresses(TUint aControllingProcessId, TDes8* aKernelInfoBuf);
 	TInt AcquireCodeSegMutex();
+	TInt AcquireCodeSegMutexAndFilterCodesegsForProcess(TUint aProcessId);
 	TInt ReleaseCodeSegMutex();
 	TInt GetNextCodeSegInfo(TDes8* aCodeSegInfoBuf);
 	TInt ObjectDie(TObjectKillParamsBuf& aObjectKillParamsBuf);
@@ -173,12 +178,19 @@
 private:
 	DThread* iClient;
 	TBool iLocks[ENumObjectTypes];
-	TBool iCodeSegLock;
-	DCodeSeg* iCurrentCodeSeg;
+	enum TCodesegLogStatus
+		{
+		ENotHeld,
+		EHeld,
+		EHeldAndTraversing,
+		} iCodeSegLock;
+	SDblQueLink* iCurrentCodeSegLink;
 	DThreadChangeHandler* iEventHandler;
 	DPropertyAccess* iPropertyAccess;
 	TAny* iClientBreakpointNotifyPkg;
 	TRequestStatus* iClientBreakpointNotifyStatus;
+
+	SDblQue iFilteredCodesegQue;
 	};
 
 
@@ -563,6 +575,8 @@
 		}
     case RMemoryAccess::EControlAcquireCodeSegMutex:
     	return AcquireCodeSegMutex();
+    case RMemoryAccess::EControlAcquireCodeSegMutexAndFilterCodesegsForProcess:
+		return AcquireCodeSegMutexAndFilterCodesegsForProcess((TUint)a1);
     case RMemoryAccess::EControlReleaseCodeSegMutex:
     	return ReleaseCodeSegMutex();
     case RMemoryAccess::EControlGetNextCodeSegInfo:
@@ -1201,7 +1215,7 @@
 		if (codeSegLock)
 			{
 			Kern::MutexWait(*codeSegLock);
-			iCodeSegLock = ETrue;
+			iCodeSegLock = EHeld;
 			}
 		else
 			{
@@ -1212,6 +1226,34 @@
 	return err;    	
 	}
 
+TInt DMemoryAccess::AcquireCodeSegMutexAndFilterCodesegsForProcess(TUint aProcessId)
+	{
+	TInt err = KErrNone;
+	NKern::ThreadEnterCS();
+	Kern::Containers()[EProcess]->Wait();
+	DProcess* process = Kern::ProcessFromId(aProcessId);
+	if (process == NULL || process->Open() != KErrNone)
+		{
+		err = KErrNotFound;
+		}
+	Kern::Containers()[EProcess]->Signal();
+
+	if (!err)
+		{
+		err = AcquireCodeSegMutex();
+		}
+	if (!err)
+		{
+		iCodeSegLock = EHeldAndTraversing;
+		TInt numTraversed = process->TraverseCodeSegs(&iFilteredCodesegQue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
+		err = numTraversed;
+		}
+
+	if (process) process->Close(NULL);
+	NKern::ThreadLeaveCS();
+	return err;
+	}
+
 TInt DMemoryAccess::GetObjectAddresses(TObjectType aObjectType, const TDesC8& aOwningProcess, TDes8* aKernelInfoBuf)
 	{
 	DObjectCon* const * cons = Kern::Containers();
@@ -1325,30 +1367,20 @@
 TInt DMemoryAccess::ReleaseCodeSegMutex()
 	{
 	// Kern::Printf("[DMemoryAccess] ::ReleaseCodeSegMutex");
-	TInt err=KErrNone;
-
-	if (!iCodeSegLock)
-		{ //Check the lock on code segs is not currently held
-		Kern::ThreadKill(iClient, EExitPanic, EMemAccessMutexNotHeld, KMemAccessPanicCategory);
-		err = KErrAbort;
+	if (iCodeSegLock == ENotHeld)
+		{
+		return KErrNotReady;
 		}
 
-	DMutex* const codeSegLock = Kern::CodeSegLock();
-
-	if (!err)
+	if (iCodeSegLock == EHeldAndTraversing)
 		{
-		if (codeSegLock)
-			{
-			Kern::MutexSignal(*codeSegLock);
-			iCodeSegLock = EFalse;
-			}
-		else
-			{
-			err = KErrNotFound;
-			}
+		DCodeSeg::EmptyQueue(iFilteredCodesegQue, DCodeSeg::EMarkDebug);
 		}
+
+	Kern::MutexSignal(*Kern::CodeSegLock());
+	iCodeSegLock = ENotHeld;
 	// Kern::Printf("[DMemoryAccess] ::ReleaseCodeSegMutex returning %d", err);
-	return err;    	
+	return KErrNone;
 	}
 
 
@@ -1357,28 +1389,37 @@
 	// Kern::Printf("[DMemoryAccess] ::GetNextCodeSegInfo");
 	TInt err = KErrNone;
 	
-	SDblQue* p = Kern::CodeSegList();
-	SDblQueLink* anchor=&p->iA;
-
-	if (!iCurrentCodeSeg)
+	SDblQue* p;
+	if (iCodeSegLock == EHeldAndTraversing)
 		{
-		iCurrentCodeSeg = _LOFF(anchor->iNext, DCodeSeg, iLink);
-		}
-
-	if (iCurrentCodeSeg->iLink.iNext != anchor)
-		{
-		iCurrentCodeSeg = _LOFF(iCurrentCodeSeg->iLink.iNext, DCodeSeg, iLink);
+		p = &iFilteredCodesegQue;
 		}
 	else
 		{
-		iCurrentCodeSeg = NULL;
+		p = Kern::CodeSegList();
+		}
+	SDblQueLink* anchor=&p->iA;
+
+	if (!iCurrentCodeSegLink)
+		{
+		iCurrentCodeSegLink = anchor;
+		}
+
+	if (iCurrentCodeSegLink->iNext != anchor)
+		{
+		iCurrentCodeSegLink = iCurrentCodeSegLink->iNext;
+		}
+	else
+		{
+		iCurrentCodeSegLink = NULL;
 		err = KErrNotFound;
 		}
 		
 	if (!err)
 		{
 		//TCodeSegKernelInfoBuf* localInfoBuf = new TCodeSegKernelInfoBuf;
-		TPckgBuf<TTomsciCodeSegKernelInfo>* localInfoBuf = new TPckgBuf<TTomsciCodeSegKernelInfo>;
+		DCodeSeg* currentCodeseg = (iCodeSegLock == EHeldAndTraversing) ? _LOFF(iCurrentCodeSegLink, DCodeSeg, iTempLink) : _LOFF(iCurrentCodeSegLink, DCodeSeg, iLink);
+		TPckgBuf<TCodeSegKernelInfo>* localInfoBuf = new TPckgBuf<TCodeSegKernelInfo>;
 		if (!localInfoBuf)
 			{
 			err = KErrNoMemory;
@@ -1386,14 +1427,21 @@
 		else
 			{	
 			//Get the code seg info
-			(*localInfoBuf)().iRunAddress = iCurrentCodeSeg->iRunAddress;
-			(*localInfoBuf)().iSize = iCurrentCodeSeg->iSize;
-			(*localInfoBuf)().iFileName = iCurrentCodeSeg->iFileName->Right((*localInfoBuf)().iFileName.MaxLength());
-			(*localInfoBuf)().iAccessCount = iCurrentCodeSeg->iAccessCount;
-			(*localInfoBuf)().iAddressOfKernelObject = (TUint8*)iCurrentCodeSeg;
-			(*localInfoBuf)().iName = iCurrentCodeSeg->iRootName;
-			(*localInfoBuf)().iDepCount = iCurrentCodeSeg->iDepCount;
-
+			(*localInfoBuf)().iRunAddress = currentCodeseg->iRunAddress;
+			(*localInfoBuf)().iSize = currentCodeseg->iSize;
+			if (currentCodeseg->iFileName)
+				{
+				(*localInfoBuf)().iFileName = currentCodeseg->iFileName->Right((*localInfoBuf)().iFileName.MaxLength());
+				}
+			(*localInfoBuf)().iAccessCount = currentCodeseg->iAccessCount;
+			(*localInfoBuf)().iAddressOfKernelObject = (TUint8*)currentCodeseg;
+			(*localInfoBuf)().iName = currentCodeseg->iRootName;
+			(*localInfoBuf)().iDepCount = currentCodeseg->iDepCount;
+#ifdef __EPOC32__
+			(*localInfoBuf)().iXip = ((DEpocCodeSeg*)currentCodeseg)->iXIP;
+#else
+			(*localInfoBuf)().iXip = EFalse;
+#endif
 			//Copy the local info buffer into the client's address space
 		    err = Kern::ThreadDesWrite(iClient, aCodeSegInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);
 			delete localInfoBuf;
--- a/libraries/memoryaccess/memoryaccess.h	Thu Jul 29 12:03:43 2010 +1000
+++ b/libraries/memoryaccess/memoryaccess.h	Thu Jul 29 12:05:54 2010 +1000
@@ -305,23 +305,26 @@
 	};
 typedef TPckgBuf<TCondVarKernelInfo> TCondVarKernelInfoBuf;	 
 
-class TCodeSegKernelInfo
+class TCodeSegKernelInfoBase
 	{
 public:
 	TUint32 iRunAddress;
 	TInt iSize;
 	TFileName8 iFileName;
 	};
-typedef TPckgBuf<TCodeSegKernelInfo> TCodeSegKernelInfoBuf;	 
 
-class TTomsciCodeSegKernelInfo : public TCodeSegKernelInfo
+// We don't really need a base class, it's just for BC reasons 
+class TCodeSegKernelInfo : public TCodeSegKernelInfoBase
 	{
 public:
 	TUint8* iAddressOfKernelObject;
 	TFullName8 iName;
 	TInt iAccessCount;
 	TInt iDepCount;
+	TBool iXip;
 	};
+typedef TPckgBuf<TCodeSegKernelInfo> TCodeSegKernelInfoBuf;	 
+
 
 class TProp
 	{
@@ -451,6 +454,7 @@
 		EControlPropertyNotify,
 		EControlPropertyNotifyCancel,
 		EControlSubscribeToProperty,
+		EControlAcquireCodeSegMutexAndFilterCodesegsForProcess,
 		ENumRequests,  // Add new commands above this line
         };
 public:
@@ -492,6 +496,7 @@
 	TInt GetObjectInfoByHandle (TObjectType aObjectType, TInt aThreadId, TInt aObjectHandle, TDes8& aObjectInfoBuf);
 	//Wait on the kernel's code seg mutex
 	TInt AcquireCodeSegMutex();
+	TInt AcquireCodeSegMutexAndFilterCodesegsForProcess(TUint aProcessId);
 	//Signal the kernel's code seg mutex
 	TInt ReleaseCodeSegMutex();
 	//Get info about the next code seg.  Call repeatedly to iterate all code segs.  Call AcquireCodeSegMutex before calling.
@@ -683,6 +688,8 @@
 	}
 inline TInt RMemoryAccess::AcquireCodeSegMutex()
 	{	return DoControl(EControlAcquireCodeSegMutex, NULL, NULL);		}
+inline TInt RMemoryAccess::AcquireCodeSegMutexAndFilterCodesegsForProcess(TUint aProcessId)
+	{	return DoControl(EControlAcquireCodeSegMutexAndFilterCodesegsForProcess, (TAny*)aProcessId);	}
 inline TInt RMemoryAccess::ReleaseCodeSegMutex()
 	{	return DoControl(EControlReleaseCodeSegMutex, NULL, NULL);		}
 inline TInt RMemoryAccess::GetNextCodeSegInfo(TDes8& aCodeSegInfoBuf)
--- a/libraries/qr3/src/KernLbxModel.cpp	Thu Jul 29 12:03:43 2010 +1000
+++ b/libraries/qr3/src/KernLbxModel.cpp	Thu Jul 29 12:05:54 2010 +1000
@@ -289,7 +289,7 @@
 		}
 	case EListCodeSeg:
 		{
-		TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(aInfo);
+		TCodeSegKernelInfo& info = *reinterpret_cast<TCodeSegKernelInfo*>(aInfo);
 		name.Copy(info.iName);
 
 		TBuf<16> size;
@@ -418,7 +418,7 @@
 	case EListCodeSeg:
 		{
 		if (i == 0) clogger.Log(KCodesegDesc);
-		TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(aInfo);
+		TCodeSegKernelInfo& info = *reinterpret_cast<TCodeSegKernelInfo*>(aInfo);
 		TBuf8<16> size;
 		HR(size, info.iSize);
 		clogger.Log(KCodesegFmt, &info.iName, info.iSize, &size, info.iAccessCount, info.iDepCount);
@@ -598,7 +598,7 @@
 			}
 		case EListCodeSeg:
 			{
-			TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(iInfo);
+			TCodeSegKernelInfo& info = *reinterpret_cast<TCodeSegKernelInfo*>(iInfo);
 			_LIT(KInfo, "Code segment info");
 			aTitle.Copy(KInfo);
 			inf.Copy(info.iName);
@@ -985,9 +985,9 @@
 	if (iCurrentList == EListCodeSeg)
 		{
 		mem.AcquireCodeSegMutex();
-		TTomsciCodeSegKernelInfo* inf = new(ELeave) TTomsciCodeSegKernelInfo;
+		TCodeSegKernelInfo* inf = new(ELeave) TCodeSegKernelInfo;
 		info = reinterpret_cast<TObjectKernelInfo*>(inf); // These aren't actually related classes, just convenient
-		buf.Set(TPckg<TTomsciCodeSegKernelInfo>(*inf));
+		buf.Set(TPckg<TCodeSegKernelInfo>(*inf));
 		while (mem.GetNextCodeSegInfo(buf) == KErrNone)
 			{
 			TRAPD(err, model.NewKernDataL(iCurrentList, info));
@@ -996,8 +996,8 @@
 				break;
 				}
 			inf = NULL;
-			inf = new(ELeave) TTomsciCodeSegKernelInfo;
-			buf.Set(TPckg<TTomsciCodeSegKernelInfo>(*inf));
+			inf = new(ELeave) TCodeSegKernelInfo;
+			buf.Set(TPckg<TCodeSegKernelInfo>(*inf));
 			info = reinterpret_cast<TObjectKernelInfo*>(inf); // These aren't actually related classes, just convenient
 			}
 		delete inf;