--- a/kernel/eka/debug/securityServer/inc/c_security_svr_async.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/inc/c_security_svr_async.h Mon Mar 15 12:45:50 2010 +0200
@@ -53,15 +53,39 @@
virtual TInt RunError(TInt aError);
private:
- RMessagePtr2 iMessage; // The last GetEvent message details. Needed for completion by RunL()
+
+ /*
+ * The last GetEvent message details. Needed for completion by RunL()
+ */
+ RMessagePtr2 iMessage;
- Debug::TEventInfo iInfo; // Temporary storage area for rm_debug.ldd to return data asynchronously.
+ /*
+ * Temporary storage area for rm_debug.ldd to return data asynchronously
+ */
+ Debug::TEventInfo iInfo;
+
+ /*
+ * Identity of this server session. Used for completing iMessage
+ */
+ CSecuritySvrSession* iSession;
- CSecuritySvrSession* iSession; // Identity of this server session. Used for completing iMessage
+ /*
+ * Name of the process being debugged associated with this AO
+ */
+ RBuf8 iProcessName;
- RBuf8 iProcessName; // Name of the process being debugged associated with this AO
-
- TProcessId iAgentId; // Debug Agent Id
+ /*
+ * Debug Agent Id
+ */
+ TProcessId iAgentId;
+
+ /*
+ * Balance between event requests and event deliveries.
+ * @see GetEvent()
+ * @see NotifyEvent()
+ * @see DoCancel()
+ */
+ TInt iEventBalance;
};
#endif // C_SECURITY_SVR_ASYNC_H
--- a/kernel/eka/debug/securityServer/inc/c_security_svr_session.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/inc/c_security_svr_session.h Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
--- a/kernel/eka/debug/securityServer/src/c_process_pair.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/src/c_process_pair.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -61,7 +61,7 @@
@param aProcessPair a CProcessPair object to match with this one
-@return ETrue is process id and name match, EFalse otherwise
+@return 0 if process ids and names do not match, non-zero if they do
*/
TBool CProcessPair::operator==(const CProcessPair &aProcessPair) const
{
@@ -74,7 +74,7 @@
@param aProcessName process name to check
@param aProcessId process id to check
-@return ETrue is process id and name match, EFalse otherwise
+@return 0 if process ids and names do not match, non-zero if they do
*/
TBool CProcessPair::Equals(const TDesC& aProcessName, const TProcessId aProcessId) const
{
@@ -86,7 +86,7 @@
@param aProcessPair a CProcessPair object to compare with this one
-@return ETrue is process id matches, EFalse otherwise
+@return 0 if process ids do not match, non-zero if they do
*/
TBool CProcessPair::ProcessIdMatches(const CProcessPair &aProcessPair) const
{
@@ -98,7 +98,7 @@
@param aProcessId a process ID to compare with this pair's process ID
-@return ETrue is process id matches, EFalse otherwise
+@return 0 if process ids do not match, non-zero if they do
*/
TBool CProcessPair::ProcessIdMatches(const TProcessId &aProcessId) const
{
@@ -110,7 +110,7 @@
@param aProcessPair a CProcessPair object to compare with this one
-@return ETrue is process names match, EFalse otherwise
+@return 0 if process names do not match, non-zero if they do
*/
TBool CProcessPair::ProcessNameMatches(const CProcessPair &aProcessPair) const
{
@@ -122,11 +122,10 @@
@param aProcessName a process name to compare with this pair's process name
-@return ETrue is process names match, EFalse otherwise
+@return 0 if process names do not match, non-zero if they do
*/
TBool CProcessPair::ProcessNameMatches(const TDesC& aProcessName) const
{
- TInt equal = iProcessName->CompareF(aProcessName);
- return (equal == 0) ? ETrue : EFalse;
+ return iProcessName->CompareF(aProcessName) == 0;
}
--- a/kernel/eka/debug/securityServer/src/c_security_svr_async.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/src/c_security_svr_async.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -25,10 +25,11 @@
// ctor
CSecuritySvrAsync::CSecuritySvrAsync(CSecuritySvrSession* aSession, TProcessId aAgentId)
-: CActive(CActive::EPriorityStandard),
- iSession(aSession),
- iProcessName(NULL),
- iAgentId(aAgentId)
+ : CActive(CActive::EPriorityStandard),
+ iSession(aSession),
+ iProcessName(NULL),
+ iAgentId(aAgentId),
+ iEventBalance(0)
{
LOG_MSG("CSecuritySvrAsync::CSecuritySvrAsync()");
CActiveScheduler::Add(this);
@@ -72,7 +73,9 @@
// RunL() completes a previously issued call (currently only GetEvent() completion)
void CSecuritySvrAsync::RunL()
{
- LOG_MSG("CSecuritySvrAsync::RunL()");
+
+ LOG_MSG3("CSecuritySvrAsync::RunL() &iInfo=0x%08x, iEventBalance=%d", (TUint8*)&iInfo, iEventBalance);
+
// Something bad happened in the driver
User::LeaveIfError(iStatus.Int());
@@ -96,44 +99,54 @@
iMessage.WriteL(1,data,0);
iMessage.Complete(KErrNone);
+ --iEventBalance;
}
// Cancels the oustanding GetEvent call. May cope with other async calls in future.
void CSecuritySvrAsync::DoCancel()
{
- LOG_MSG("CSecuritySvrAsync::DoCancel()");
+ LOG_MSG2("CSecuritySvrAsync::DoCancel() iEventBalance=%d", iEventBalance);
iSession->Server().iKernelDriver.CancelGetEvent(iProcessName,iAgentId.Id());
iMessage.Complete(KErrCancel);
+ iEventBalance=0;
}
// Report any leave to the client if possible.
TInt CSecuritySvrAsync::RunError(TInt aError)
{
- LOG_MSG("CSecuritySvrAsync::RunError()");
+ LOG_MSG2("CSecuritySvrAsync::RunError()=%d", aError);
iMessage.Complete(aError);
return KErrNone;
}
-// Start an Asynchronous GetEvent call to the rm_debug.ldd driver
-// and activate this Active Object.
+/*
+ * Start an asynchronous GetEvent call to the debug driver
+ * and activates this active object.
+ */
void CSecuritySvrAsync::GetEvent(const RMessage2& aMessage)
{
- LOG_MSG("CSecuritySvrAsync::GetEvent()");
iMessage = aMessage;
- iSession->Server().iKernelDriver.GetEvent(iProcessName,iAgentId.Id(),iStatus,iInfo);
+ iEventBalance++;
+ LOG_MSG5("CSecuritySvrAsync::GetEvent() this = 0x%08x, iInfo=0x%08x, iStatus=0x%08x \
+ iEventBalance=%d : >SetActive() > GetEvent() ",
+ this, &iInfo, &iStatus, iEventBalance );
+ /*
+ SetActive is called before sending the message to the driver so
+ that we do not get stray signal panics, since the driver may complete immediately
+ */
SetActive();
+ iSession->Server().iKernelDriver.GetEvent(iProcessName,iAgentId.Id(),iStatus,iInfo);
}
// Used for identifying which AO is associated with a debugged process
const TDesC8& CSecuritySvrAsync::ProcessName(void)
-{
- LOG_MSG("CSecuritySvrAsync::ProcessName()");
+ {
return iProcessName;
-}
+ }
// End of file - c_security_svr_async.cpp
--- a/kernel/eka/debug/securityServer/src/c_security_svr_session.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/src/c_security_svr_session.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
@@ -1040,7 +1040,7 @@
{
LOG_MSG( "CSecuritySvrSession::AttachProcessL()\n" );
- TBool aPassive = aMessage.Int0() ? ETrue : EFalse;
+ const TBool passive = aMessage.Int0();
TInt deslen = aMessage.GetDesLengthL(1);
@@ -1142,7 +1142,7 @@
IsDebuggableL(processName);
}
- User::LeaveIfError(Server().AttachProcessL(processName, processId, aPassive));
+ User::LeaveIfError(Server().AttachProcessL(processName, processId, passive));
// Inform the kernel driver about the attachment, so that it
// can track per-agent data about the process.
@@ -1361,10 +1361,16 @@
}
if ( i == KMaxLocalDrives)
{
- LOG_MSG("No crash log partition found with valid crash log signature found. Exiting...");
- User::Leave (KErrNotFound);
+ LOG_MSG("No crash log partition found with valid crash log signature found. Exiting...");
+ User::Leave (KErrNotFound);
}
-
+
+ // Nand Flash not currently supported.
+ if (iCaps.iType == EMediaNANDFlash)
+ {
+ LOG_MSG( "CSecuritySvrSession::ConnectCrashPartitionL() Nand Flash not currently supported\n" );
+ User::Leave (KErrNotSupported);
+ }
}
/** Checks that aHeaderData contains enough data to cast it to the
appropriate header type.
--- a/kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -31,23 +31,24 @@
#include "d_debug_agent.h"
#include "debug_utils.h"
-using namespace Debug;
+#include "d_debug_agent.inl"
-#define NUMBER_OF_EVENTS_TO_QUEUE 100
-#define CRITICAL_BUFFER_SIZE (NUMBER_OF_EVENTS_TO_QUEUE - 50)
+using namespace Debug;
// ctor
-DDebugAgent::DDebugAgent(TUint64 aId)
-: iId(aId),
- iEventInfo(NULL),
- iEventQueue(NUMBER_OF_EVENTS_TO_QUEUE, 0),
- iRequestGetEventStatus(NULL),
- iClientThread(0),
- iHead(0),
- iTail(0),
- iIgnoringTrace(EFalse)
+DDebugAgent::DDebugAgent(TUint64 aId) :
+ iId(aId),
+ iRequestGetEventStatus(NULL),
+ iClientThread(0),
+ iEventQueue(KNumberOfEventsToQueue, 0),
+ iHead(0),
+ iTail(0),
+ iEventQueueLock(NULL),
+ iFreeSlots(KNumberOfEventsToQueue),
+ iIgnoringTrace(EFalse),
+ iEventBalance(0)
{
- LOG_MSG("DDebugAgent::DDebugAgent() ");
+ LOG_MSG2("DDebugAgent::DDebugAgent(), this=0x%x ", this);
// Initialize all the Event Actions to Ignore
for(TInt i=0; i<EEventsLast; i++)
@@ -69,32 +70,59 @@
delete agent;
return (NULL);
}
+
+ // Use a semaphore to serialise access
+ TInt err = Kern::SemaphoreCreate(agent->iEventQueueLock, _L("RM_DebugAgentQueueLock"), 1 /* Initial count */);
+ if (err != KErrNone)
+ return NULL;
+
return agent;
}
+/** Standard contructor.
+ * Fills event queue with empty events
+ * @return : standard system error code
+ */
TInt DDebugAgent::Construct()
{
// Empty the event queue
LOG_MSG("DDebugAgent::Construct()");
TDriverEventInfo emptyEvent;
+ TInt err = KErrNone;
- for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
+ for (TInt i=0; i<KNumberOfEventsToQueue; i++)
{
- TInt err = iEventQueue.Append(emptyEvent);
- if (KErrNone != err)
+ err = iEventQueue.Append(emptyEvent);
+ if (err != KErrNone)
{
LOG_MSG("Error appending blank event entry");
return err;
}
}
- return KErrNone;
+
+ err = Kern::CreateClientDataRequest(iRequestGetEventStatus);
+ if(err != KErrNone)
+ {
+ LOG_MSG("Error creating TClientDataRequest");
+ return err;
+ }
+
+ LOG_MSG2("DDebugAgent::Construct() iRequestGetEventStatus=0x%08x", iRequestGetEventStatus);
+
+ return err;
}
-
// dtor
DDebugAgent::~DDebugAgent()
{
iEventQueue.Reset();
+
+ if (iEventQueueLock)
+ iEventQueueLock->Close(NULL);
+
+ if(iRequestGetEventStatus)
+ Kern::DestroyClientRequest(iRequestGetEventStatus);
+
}
// Associate an action with a particular kernel event
@@ -112,9 +140,9 @@
return KErrNone;
}
-/* Get the aEventAction associated with aEvent
+/** Get the aEventAction associated with aEvent
*
- * Returns : aEventAction (always +ve), or KErrArgument.
+ * @return : aEventAction (always +ve), or KErrArgument.
*/
TInt DDebugAgent::EventAction(TEventType aEvent)
{
@@ -129,90 +157,110 @@
return iEventActions[aEvent];
}
-// Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
-// If there is no event in the queue for this process+agent combination, store the details
-// so that it can be notified later when an event actually occurs.
-//
-// @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
-// @param aEventInfo - Address of TEventInfo structure to place event data when available
-// @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
-void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, TEventInfo* aEventInfo, DThread* aClientThread)
+/** Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
+ * If there is no event in the queue for this process+agent combination, store the details
+ * so that it can be notified later when an event actually occurs.
+ *
+ * @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
+ * @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
+ */
+void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread)
{
+ LockEventQueue();
+
+ iRequestGetEventStatus->Reset();
+ TInt err = iRequestGetEventStatus->SetStatus( aAsyncGetValueRequest->StatusPtr() );
+ if (err != KErrNone)
+ {
+ LOG_MSG2("Error :iRequestGetEventStatus->SetStatus ret %d", err);
+ return;
+ }
+
+ iRequestGetEventStatus->SetDestPtr( aAsyncGetValueRequest->DestPtr() );
+
+ iEventBalance++;
+
+ LOG_MSG4("DDebugAgent::GetEvent: this=0x%08x, iRequestGetEventStatus=0x%08x, iEventBalance=%d",
+ this, iRequestGetEventStatus, iEventBalance );
+
iClientThread = aClientThread;
-
+
if (BufferEmpty())
{
- LOG_MSG("no events available");
-
- // store the pointer so we can modify it later
- iEventInfo = (TEventInfo *)aEventInfo;
- iRequestGetEventStatus = aAsyncGetValueRequest;
+ LOG_MSG2("Event buffer empty, iEventBalance=%d", iEventBalance);
+ UnlockEventQueue();
return;
}
- LOG_MSG("Event available");
+ LOG_MSG2("Event already available at queue pos=%d", iTail);
// returning the event to the client
- TInt err = iEventQueue[iTail].WriteEventToClientThread(aAsyncGetValueRequest,iClientThread);
- if (KErrNone != err)
+ err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
+ if (err != KErrNone)
{
LOG_MSG2("Error writing event info: %d", err);
+ UnlockEventQueue();
return;
}
// signal the DSS thread
- Kern::QueueRequestComplete(iClientThread, aAsyncGetValueRequest, KErrNone);
+ Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
+ iEventBalance--;
iEventQueue[iTail].Reset();
// move to the next slot
- IncrementPosition(iTail);
+ IncrementTailPosition();
+
+ UnlockEventQueue();
}
-// Stop waiting for an event to occur. This means events will be placed in the iEventQueue
-// until GetEvent is called.
+/**
+ * Stop waiting for an event to occur. This means events will be placed
+ * in the iEventQueue (by setting iEventBalance to 0) until GetEvent is called.
+ */
TInt DDebugAgent::CancelGetEvent(void)
{
+ LOG_MSG2("DDebugAgent::CancelGetEvent. iEventBalance=%d. > QueueRequestComplete", iEventBalance);
Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
- iEventInfo = NULL;
- iRequestGetEventStatus = 0;
+ iEventBalance=0;
iClientThread = 0;
-
return KErrNone;
}
-// Signal a kernel event to the user-side DSS when it occurs, or queue it for later
-// if the user-side has not called GetEvent (see above).
-//
-// @param aEventInfo - the details of the event to queue.
+/** Signal a kernel event to the user-side DSS when it occurs, or queue it for later
+ * if the user-side has not called GetEvent (see above).
+ *
+ * @param aEventInfo - the details of the event to queue.
+ */
void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
{
- LOG_MSG("DDebugAgent::NotifyEvent()");
- // Action depends on the TKernelEvent type in aEventInfo.iType
-
- // Added to fix the pass by value issue seen in Coverity.
- // Function is changed to pass by reference but temp object is explicitly created.
- TDriverEventInfo eventInfo = aEventInfo;
if(aEventInfo.iEventType >= EEventsLast)
{
- // unknown event type so return
+ LOG_MSG3("DDebugAgent::NotifyEvent(),iEventType %d, this=0x%x. Ignoring since > EEventsLast", aEventInfo.iEventType, this);
return;
}
- TKernelEventAction action = iEventActions[eventInfo.iEventType];
+ LockEventQueue();
+
+ DThread* currentThread = &Kern::CurrentThread();
+
+ LOG_MSG5("DDebugAgent::NotifyEvent(), iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
+ aEventInfo.iEventType, this, currentThread, iEventBalance );
+ TKernelEventAction action = iEventActions[aEventInfo.iEventType];
switch (action)
{
case EActionSuspend:
{
LOG_MSG("DDebugAgent::NotifyEvent() Suspend thread");
- DThread* currentThread = &Kern::CurrentThread();
- switch(eventInfo.iEventType)
+
+ switch(aEventInfo.iEventType)
{
case EEventsAddLibrary:
case EEventsRemoveLibrary:
- currentThread = DebugUtils::OpenThreadHandle(eventInfo.iThreadId);
+ currentThread = DebugUtils::OpenThreadHandle(aEventInfo.iThreadId);
if(currentThread)
{
currentThread->Close(NULL);
@@ -221,8 +269,8 @@
default:
break;
}
- TInt err = TheDProcessTracker.SuspendThread(currentThread, eventInfo.FreezeOnSuspend());
- if(!( (err == KErrNone) || (err == KErrAlreadyExists) ))
+ TInt err = TheDProcessTracker.SuspendThread(currentThread, aEventInfo.FreezeOnSuspend());
+ if((err != KErrNone) && (err != KErrAlreadyExists))
{
// Is there anything we can do in the future to deal with this error having happened?
LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
@@ -232,42 +280,62 @@
// the debug agent of the event
}
case EActionContinue:
- LOG_MSG("DDebugAgent::NotifyEvent() Continue");
-
- // Tell the user about this event
- if (iEventInfo && iClientThread)
{
- LOG_MSG("Completing event\r\n");
+ // Queue this event
+ QueueEvent(aEventInfo);
- // returning the event to the client
- TInt err = eventInfo.WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
- if (KErrNone != err)
+ // Tell the user about the oldest event in the queue
+ if ( iClientThread )
{
- LOG_MSG2("Error writing event info: %d", err);
- }
+ if( iRequestGetEventStatus && (iEventBalance > 0) )
+ {
+ // Fill the event data
+ TInt err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
+ if (err != KErrNone)
+ {
+ LOG_MSG2("Error writing event info: %d", err);
+ }
+
+ // signal the debugger thread
+ LOG_MSG4("> QueueRequestComplete iRequestGetEventStatus=0x%08x, iEventBalance=%d, iTail=%d",
+ iRequestGetEventStatus->iStatus, iEventBalance, iTail );
+ Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
+
+ iEventBalance--;
- // clear this since we've completed the request
- iEventInfo = NULL;
+ iEventQueue[iTail].Reset();
- // signal the debugger thread
- Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
- }
+ // move to the next slot
+ IncrementTailPosition();
+ }
+ else
+ {
+ if( !iRequestGetEventStatus )
+ {
+ LOG_MSG("iRequestGetEventStatus is NULL so not signalling client" );
+ }
+ else
+ {
+ LOG_MSG2("Queued event. iEventBalance=%d (unbalanced event requests vs notifications)",
+ iEventBalance );
+ }
+ }
+ }
else
- {
- LOG_MSG("Queuing event\r\n");
-
- QueueEvent(eventInfo);
-
+ {
+ LOG_MSG("DDebugAgent::NotifyEvent() : Not informing client since its thread is NULL");
+ }
+ break;
}
- break;
-
case EActionIgnore:
default:
- LOG_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
+ LOG_EVENT_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
// Ignore everything we don't understand.
- return;
+
}
+ UnlockEventQueue();
+
}
// Used to identify which Debug Agent this DDebugAgent is associated with.
@@ -276,93 +344,77 @@
return iId;
}
-// Used to add an event to the event queue for this debug agent
-void DDebugAgent::QueueEvent(TDriverEventInfo& aEventInfo)
+/**
+ * Used to add an event to the event queue for this debug agent if event
+ * queue is not at critical level. If it is at critical and it is trace event,
+ * we start ignoring trace events and insert a lost trace event.
+ * If the buffer cannot store an event, only insert a buffer full event.
+ * @see EEventsBufferFull
+ * @see EEventsUserTracesLost
+ * @see TDriverEventInfo
+ * @see iEventQueue
+ */
+void DDebugAgent::QueueEvent(const TDriverEventInfo& aEventInfo)
{
// Have we caught the tail?
if(BufferFull())
{
+ LOG_MSG("DDebugAgent::QueueEvent : BufferFull. Not queueing");
return;
}
-
- //check to see if we wish to ignore this event - we dump trace events as they are lower priority than the other events
- if(BufferAtCriticalLevel())
+
+ // Assert if we think there is space but the slot is not marked empty
+ __NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown);
+
+ const TBool bufferAtCritical = BufferAtCriticalLevel();
+
+ if(!bufferAtCritical)
{
+ //reset the iIgnoringTrace flag as we are not at
+ //critical level and can store event
+ iIgnoringTrace = EFalse;
+
+ // Insert the event into the ring buffer at iHead
+ iEventQueue[iHead] = aEventInfo;
+ IncrementHeadPosition();
+ }
+ else if(bufferAtCritical && BufferCanStoreEvent())
+ {
+ LOG_MSG("DDebugAgent::QueueEvent : BufferCritical");
if(aEventInfo.iEventType == EEventsUserTrace)
{
if(!iIgnoringTrace)
{
- //if this is the first time we are ignoring trace events, we need to issue a EEventsUserTracesLost event
- aEventInfo.Reset();
- aEventInfo.iEventType = EEventsUserTracesLost;
-
+ //if this is the first time we are ignoring trace events,
+ //we need to issue a EEventsUserTracesLost event
+ iEventQueue[iHead].Reset();
+ iEventQueue[iHead].iEventType = EEventsUserTracesLost;
+ IncrementHeadPosition();
+
iIgnoringTrace = ETrue;
}
else
{
//otherwise, ignore this event
- return;
+ LOG_MSG("DDebugAgent::QueueEvent : Ignore EEventsUserTrace event");
}
}
+ else
+ {
+ // Store the event since its not a trace event
+ iEventQueue[iHead] = aEventInfo;
+ IncrementHeadPosition();
+ }
}
else
{
- //reset the iIgnoringTrace flag as we are not at critical level
- iIgnoringTrace = EFalse;
- }
-
- // only one space left so store a EEventsBufferFull event
- if(!BufferCanStoreEvent())
- {
- aEventInfo.Reset();
- aEventInfo.iEventType = EEventsBufferFull;
+ //At critical level and cannot store new events, so
+ //only one space left. Store a EEventsBufferFull event
+ LOG_MSG("DDebugAgent::QueueEvent : Event Buffer Full, ignoring event");
+ iEventQueue[iHead].Reset();
+ iEventQueue[iHead].iEventType = EEventsBufferFull;
+ IncrementHeadPosition();
}
-
- __NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown); // we think there is space but the slot is not marked empty
-
- // Insert the event into the ring buffer at iHead
- iEventQueue[iHead] = aEventInfo;
- IncrementPosition(iHead);
- }
-
-// Checks whether the event queue is empty
-TBool DDebugAgent::BufferEmpty() const
- {
- return (NumberOfEmptySlots() == NUMBER_OF_EVENTS_TO_QUEUE);
- }
-
-// Checks whether the event queue is full
-TBool DDebugAgent::BufferFull() const
- {
- return (NumberOfEmptySlots() == 0);
}
-// Checks whether there is room in the event queue to store an event (i.e. at least two free slots)
-TBool DDebugAgent::BufferCanStoreEvent() const
- {
- return (NumberOfEmptySlots() > 1);
- }
-
-//This looks to see if the buffer is close to being full and should only accept higher priority debug events (user trace is the only low priority event)
-TBool DDebugAgent::BufferAtCriticalLevel() const
- {
- return (NumberOfEmptySlots() < NUMBER_OF_EVENTS_TO_QUEUE - CRITICAL_BUFFER_SIZE);
- }
-
-// increments aPosition, wrapping at NUMBER_OF_EVENTS_TO_QUEUE if necessary
-void DDebugAgent::IncrementPosition(TInt& aPosition)
- {
- aPosition = (aPosition + 1) % NUMBER_OF_EVENTS_TO_QUEUE;
- }
-
-// finds the number of empty slots in the event queue
-TInt DDebugAgent::NumberOfEmptySlots() const
- {
- if(iHead < iTail)
- {
- return (iTail - iHead) - 1;
- }
- // iHead >= iTail
- return NUMBER_OF_EVENTS_TO_QUEUE - (iHead - iTail);
- }
-
+// End of file - d_debug_agent.cpp
--- a/kernel/eka/drivers/debug/rmdebug/d_debug_agent.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_debug_agent.h Mon Mar 15 12:45:50 2010 +0200
@@ -22,6 +22,12 @@
#include <rm_debug_api.h>
#include "d_driver_event_info.h"
+/**
+* Handles events from the kernel, filters them according to the debug agent's requests,
+* and signals these events to the user side in FIFO-style.
+* @see TKernelEventAction
+* @see TEventInfo
+*/
class DDebugAgent : public DBase
{
public:
@@ -29,7 +35,7 @@
~DDebugAgent();
TInt SetEventAction(Debug::TEventType aEvent, Debug::TKernelEventAction aEventAction);
- void GetEvent(TClientDataRequest<Debug::TEventInfo>* aAsyncGetValueRequest, Debug::TEventInfo* aEventInfo, DThread* aClientThread);
+ void GetEvent(TClientDataRequest<Debug::TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread);
TInt EventAction(Debug::TEventType aEvent);
TInt CancelGetEvent(void);
@@ -41,31 +47,99 @@
TInt Construct();
private:
- void QueueEvent(TDriverEventInfo& aEventInfo);
+ void QueueEvent(const TDriverEventInfo& aEventInfo);
TBool BufferEmpty() const;
TBool BufferFull() const;
TBool BufferCanStoreEvent() const;
TBool BufferAtCriticalLevel() const;
- void IncrementPosition(TInt& aPosition);
+ void IncrementHeadPosition(void);
+ void IncrementTailPosition(void);
TInt NumberOfEmptySlots() const;
+ void LockEventQueue(void);
+ void UnlockEventQueue(void);
private:
+
TUint64 iId;
Debug::TKernelEventAction iEventActions[Debug::EEventsLast];
- //iEventInfo is a pointer to an object owned by the security server, so
- //no clean up needs be performed on it
- Debug::TEventInfo* iEventInfo;
- RArray<TDriverEventInfo> iEventQueue; // ring buffer.
+ /**
+ * Object used to write events back to DSS thread
+ * @see TEventInfo
+ */
TClientDataRequest<Debug::TEventInfo>* iRequestGetEventStatus;
+
DThread* iClientThread;
- // Ring buffer data
- TInt iHead; // points to the next empty slot in iEventQueue (exc. when iFull == ETrue)
- TInt iTail; // points to the oldest full slot in iEventQueue (exc. when iEmpty == ETrue)
+ /**
+ * Ring buffer of pending events. Access to it is controlled by
+ * @see iEventQueueLock
+ */
+ RArray<TDriverEventInfo> iEventQueue;
+
+ /**
+ * Ring buffer head. Points to the next empty slot in iEventQueue
+ * @see iEventQueue
+ */
+ TInt iHead;
+
+ /**
+ * Ring buffer tail. Points to the oldest full slot in iEventQueue
+ * @see iEventQueue
+ */
+ TInt iTail;
+
+ /**
+ * Control access to event queue.
+ * @see iEventQueue
+ */
+ DSemaphore* iEventQueueLock;
+
+ /**
+ * Keeps track of how many free slots are available in the event queue.
+ * @see iEventQueue
+ */
+ TInt iFreeSlots;
+
+ /**
+ * Boolean to indicate if we have told the agent that we are ignoring trace events
+ * @see QueueEvent
+ */
+ TBool iIgnoringTrace;
- //if we have told the agent that we are ignoring trace events
- TBool iIgnoringTrace;
+ /**
+ * Used to control the delivery of events to the client so that only
+ * when more requests than deliveries have taken place can we deliver the
+ * next event
+ *
+ * Incremented when a request for event takes place
+ * @see GetEvent
+ *
+ * Decremented when an event is delivered.
+ * @see NotifyEvent
+ *
+ * Cleared when event requests are cancelled
+ * @see CancelGetEvent
+ *
+ */
+ TInt iEventBalance;
+
+ /**
+ * Length of kernel-event queue.
+ * This is a power of two for efficiency when using the
+ * remainder operator
+ * @see DDebugAgent::iEventQueue
+ */
+ static const TUint KNumberOfEventsToQueue = 128;
+
+ /**
+ * This determines the number of events at which we stop accepting
+ * low priority events into the event queue.
+ * @see DDebugAgent::BufferAtCriticalLevel
+ * @see DDebugAgent::iEventQueue
+ */
+ static const TUint KCriticalBufferSize = 64;
+
};
#endif // D_DEBUG_AGENT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/debug/rmdebug/d_debug_agent.inl Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,106 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Inline methods for debug agent class
+//
+
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#ifndef D_DEBUG_AGENT_INL
+#define D_DEBUG_AGENT_INL
+
+
+/**
+ Checks whether the event queue is empty
+*/
+inline TBool DDebugAgent::BufferEmpty() const
+ {
+ return (NumberOfEmptySlots() == KNumberOfEventsToQueue);
+ }
+
+/**
+ Checks whether the event queue is full
+*/
+inline TBool DDebugAgent::BufferFull() const
+ {
+ return (NumberOfEmptySlots() == 0);
+ }
+
+/**
+ Checks whether there is room in the event queue to store an event
+*/
+inline TBool DDebugAgent::BufferCanStoreEvent() const
+ {
+ return (NumberOfEmptySlots() > 0);
+ }
+
+/**
+ This looks to see if the buffer is close to being full and should only
+ accept higher priority debug events (user trace is the only low priority event)
+*/
+inline TBool DDebugAgent::BufferAtCriticalLevel() const
+ {
+ return (NumberOfEmptySlots() < KNumberOfEventsToQueue - KCriticalBufferSize);
+ }
+
+/**
+ Increments Head position, wrapping at KNumberOfEventsToQueue if necessary
+*/
+inline void DDebugAgent::IncrementHeadPosition(void)
+ {
+ iHead = (iHead + 1) % KNumberOfEventsToQueue;
+
+ iFreeSlots--;
+ }
+
+/**
+ Increments Tail position, wrapping at KNumberOfEventsToQueue if necessary
+*/
+inline void DDebugAgent::IncrementTailPosition(void)
+ {
+ iTail = (iTail + 1) % KNumberOfEventsToQueue;
+
+ iFreeSlots++;
+}
+
+/**
+ Returns the number of free slots in the event queue
+*/
+inline TInt DDebugAgent::NumberOfEmptySlots() const
+ {
+ return iFreeSlots;
+ }
+
+/**
+ Lock access to this agent's event queue
+*/
+inline void DDebugAgent::LockEventQueue(void)
+ {
+ Kern::SemaphoreWait(*iEventQueueLock);
+ }
+
+/**
+ Release the lock on this agent's event queue
+*/
+inline void DDebugAgent::UnlockEventQueue(void)
+ {
+ Kern::SemaphoreSignal(*iEventQueueLock);
+ }
+
+
+#endif // D_DEBUG_AGENT_INL
--- a/kernel/eka/drivers/debug/rmdebug/d_list_manager.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_list_manager.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -422,7 +422,7 @@
}
//calculate data values
TFileName fileName(codeSeg->iFileName->Ptr());
- TBool isXip = (codeSeg->iXIP) ? ETrue : EFalse;
+ TBool isXip = (TBool)(codeSeg->iXIP);
//get the code seg type, can ignore error as have already checked codeSeg is not NULL
TCodeSegType type = EUnknownCodeSegType;
@@ -535,7 +535,7 @@
}
TFileName fileName(codeSeg->iFileName->Ptr());
- TBool isXip = (codeSeg->iXIP) ? ETrue : EFalse;
+ TBool isXip = (TBool)(codeSeg->iXIP);
//get the code seg type, can ignore error as have already checked codeSeg is not NULL
TCodeSegType type = EUnknownCodeSegType;
--- a/kernel/eka/drivers/debug/rmdebug/d_process_tracker.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_process_tracker.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -76,24 +76,30 @@
{
return KErrNoMemory;
}
-
+ LOG_MSG2(" AttachProcess: < new DTargetProcess=0x%08x", tmpProcess );
+
// Set the name
TInt err = KErrNone;
err = tmpProcess->SetProcessName(aProcessName);
if (err != KErrNone)
{
+ LOG_MSG2(" AttachProcess: < SetProcessName returned %d", err );
return err;
}
// Is this process being debugged (ie already attached?)
TInt index;
TBool found = EFalse;
- for(index=0;index<iProcesses.Count();index++)
+
+ TInt numberOfProcesses = iProcesses.Count();
+ for(index=0; index<numberOfProcesses; index++)
{
const TPtr8& tmpPtr8(iProcesses[index]->ProcessName() );
if ( tmpPtr8.CompareF(aProcessName) == 0)
{
+ LOG_MSG3(" Proc count=%d, found proc in iProcesses at %d. Count=%d",
+ index, iProcesses.Count() );
found = ETrue;
break;
}
@@ -104,6 +110,8 @@
// Yes, it is being debugged
// Add the agent to the list of agents for this process
+ LOG_MSG3(" > AddAgent(agent id %d) to existing iProcesses[%d]", I64LOW(aAgentId), index );
+
iProcesses[index]->AddAgent(aAgentId);
return KErrNone;
@@ -113,6 +121,8 @@
// No, it is not being debugged
// Add the agent to the list of agents for this process
+ LOG_MSG2(" > AddAgent(agent %d) to new proc at index 0", I64LOW(aAgentId) );
+
tmpProcess->AddAgent(aAgentId);
// Add the process to the list of processes being debugged
@@ -143,7 +153,9 @@
TInt i;
TBool found = EFalse;
DTargetProcess* foundProcess = 0;
- for(i=0;i<iProcesses.Count();i++)
+
+ TInt numberOfProcesses = iProcesses.Count();
+ for(i=0; i<numberOfProcesses; i++)
{
foundProcess = iProcesses[i];
@@ -186,7 +198,8 @@
TInt DProcessTracker::DetachAgent(const TUint64 aAgentId)
{
// Remove this agent from all the processes being tracked.
- for(TInt i=0;i<iProcesses.Count();i++)
+ TInt numberOfProcesses = iProcesses.Count();
+ for(TInt i=0; i<numberOfProcesses; i++)
{
// remove the agent from the process (we don't care about the return code)
iProcesses[i]->RemoveAgent(aAgentId);
@@ -226,13 +239,15 @@
if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
{
return 0; // not found
- };
+ }
// Can we find this in the array?
TInt i;
TBool found = EFalse;
DTargetProcess* foundProcess = 0;
- for(i=0;i<iProcesses.Count();i++)
+
+ TInt numberOfProcesses = iProcesses.Count();
+ for(i=0; i<numberOfProcesses; i++)
{
foundProcess = iProcesses[i];
@@ -247,6 +262,7 @@
if (found == EFalse)
{
+ LOG_EVENT_MSG("DProcessTracker::FindProcess, not found" );
return 0; // not found
}
@@ -272,73 +288,58 @@
*/
DTargetProcess* DProcessTracker::FuzzyFindProcess(const TDesC8& aProcessName)
{
-
// Valid ProcessName?
if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
{
return 0; // not found
- };
+ }
// Can we find this in the array?
- TInt i;
TBool found = EFalse;
DTargetProcess* foundProcess = 0;
- for(i=0;i<iProcesses.Count();i++)
+ const TChar KBackSlash('\\');
+
+ TInt numberOfProcesses = iProcesses.Count();
+ for(TInt i=0; i < numberOfProcesses; i++)
{
foundProcess = iProcesses[i];
- const TPtr8& tmpPtr8( foundProcess->ProcessName() );
-
- if ( tmpPtr8.CompareF(aProcessName) == 0)
+ TInt procListBackSlash = foundProcess->ProcessName().LocateReverse( KBackSlash );
+ if( procListBackSlash == KErrNotFound )
{
- found = ETrue;
- break;
+ procListBackSlash = 0;
}
else
{
- // need to compare centre of this string
- //
- // e.g.
- // z:\sys\bin\foobar.exe
- // might be seen as:
- // foobar.exe
- //
- // Algorithm is start at the right side of foundProcess->ProcessName
- // move left until we have some backslash, then finish.
- TInt right= tmpPtr8.Size() - 1;
- TInt left = right;
+ //Now move to the char after the backlash
+ procListBackSlash++;
+ }
+
+ TInt eventBackSlash = aProcessName.LocateReverse( KBackSlash );
+ if( eventBackSlash == KErrNotFound )
+ {
+ eventBackSlash = 0;
+ }
+ else
+ {
+ //Now move to the char after the backlash
+ eventBackSlash++;
+ }
- // search for the rightmost backslash
- while(left > 0)
- {
- if(tmpPtr8[left] == (TUint8)'\\')
- break;
-
- --left; // move left one character
- }
- // now we have
- // left = index of rightmost backslash in foundProcess->ProcessName()
- // right = index of rightmost character in foundProcess->ProcessName()
-
- // We must expect that the size of names matches
- TInt foundSize = right - left; // == sizeof("foobar.exe")
- TInt suppliedSize = aProcessName.Size();
+ if( ( procListBackSlash == 0 ) && ( eventBackSlash == 0 ) )
+ {
+ //There were no backslashes on either name, so no point in continuing
+ break;
+ }
- if (foundSize != suppliedSize)
- {
- // must be something else
- break;
- }
+ TPtrC8 eventCleanName( aProcessName.Mid( eventBackSlash ) );
+ TPtrC8 procListCleanName( foundProcess->ProcessName().Mid( procListBackSlash ) );
- for(TInt i=0;i< foundSize;i++)
- {
- if (tmpPtr8[left+i] != aProcessName[1+i])
- {
- break;
- }
- }
- // All the characters match if we get here
+ if ( eventCleanName.CompareF( procListCleanName ) == 0 )
+ {
+ LOG_MSG2("DProcessTracker::FuzzyFindProcess() found a match : process list[%d]", i );
found = ETrue;
+ break;
}
}
@@ -360,7 +361,8 @@
}
//iterate through the processes trying to match the name, and check suspended if found
- for(TInt i=0; i<iProcesses.Count(); i++)
+ TInt numberOfProcesses = iProcesses.Count();
+ for(TInt i=0; i < numberOfProcesses; i++)
{
if(iProcesses[i]->ProcessName().CompareF(*name) == 0)
{
@@ -407,7 +409,8 @@
}
//iterate through the processes trying to match the name, try to suspend the thread if found
- for(TInt i=0; i<iProcesses.Count(); i++)
+ TInt numberOfProcesses = iProcesses.Count();
+ for(TInt i=0; i < numberOfProcesses; i++)
{
if(iProcesses[i]->ProcessName().CompareF(*name) == 0)
{
@@ -421,7 +424,8 @@
void DProcessTracker::FSWait()
{
- for(TInt i=0; i<iProcesses.Count(); i++)
+ TInt numberOfProcesses = iProcesses.Count();
+ for(TInt i=0; i < numberOfProcesses; i++)
{
iProcesses[i]->FSWait();
}
@@ -447,7 +451,8 @@
}
//iterate through the processes trying to match the name, try to resume the thread if found
- for(TInt i=0; i<iProcesses.Count(); i++)
+ TInt numberOfProcesses = iProcesses.Count();
+ for(TInt i=0; i < numberOfProcesses; i++)
{
if(iProcesses[i]->ProcessName().CompareF(*name) == 0)
{
--- a/kernel/eka/drivers/debug/rmdebug/d_rmd_stepping.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_rmd_stepping.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -46,15 +46,15 @@
// DRMDStepping::~DRM_DebugChannel
//
DRMDStepping::~DRMDStepping()
-{
+ {
// to do
-}
+ }
//
// DRMDStepping::IsExecuted
//
TBool DRMDStepping::IsExecuted(TUint8 aCondition ,TUint32 aStatusRegister)
-{
+ {
LOG_MSG("DRMDStepping::IsExecuted()");
TBool N = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000008;
@@ -63,7 +63,7 @@
TBool V = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000001;
switch(aCondition)
- {
+ {
case 0:
return Z;
case 1:
@@ -95,16 +95,16 @@
case 14:
case 15:
return ETrue;
- }
+ }
return EFalse;
-}
+ }
//
// DRMDStepping::IsPreviousInstructionMovePCToLR
//
TBool DRMDStepping::IsPreviousInstructionMovePCToLR(DThread *aThread)
-{
+ {
LOG_MSG("DRMDStepping::IsPreviousInstructionMovePCToLR()");
TInt err = KErrNone;
@@ -122,114 +122,114 @@
TUint32 address = 0;
err = iChannel->ReadKernelRegisterValue(aThread, PC_REGISTER, address);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
address -= 4;
TBuf8<4> previousInstruction;
err = iChannel->DoReadMemory(aThread, address, 4, previousInstruction);
if (KErrNone != err)
- {
+ {
LOG_MSG2("Error %d reading memory at address %x", address);
return EFalse;
- }
+ }
const TUint32 movePCToLRIgnoringCondition = 0x01A0E00F;
TUint32 inst = *(TUint32 *)previousInstruction.Ptr();
if ((inst & 0x0FFFFFFF) == movePCToLRIgnoringCondition)
- {
+ {
return ETrue;
- }
+ }
return EFalse;
-}
+ }
//
// DRMDStepping::DecodeDataProcessingInstruction
//
void DRMDStepping::DecodeDataProcessingInstruction(TUint8 aOpcode, TUint32 aOp1, TUint32 aOp2, TUint32 aStatusRegister, TUint32 &aBreakAddress)
-{
+ {
LOG_MSG("DRMDStepping::DecodeDataProcessingInstruction()");
switch(aOpcode)
- {
+ {
case 0:
- {
+ {
// AND
aBreakAddress = aOp1 & aOp2;
break;
- }
+ }
case 1:
- {
+ {
// EOR
aBreakAddress = aOp1 ^ aOp2;
break;
- }
+ }
case 2:
- {
+ {
// SUB
aBreakAddress = aOp1 - aOp2;
break;
- }
+ }
case 3:
- {
+ {
// RSB
aBreakAddress = aOp2 - aOp1;
break;
- }
+ }
case 4:
- {
+ {
// ADD
aBreakAddress = aOp1 + aOp2;
break;
- }
+ }
case 5:
- {
+ {
// ADC
aBreakAddress = aOp1 + aOp2 + (aStatusRegister & arm_carry_bit()) ? 1 : 0;
break;
- }
+ }
case 6:
- {
+ {
// SBC
aBreakAddress = aOp1 - aOp2 - (aStatusRegister & arm_carry_bit()) ? 0 : 1;
break;
- }
+ }
case 7:
- {
+ {
// RSC
aBreakAddress = aOp2 - aOp1 - (aStatusRegister & arm_carry_bit()) ? 0 : 1;
break;
- }
+ }
case 12:
- {
+ {
// ORR
aBreakAddress = aOp1 | aOp2;
break;
- }
+ }
case 13:
- {
+ {
// MOV
aBreakAddress = aOp2;
break;
- }
+ }
case 14:
- {
+ {
// BIC
aBreakAddress = aOp1 & ~aOp2;
break;
- }
+ }
case 15:
- {
+ {
// MVN
aBreakAddress = ~aOp2;
break;
+ }
}
}
-}
//
// DRMDStepping::CurrentInstruction
@@ -315,7 +315,7 @@
// to remove obsolete parameters.
//
TUint32 DRMDStepping::PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 aStatusRegister, TInt aInstSize, /*TBool aStepInto,*/ TUint32 &aNewRangeEnd, TBool &aChangingModes)
-{
+ {
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes()");
// by default we will set the breakpoint at the next instruction
@@ -324,12 +324,12 @@
TInt err = KErrNone;
// determine the architecture
- TUint32 cpuid;
- asm("mrc p15, 0, cpuid, c0, c0, 0 ");
+ TUint32 cpuid;
+ asm("mrc p15, 0, cpuid, c0, c0, 0 ");
LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes() - cpuid = 0x%08x\n",cpuid);
- cpuid >>= 8;
- cpuid &= 0xFF;
+ cpuid >>= 8;
+ cpuid &= 0xFF;
// determine the architecture mode for the current instruction
TArchitectureMode mode = EArmMode; // Default assumption is ARM
@@ -345,9 +345,9 @@
// Decode instruction based on current CPU mode
switch(mode)
- {
+ {
case Debug::EArmMode:
- {
+ {
// Obtain the current instruction bit pattern
TUint32 inst;
ReturnIfError(CurrentInstruction(aThread,inst));
@@ -356,64 +356,64 @@
// check the conditions to see if this will actually get executed
if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister))
- {
+ {
switch(arm_opcode(inst)) // bits 27-25
- {
+ {
case 0:
- {
- switch((inst & 0x00000010) >> 4) // bit 4
{
+ switch((inst & 0x00000010) >> 4) // bit 4
+ {
case 0:
- {
+ {
switch((inst & 0x01800000) >> 23) // bits 24-23
- {
+ {
case 2:
- {
+ {
// move to/from status register. pc updates not allowed
// or TST, TEQ, CMP, CMN which don't modify the PC
break;
- }
+ }
default:
- {
+ {
// Data processing immediate shift
if (arm_rd(inst) == PC_REGISTER)
- {
+ {
TUint32 rn = aCurrentPC + 8;
if (arm_rn(inst) != PC_REGISTER) // bits 19-16
- {
+ {
err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
+ }
}
- }
TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
+ }
+ break;
}
- break;
}
+ break;
}
- break;
- }
case 1:
- {
+ {
switch((inst & 0x00000080) >> 7) // bit 7
- {
- case 0:
{
- switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
+ case 0:
{
+ switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
+ {
case 0x10:
- {
+ {
// from figure 3-3
switch((inst & 0x000000F0) >> 4) // bits 7-4
- {
+ {
case 1:
- {
+ {
if (((inst & 0x00400000) >> 22) == 0) // bit 22
- {
+ {
// BX
// this is a strange case. normally this is used in the epilogue to branch the the link
// register. sometimes it is used to call a function, and the LR is stored in the previous
@@ -421,324 +421,319 @@
// we need to read the previous instruction to see what we should do
err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
if ((breakAddress & 0x00000001) == 1)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
- }
+ }
break;
- }
+ }
case 3:
- {
+ {
// BLX
- {
+ {
err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
if ((breakAddress & 0x00000001) == 1)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
- }
+ }
break;
- }
+ }
default:
- {
+ {
// either doesn't modify the PC or it is illegal to
break;
+ }
}
- }
break;
- }
+ }
default:
- {
+ {
// Data processing register shift
if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
- {
+ {
// TST, TEQ, CMP, CMN don't modify the PC
- }
+ }
else if (arm_rd(inst) == PC_REGISTER)
- {
+ {
// destination register is the PC
TUint32 rn = aCurrentPC + 8;
if (arm_rn(inst) != PC_REGISTER) // bits 19-16
- {
+ {
err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
+ }
}
- }
TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
- }
+ }
break;
+ }
}
+ break;
}
- break;
- }
default:
- {
+ {
// from figure 3-2, updates to the PC illegal
break;
+ }
}
- }
break;
+ }
}
- }
break;
- }
+ }
case 1:
- {
+ {
if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
- {
+ {
// cannot modify the PC
break;
- }
+ }
else if (arm_rd(inst) == PC_REGISTER)
- {
+ {
// destination register is the PC
TUint32 rn;
err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); // bits 19-16
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
TUint32 shifter = ((arm_data_imm(inst) >> arm_data_rot(inst)) | (arm_data_imm(inst) << (32 - arm_data_rot(inst)))) & 0xffffffff;
DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
- }
+ }
break;
- }
+ }
case 2:
- {
+ {
// load/store immediate offset
if (arm_load(inst)) // bit 20
- {
+ {
// loading a register from memory
if (arm_rd(inst) == PC_REGISTER)
- {
+ {
// loading the PC register
TUint32 base;
err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
/* Note: At runtime the PC would be 8 further on
*/
if (arm_rn(inst) == PC_REGISTER)
- {
+ {
base = aCurrentPC + 8;
- }
+ }
TUint32 offset = 0;
-
- if (arm_single_pre(inst))
- {
- // Pre-indexing
- offset = arm_single_imm(inst);
-
- if (arm_single_u(inst))
+
+ if (arm_single_pre(inst))
{
- base += offset;
- }
+ // Pre-indexing
+ offset = arm_single_imm(inst);
+
+ if (arm_single_u(inst))
+ {
+ base += offset;
+ }
else
- {
- base -= offset;
+ {
+ base -= offset;
+ }
}
- }
TBuf8<4> destination;
err = iChannel->DoReadMemory(aThread, base, 4, destination);
if (KErrNone == err)
- {
+ {
breakAddress = *(TUint32 *)destination.Ptr();
-
+
if ((breakAddress & 0x00000001) == 1)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
- }
+ }
else
- {
+ {
LOG_MSG("Error reading memory in decoding step instruction");
+ }
}
}
- }
break;
- }
+ }
case 3:
- {
+ {
if (((inst & 0xF0000000) != 0xF0000000) && ((inst & 0x00000010) == 0))
- {
+ {
// load/store register offset
if (arm_load(inst)) // bit 20
- {
+ {
// loading a register from memory
if (arm_rd(inst) == PC_REGISTER)
- {
+ {
// loading the PC register
TUint32 base = 0;
if(arm_rn(inst) == PC_REGISTER)
- {
+ {
base = aCurrentPC + 8;
- }
+ }
else
- {
+ {
err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
+ }
}
- }
TUint32 offset = 0;
if (arm_single_pre(inst))
- {
+ {
offset = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
if (arm_single_u(inst))
- {
+ {
base += offset;
- }
+ }
else
- {
+ {
base -= offset;
+ }
}
- }
TBuf8<4> destination;
err = iChannel->DoReadMemory(aThread, base, 4, destination);
if (KErrNone == err)
- {
+ {
breakAddress = *(TUint32 *)destination.Ptr();
if ((breakAddress & 0x00000001) == 1)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
- }
+ }
else
- {
+ {
LOG_MSG("Error reading memory in decoding step instruction");
+ }
}
}
- }
- }
+ }
break;
- }
+ }
case 4:
- {
+ {
if ((inst & 0xF0000000) != 0xF0000000)
- {
+ {
// load/store multiple
if (arm_load(inst)) // bit 20
- {
+ {
// loading a register from memory
if (((inst & 0x00008000) >> 15))
- {
+ {
// loading the PC register
TInt offset = 0;
if (arm_block_u(inst))
- {
+ {
TUint32 reglist = arm_block_reglist(inst);
offset = iChannel->Bitcount(reglist) * 4 - 4;
if (arm_block_pre(inst))
offset += 4;
- }
+ }
else if (arm_block_pre(inst))
- {
+ {
offset = -4;
- }
-
+ }
+
TUint32 temp = 0;
err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), temp);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
-
+ }
+
temp += offset;
TBuf8<4> destination;
err = iChannel->DoReadMemory(aThread, temp, 4, destination);
-
+
if (KErrNone == err)
- {
+ {
breakAddress = *(TUint32 *)destination.Ptr();
if ((breakAddress & 0x00000001) == 1)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
- }
+ }
else
- {
+ {
LOG_MSG("Error reading memory in decoding step instruction");
+ }
}
}
- }
+ }
+ break;
}
- break;
- }
case 5:
- {
+ {
if ((inst & 0xF0000000) == 0xF0000000)
- {
+ {
// BLX
- {
- breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+ breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
- // Unconditionally change into Thumb mode
- aChangingModes = ETrue;
-
- breakAddress &= 0xFFFFFFFE;
+ // Unconditionally change into Thumb mode
+ aChangingModes = ETrue;
+ breakAddress &= 0xFFFFFFFE;
}
- }
else
- {
+ {
if ((inst & 0x01000000)) // bit 24
- {
+ {
// BL
- {
breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
}
- }
else
- {
+ {
// B
breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+ }
}
- }
break;
- }
- }
- }
- }
+ } // case 5
+ } //switch(arm_opcode(inst)) // bits 27-25
+ } // if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister))
+ } // case Debug::EArmMode:
break;
case Debug::EThumbMode:
- {
+ {
// Thumb Mode
//
// Notes: This now includes the extra code
@@ -758,22 +753,21 @@
// v6T2 instructions
-// Note: v6T2 decoding is only enabled for DEBUG builds or if using an
-// an ARM_V6T2 supporting build system. At the time of writing, no
-// ARM_V6T2 supporting build system exists, so the stepping code cannot
-// be said to be known to work. Hence it is not run for release builds
+ // Note: v6T2 decoding is only enabled for DEBUG builds or if using an
+ // an ARM_V6T2 supporting build system. At the time of writing, no
+ // ARM_V6T2 supporting build system exists, so the stepping code cannot
+ // be said to be known to work. Hence it is not run for release builds
TBool use_v6t2_decodings = EFalse;
#if defined(DEBUG) || defined(__ARMV6T2__)
use_v6t2_decodings = ETrue;
-
#endif
// coverity[dead_error_line]
if (use_v6t2_decodings)
- {
+ {
// 16-bit encodings
-
+
// A6.2.5 Misc 16-bit instructions
// DONE Compare and branch on zero (page A8-66)
// If then hints
@@ -782,7 +776,7 @@
//
// Compare and branch on Nonzero and Compare and Branch on Zero.
if ((inst & 0xF500) == 0xB100)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.27 CBNZ, CBZ");
// Decoding as per ARM ARM description
@@ -821,7 +815,7 @@
//
// If Then instruction
if ((inst & 0xFF00) == 0xBF00)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT");
// Decoding as per ARM ARM description
@@ -829,18 +823,18 @@
TUint32 mask = inst & 0x000F;
if (firstcond == 0xF)
- {
+ {
// unpredictable
LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT - Unpredictable");
break;
- }
+ }
if ((firstcond == 0xE) && (BitCount(mask) != 1))
- {
+ {
// unpredictable
LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT - Unpredictable");
break;
- }
+ }
// should check if 'in-it-block'
LOG_MSG("Cannot step IT instructions.");
@@ -861,7 +855,7 @@
// perhaps we can just totally ignore this state, and always do the two-instruction
// breakpoint thing? Not if there is any possibility that the address target
// would be invalid for the non-taken branch address...
- }
+ }
// 32-bit encodings.
@@ -873,12 +867,12 @@
// ARM ARM DDI0406A - section A8.6.26
if (inst32 & 0xFFF0FFFF == 0xE3C08F00)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.26 - BXJ is not supported");
// Decoding as per ARM ARM description
// TUint32 Rm = inst32 & 0x000F0000; // not needed yet
- }
+ }
// return from exception... SUBS PC,LR. page b6-25
//
@@ -886,7 +880,7 @@
//
// Encoding T1
if (inst32 & 0xFFFFFF00 == 0xF3DE8F00)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section B6.1.13 - SUBS PC,LR Encoding T1");
// Decoding as per ARM ARM description
@@ -906,13 +900,13 @@
TUint32 result = lrVal - operand2;
breakAddress = result;
- }
-
+ }
+
// ARM ARM DDI0406A - section A8.6.16 - B
//
// Branch Encoding T3
if (inst32 & 0xF800D000 == 0xF0008000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.16 - B Encoding T3");
// Decoding as per ARM ARM description
@@ -931,13 +925,13 @@
imm32 = (imm32 << 1) | 0;
breakAddress = aCurrentPC + imm32;
- }
+ }
// ARM ARM DDI0406A - section A8.6.16 - B
//
// Branch Encoding T4
if (inst32 & 0xF800D000 == 0xF0009000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.16 - B");
// Decoding as per ARM ARM description
@@ -959,14 +953,14 @@
imm32 = (imm32 << 1) | 0;
breakAddress = aCurrentPC + imm32;
- }
+ }
// ARM ARM DDI0406A - section A8.6.225 - TBB, TBH
//
// Table Branch Byte, Table Branch Halfword
if (inst32 & 0xFFF0FFE0 == 0xE8D0F000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.225 TBB,TBH Encoding T1");
// Decoding as per ARM ARM description
@@ -976,10 +970,10 @@
// Unpredictable?
if (Rm == 13 || Rm == 15)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.225 TBB,TBH Encoding T1 - Unpredictable");
break;
- }
+ }
TUint32 halfwords;
TUint32 address;
@@ -989,26 +983,25 @@
ReturnIfError(RegisterValue(aThread,Rm,offset));
if (H)
- {
-
+ {
address += offset << 1;
- }
+ }
else
- {
+ {
address += offset;
- }
+ }
ReturnIfError(ReadMem32(aThread,address,halfwords));
breakAddress = aCurrentPC + 2*halfwords;
break;
- }
+ }
// ARM ARM DDI0406A - section A8.6.55 - LDMDB, LDMEA
//
// LDMDB Encoding T1
if (inst32 & 0xFFD02000 == 0xE9100000)
- {
+ {
LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1");
// Decoding as per ARM ARM description
@@ -1022,10 +1015,10 @@
// Unpredictable?
if (Rn == 15 || BitCount(registers) < 2 || ((P == 1) && (M==1)))
- {
+ {
LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1 - Unpredictable");
break;
- }
+ }
TUint32 address;
ReturnIfError(RegisterValue(aThread,Rn,address));
@@ -1033,28 +1026,28 @@
address -= 4*BitCount(registers);
for(TInt i=0; i<15; i++)
- {
+ {
if (IsBitSet(registers,i))
- {
+ {
address +=4;
+ }
}
- }
if (IsBitSet(registers,15))
- {
+ {
TUint32 RnVal = 0;
ReturnIfError(ReadMem32(aThread,address,RnVal));
breakAddress = RnVal;
- }
+ }
break;
- }
+ }
// ARM ARM DDI0406A - section A8.6.121 POP
//
// POP.W Encoding T2
if (inst32 & 0xFFFF2000 == 0xE8BD0000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2");
// Decoding as per ARM ARM description
@@ -1064,33 +1057,33 @@
// Unpredictable?
if ( (BitCount(registers)<2) || ((P == 1)&&(M == 1)) )
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2 - Unpredictable");
break;
- }
+ }
TUint32 address;
ReturnIfError(RegisterValue(aThread,13,address));
for(TInt i=0; i< 15; i++)
- {
+ {
if (IsBitSet(registers,i))
- {
+ {
address += 4;
+ }
}
- }
// Is the PC written?
if (IsBitSet(registers,15))
- {
+ {
// Yes
ReturnIfError(ReadMem32(aThread,address,breakAddress));
+ }
}
- }
// POP Encoding T3
if (inst32 & 0xFFFF0FFFF == 0xF85D0B04)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3");
// Decoding as per ARM ARM description
@@ -1099,37 +1092,37 @@
// Unpredictable?
if (Rt == 13 || Rt == 15)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3 - Unpredictable");
break;
- }
+ }
TUint32 address;
ReturnIfError(RegisterValue(aThread,13,address));
for(TInt i=0; i< 15; i++)
- {
+ {
if (IsBitSet(registers,i))
- {
+ {
address += 4;
+ }
}
- }
// Is the PC written?
if (IsBitSet(registers,15))
- {
+ {
// Yes
ReturnIfError(ReadMem32(aThread,address,breakAddress));
- }
+ }
break;
- }
+ }
// ARM ARM DDI0406A - section A8.6.53 LDM
//
// Load Multiple Encoding T2
if ((inst32 & 0xFFD02000) == 0xE8900000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2");
// Decoding as per ARM ARM description
@@ -1142,17 +1135,17 @@
// POP?
if ( (W == 1) && (Rn == 13) )
- {
+ {
// POP instruction
LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2 - POP");
- }
+ }
// Unpredictable?
if (Rn == 15 || BitCount(register_list) < 2 || ((P == 1) && (M == 1)) )
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2 - Unpredictable");
break;
- }
+ }
TUint32 RnVal;
ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1161,28 +1154,28 @@
// Calculate offset of address
for(TInt i = 0; i < 15; i++)
- {
+ {
if (IsBitSet(registers,i))
{
address += 4;
}
- }
+ }
// Does it load the PC?
if (IsBitSet(registers,15))
- {
+ {
// Obtain the value loaded into the PC
ReturnIfError(ReadMem32(aThread,address,breakAddress));
- }
+ }
break;
- }
+ }
// ARM ARM DDI0406A - section B6.1.8 RFE
//
// Return From Exception Encoding T1 RFEDB
if ((inst32 & 0xFFD0FFFF) == 0xE810C000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T1");
// Decoding as per ARM ARM description
@@ -1195,11 +1188,11 @@
// Do calculation
if (Rn == 15)
- {
+ {
// Unpredictable
LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T1 - Unpredictable");
break;
- }
+ }
TUint32 RnVal = 0;
ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1208,22 +1201,22 @@
ReturnIfError(ReadMem32(aThread,RnVal,address));
if (increment)
- {
+ {
address -= 8;
- }
+ }
if (wordhigher)
- {
+ {
address += 4;
- }
+ }
breakAddress = address;
break;
- }
+ }
// Return From Exception Encoding T2 RFEIA
if ((inst32 & 0xFFD0FFFF) == 0xE990C000)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T2");
// Decoding as per ARM ARM description
@@ -1236,11 +1229,11 @@
// Do calculation
if (Rn == 15)
- {
+ {
// Unpredictable
LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T2 - Unpredictable");
break;
- }
+ }
TUint32 RnVal = 0;
ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1249,22 +1242,22 @@
ReturnIfError(ReadMem32(aThread,RnVal,address));
if (increment)
- {
+ {
address -= 8;
- }
+ }
if (wordhigher)
- {
+ {
address += 4;
- }
+ }
breakAddress = RnVal;
break;
- }
+ }
// Return From Exception Encoding A1 RFE<amode>
if ((inst32 & 0xFE50FFFF) == 0xF8100A00)
- {
+ {
LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1");
// Decoding as per ARM ARM description
@@ -1279,11 +1272,11 @@
// Do calculation
if (Rn == 15)
- {
+ {
// Unpredictable
LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1 - Unpredictable");
break;
- }
+ }
TUint32 RnVal = 0;
ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1292,94 +1285,94 @@
ReturnIfError(ReadMem32(aThread,RnVal,address));
if (increment)
- {
+ {
address -= 8;
- }
+ }
if (wordhigher)
- {
+ {
address += 4;
- }
+ }
breakAddress = address;
break;
+ }
}
- }
// v4T/v5T/v6T instructions
switch(thumb_opcode(inst))
- {
+ {
case 0x08:
- {
+ {
// Data-processing. See ARM ARM DDI0406A, section A6-8, A6.2.2.
if ((thumb_inst_7_15(inst) == 0x08F))
- {
+ {
// BLX(2)
err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
if ((breakAddress & 0x00000001) == 0)
- {
+ {
aChangingModes = ETrue;
- }
-
+ }
+
breakAddress &= 0xFFFFFFFE;
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX (2)");
- }
+ }
else if (thumb_inst_7_15(inst) == 0x08E)
- {
+ {
// BX
err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
if ((breakAddress & 0x00000001) == 0)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BX");
- }
+ }
else if ((thumb_inst_8_15(inst) == 0x46) && ((inst & 0x87) == 0x87))
- {
+ {
// MOV with PC as the destination
err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as MOV with PC as the destination");
- }
+ }
else if ((thumb_inst_8_15(inst) == 0x44) && ((inst & 0x87) == 0x87))
- {
+ {
// ADD with PC as the destination
err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
breakAddress += aCurrentPC + 4; // +4 because we need to use the PC+4 according to ARM ARM DDI0406A, section A6.1.2.
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as ADD with PC as the destination");
- }
+ }
break;
- }
+ }
case 0x13:
- {
+ {
// Load/Store single data item. See ARM ARM DDI0406A, section A6-10
//This instruction doesn't modify the PC.
@@ -1393,81 +1386,81 @@
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as This instruction doesn't modify the PC.");
break;
- }
+ }
case 0x17:
- {
+ {
// Misc 16-bit instruction. See ARM ARM DDI0406A, section A6-11
if (thumb_inst_8_15(inst) == 0xBD)
- {
+ {
// POP with the PC in the list
TUint32 regList = (inst & 0x00FF);
TInt offset = 0;
err = iChannel->ReadKernelRegisterValue(aThread, SP_REGISTER, (T4ByteRegisterValue&)offset);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
offset += (iChannel->Bitcount(regList) * 4);
TBuf8<4> destination;
err = iChannel->DoReadMemory(aThread, offset, 4, destination);
if (KErrNone == err)
- {
+ {
breakAddress = *(TUint32 *)destination.Ptr();
if ((breakAddress & 0x00000001) == 0)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFE;
- }
+ }
else
- {
+ {
LOG_MSG("Error reading memory in decoding step instruction");
- }
+ }
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as POP with the PC in the list");
- }
+ }
break;
- }
+ }
case 0x1A:
case 0x1B:
- {
+ {
// Conditional branch, and supervisor call. See ARM ARM DDI0406A, section A6-13
if (thumb_inst_8_15(inst) < 0xDE)
- {
+ {
// B(1) conditional branch
if (IsExecuted(((inst & 0x0F00) >> 8), aStatusRegister))
- {
+ {
TUint32 offset = ((inst & 0x000000FF) << 1);
if (offset & 0x00000100)
- {
+ {
offset |= 0xFFFFFF00;
- }
+ }
breakAddress = aCurrentPC + 4 + offset;
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(1) conditional branch");
+ }
}
- }
break;
- }
+ }
case 0x1C:
- {
+ {
// Unconditional branch, See ARM ARM DDI0406A, section A8-44.
// B(2) unconditional branch
TUint32 offset = (inst & 0x000007FF) << 1;
if (offset & 0x00000800)
- {
+ {
offset |= 0xFFFFF800;
- }
+ }
breakAddress = aCurrentPC + 4 + offset;
@@ -1475,114 +1468,111 @@
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(2) unconditional branch");
break;
- }
+ }
case 0x1D:
- {
+ {
if (!(inst & 0x0001))
- {
+ {
// BLX(1)
err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
if(err != KErrNone)
- {
+ {
LOG_MSG2("Non-zero error code discarded: %d", err);
- }
+ }
breakAddress += ((inst & 0x07FF) << 1);
if ((breakAddress & 0x00000001) == 0)
- {
+ {
aChangingModes = ETrue;
- }
+ }
breakAddress &= 0xFFFFFFFC;
// Report how we decoded this instruction
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX(1)");
- }
+ }
break;
- }
+ }
case 0x1E:
- {
- // Check for ARMv7 CPU
- if(cpuid == 0xC0)
- {
- // BL/BLX 32-bit instruction
- aNewRangeEnd += 4;
+ {
+ // Check for ARMv7 CPU
+ if(cpuid == 0xC0)
+ {
+ // BL/BLX 32-bit instruction
+ aNewRangeEnd += 4;
breakAddress = (TUint32)thumb_instr_b_dest(inst32, aCurrentPC);
- if((inst32 >> 27) == 0x1D)
- {
- // BLX(1)
- if ((breakAddress & 0x00000001) == 0)
- {
- aChangingModes = ETrue;
- }
-
- breakAddress &= 0xFFFFFFFC;
+ if((inst32 >> 27) == 0x1D)
+ {
+ // BLX(1)
+ if ((breakAddress & 0x00000001) == 0)
+ {
+ aChangingModes = ETrue;
+ }
+
+ breakAddress &= 0xFFFFFFFC;
- // Report how we decoded this instruction
- LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)");
- }
- else
- {
- // Report how we decoded this instruction
- LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction");
- }
- LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress);
- }
- else
- {
- // BL/BLX prefix - destination is encoded in this and the next instruction
- aNewRangeEnd += 2;
+ // Report how we decoded this instruction
+ LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)");
+ }
+ else
+ {
+ // Report how we decoded this instruction
+ LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction");
+ }
+ LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress);
+ } // if(cpuid == 0xC0)
+ else
+ {
+ // BL/BLX prefix - destination is encoded in this and the next instruction
+ aNewRangeEnd += 2;
- // Report how we decoded this instruction
- LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction");
- }
-
+ // Report how we decoded this instruction
+ LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction");
+ }
break;
- }
+ }
case 0x1F:
- {
{
- // BL
- err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
- if(err != KErrNone)
+ // BL
+ err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
+ if(err != KErrNone)
{
- LOG_MSG2("Non-zero error code discarded: %d", err);
+ LOG_MSG2("Non-zero error code discarded: %d", err);
}
- breakAddress += ((inst & 0x07FF) << 1);
+ breakAddress += ((inst & 0x07FF) << 1);
- // Report how we decoded this instruction
- LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL");
+ // Report how we decoded this instruction
+ LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL");
+ break;
+ }
+ default:
+ {
+ // Don't know any better at this point!
+ LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction");
}
break;
- }
- default:
- {
- // Don't know any better at this point!
- LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction");
- }
- break;
- }
- }
+ } // switch(thumb_opcode(inst))
+ } // case Debug::EThumbMode:
break;
-
+
case Debug::EThumb2EEMode:
- {
+ {
// Not yet supported
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Debug::EThumb2Mode is not supported");
- }
- break;
+ }
+ break;
default:
LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Cannot determine CPU mode architecture");
- }
+ } // switch(mode)
LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes : return 0x%08x",breakAddress);
return breakAddress;
-}
+ }
// Obtain a 32-bit memory value with minimum fuss
TInt DRMDStepping::ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue)
@@ -1646,7 +1636,7 @@
// Encodings from ARM ARM DDI0406A, section 9.2.1
enum TThumb2EEOpcode
-{
+ {
EThumb2HDP, // Handler Branch with Parameter
EThumb2UNDEF, // UNDEFINED
EThumb2HB, // Handler Branch, Handler Branch with Link
@@ -1656,76 +1646,76 @@
EThumb2LDRL, // Load Register from a literal pool
EThumb2LDRA, // Load Register (array operations)
EThumb2STR // Store Register to a frame
-};
+ };
//
// DRMDStepping::ShiftedRegValue
//
TUint32 DRMDStepping::ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister)
-{
- LOG_MSG("DRM_DebugChannel::ShiftedRegValue()");
+ {
+ LOG_MSG("DRMDStepping::ShiftedRegValue()");
TUint32 shift = 0;
if (aInstruction & 0x10) // bit 4
- {
+ {
shift = (arm_rs(aInstruction) == PC_REGISTER ? aCurrentPC + 8 : aStatusRegister) & 0xFF;
- }
+ }
else
- {
+ {
shift = arm_data_c(aInstruction);
- }
+ }
TInt rm = arm_rm(aInstruction);
TUint32 res = 0;
if(rm == PC_REGISTER)
- {
+ {
res = aCurrentPC + ((aInstruction & 0x10) ? 12 : 8);
- }
+ }
else
- {
+ {
TInt err = iChannel->ReadKernelRegisterValue(aThread, rm, res);
if(err != KErrNone)
- {
+ {
LOG_MSG2("DRMDStepping::ShiftedRegValue - Non-zero error code discarded: %d", err);
+ }
}
- }
switch(arm_data_shift(aInstruction))
- {
+ {
case 0: // LSL
- {
+ {
res = shift >= 32 ? 0 : res << shift;
break;
- }
+ }
case 1: // LSR
- {
+ {
res = shift >= 32 ? 0 : res >> shift;
break;
- }
+ }
case 2: // ASR
- {
+ {
if (shift >= 32)
shift = 31;
res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift);
break;
- }
+ }
case 3: // ROR/RRX
- {
+ {
shift &= 31;
if (shift == 0)
- {
+ {
res = (res >> 1) | ((aStatusRegister & arm_carry_bit()) ? 0x80000000L : 0);
- }
+ }
else
- {
+ {
res = (res >> shift) | (res << (32 - shift));
- }
+ }
break;
- }
- }
+ }
+ }
- return res & 0xFFFFFFFF;
+ return res & 0xFFFFFFFF;
}
//
--- a/kernel/eka/drivers/debug/rmdebug/d_target_process.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_target_process.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -16,7 +16,7 @@
// each process being debugged.
// Note: Although TheDProcessTracker object is a global, it should be unique
// as only the Debug Security Server should load and use this driver.
-//
+//
//
#include <e32def.h>
@@ -101,12 +101,12 @@
DDebugAgent* DTargetProcess::Agent(TUint64 aAgentId)
{
for(TInt i = 0; i < iAgentList.Count(); i++)
- {
+ {
if (iAgentList[i]->Id() == aAgentId)
- {
+ {
return iAgentList[i];
+ }
}
- }
// what do we return if we don't have any agents?
return NULL;
@@ -115,8 +115,11 @@
// Adds aAgentId as a tracking agent for this process.
TInt DTargetProcess::AddAgent(TUint64 aAgentId)
{
- LOG_MSG("DTargetProcess::AddAgent()");
+
DDebugAgent* agent = DDebugAgent::New(aAgentId);
+ LOG_MSG4("DTargetProcess::AddAgent(), agentId=%d, curr iAgentList.Count=%d, new agent=0x%08x",
+ I64LOW(aAgentId), iAgentList.Count(), agent );
+
if(agent == NULL)
{
LOG_MSG("DTargetProcess::AddAgent() couldn't allocate memory for DDebugAgent");
@@ -172,19 +175,19 @@
//if resuming the suspended thread failed for an obscure reason return it
if((err1 != KErrNotFound) && (err1 != KErrNone))
{
- LOG_MSG2("DTargetProcess::ResumeThread() unexpected exit, err1: %d", err1);
+ LOG_MSG2("DTargetProcess::ResumeThread() BUG : unexpected exit, err1: %d", err1);
return err1;
}
//if resuming the frozen thread failed for an obscure reason return it
if((err2 != KErrNotFound) && (err2 != KErrNone))
{
- LOG_MSG2("DTargetProcess::ResumeThread() unexpected exit, err2: %d", err2);
+ LOG_MSG2("DTargetProcess::ResumeThread() BUG : unexpected exit, err2: %d", err2);
return err2;
}
// if resuming the suspended thread succeeded in both cases, we have a consistency problem
if ((err1 == KErrNone) && (err2 == KErrNone))
{
- LOG_MSG("DTargetProcess::ResumeThread() unexpected exit, err1 == err2 == KErrNone");
+ LOG_MSG("DTargetProcess::ResumeThread() BUG : unexpected exit, err1 == err2 == KErrNone");
}
//if the thread was in neither list return KErrNotFound, otherwise KErrNone
@@ -232,7 +235,7 @@
if(iSuspendedThreads[i] == threadId)
{
iSuspendedThreads.Remove(i);
- LOG_MSG2("DTargetProcess::ResumeSuspendedThread()> Kern::ThreadResume() 0x%x", aThread);
+ LOG_MSG2("DTargetProcess::ResumeSuspendedThread()> Kern::ThreadResume() 0x%08x", aThread);
Kern::ThreadResume(*aThread);
return KErrNone;
}
@@ -292,7 +295,8 @@
NFastSemaphore* sem = new NFastSemaphore();
NKern::ThreadLeaveCS();
sem->iOwningThread = &(Kern::CurrentThread().iNThread);
- LOG_EVENT_MSG2("DTargetProcess::FreezeThread(): new NFastSemaphore() curr thread=0x%x", sem->iOwningThread);
+ LOG_MSG3("DTargetProcess::FreezeThread(): new NFastSemaphore() owning thread==curr NThread=0x%08x, DThread=0x%08x",
+ sem->iOwningThread, &(Kern::CurrentThread()) );
return iFrozenThreadSemaphores.Append(sem);
}
@@ -322,6 +326,7 @@
TInt err = iSuspendedThreads.Append(threadId);
if(err == KErrNone)
{
+ LOG_MSG2("DTargetProcess::DoSuspendThread >Kern::ThreadSuspend() 0x%08x", aThread );
Kern::ThreadSuspend(*aThread, 1);
}
return err;
@@ -341,13 +346,13 @@
*/
void DTargetProcess::FSWait()
{
- LOG_MSG2("DTargetProcess::NotifyEvent(): number of attached agents: %d", AgentCount());
- NThread* currentThread = &(Kern::CurrentThread().iNThread);
+ NThread* currentNThread = &(Kern::CurrentThread().iNThread);
for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
{
- if(iFrozenThreadSemaphores[i]->iOwningThread == currentThread)
+ if(iFrozenThreadSemaphores[i]->iOwningThread == currentNThread)
{
- LOG_MSG3("DTargetProcess::FSWait(): > FSWait frozen sem %d, curr thread=0x%x", i, currentThread);
+ LOG_MSG4("DTargetProcess::FSWait(): > FSWait frozen sem %d, currentNThread=0x%08x, id=0x%x",
+ i, currentNThread, Kern::CurrentThread().iId );
NKern::FSWait(iFrozenThreadSemaphores[i]);
return;
}
@@ -399,7 +404,8 @@
void DTargetProcess::NotifyEvent(const TDriverEventInfo& aEventInfo)
{
// Stuff the event info into all the tracking agents event queues
- LOG_MSG2("DTargetProcess::NotifyEvent(): number of attached agents: %d", AgentCount());
+ LOG_MSG4("DTargetProcess::NotifyEvent(): num attached agents: %d, iEventType=%d, this=0x%08x",
+ AgentCount(), aEventInfo.iEventType, this);
for(TInt i = 0; i < AgentCount(); i++)
{
--- a/kernel/eka/drivers/debug/rmdebug/rm_debug_eventhandler.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/rm_debug_eventhandler.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -44,7 +44,6 @@
iEventHandlers[EEventUserTrace] = &DRM_DebugChannel::HandleUserTrace;
iEventHandlers[EEventRemoveLibrary] = &DRM_DebugChannel::RemoveLibrary;
iEventHandlers[EEventAddLibrary] = &DRM_DebugChannel::AddLibrary;
- iEventHandlers[EEventRemoveProcess] = &DRM_DebugChannel::RemoveProcess;
iEventHandlers[EEventStartThread] = &DRM_DebugChannel::StartThread;
iEventHandlers[EEventSwExc] = &DRM_DebugChannel::HandleSwException;
iEventHandlers[EEventHwExc] = &DRM_DebugChannel::HandleHwException;
@@ -55,7 +54,7 @@
TInt DRM_DebugEventHandler::Create(DLogicalDevice* aDevice, DLogicalChannel* aChannel, DThread* aClient)
{
- LOG_MSG("DRM_DebugEventHandler::Create()");
+ LOG_MSG3("DRM_DebugEventHandler::Create(), aClientthread=0x%08x id=%d", aClient, aClient->iId);
TInt err;
err = aDevice->Open();
@@ -71,7 +70,7 @@
iClientThread = aClient;
// Use a semaphore to protect our data structures from concurrent access.
- err = Kern::SemaphoreCreate(iLock, _L("RM_DebugEventHandlerLock"), 1 /* Initial count */);
+ err = Kern::SemaphoreCreate(iProtectionLock, _L("RM_DebugEventHandlerLock"), 1 /* Initial count */);
if (err != KErrNone)
return err;
@@ -84,8 +83,8 @@
{
LOG_MSG("DRM_DebugEventHandler::~DRM_DebugEventHandler()");
- if (iLock)
- iLock->Close(NULL);
+ if (iProtectionLock)
+ iProtectionLock->Close(NULL);
if (iDevice)
iDevice->Close(NULL);
@@ -125,11 +124,23 @@
TUint DRM_DebugEventHandler::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2)
{
- if((!iTracking) || (aType > (TUint32)EEventLimit))
+
+ /*
+ * Check if we are tracking things at all OR
+ * this event is beyond the limit of known events OR
+ * this event is from the debug thread itself (don't want to debug ourselves) OR
+ * this event has a handler (there is no point in proceeding without a handler)
+ */
+ if( (!iTracking) ||
+ (aType > (TUint32)EEventLimit) ||
+ (iClientThread == &Kern::CurrentThread()) ||
+ (iEventHandlers[aType] == &DRM_DebugChannel::HandleUnsupportedEvent) )
{
return ERunNext;
}
+
return HandleSpecificEvent(aType,a1,a2) ? EExcHandled : ERunNext;
+
}
TBool DRM_DebugEventHandler::HandleSpecificEvent(TKernelEvent aType, TAny* a1, TAny* a2)
@@ -137,14 +148,14 @@
TBool ret = EFalse;
NKern::ThreadEnterCS();
- Kern::SemaphoreWait(*iLock);
-
+ LockDataAccess();
+
+
if (iChannel)
{
ret = (iChannel->*(iEventHandlers[aType]))(a1, a2);
}
-
- Kern::SemaphoreSignal(*iLock);
+ ReleaseDataAccess();
NKern::ThreadLeaveCS();
switch(aType)
--- a/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -59,41 +59,41 @@
// DRM_DebugDriverFactory constructor
//
DRM_DebugDriverFactory::DRM_DebugDriverFactory()
-{
+ {
iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
-}
+ }
//
// DRM_DebugDriverFactory::Create
//
TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
-{
+ {
if (iOpenChannels != 0)
return KErrInUse; // a channel is already open
aChannel = new DRM_DebugChannel(this);
return aChannel ? KErrNone : KErrNoMemory;
-}
+ }
//
// DRM_DebugDriverFactory::Install
//
TInt DRM_DebugDriverFactory::Install()
-{
- return(SetName(&KRM_DebugDriverName));
-}
+ {
+ return(SetName(&KRM_DebugDriverName));
+ }
//
// DRM_DebugDriverFactory::Install
//
void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
-{
- TCapsRM_DebugDriver b;
- b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
+ {
+ TCapsRM_DebugDriver b;
+ b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
-}
+ }
/////////////////////////////////////////////////////////////////////////
//
@@ -106,37 +106,41 @@
//
DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
: iExcludedROMAddressStart(ROM_LINEAR_BASE),
- iExcludedROMAddressEnd(0),
- iPageSize(0x1000),
- iBreakManager(0),
- iStepper(0),
- iStepLock(0),
- iDfcQ(NULL),
- iInitialisedCodeModifier(0),
- iAsyncGetValueRequest(NULL)
-{
+ iExcludedROMAddressEnd(0),
+ iPageSize(0x1000),
+ iBreakManager(0),
+ iStepper(0),
+ iStepLock(0),
+ iDfcQ(NULL),
+ iInitialisedCodeModifier(0),
+ iAsyncGetValueRequest(NULL)
+ {
LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
iDevice = aLogicalDevice;
- iClientThread = &Kern::CurrentThread();
+ iClientThread = &Kern::CurrentThread();
iClientThread->Open();
+ LOG_MSG3("DRM_DebugChannel::DRM_DebugChannel() clientThread = 0x%08x, id=%d",
+ iClientThread, iClientThread->iId );
+
+
iPageSize = Kern::RoundToPageSize(1);
-}
+ }
//
// DRM_DebugChannel destructor
//
DRM_DebugChannel::~DRM_DebugChannel()
-{
+ {
LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
if (iAsyncGetValueRequest)
- {
+ {
Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
Kern::DestroyClientRequest(iAsyncGetValueRequest);
- }
+ }
NKern::ThreadEnterCS();
Kern::SafeClose((DObject*&)iClientThread, NULL);
@@ -144,19 +148,19 @@
// Close breakpoint manager
if (iBreakManager)
- {
+ {
NKern::ThreadEnterCS();
delete iBreakManager;
NKern::ThreadLeaveCS();
- }
+ }
// Close stepping manager
if (iStepper)
- {
+ {
NKern::ThreadEnterCS();
delete iStepper;
NKern::ThreadLeaveCS();
- }
+ }
//close the debug process list
iDebugProcessList.Close();
@@ -165,10 +169,10 @@
//close the code modifier
if (iInitialisedCodeModifier)
- {
+ {
DebugSupport::CloseCodeModifier();
+ }
}
-}
void DRM_DebugChannel::DestroyDfcQ()
{
@@ -185,47 +189,45 @@
// DRM_DebugChannel::DoCreate
//
TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
-{
+ {
LOG_MSG("DRM_DebugChannel::DoCreate()");
TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
if(err != KErrNone)
return err;
- if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
+ if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
return KErrNotSupported;
- // Do the security check here so that any arbitrary application doesn't make
- // use of Trk kernel driver.
- if (!DoSecurityCheck())
- {
+ // Do the security check here so that any arbitrary application doesn't make
+ // use of Trk kernel driver.
+ if (!DoSecurityCheck())
+ {
LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
- return KErrPermissionDenied;
- }
-
- if (anInfo)
- {
- // this is the end address of the user library.
- // this doesn't seem to be valid for EKA2.
- // right now we dont need this for EKA2 since we are not worried
- // about kernel being stopped as kernel is multithreaded.
- // just retaining this for future use.
+ return KErrPermissionDenied;
+ }
+
+ if (anInfo)
+ {
+ // this is the end address of the user library.
+ // this doesn't seem to be valid for EKA2.
+ // right now we dont need this for EKA2 since we are not worried
+ // about kernel being stopped as kernel is multithreaded.
+ // just retaining this for future use.
TBuf8<32> buf;
TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
if(err != KErrNone)
return err;
-
- //iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
- }
+ }
// Allocate a D_RMD_Breakpoints class as a breakpoint manager
NKern::ThreadEnterCS();
iBreakManager = new D_RMD_Breakpoints(this);
NKern::ThreadLeaveCS();
if (iBreakManager == NULL)
- {
+ {
LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
return KErrNoMemory;
- }
+ }
// Initialise the new breakpoint manager object
iBreakManager->Init();
@@ -235,10 +237,10 @@
iStepper = new DRMDStepping(this);
NKern::ThreadLeaveCS();
if (iStepper == NULL)
- {
+ {
LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
return KErrNoMemory;
- }
+ }
// Initialize the code modifier for managing breakpoints.
TUint caps; //ignored for now
@@ -246,13 +248,13 @@
//if code modifier initializer failed,
//return here, since we can't set an breakpoints
if(err != KErrNone)
- {
+ {
return err;
- }
+ }
else
- {
+ {
iInitialisedCodeModifier = ETrue;
- }
+ }
//create and set the driver's Dfc queue
err = CreateDfcQ();
@@ -273,15 +275,29 @@
//return KErrNone;
return iEventHandler->Start();
-}
-
-//
-// DRM_DebugChannel::SendMsg
-//
+ }
+
+/**
+Forward call to either synch or asynch methods while serialising all calls via lock.
+
+Protect access via a the event handler lock to
+serialise all calls and protect concurrent access to data structures
+
+@param aMsg pointer to a TMessageBase object
+
+@return error returned by called methods
+
+@see DRM_DebugEventHandler::HandleSpecificEvent where lock is also used
+@see DRM_DebugEventHandler::iProtectionLock
+
+*/
TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
{
- LOG_MSG("DRM_DebugChannel::SendMsg()");
-
+ DThread * currThread = &Kern::CurrentThread();
+ LOG_MSG3("DRM_DebugChannel::SendMsg() currThread = 0x%08x, iClientThread=0x%08x", currThread, iClientThread );
+
+ iEventHandler->LockDataAccess();
+
TThreadMessage& m = *(TThreadMessage*)aMsg;
TInt id = m.iValue;
TInt err = KErrNone;
@@ -298,6 +314,8 @@
{
err = DLogicalChannel::SendMsg(aMsg);
}
+
+ iEventHandler->ReleaseDataAccess();
return err;
}
@@ -330,7 +348,8 @@
//
TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
{
- LOG_MSG("DRM_DebugChannel::PreAsyncGetValue()");
+ LOG_MSG3("DRM_DebugChannel::PreAsyncGetValue() TEventInfo=0x%08x, TRequestStatus=0x%08x",
+ aValue, aStatus );
iAsyncGetValueRequest->Reset();
@@ -364,89 +383,93 @@
// to a user-side struct defining the cancellation
//
void DRM_DebugChannel::DoCancel(TInt aReqNo)
-{
+ {
LOG_MSG("DRM_DebugChannel::DoCancel()");
TRMD_DebugCancelInfo info;
TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
if (err != KErrNone)
- {
+ {
// How do we cancel something we know nothing about???
LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
return;
- }
+ }
// Find the process
DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
if (pProcess == NULL)
- {
+ {
// We are doomed. We don't know which event to cancel..
LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
return;
- }
+ }
// Find the agent
DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
if (debugAgent == NULL)
- {
+ {
// Bad agent means there is no tracking agent
LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
return;
- }
+ }
// Agent completes/pends the request as appropriate.
debugAgent->CancelGetEvent();
-}
+ }
//
// DRM_DebugChannel::DoRequest
//
void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
-{
- LOG_MSG("DRM_DebugChannel::DoRequest()");
+ {
+ LOG_MSG4("DRM_DebugChannel::DoRequest(), iClientThread=0x%08x, tid=0x%08x, TRequestStatus=0x%08x",
+ iClientThread, I64LOW(iClientThread->iId), aStatus);
switch(aReqNo)
- {
+ {
case RRM_DebugDriver::ERequestGetEvent:
- {
+ {
TEventMetaData eventMetaData;
TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
if (err != KErrNone)
- {
+ {
LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
// We could not read information from the user, so the a2 argument is probably wrong
Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
return;
- }
+ }
// Find the process
DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
if (pProcess == NULL)
- {
+ {
LOG_MSG("Cannot identify process being debugged");
// We could not locate the process, so the user asked for the wrong one.
Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
return;
- }
+ }
// Find the agent
DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
+ LOG_MSG5(" For agent pid=%d, DTargetProcess=0x%08x, Agent=0x%08x, iAsyncGetValueRequest0x%08x",
+ I64LOW(eventMetaData.iDebugAgentProcessId), pProcess, debugAgent, iAsyncGetValueRequest );
+
if (debugAgent == NULL)
- {
+ {
// Bad agent means there is no tracking agent
LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
return;
- }
+ }
// Agent completes/pends the request as appropriate.
- debugAgent->GetEvent(iAsyncGetValueRequest, (TEventInfo*)a1, iClientThread);
+ debugAgent->GetEvent(iAsyncGetValueRequest, iClientThread);
break;
- }
+ }
default:
{
// Don't know what to do, should not get here!
@@ -454,14 +477,14 @@
Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
}
+ }
}
-}
//
// DRM_DebugChannel::DoControl
//
TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
-{
+ {
LOG_MSG("DRM_DebugChannel::DoControl()");
LOG_MSG2("DoControl Function %d", aFunction);
@@ -470,121 +493,121 @@
DThread* threadObj = NULL;
switch(aFunction)
- {
+ {
/* Security first */
case RRM_DebugDriver::EControlIsDebuggable:
- {
+ {
err = IsDebuggable((TUint32)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlSetBreak:
- {
+ {
err = SetBreak((TSetBreakInfo*)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlClearBreak:
- {
+ {
err = iBreakManager->DoClearBreak((TInt32)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlModifyBreak:
- {
+ {
err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlModifyProcessBreak:
- {
+ {
err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlBreakInfo:
- {
+ {
err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlSuspendThread:
- {
+ {
threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
if (threadObj)
{
err = DoSuspendThread(threadObj);
}
break;
- }
+ }
case RRM_DebugDriver::EControlResumeThread:
- {
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = DoResumeThread(threadObj);
+ }
+ break;
+ }
+ case RRM_DebugDriver::EControlStepRange:
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
+ }
+ break;
+ }
+ case RRM_DebugDriver::EControlReadMemory:
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
+ }
+ break;
+ }
+ case RRM_DebugDriver::EControlWriteMemory:
+ {
threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
if (threadObj)
- {
- err = DoResumeThread(threadObj);
- }
- break;
- }
- case RRM_DebugDriver::EControlStepRange:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
- }
+ {
+ err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
+ }
break;
- }
- case RRM_DebugDriver::EControlReadMemory:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlWriteMemory:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
- }
- break;
- }
+ }
case RRM_DebugDriver::EControlReadRegistersLegacy:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
- }
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
+ }
break;
- }
+ }
case RRM_DebugDriver::EControlWriteRegistersLegacy:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
- }
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
+ }
break;
- }
+ }
case RRM_DebugDriver::EControlReadRegisters:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
- }
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
+ }
break;
- }
+ }
case RRM_DebugDriver::EControlWriteRegisters:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
- }
+ {
+ threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+ if (threadObj)
+ {
+ err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
+ }
break;
- }
+ }
case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
TDebugFunctionality df;
@@ -594,9 +617,9 @@
// Return size to user-side in a safe manner
err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
break;
- }
+ }
case RRM_DebugDriver::EControlGetDebugFunctionality:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
TDebugFunctionality df;
@@ -608,64 +631,64 @@
TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
NKern::ThreadLeaveCS();
if (dfbuffer==NULL)
- {
+ {
LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
// could not allocate memory
return KErrNoMemory;
- }
+ }
// Temporary descriptor to hold DF data
TPtr8 tmpPtr(dfbuffer,0,dfsize);
// Obtain the DF data
if (df.GetDebugFunctionality(tmpPtr) )
- {
+ {
// Return the DF data to the user-side
err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
- }
+ }
else
- {
+ {
// Failed.
err = KErrGeneral;
- }
+ }
// Free tmp buffer
NKern::ThreadEnterCS();
Kern::Free(dfbuffer);
NKern::ThreadLeaveCS();
break;
- }
+ }
case RRM_DebugDriver::EControlAttachProcess:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
err = AttachProcess(a1,a2);
break;
- }
+ }
case RRM_DebugDriver::EControlDetachProcess:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
err = DetachProcess(a1,a2);
break;
- }
+ }
case RRM_DebugDriver::EControlDetachAgent:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
err = DetachAgent(a1,a2);
break;
- }
+ }
case RRM_DebugDriver::EControlSetEventAction:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
err = SetEventAction(a1,a2);
break;
- }
+ }
case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
@@ -673,95 +696,95 @@
// Return size to user-side in a safe manner
err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
break;
- }
+ }
case RRM_DebugDriver::EControlGetList:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlGetList\n");
err = GetList((TListInformation*)a1);
break;
- }
+ }
case RRM_DebugDriver::EControlStep:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlStep\n");
err = Step((TUint32)a1,(TUint32)a2);
break;
- }
+ }
case RRM_DebugDriver::EControlKillProcess:
- {
+ {
LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
err = KillProcess((TUint32)a1,(TUint32)a2);
break;
- }
+ }
default:
- {
+ {
err = KErrGeneral;
+ }
}
- }
if (KErrNone != err)
- {
+ {
LOG_MSG2("Error %d from control function", err);
- }
-
- if (threadObj)
- {
- // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
- threadObj->Close(NULL);
- }
+ }
+
+ if (threadObj)
+ {
+ // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
+ threadObj->Close(NULL);
+ }
return err;
-}
+ }
void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
-{
+ {
LOG_MSG("DRM_DebugChannel::HandleMsg()");
TThreadMessage& m = *(TThreadMessage*)aMsg;
TInt id = m.iValue;
if (id == (TInt)ECloseMsg)
- {
+ {
if (iEventHandler)
- {
+ {
iEventHandler->Stop();
iEventHandler->Close();
iEventHandler = NULL;
- }
+ }
m.Complete(KErrNone, EFalse);
return;
- }
+ }
if (id == KMaxTInt)
- {
+ {
// DoCancel
DoCancel(m.Int0());
m.Complete(KErrNone, ETrue);
return;
- }
+ }
if (id < 0)
- {
+ {
// DoRequest
TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
m.Complete(KErrNone, ETrue);
- }
+ }
else
- {
+ {
// DoControl
TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
m.Complete(err, ETrue);
+ }
}
-}
//
// DRM_DebugChannel::RemoveProcess
//
TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
{
- LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
+ LOG_MSG("DRM_DebugChannel::RemoveProcess()");
DProcess *aProcess = (DProcess*)a1;
@@ -797,7 +820,6 @@
{
LOG_MSG2("Error in getting memory info: %d", err);
}
-
}
if (!codeAddress || !codeSize)
@@ -831,7 +853,7 @@
// DRM_DebugChannel::StartThread
//
TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
-{
+ {
LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
DThread *aThread = (DThread*)a1;
@@ -881,13 +903,13 @@
}
}
return EFalse;
-}
+ }
//
// DRM_DebugChannel::HandleAddProcessEvent
//
TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
-{
+ {
LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
DProcess *aProcess = (DProcess*)a1;
@@ -905,7 +927,7 @@
info.iEventType = EEventsAddProcess;
info.iProcessId = aProcess->iId;
- info.iCreatorThreadId = aThread ? aThread->iId : 0;
+ info.iCreatorThreadId = aThread ? aThread->iId : 0;
info.iProcessIdValid = ETrue;
// Copy TUids
@@ -945,14 +967,14 @@
}
return EFalse;
-}
+ }
//
// DRM_DebugChannel::HandleRemoveProcessEvent
//
TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
-{
- LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
+ {
+ LOG_MSG("DRM_DebugChannel::HandleRemoveProcessEvent()");
DProcess *aProcess = (DProcess*)a1;
if(!aProcess)
@@ -1004,13 +1026,13 @@
}
return EFalse;
-}
+ }
//
// DRM_DebugChannel::AddLibrary
//
TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
-{
+ {
LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
DLibrary *aLibrary = (DLibrary*)a1;
@@ -1018,24 +1040,24 @@
// sanity check
if (!aLibrary)
- {
+ {
LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
return EFalse;
- }
+ }
if (!aThread)
- {
+ {
LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
return EFalse;
- }
+ }
LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
if (aThread)
- {
+ {
// make sure this is not the debugger thread
if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
- {
+ {
TDriverEventInfo info;
info.iEventType = EEventsAddLibrary;
@@ -1047,10 +1069,10 @@
//get the code address
DCodeSeg* codeSeg = aLibrary->iCodeSeg;
if (!codeSeg)
- {
+ {
LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
return EFalse;
- }
+ }
// Uid3
info.iUids = codeSeg->iUids;
@@ -1059,10 +1081,10 @@
TModuleMemoryInfo memoryInfo;
TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
if (err != KErrNone)
- {
+ {
LOG_EVENT_MSG2("Error in getting memory info: %d", err);
return EFalse;
- }
+ }
info.iCodeAddress = memoryInfo.iCodeBase;
info.iDataAddress = memoryInfo.iInitialisedDataBase;
@@ -1073,11 +1095,11 @@
info.iArg1 = a1;
info.iArg2 = a2;
NotifyEvent(info);
+ }
+
}
-
+ return EFalse;
}
- return EFalse;
-}
//
// DRM_DebugChannel::RemoveLibrary
@@ -1164,16 +1186,17 @@
// DRM_DebugChannel::HandleEventKillThread
//
TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
-{
- LOG_EVENT_MSG("DRM_DebugChannel::HandleEventKillThread");
+ {
+
+ LOG_MSG2("DRM_DebugChannel::HandleEventKillThread(Thread a1=0x%08x)", a1 );
DThread* currentThread = &Kern::CurrentThread();
if (!currentThread)
- {
+ {
LOG_MSG("Error getting current thread");
__NK_ASSERT_DEBUG(currentThread);
return EFalse;
- }
+ }
// a1 should point to the current thread, check this to make sure it does
__NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
@@ -1187,14 +1210,14 @@
// 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
if(err != KErrNone)
- {
+ {
LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
- }
+ }
if (currentThread->iExitType == EExitPanic)
- {
+ {
info.iPanicCategory.Copy(currentThread->iExitCategory);
- }
+ }
info.iExceptionNumber = currentThread->iExitReason;
info.iExitType = currentThread->iExitType;
info.iEventType = EEventsKillThread;
@@ -1226,13 +1249,13 @@
NotifyEvent(info);
return ETrue;
-}
+ }
//
// DRM_DebugChannel::HandleSwException
//
TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
-{
+ {
LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
TExcType aExcType = (TExcType)(TInt)a1;
@@ -1240,11 +1263,11 @@
DThread* currentThread = &Kern::CurrentThread();
if (!currentThread)
- {
+ {
LOG_MSG("Error getting current thread");
__NK_ASSERT_DEBUG(currentThread);
return EFalse;
- }
+ }
info.iProcessId = currentThread->iOwningProcess->iId;
info.iProcessIdValid = ETrue;
@@ -1252,9 +1275,9 @@
info.iThreadIdValid = ETrue;
TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
if(err != KErrNone)
- {
+ {
LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
- }
+ }
info.iExceptionNumber = aExcType;
info.iEventType = EEventsSwExc;
info.iArg1 = a1;
@@ -1263,35 +1286,33 @@
NotifyEvent(info);
return EFalse;
-}
+ }
//
// DRM_DebugChannel::HandleHwException
//
TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
-{
- LOG_EVENT_MSG("DRM_DebugChannel::HandleHwException()");
+ {
TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
// sanity check
if (!aExcInfo)
- {
+ {
LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
__NK_ASSERT_DEBUG(aExcInfo);
return EFalse;
- }
+ }
TDriverEventInfo info;
DThread* currentThread = &Kern::CurrentThread();
- LOG_EVENT_MSG2("DRM_DebugChannel::HandleHwException current thread = 0x%x", currentThread);
if (!currentThread)
- {
+ {
LOG_MSG("Error getting current thread");
__NK_ASSERT_DEBUG(currentThread);
return EFalse;
- }
+ }
info.iProcessId = currentThread->iOwningProcess->iId;
info.iProcessIdValid = ETrue;
@@ -1299,8 +1320,10 @@
info.iThreadIdValid = ETrue;
info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
- LOG_EVENT_MSG3("DRM_DebugChannel::HandleHwException iFaultAddress=0x%x, iFaultStatus=0x%x",
- aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
+
+ LOG_MSG5("DRM_DebugChannel::HandleHwException current thread = 0x%08x, CritSect count=%d,\n"
+ " iFaultAddress=0x%08x, iFaultStatus=0x%08x",
+ currentThread, currentThread->iNThread.iCsCount, aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
@@ -1320,18 +1343,16 @@
info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
- LOG_EVENT_MSG5(" R12=0x%x, R13=0x%x, R14=0x%x, R15=0x%x ",
- aExcInfo->iR12, aExcInfo->iR13, aExcInfo->iR14, aExcInfo->iR15);
info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
- LOG_EVENT_MSG5(" iCpsr=0x%x, iR13Svc=0x%x, iR14Svc=0x%x, iSpsrSvc=0x%x ",
- aExcInfo->iCpsr, aExcInfo->iR13Svc, aExcInfo->iR14Svc, aExcInfo->iSpsrSvc);
+ LOG_MSG5(" iCpsr=0x%x, iExcCode=0x%x, R14=0x%x, R15=0x%x",
+ aExcInfo->iCpsr, aExcInfo->iExcCode, aExcInfo->iR14, aExcInfo->iR15);
switch (aExcInfo->iExcCode)
- {
+ {
case 0:
info.iExceptionNumber = EExcCodeAbort;
LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
@@ -1348,8 +1369,8 @@
// new event? Something gone wrong?
__NK_ASSERT_DEBUG(EFalse);
return EFalse;
-
- }
+ }
+
info.iEventType = EEventsHwExc;
info.iArg1 = a1;
@@ -1362,22 +1383,22 @@
NotifyEvent(info);
return EFalse;
-}
+ }
//
// DRM_DebugChannel::HandUserTrace
//
TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
-{
+ {
LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
DThread* currentThread = &Kern::CurrentThread();
if (!currentThread)
- {
+ {
LOG_EVENT_MSG("Error getting current thread");
__NK_ASSERT_DEBUG(currentThread);
return EFalse;
- }
+ }
TDriverEventInfo info;
info.iProcessId = currentThread->iOwningProcess->iId;
@@ -1402,14 +1423,14 @@
NotifyEvent(info);
return EFalse;
-}
+ }
//
// DRM_DebugChannel::HandleException
//
TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
-{
- LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
+ {
+ LOG_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
TInt err = KErrNone;
@@ -1420,38 +1441,39 @@
TUint32 regValue;
err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
if(err != KErrNone)
- {
- LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
- }
+ {
+ LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
+ }
+
if (regValue & ECpuThumb)
- {
+ {
inst = KThumbBreakPoint;
instSize = 2;
- }
+ }
TUint32 instruction = 0;
err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
if (KErrNone != err)
- LOG_EVENT_MSG2("Error reading instruction at currentpc: %d", err);
+ LOG_MSG2("Error reading instruction at currentpc: %d", err);
if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
- {
+ {
TInt err = DoSuspendThread(aCurrentThread);
if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
{
- LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
+ LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
return EFalse;
}
// the exception was a breakpoint instruction. see if we have a breakpoint at that address
TBreakEntry* breakEntry = NULL;
do
- {
+ {
breakEntry = iBreakManager->GetNextBreak(breakEntry);
if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
- {
- LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
+ {
+ LOG_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
TBreakEntry tempBreakEntry = *breakEntry;
@@ -1465,7 +1487,7 @@
// see if this is a temp breakpoint
if (iBreakManager->IsTemporaryBreak(*breakEntry))
- {
+ {
// this was a temp breakpoint, so we need to clear it now
err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
if (KErrNone != err)
@@ -1476,36 +1498,36 @@
// reduce the number of steps to complete by 1
tempBreakEntry.iNumSteps--;
- LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
+ LOG_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
// New. If we have not finished do all the steps, continue stepping and don't notify event
if (tempBreakEntry.iNumSteps)
- {
- LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
+ {
+ LOG_MSG("Continuing stepping...not telling the agent yet\n");
err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
if (err != KErrNone)
- {
+ {
LOG_EVENT_MSG("Failed to continue stepping\n");
// what do we do? might as well stop here and tell the user
NotifyEvent(aEventInfo);
return ETrue;
- }
+ }
// continue as though no event occured. No need to suspend/resume anything...
- LOG_EVENT_MSG("Continuing to step\n");
+ LOG_MSG("Continuing to step\n");
return ETrue;
- }
+ }
// Is this a case where we just want to continue?
if (tempBreakEntry.iResumeOnceOutOfRange)
- {
- LOG_EVENT_MSG("PC is out of range, continuing thread");
+ {
+ LOG_MSG("PC is out of range, continuing thread");
DoResumeThread(aCurrentThread);
return ETrue;
- }
+ }
}
// if the breakpoint is thread specific, make sure it's the right thread
@@ -1517,49 +1539,49 @@
(!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
if (needToResume)
- {
- LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
+ {
+ LOG_MSG("breakpoint does not match threadId, calling DoResumeThread");
err = DoResumeThread(aCurrentThread);
if (KErrNone != err)
- LOG_EVENT_MSG2("Error in DoResumeThread: %d", err);
+ LOG_MSG2("Error in DoResumeThread: %d", err);
return EFalse;
- }
+ }
//normal user break point, just notify the event
break;
- }
- } while(breakEntry);
- }
+ }
+ } while(breakEntry);
+ }
NotifyEvent(aEventInfo);
return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
-}
+ }
//
// DRM_DebugChannel::SetBreak
//
TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
-{
+ {
LOG_MSG("DRM_DebugChannel::SetBreak()");
TInt err = KErrNone;
if (!aBreakInfo)
- {
+ {
LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
return KErrArgument;
- }
+ }
//User side memory is not accessible directly
TSetBreakInfo info;
err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
if (err != KErrNone)
- {
+ {
LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
return err;
- }
+ }
DProcess* process = NULL;
if(info.iThreadSpecific)
@@ -1583,11 +1605,13 @@
{
process = DebugUtils::OpenProcessHandle(info.iId);
}
+
if(!process)
{
LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
return KErrNotFound;
}
+
TBool found = EFalse;
for(TInt i=0; i<iDebugProcessList.Count(); i++)
{
@@ -1596,6 +1620,7 @@
found = ETrue;
}
}
+
if(!found)
{
DCodeSeg* codeSeg = process->iCodeSeg;
@@ -1623,24 +1648,25 @@
return KErrArgument;
if (err == KErrNone)
- {
+ {
TInt32 iBreakId;
err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
if (err == KErrNone)
- {
+ {
err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
+ }
}
- }
+
return err;
-}
+ }
//
// DRM_DebugChannel::StepRange
//
TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
-{
+ {
LOG_MSG("DRM_DebugChannel::StepRange()");
TInt err = KErrNone;
@@ -1663,7 +1689,7 @@
err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
return err;
-}
+ }
/**
Read memory from a target thread and return the data to the client. If the
@@ -1680,7 +1706,7 @@
or another of the system wide error codes
*/
TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
-{
+ {
LOG_MSG("DRM_DebugChannel::ReadMemory()");
TInt err = KErrNone;
@@ -1700,9 +1726,9 @@
TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
NKern::ThreadLeaveCS();
if (!data)
- {
+ {
return KErrNoMemory;
- }
+ }
TPtr8 dataDes(data, info.iLength);
@@ -1717,7 +1743,7 @@
NKern::ThreadLeaveCS();
return err;
-}
+ }
/**
Attempt to write memory to aThread's address space
@@ -1734,7 +1760,7 @@
or another of the system wide error codes
*/
TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
-{
+ {
LOG_MSG("DRM_DebugChannel::WriteMemory()");
TInt err = KErrNone;
@@ -1754,30 +1780,30 @@
TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
NKern::ThreadLeaveCS();
if (!data)
- {
+ {
return KErrNoMemory;
- }
+ }
TPtr8 dataDes(data, info.iLength);
err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
if (err == KErrNone)
- {
+ {
err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
- }
+ }
NKern::ThreadEnterCS();
Kern::Free(data);
NKern::ThreadLeaveCS();
return err;
-}
+ }
//
// DRM_DebugChannel::ReadRegisters
//
TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
-{
+ {
LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
TInt err = KErrNone;
@@ -1799,24 +1825,24 @@
TUint8 *values = (TUint8*)Kern::Alloc(length);
NKern::ThreadLeaveCS();
if (!values)
- {
+ {
return KErrNoMemory;
- }
+ }
TPtr8 valuesDes(values, length);
err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
if (err == KErrNone)
- {
+ {
err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
- }
+ }
NKern::ThreadEnterCS();
Kern::Free(values);
NKern::ThreadLeaveCS();
return err;
-}
+ }
/**
Get listing information.
@@ -1922,6 +1948,7 @@
//if no error then write the buffer back
err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
}
+
//write back the size of the data regardless of any error
TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
if(writeErr != KErrNone)
@@ -1956,7 +1983,7 @@
KErrDied, if the thread with thread ID aThreadId is dead
*/
TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
-{
+ {
LOG_MSG("DRM_DebugChannel::ReadRegisters()");
TInt err = KErrNone;
@@ -1978,11 +2005,11 @@
if(err != KErrNone)
{
if(err == KErrNoMemory)
- {
+ {
NKern::ThreadEnterCS();
Kern::Free((TAny*)ids.Ptr());
NKern::ThreadLeaveCS();
- }
+ }
return err;
}
@@ -1992,10 +2019,12 @@
if(err != KErrNone)
{
if(err == KErrNoMemory)
- { NKern::ThreadEnterCS();
+ {
+ NKern::ThreadEnterCS();
Kern::Free((TAny*)values.Ptr());
NKern::ThreadLeaveCS();
- }
+ }
+
NKern::ThreadEnterCS();
Kern::Free((TAny*)ids.Ptr());
NKern::ThreadLeaveCS();
@@ -2008,11 +2037,11 @@
if(err != KErrNone)
{
if(err == KErrNoMemory)
- {
+ {
NKern::ThreadEnterCS();
Kern::Free((TAny*)flags.Ptr());
NKern::ThreadLeaveCS();
- }
+ }
NKern::ThreadEnterCS();
Kern::Free((TAny*)ids.Ptr());
Kern::Free((TAny*)values.Ptr());
@@ -2037,13 +2066,13 @@
NKern::ThreadLeaveCS();
return err;
-}
+ }
/**
@deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
*/
TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
-{
+ {
LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
TInt err = KErrNone;
@@ -2065,24 +2094,24 @@
TUint8 *values = (TUint8*)Kern::Alloc(length);
NKern::ThreadLeaveCS();
if (!values)
- {
+ {
return KErrNoMemory;
- }
+ }
TPtr8 valuesDes(values, length);
err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
if (err == KErrNone)
- {
+ {
err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
- }
+ }
NKern::ThreadEnterCS();
Kern::Free(values);
NKern::ThreadLeaveCS();
return err;
-}
+ }
/**
Write registers and store flags data in aRegisterInfo
@@ -2103,7 +2132,7 @@
KErrDied, if the thread with thread ID aThreadId is dead
*/
TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
-{
+ {
LOG_MSG("DRM_DebugChannel::WriteRegisters()");
TInt err = KErrNone;
@@ -2181,7 +2210,7 @@
NKern::ThreadLeaveCS();
return err;
-}
+ }
/**
Suspends execution of the specified thread.
@@ -2239,6 +2268,7 @@
}
}
} while(breakEntry);
+
return TheDProcessTracker.ResumeThread(aThread);
}
@@ -2246,7 +2276,7 @@
// DRM_DebugChannel::DoStepRange
//
TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
-{
+ {
LOG_MSG("DRM_DebugChannel::DoStepRange()");
if (!aThread)
@@ -2285,7 +2315,7 @@
LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
return TheDProcessTracker.ResumeThread(aThread);
-}
+ }
/**
Read memory from the specified addres into the aData descriptor. If there is a
@@ -2382,7 +2412,7 @@
TInt err = KErrNone;
// trap exceptions in case the address is invalid
- XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
+ XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
err = (KErrNone == r) ? err : r;
@@ -2436,8 +2466,8 @@
// DRM_DebugChannel::DoReadRegisters
//
TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
-{
- LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
+ {
+ LOG_EVENT_MSG("DRM_DebugChannel::DoReadRegisters()");
// make sure the parameters are valid
if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
@@ -2448,19 +2478,19 @@
return KErrArgument;
TArmRegSet regSet;
- TUint32 unused;
+ TUint32 unused;
NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
- TArmReg *reg = ®Set.iR0;
+ TArmReg *reg = ®Set.iR0;
if (!reg)
return KErrGeneral;
- for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
- aValues.Append((TUint8 *)®[i], sizeof(TArmReg));
+ for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
+ aValues.Append((TUint8 *)®[i], sizeof(TArmReg));
return KErrNone;
}
@@ -2510,7 +2540,7 @@
KErrGeneral if there was a problem initialising the register set
*/
TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
-{
+ {
LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
// make sure the parameters are valid
@@ -2613,13 +2643,13 @@
}
}
return KErrNone;
-}
+ }
//
// DRM_DebugChannel::DoWriteRegisters
//
TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
-{
+ {
LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
// make sure the parameters are valid
@@ -2643,7 +2673,7 @@
NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
return KErrNone;
-}
+ }
/**
Write registers and store flags indicating which registers could be read in
@@ -2662,7 +2692,7 @@
KErrGeneral if there was a problem initialising the register set
*/
TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
-{
+ {
LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
// make sure the parameters are valid
@@ -2765,23 +2795,23 @@
// DRM_DebugChannel::DoSecurityCheck
//
TBool DRM_DebugChannel::DoSecurityCheck()
-{
+ {
LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
DProcess* clientProcess = iClientThread->iOwningProcess;
if (clientProcess)
- {
+ {
SSecurityInfo secureInfo = clientProcess->iS;
LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
// Ensure we really are communicating with the Debug Security Server
if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
- {
+ {
return ETrue;
+ }
}
+ return EFalse;
}
- return EFalse;
-}
/**
Attempt to read memory from aThread's address space
@@ -2795,7 +2825,7 @@
or another of the system wide error codes
*/
TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
-{
+ {
LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
// make sure the parameters are valid
@@ -2814,7 +2844,7 @@
LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
-}
+ }
/**
Attempt to write memory to aThread's address space
@@ -2828,7 +2858,7 @@
error codes
*/
TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
-{
+ {
LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
//check that the thread is suspended before writing the memory
@@ -2840,30 +2870,30 @@
LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
-}
+ }
/**
@deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
*/
TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
-{
+ {
LOG_MSG("DRM_DebugChannel::ReadRegister()");
if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
- {
+ {
LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
return 0;
- }
+ }
TArmRegSet regSet;
- TUint32 unused;
+ TUint32 unused;
NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
- TArmReg *reg = ®Set.iR0;
+ TArmReg *reg = ®Set.iR0;
return ((TUint32 *)reg)[aNum];
-}
+ }
/**
Given a TArmReg register ID, read the value of the register. The register value
@@ -2879,7 +2909,7 @@
or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
*/
TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
-{
+ {
//get register ID as a TRegisterInfo ID
TRegisterInfo regId;
TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
@@ -2906,33 +2936,34 @@
or a return value from DRM_DebugChannel::DoReadRegisters
*/
TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
-{
+ {
//allocate temporary buffers to store data
NKern::ThreadEnterCS();
TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
NKern::ThreadLeaveCS();
if(id == NULL)
- {
+ {
return KErrNoMemory;
- }
+ }
+
TPtr8 idPtr(id, sizeof(TRegisterInfo));
NKern::ThreadEnterCS();
TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
NKern::ThreadLeaveCS();
if(value == NULL)
- {
+ {
return KErrNoMemory;
- }
+ }
TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
NKern::ThreadEnterCS();
TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
NKern::ThreadLeaveCS();
if(flag == NULL)
- {
+ {
return KErrNoMemory;
- }
+ }
TPtr8 flagPtr(flag, sizeof(TUint8));
//store register id in buffer
@@ -2941,18 +2972,18 @@
//read registers
TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
if(err == KErrNone)
- {
+ {
if(*flag == EValid)
- {
+ {
//register could be read so store value
aValue = *(T4ByteRegisterValue*)value;
- }
+ }
else
- {
+ {
//register couldn't be read for some reason
err = *flag;
+ }
}
- }
//free memory
NKern::ThreadEnterCS();
@@ -2962,13 +2993,13 @@
NKern::ThreadLeaveCS();
return err;
-}
+ }
//
// DRM_DebugChannel::NotifyEvent
//
void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
-{
+ {
LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
// Look for the relevant DTargetProcess
@@ -3016,7 +3047,7 @@
}
foundProcess->NotifyEvent(aEventInfo);
-}
+ }
#ifndef __LAUNCH_AS_EXTENSION__
DECLARE_STANDARD_LDD()
@@ -3112,23 +3143,23 @@
* to both co-exist and exist independantly of the existing one *
*/
DDebuggerInfo::DDebuggerInfo():
- iObjectOffsetTable(NULL),
- iObjectOffsetTableCount(NULL),
- iThreadContextTable(NULL),
- iStopModeExtension(new DStopModeExtension()),
- iContainers(NULL),
- iCodeSegLock(NULL),
- iCodeSegGlobalList(NULL),
- iScheduler(NULL),
- iShadowPages(NULL),
- iShadowPageCount(0),
- iCurrentThread(NULL),
- iEventMask(),
- iEventHandlerBreakpoint(0),
- iMemModelObjectOffsetTable(NULL),
- iMemModelObjectOffsetTableCount(0)
- {
- }
+ iObjectOffsetTable(NULL),
+ iObjectOffsetTableCount(NULL),
+ iThreadContextTable(NULL),
+ iStopModeExtension(new DStopModeExtension()),
+ iContainers(NULL),
+ iCodeSegLock(NULL),
+ iCodeSegGlobalList(NULL),
+ iScheduler(NULL),
+ iShadowPages(NULL),
+ iShadowPageCount(0),
+ iCurrentThread(NULL),
+ iEventMask(),
+ iEventHandlerBreakpoint(0),
+ iMemModelObjectOffsetTable(NULL),
+ iMemModelObjectOffsetTableCount(0)
+ {
+ }
/**
* Installs the stop-mode debugger extension
@@ -3136,9 +3167,9 @@
* existence in the superpage
*/
void DStopModeExtension::Install(DStopModeExtension* aExt)
- {
- Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
- }
+ {
+ Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
+ }
#endif
@@ -3342,7 +3373,7 @@
*/
TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
{
- return ( aFlags & (1<<aIndex) ) ? ETrue : EFalse;
+ return aFlags & (1<<aIndex);
}
/* Register the attachment of a debug agent to a process to be debugged
@@ -3475,38 +3506,38 @@
TUint8* buffer = (TUint8*)Kern::AllocZ(length);
NKern::ThreadLeaveCS();
if (buffer==NULL)
- {
+ {
// Out of memory
return KErrNoMemory;
- }
+ }
TPtr8 targetProcessName(buffer,length,length);
// Read the user-side data into targetProcessName
err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
if (err != KErrNone)
- {
+ {
// Something bad happened so free the memory and return
NKern::ThreadEnterCS();
Kern::Free(buffer);
NKern::ThreadLeaveCS();
return err;
- }
+ }
// Obtain the AgentId
TUint64 debugAgentId = 0;
err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
if (err != KErrNone)
- {
+ {
// Something bad happened so free the memory and return
NKern::ThreadEnterCS();
Kern::Free(buffer);
NKern::ThreadLeaveCS();
return err;
- }
+ }
// Remove the process from our list of tracked processes
err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
@@ -3531,9 +3562,9 @@
TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
if (err != KErrNone)
- {
+ {
return err;
- }
+ }
// Remove the process from our list of tracked processes
return TheDProcessTracker.DetachAgent(debugAgentId);
@@ -3578,30 +3609,30 @@
TUint8* buffer = (TUint8*)Kern::AllocZ(length);
NKern::ThreadLeaveCS();
if (buffer==NULL)
- {
+ {
// Out of memory
return KErrNoMemory;
- }
+ }
TPtr8 targetProcessName(buffer,length,length);
// Read the user-side data into targetProcessName
err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
if (err != KErrNone)
- {
+ {
// Something bad happened so free the memory and return
NKern::ThreadEnterCS();
Kern::Free(buffer);
NKern::ThreadLeaveCS();
return err;
- }
+ }
// Read the Event and Action from the user-side
TRM_DebugEventActionInfo info(0,0,0);
err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
if (err != KErrNone)
- {
+ {
// Could not read event action data from the user-side
// Free memory used for targetProcessName
@@ -3610,12 +3641,12 @@
NKern::ThreadLeaveCS();
return err;
- }
+ }
// Find the target process
DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
if (pProcess == NULL)
- {
+ {
// Could not find this process
// Free memory used for targetProcessName
@@ -3624,14 +3655,14 @@
NKern::ThreadLeaveCS();
return KErrArgument;
- }
+ }
TUint64 debugAgentId = info.iAgentId;
// Find the agent
DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
if (debugAgent == NULL)
- {
+ {
// Bad agent means there is no tracking agent
LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
@@ -3641,7 +3672,7 @@
NKern::ThreadLeaveCS();
return KErrGeneral;
- }
+ }
// Set the event action
debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
@@ -3752,9 +3783,9 @@
}
if (err == KErrNone)
- {
+ {
LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
- }
+ }
return err;
}
--- a/kernel/eka/drivers/dma/dmapil.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/dma/dmapil.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
@@ -861,7 +861,11 @@
// release threads doing CancelAll()
waiters->Signal();
}
- else if (!error && iController->IsIdle(*this) && !iReqQ.IsEmpty() && !iDfc.Queued())
+ // (iController may be NULL here if the channel was closed in the client callback.)
+ else if (!error &&
+ iController && iController->IsIdle(*this) &&
+ !iReqQ.IsEmpty() &&
+ !iDfc.Queued())
{
// Wait for a bit. If during that time the condition goes away then it
// was a 'spurious missed interrupt', in which case we just do nothing.
--- a/kernel/eka/drivers/media/base_e32_drivers_media.mrp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/media/base_e32_drivers_media.mrp Mon Mar 15 12:45:50 2010 +0200
@@ -23,8 +23,6 @@
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\stackbody.cpp
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\stackbody.h
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\distribution.policy.s60
-source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\Obtaining_PSL_Software_Source_Code.txt
-source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\distribution.policy.s60
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\sdcard.cpp
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\epbussd.mmp
source \sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\distribution.policy.s60
--- a/kernel/eka/drivers/pbus/spbus.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/pbus/spbus.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1111,6 +1111,9 @@
OstTraceFunctionEntry1( DPBUSSOCKET_DOORCLOSEEVENT_ENTRY, this );
__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::DoorCloseEvent state %d",iSocketNumber,iState));
OstTraceExt2(TRACE_INTERNALS, DPBUSSOCKET_DOORCLOSEEVENT , "iSocketNumber=%d; iState=%d",iSocketNumber,iState);
+
+ if (iPostponedEvents & EMediaChange)
+ iPostponedEvents &= ~EMediaChange;
// NB If there are multiple doors then the bus may already be powererd up,
// so it's not possible to determine the bus state.
--- a/kernel/eka/drivers/usbc/d_usbc.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/usbc/d_usbc.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1959,7 +1959,12 @@
// Parcel out the memory between endpoints
TUint8* newAddr = reinterpret_cast<TUint8*>(chunk->LinearAddress());
__KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory alloc new chunk=0x%x, size=%d", newAddr,bufSizes[chunkInd]));
- chunkChanged = (newAddr != oldAddr);
+ // The check is important to avoid chunkChanged to be corrupted.
+ // This code change is to fix the problem that one chunk is used by multiple interfaces.
+ if(!chunkChanged)
+ {
+ chunkChanged = (newAddr != oldAddr);
+ }
aHwChunks[chunkInd] = chunk;
}
chunkInd++;
--- a/kernel/eka/drivers/usbcc/ps_usbc.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/usbcc/ps_usbc.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -180,11 +180,13 @@
}
DeActivateHardwareController(); // turn off UDC altogether
iStackIsActive = EFalse;
+ // Notify registered clients on the user side about a USB device state
+ // change event and a transition to the "Undefined" state.
+ // Note: the state should be changed to "Undefined" before calling RunClientCallbacks(),
+ // otherwise the "Undefined" state will probably be lost.
+ NextDeviceState(EUsbcDeviceStateUndefined);
// Complete all pending requests, returning KErrDisconnected
RunClientCallbacks();
- // Notify registered clients on the user side about a USB device state
- // change event and a transition to the "Undefined" state.
- NextDeviceState(EUsbcDeviceStateUndefined);
}
--- a/kernel/eka/include/drivers/rm_debug_eventhandler.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/drivers/rm_debug_eventhandler.h Mon Mar 15 12:45:50 2010 +0200
@@ -27,14 +27,24 @@
TInt Start();
TInt Stop();
+ inline void DRM_DebugEventHandler::LockDataAccess()
+ {
+ Kern::SemaphoreWait(*iProtectionLock);
+ }
+
+ inline void DRM_DebugEventHandler::ReleaseDataAccess()
+ {
+ Kern::SemaphoreSignal(*iProtectionLock);
+ }
+
private:
static TUint EventHandler(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis);
TUint HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2);
TBool HandleSpecificEvent(TKernelEvent aType, TAny* a1, TAny* a2);
private:
- /** Lock serialising calls to event handler */
- DSemaphore* iLock;
+ /** Used to serialise access data structures */
+ DSemaphore* iProtectionLock;
TBool iTracking;
--- a/kernel/eka/include/e32ver.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/e32ver.h Mon Mar 15 12:45:50 2010 +0200
@@ -28,7 +28,7 @@
const TInt KE32MajorVersionNumber=2;
const TInt KE32MinorVersionNumber=0;
-const TInt KE32BuildVersionNumber=2083;
+const TInt KE32BuildVersionNumber=2091;
const TInt KMachineConfigurationMajorVersionNumber=1;
const TInt KMachineConfigurationMinorVersionNumber=0;
--- a/kernel/eka/include/nkern/nk_priv.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/nkern/nk_priv.h Mon Mar 15 12:45:50 2010 +0200
@@ -541,10 +541,12 @@
#define MASK_NOT_IDFC 0x800
#define MASK_NOT_THREAD 0x1000
#define MASK_NO_CRITICAL_IF_USER 0x2000
+#define MASK_ALWAYS_FAIL 0x4000
+#define MASK_NO_RESCHED 0x8000
+#define MASK_NO_KILL_OR_SUSPEND 0x10000
+
#define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC )
#define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL )
-#define MASK_ALWAYS_FAIL 0x4000
-#define MASK_NO_RESCHED 0x8000
#if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
#define CHECK_PRECONDITIONS(mask,function)
--- a/kernel/eka/include/nkernsmp/nk_priv.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/nkernsmp/nk_priv.h Mon Mar 15 12:45:50 2010 +0200
@@ -810,10 +810,12 @@
#define MASK_NOT_IDFC 0x800
#define MASK_NOT_THREAD 0x1000
#define MASK_NO_CRITICAL_IF_USER 0x2000
+#define MASK_ALWAYS_FAIL 0x4000
+#define MASK_NO_RESCHED 0x8000
+#define MASK_NO_KILL_OR_SUSPEND 0x10000
+
#define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC )
#define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL )
-#define MASK_ALWAYS_FAIL 0x4000
-#define MASK_NO_RESCHED 0x8000
#if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
#define CHECK_PRECONDITIONS(mask,function)
--- a/kernel/eka/kernel/server.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/kernel/server.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1009,7 +1009,7 @@
*/
EXPORT_C void DBase::AsyncDelete()
{
- CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC | MASK_CRITICAL, "DObject::AsyncDelete");
+ CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC, "DObject::AsyncDelete");
__KTRACE_OPT(KSERVER,Kern::Printf("DBase::AsyncDelete() %08x",this));
DBase* oldHead = K::AsyncDeleteHead;
@@ -1039,22 +1039,14 @@
// Asynchronously free a kernel heap cell (must be >=4 bytes in length)
//
{
- CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC | MASK_CRITICAL, "Kern::AsyncFree");
+ CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC, "Kern::AsyncFree");
__KTRACE_OPT(KSERVER,Kern::Printf("Kern::AsyncFree(%08x)",aPtr));
- DThread* pT=TheCurrentThread;
-
- // if we are already running in the kernel server, just free the cell now
- if (pT==K::TheKernelThread)
- Kern::Free(aPtr);
- else
- {
- TAny* oldHead = K::AsyncFreeHead;
- do {
- *(TAny**)aPtr = oldHead; // use first word of cell as link field
- } while (!__e32_atomic_cas_rel_ptr(&K::AsyncFreeHead, &oldHead, aPtr));
- if (!oldHead)
- K::AsyncFreeDfc.Enque();
- }
+ TAny* oldHead = K::AsyncFreeHead;
+ do {
+ *(TAny**)aPtr = oldHead; // use first word of cell as link field
+ } while (!__e32_atomic_cas_rel_ptr(&K::AsyncFreeHead, &oldHead, aPtr));
+ if (!oldHead)
+ K::AsyncFreeDfc.Enque();
}
--- a/kernel/eka/kernel/sutils.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/kernel/sutils.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -2967,12 +2967,17 @@
else if (!nt || nt->iCsCount==0)
m &= ~MASK_NO_CRITICAL;
}
- if (m & MASK_CRITICAL)
+ if (m & (MASK_CRITICAL|MASK_NO_KILL_OR_SUSPEND))
{
if (t && (t->iThreadType!=EThreadUser || nt->iCsCount>0))
- m &= ~MASK_CRITICAL;
+ m &= ~(MASK_CRITICAL|MASK_NO_KILL_OR_SUSPEND);
else if (!nt || nt->iCsCount>0)
- m &= ~MASK_CRITICAL;
+ m &= ~(MASK_CRITICAL|MASK_NO_KILL_OR_SUSPEND);
+ }
+ if (m & MASK_NO_KILL_OR_SUSPEND)
+ {
+ if (!nt || NKern::KernelLocked() || NKern::HeldFastMutex())
+ m &= ~MASK_NO_KILL_OR_SUSPEND;
}
if (m & MASK_KERNEL_LOCKED)
{
@@ -3074,6 +3079,8 @@
Kern::Printf("Assertion failed");
if (m & MASK_NO_RESCHED)
Kern::Printf("Assertion failed: Don't call from thread with kernel unlocked");
+ if (m & MASK_NO_KILL_OR_SUSPEND)
+ Kern::Printf("Assertion failed: Must not be suspended or killed here");
#ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__
if (aFunction)
--- a/kernel/eka/memmodel/emul/win32/mprocess.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/memmodel/emul/win32/mprocess.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -191,14 +191,18 @@
TInt count=0;
TInt err = KErrNone;
- data.iDataCopy = Kern::Alloc(seg->iRealDataSize);
- data.iBssCopy = Kern::Alloc(seg->iRealBssSize);
+
+ // Scheduling must be disabled while we are allocating memory from Windows' heap
+ NKern::Lock();
+ data.iDataCopy = GlobalAlloc(GMEM_FIXED, seg->iRealDataSize);
+ data.iBssCopy = GlobalAlloc(GMEM_FIXED, seg->iRealBssSize);
+ NKern::Unlock();
if (!data.iDataCopy || !data.iBssCopy)
{
err = KErrNoMemory;
goto failed;
}
-
+
memcpy(data.iDataCopy, seg->iDataCopy, seg->iRealDataSize); // start with init data
memclr(data.iBssCopy, seg->iRealBssSize); // initialized to zeros
@@ -215,8 +219,11 @@
return KErrNone;
failed:
- Kern::Free(data.iDataCopy);
- Kern::Free(data.iBssCopy);
+ // Scheduling must be disabled while we are freeing memory from Windows' heap
+ NKern::Lock();
+ GlobalFree(data.iDataCopy);
+ GlobalFree(data.iBssCopy);
+ NKern::Unlock();
return err;
}
@@ -245,9 +252,13 @@
if (ix < 0)
return;
-
- Kern::Free(data.iDataCopy);
- Kern::Free(data.iBssCopy);
+
+ // Scheduling must be disabled while we are freeing memory from Windows' heap
+ NKern::Lock();
+ GlobalFree(data.iDataCopy);
+ GlobalFree(data.iBssCopy);
+ NKern::Unlock();
+
__KTRACE_OPT(KDLL,Kern::Printf("Process %O UnmapCodeSeg(%C)", this, aSeg));
}
@@ -261,10 +272,10 @@
NKern::Lock();
if (data.iCodeSeg->iLiveProcess == this)
data.iCodeSeg->iLiveProcess = NULL;
+ iDllData.Remove(ii);
+ GlobalFree(data.iDataCopy);
+ GlobalFree(data.iBssCopy);
NKern::Unlock();
- iDllData.Remove(ii);
- Kern::Free(data.iDataCopy);
- Kern::Free(data.iBssCopy);
}
}
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -204,17 +204,18 @@
void DReferenceCountedObject::Open()
{
- __ASSERT_CRITICAL
- TBool ok = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
- __NK_ASSERT_ALWAYS(ok);
+ CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND, "DReferenceCountedObject::Open");
+ TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
+ if (orig <= 0)
+ __crash();
}
TBool DReferenceCountedObject::TryOpen()
{
- __ASSERT_CRITICAL
- TBool ok = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
- return ok;
+ CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND, "DReferenceCountedObject::Open");
+ TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
+ return (orig>0);
}
@@ -245,20 +246,23 @@
void DReferenceCountedObject::Close()
{
- __ASSERT_CRITICAL
__NK_ASSERT_DEBUG(CheckCloseIsSafe());
- __NK_ASSERT_DEBUG(iReferenceCount>0);
- if (__e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0) == 1)
+ TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0);
+ if (orig == 1)
delete this;
+ else if (orig <= 0)
+ __crash();
}
void DReferenceCountedObject::AsyncClose()
{
- __ASSERT_CRITICAL
- __NK_ASSERT_DEBUG(iReferenceCount>0);
- if (__e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0) == 1)
+ CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND, "DReferenceCountedObject::AsyncClose");
+ TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0);
+ if (orig == 1)
AsyncDelete();
+ else if (orig <= 0)
+ __crash();
}
--- a/kernel/eka/nkern/win32/ncsched.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/nkern/win32/ncsched.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -835,6 +835,61 @@
#include <winnt.h>
+// Uncomment the following line to turn on tracing when we examine the call stack
+// #define DUMP_STACK_BACKTRACE
+
+#ifdef DUMP_STACK_BACKTRACE
+
+#include <psapi.h>
+
+typedef BOOL (WINAPI GMIFunc)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb);
+typedef BOOL (WINAPI EPMFunc)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
+typedef DWORD (WINAPI GMBNFunc)(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize);
+
+void PrintAllModuleInfo()
+ {
+ HMODULE psapiLibrary = LoadLibraryA("psapi.dll");
+ __NK_ASSERT_ALWAYS(psapiLibrary != NULL);
+
+ EPMFunc* epmFunc = (EPMFunc*)GetProcAddress(psapiLibrary, "EnumProcessModules");
+ __NK_ASSERT_ALWAYS(epmFunc != NULL);
+
+ GMIFunc* gmiFunc = (GMIFunc*)GetProcAddress(psapiLibrary, "GetModuleInformation");
+ __NK_ASSERT_ALWAYS(gmiFunc != NULL);
+
+ GMBNFunc* gmbnFunc = (GMBNFunc*)GetProcAddress(psapiLibrary, "GetModuleBaseNameA");
+ __NK_ASSERT_ALWAYS(gmbnFunc != NULL);
+
+ const TInt maxModules = 256;
+ HMODULE modules[maxModules];
+
+ DWORD spaceNeeded;
+ BOOL r = epmFunc(GetCurrentProcess(), modules, sizeof(HMODULE) * maxModules, &spaceNeeded);
+ __NK_ASSERT_ALWAYS(r);
+ __NK_ASSERT_ALWAYS(spaceNeeded <= sizeof(HMODULE) * maxModules);
+
+ for (TUint i = 0 ; i < spaceNeeded / sizeof(HMODULE) ; ++i)
+ {
+ HMODULE library = modules[i];
+
+ const TUint maxNameLen = 64;
+ char name[maxNameLen];
+ WORD len = gmbnFunc(GetCurrentProcess(), library, name, sizeof(name));
+ __NK_ASSERT_ALWAYS(len > 0 && len < maxNameLen);
+
+ MODULEINFO info;
+ r = gmiFunc(GetCurrentProcess(), library, &info, sizeof(info));
+ __NK_ASSERT_ALWAYS(r);
+
+ DEBUGPRINT("Module %s found at %08x to %08x", name, (TUint)info.lpBaseOfDll, (TUint)info.lpBaseOfDll + info.SizeOfImage);
+ }
+
+ r = FreeLibrary(psapiLibrary);
+ __NK_ASSERT_ALWAYS(r);
+ }
+
+#endif
+
const TInt KWin32NonPreemptibleFunctionCount = 2;
struct TWin32FunctionInfo
@@ -845,14 +900,37 @@
static TWin32FunctionInfo Win32NonPreemptibleFunctions[KWin32NonPreemptibleFunctionCount];
-TWin32FunctionInfo Win32FindExportedFunction(const char* aModuleName, const char* aFunctionName)
+HMODULE GetFirstLoadedModuleHandleA(const char* aModuleName1, const char* aModuleName2)
+ {
+ HMODULE result = GetModuleHandleA(aModuleName1);
+ return result ? result : GetModuleHandleA(aModuleName2);
+ }
+
+TWin32FunctionInfo Win32FindExportedFunction(const char* aFunctionName, ...)
{
- HMODULE library = GetModuleHandleA(aModuleName);
+ const char *libname;
+ HMODULE library = NULL;
+
+ va_list arg;
+ va_start(arg, aFunctionName);
+
+ // Loop through arguments until we find a library we can get a handle to. List of library names
+ // is NULL-terminated.
+ while ((libname = va_arg(arg, const char *)) != NULL)
+ {
+ library = GetModuleHandleA(libname);
+ if (library != NULL)
+ break;
+ }
+
+ va_end(arg);
+
+ // Make sure we did get a valid library
__NK_ASSERT_ALWAYS(library != NULL);
-
+
// Find the start address of the function
TUint start = (TUint)GetProcAddress(library, aFunctionName);
- __NK_ASSERT_ALWAYS(start);
+ __NK_ASSERT_ALWAYS(start != 0);
// Now have to check all other exports to find the end of the function
TUint end = 0xffffffff;
@@ -867,15 +945,26 @@
++i;
}
__NK_ASSERT_ALWAYS(end != 0xffffffff);
-
+
TWin32FunctionInfo result = { start, end - start };
+
+#ifdef DUMP_STACK_BACKTRACE
+ DEBUGPRINT("Function %s found at %08x to %08x", aFunctionName, start, end);
+#endif
+
return result;
}
void Win32FindNonPreemptibleFunctions()
{
- Win32NonPreemptibleFunctions[0] = Win32FindExportedFunction("kernel32.dll", "RaiseException");
- Win32NonPreemptibleFunctions[1] = Win32FindExportedFunction("ntdll.dll", "KiUserExceptionDispatcher");
+#ifdef DUMP_STACK_BACKTRACE
+ PrintAllModuleInfo();
+#endif
+
+ TUint i = 0;
+ Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("RaiseException", "kernelbase.dll", "kernel32.dll", NULL);
+ Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("KiUserExceptionDispatcher", "ntdll.dll", NULL);
+ __NK_ASSERT_ALWAYS(i == KWin32NonPreemptibleFunctionCount);
}
TBool Win32IsThreadInNonPreemptibleFunction(HANDLE aWinThread, TLinAddr aStackTop)
@@ -892,9 +981,17 @@
TUint ebp = c.Ebp;
TUint lastEbp = c.Esp;
+ #ifdef DUMP_STACK_BACKTRACE
+ DEBUGPRINT("Stack backtrace for thread %x", aWinThread);
+ #endif
+
// Walk the call stack
for (TInt i = 0 ; i < KMaxSearchDepth ; ++i)
{
+ #ifdef DUMP_STACK_BACKTRACE
+ DEBUGPRINT(" %08x", eip);
+ #endif
+
for (TInt j = 0 ; j < KWin32NonPreemptibleFunctionCount ; ++j)
{
const TWin32FunctionInfo& info = Win32NonPreemptibleFunctions[j];
--- a/kernel/eka/release.txt Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/release.txt Mon Mar 15 12:45:50 2010 +0200
@@ -1,3 +1,96 @@
+Version 2.00.2091
+=================
+(Made by vfebvre 25/02/2010)
+
+1. gcochran
+ 1. DEF144355 t_context locks up on Vasco/HW79
+
+2. davegord
+ 1. DEF144641 Data import/export across DLL boundaries doesn't work in all cases
+ Implements REQ417-62614 "Data exports across DLL boundaries"
+
+
+Version 2.00.2090
+=================
+(Made by vfebvre 24/02/2010)
+
+1. jcoppear
+ 1. PDEF144517: Emulator crashes when run under Carbide debugger on Windows 7
+
+2. hengrant
+ 1. DEF144604 Incorrect trace metadata included in medsd.mmp
+
+
+Version 2.00.2089
+=================
+(Made by vfebvre 23/02/2010)
+
+1. vfebvre
+ 1. DEF142659 T_SHBUF failures on X86GCC/FMM (t_shbuf:2835)
+
+
+Version 2.00.2088
+=================
+(Made by vfebvre 22/02/2010)
+
+1. kingzhan
+ 1. DEF144531 for submission: TSW defect TSW TRLM-82BCNG
+ TSW TRLM-82BCNG: t_usb_device test fails
+
+
+2. mipetzol
+ 1. DEF144549: Rapu Base Port DMA tests failing
+ The DMA channel DFC now takes into account that the channel might get
+ closed by the client in the transfer completion callback.
+
+3. martai
+ 1. DEF144546: DBase Reference counting contains incorrect debug assertions
+
+
+Version 2.00.2087
+=================
+(Made by vfebvre 22/02/2010)
+
+1. vfebvre
+ 1. DEF144532 [System Build]: Build failed for TB92SF_1052 due to missing .mrp change
+
+
+Version 2.00.2086
+=================
+(Made by vfebvre 18/02/2010)
+
+1. jimhofe
+ 1. MINOR_CHANGE: Removing obsolete txt file
+
+
+Version 2.00.2085
+=================
+(Made by vfebvre 15/02/2010)
+
+1. ferporta
+ 1. DEF142026 Core Dump Server not getting events after attaching to more than one executable
+ 2. PDEF143992 E32TEST T_RMDEBUG2_OEM fails on Navi-Engine with WDP enabled
+ 3. DEF143480 t_rmdebug2_oem, t_rmdebug2 test fails on production hw79/vasco with debug server
+
+2. paconway
+ 1. DEF144234 SD mounting issue due to postponed door-open media change
+
+
+Version 2.00.2084
+=================
+(Made by vfebvre 11/02/2010)
+
+1. kingzhan
+ 1. DEF144402 - for base submission: fix defect YXIO-824BQL RUsb::DeviceStateNotification doesn'
+ TSW YXIO-824BQL:RUsb::DeviceStateNotification doesn't notify any device status
+ change after failing to TryStart USB stack
+
+2. coliward
+ 1. DEF144164: WSD data is allocated incorrectly on the kernel heap
+ WSD was being allocated on the kernel heap, which was causing large Qt
+ programs to fail to start up, given that the kernel heap is limited to 16 MB.
+
+
Version 2.00.2083
=================
(Made by vfebvre 10/02/2010)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bmarm/t_wsd_dl1.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ ExportedData @ 1 NONAME ; TInt32 ExportedData
+ CheckExportedDataAddress__FPv @ 2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bmarm/t_wsd_dl2.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ GetAddressOfDataProxy__FRiRPvT1 @ 1 NONAME R3UNUSED ; GetAddressOfDataProxy(int &, void *&, void *&)
+ CheckWritableStaticData__Fv @ 2 NONAME ; CheckWritablStaticData(void)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bmarm/t_wsd_dl3.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+ GetAddressOfData__FRiRPvT1 @ 1 NONAME R3UNUSED ; GetAddressOfData(int &, void *&, void *&)
+ TestDataSize @ 2 NONAME ; (null)
+ WritableTestData @ 3 NONAME ; (null)
+ PointerToStaticData @ 4 NONAME ; (null)
+ PointerToWritableData @ 5 NONAME ; (null)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bwins/t_wsd_dl1.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ ?ExportedData@@3JA @ 1 NONAME ; TInt32 ExportedData
+ ?CheckExportedDataAddress@@YAHPAX@Z @2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bwins/t_wsd_dl2.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ ?GetAddressOfDataProxy@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfDataProxy(int &, void * &, void * &)
+ ?CheckWritableStaticData@@YAHXZ @ 2 NONAME ; void CheckWritablStaticData(void)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bwins/t_wsd_dl3.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+ ?GetAddressOfData@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfData(int &, void * &, void * &)
+ ?TestDataSize@@3JA @ 2 NONAME ; long TestDataSize
+ ?WritableTestData@@3PAPAXA @ 3 NONAME ; void * * WritableTestData
+ ?PointerToStaticData@@3PBQBXB @ 4 NONAME ; void const * * PointerToStaticData
+ ?PointerToWritableData@@3PAPAXA @ 5 NONAME ; void * * PointerToWritableData
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bx86/t_wsd_dl1.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ ?ExportedData@@3JA @ 1 NONAME ; TInt32 ExportedData
+ ?CheckExportedDataAddress@@YAHPAX@Z @2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bx86/t_wsd_dl2.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ ?GetAddressOfDataProxy@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfDataProxy(int &, void * &, void * &)
+ ?CheckWritableStaticData@@YAHXZ @ 2 NONAME ; void CheckWritablStaticData(void)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bx86/t_wsd_dl3.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+ ?GetAddressOfData@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfData(int &, void * &, void * &)
+ ?TestDataSize@@3JA @ 2 NONAME ; long TestDataSize
+ ?WritableTestData@@3PAPAXA @ 3 NONAME ; void * * WritableTestData
+ ?PointerToStaticData@@3PBQBXB @ 4 NONAME ; void const * * PointerToStaticData
+ ?PointerToWritableData@@3PAPAXA @ 5 NONAME ; void * * PointerToWritableData
+
--- a/kerneltest/e32test/debug/context.cia Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/debug/context.cia Mon Mar 15 12:45:50 2010 +0200
@@ -72,9 +72,9 @@
__NAKED__ TInt ThreadContextHwExc(TAny*)
{
asm("stmdb sp!, {r4-r11,lr} ");
- asm("mov r1, #0x80000000");
+ asm("mov r1, #0x00000000");
asm("bl SetRegs");
- asm("ldr r0,[r13, #1]"); // Cause alignment fault
+ asm("ldr r0,[r0]"); // Cause data abort with null access, SetRegs will have set r0=0
asm("ThreadContextHwExc_pc:");
asm("mov r0, #0 ");
asm("ldmia sp!, {r4-r11,pc} ");
--- a/kerneltest/e32test/dma/d_dma.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/dma/d_dma.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
@@ -185,6 +185,8 @@
TInt Execute(const TDesC8& aDes);
static void Dfc(DDmaRequest::TResult aResult, TAny* aArg);
TInt DoGetInfo(TAny* aInfo);
+ void FreeDmaRequests();
+ void FreeClientRequests();
private:
TUint32 iCookie;
TBufferMgr iBufMgr;
@@ -193,6 +195,7 @@
DDmaRequest* iRequests[KMaxRequests];
TClientRequest* iClientRequests[KMaxRequests];
DDmaTestChannel* iMap[KMaxRequests];
+ TBool iCloseInCb[KMaxRequests];
TUint32 iMemMemPslInfo;
DThread* iClient;
TDynamicDfcQue* iDfcQ;
@@ -277,6 +280,8 @@
}
if (! iRequests[i])
return KErrNoMemory;
+
+ iCloseInCb[i] = EFalse;
}
return KErrNone;
}
@@ -288,13 +293,10 @@
if (iChannel)
{
iChannel->CancelAll();
- TInt i;
- for (i=0; i<KMaxRequests; ++i)
- delete iRequests[i];
+ FreeDmaRequests();
iChannel->Close();
- for (i=0; i<KMaxRequests; ++i)
- Kern::DestroyClientRequest(iClientRequests[i]);
}
+ FreeClientRequests();
if (iDfcQ)
{
iDfcQ->Destroy();
@@ -302,6 +304,23 @@
iBufMgr.FreeAll();
}
+void DDmaTestChannel::FreeDmaRequests()
+ {
+ for (TInt i=0; i<KMaxRequests; ++i)
+ {
+ delete iRequests[i];
+ iRequests[i] = NULL;
+ }
+ }
+
+void DDmaTestChannel::FreeClientRequests()
+ {
+ for (TInt i=0; i<KMaxRequests; ++i)
+ {
+ Kern::DestroyClientRequest(iClientRequests[i]);
+ }
+ }
+
TInt DDmaTestChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
{
@@ -401,9 +420,23 @@
{
case 'Q':
{
- TInt arg = *p++ - '0';
- __ASSERT_DEBUG(0 <= arg && arg < KMaxRequests, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
- iRequests[arg]->Queue();
+ __ASSERT_DEBUG(p < pEnd, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
+ TInt nextChar = *p++;
+ TInt channel = -1;
+
+ if(nextChar == 'X')
+ {
+ // Channel should be closed in callback
+ __ASSERT_DEBUG(p < pEnd, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
+ channel = *p++ - '0';
+ iCloseInCb[channel] = ETrue;
+ }
+ else
+ {
+ channel = nextChar - '0';
+ }
+ __ASSERT_DEBUG(0 <= channel && channel < KMaxRequests, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
+ iRequests[channel]->Queue();
break;
}
case 'C':
@@ -424,6 +457,17 @@
TInt i = ppC - pC->iMap;
TClientRequest* req = pC->iClientRequests[i];
TInt r = (aResult==DDmaRequest::EOk) ? KErrNone : KErrGeneral;
+
+ if(pC->iCloseInCb[i])
+ {
+ pC->iCloseInCb[i] = EFalse;
+ __KTRACE_OPT(KDMA, Kern::Printf("Close channel in callback"));
+
+ pC->FreeDmaRequests();
+ pC->iChannel->Close();
+ pC->iChannel = NULL;
+ }
+
if (req->IsReady())
Kern::QueueRequestComplete(pC->iClient, req, r);
}
--- a/kerneltest/e32test/dma/t_dma.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/dma/t_dma.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
@@ -193,6 +193,30 @@
const TInt iTotalTransferSize;
};
+/**
+Test that it is possible to close a channel from a callback
+*/
+class CCloseInCb : public CTest
+ {
+public:
+ CCloseInCb()
+ : CTest(NULL, 1), iTransferSize(4 * KKilo)
+ {}
+
+ TInt virtual DoRunTest();
+
+ virtual void AnnounceTest(TDes& aDes)
+ {
+ aDes.AppendFormat(_L("CCloseInCb"));
+ CTest::AnnounceTest(aDes);
+ }
+
+ CTest* Clone() const
+ {return new CCloseInCb(*this);}
+private:
+ const TInt iTransferSize;
+
+ };
//
// Active object used to create a tester thread, log on to it and
@@ -346,6 +370,44 @@
return KErrNone;
}
+TInt CCloseInCb::DoRunTest()
+ {
+ TInt r = KErrNone;
+ RTest test(_L("CCloseInCb test"));
+
+ r = OpenChannel(1);
+ test_KErrNone(r);
+
+ const TInt KRequest = 0;
+ const TInt KSrcBuf = 0;
+ const TInt KDestBuf = 1;
+
+ const TInt size = Min(iTransferSize, Info.iMaxTransferSize);
+
+ r = iChannel.AllocBuffer(KSrcBuf, size);
+ test_KErrNone(r);
+ iChannel.FillBuffer(KSrcBuf, 'A');
+ r = iChannel.AllocBuffer(KDestBuf, size);
+ test_KErrNone(r);
+ iChannel.FillBuffer(KDestBuf, '\0');
+
+ TRequestStatus rs = KRequestPending;
+ r = iChannel.Fragment(KRequest, KSrcBuf, KDestBuf, size, &rs);
+ test_KErrNone(r);
+
+ // "X" will cause channel to be closed during callback
+ r = iChannel.Execute(_L8("QX0"));
+ test_KErrNone(r);
+
+ User::WaitForRequest(rs);
+ test_KErrNone(rs.Int());
+
+ test(iChannel.CheckBuffer(KDestBuf, 'A'));
+ iChannel.FreeAllBuffers();
+
+ test.Close();
+ return KErrNone;
+ }
// Called when thread completed.
void CTesterThread::RunL()
@@ -964,6 +1026,13 @@
test.Next(_L("Getting channel info"));
GetChannelInfo();
+ test.Next(_L("Test that channel can be closed from callback"));
+ test.Next(_L("sb"));
+ RunSbTest(maxchannel, new CCloseInCb() );
+ test.Next(_L("db"));
+ RunDbTest(maxchannel, new CCloseInCb() );
+ test.Next(_L("sg"));
+ RunSgTest(maxchannel, new CCloseInCb() );
// Size for the single transfer test
TInt totalTransferSize = 64 * KKilo;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/eabi/t_wsd_dl1.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ ExportedData @ 1 NONAME DATA 4 ; TInt32 ExportedData
+ _Z24CheckExportedDataAddressPv @ 2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/eabi/t_wsd_dl2.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+ _Z21GetAddressOfDataProxyRiRPvS1_ @ 1 NONAME
+ _Z23CheckWritableStaticDatav @ 2 NONAME
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/eabi/t_wsd_dl3.def Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+ _Z16GetAddressOfDataRiRPvS1_ @ 1 NONAME
+ TestDataSize @ 2 NONAME DATA 4
+ WritableTestData @ 3 NONAME DATA 65536
+ PointerToStaticData @ 4 NONAME DATA 4
+ PointerToWritableData @ 5 NONAME DATA 4
+
--- a/kerneltest/e32test/group/bld.inf Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/group/bld.inf Mon Mar 15 12:45:50 2010 +0200
@@ -468,6 +468,29 @@
t_wsdextension support
#endif
+// t_wsd_* suffixes:
+// x => XIP; runs from ROM
+// c => code loads & runs in RAM
+// p => pagedcode
+// u => unpagedcode
+t_wsd_dl3_xp support
+t_wsd_dl3_xu support
+t_wsd_dl2_xp support
+t_wsd_dl2_xu support
+t_wsd_dl1_xp support
+t_wsd_dl1_xu support
+t_wsd_tst_xp
+t_wsd_tst_xu
+
+t_wsd_dl3_cp support
+t_wsd_dl3_cu support
+t_wsd_dl2_cp support
+t_wsd_dl2_cu support
+t_wsd_dl1_cp support
+t_wsd_dl1_cu support
+t_wsd_tst_cp
+t_wsd_tst_cu
+
// /e32test/ethernet
../ethernet/pump/etherpump manual
../ethernet/macset/macset manual
@@ -963,22 +986,41 @@
#endif
#if defined(MARM_ARMV5) || defined(MARM_ARMV4)
-t_trkdummyapp
+../rm_debug/group/t_trkdummyapp
#endif
#if defined(MARM_ARMV5)
-t_rmdebug_dll support
-t_rmdebug_security0 support
-t_rmdebug_security1 support
-t_rmdebug_security2 support
-t_rmdebug_security3 support
-t_rmdebug_app support
-t_rmdebug2
-t_rmdebug2_oem
-t_rmdebug2_oemtoken support
-t_rmdebug2_oem2
-t_rmdebug2_oemtoken2 support
-t_crashmonitor_lib
+../rm_debug/group/t_rmdebug_dll support
+../rm_debug/group/t_rmdebug_security0 support
+../rm_debug/group/t_rmdebug_security1 support
+../rm_debug/group/t_rmdebug_security2 support
+../rm_debug/group/t_rmdebug_security3 support
+../rm_debug/group/t_rmdebug_app support
+../rm_debug/group/t_rmdebug2
+../rm_debug/group/t_rmdebug2_oem
+../rm_debug/group/t_rmdebug2_oemtoken support
+../rm_debug/group/t_rmdebug2_oem2
+../rm_debug/group/t_rmdebug2_oemtoken2 support
+../rm_debug/group/t_crashmonitor_lib
+
+../rm_debug/group/t_rmdebug_app1 support
+../rm_debug/group/t_rmdebug_app2 support
+../rm_debug/group/t_rmdebug_app3 support
+../rm_debug/group/t_rmdebug_app4 support
+../rm_debug/group/t_rmdebug_app5 support
+../rm_debug/group/t_rmdebug_app6 support
+../rm_debug/group/t_rmdebug_app7 support
+../rm_debug/group/t_rmdebug_app8 support
+../rm_debug/group/t_rmdebug_app9 support
+../rm_debug/group/t_rmdebug_app10 support
+
+../rm_debug/group/t_rmdebug_target_launcher support
+../rm_debug/group/t_rmdebug_multi_target
+
+../rm_debug/group/t_rmdebug_multi_agent support
+../rm_debug/group/t_multi_agent_launcher
+
+
#endif
t_stacksize
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1.mmh Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl1.mmh
+
+targettype dll
+sourcepath ../mmu
+source t_wsd_dl1.cpp
+deffile t_wsd_dl1.def
+nostrictdef
+capability all
+vendorid 0x70000001
+library euser.lib
+
+macro T_WSD_DL1
+epocallowdlldata
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_cp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl1_cp.mmp
+//
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET +
+PAGEDCODE
+target t_wsd_dl1_cp.dll
+#include "t_wsd_dl1.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_cu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl1_cu.mmp
+//
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET +
+UNPAGEDCODE
+target t_wsd_dl1_cu.dll
+#include "t_wsd_dl1.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_xp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl1_xp.mmp
+//
+// This binary goes in rom and is paged
+
+ROMTARGET +
+PAGEDCODE
+target t_wsd_dl1_xp.dll
+#include "t_wsd_dl1.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_xu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl1_xu.mmp
+//
+// This binary goes in rom and is unpaged
+
+ROMTARGET +
+UNPAGEDCODE
+target t_wsd_dl1_xu.dll
+#include "t_wsd_dl1.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2.mmh Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl2.mmh
+
+targettype dll
+sourcepath ../mmu
+source t_wsd_dl2.cpp
+deffile t_wsd_dl2.def
+nostrictdef
+capability all
+vendorid 0x70000001
+library euser.lib
+
+macro T_WSD_DL2
+// epocallowdlldata
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_cp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl2_cp.mmp
+//
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET +
+PAGEDCODE
+target t_wsd_dl2_cp.dll
+library t_wsd_dl3_cp.lib
+#include "t_wsd_dl2.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_cu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl2_cu.mmp
+//
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET +
+UNPAGEDCODE
+target t_wsd_dl2_cu.dll
+library t_wsd_dl3_cu.lib
+#include "t_wsd_dl2.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_xp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl2_xp.mmp
+//
+// This binary goes in rom and is paged
+
+ROMTARGET +
+PAGEDCODE
+target t_wsd_dl2_xp.dll
+library t_wsd_dl3_xp.lib
+#include "t_wsd_dl2.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_xu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl2_xu.mmp
+//
+// This binary goes in rom and is unpaged
+
+ROMTARGET +
+UNPAGEDCODE
+target t_wsd_dl2_xu.dll
+library t_wsd_dl3_xu.lib
+#include "t_wsd_dl2.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3.mmh Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl3.mmh
+
+targettype dll
+sourcepath ../mmu
+source t_wsd_dl3.cpp
+deffile t_wsd_dl3.def
+nostrictdef
+capability all
+vendorid 0x70000001
+library euser.lib
+
+macro T_WSD_DL3
+epocallowdlldata
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_cp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl3_cp.mmp
+//
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET +
+PAGEDCODE
+target t_wsd_dl3_cp.dll
+#include "t_wsd_dl3.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_cu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl3_cu.mmp
+//
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET +
+UNPAGEDCODE
+target t_wsd_dl3_cu.dll
+#include "t_wsd_dl3.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_xp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl3_xp.mmp
+//
+// This binary goes in rom and is paged
+
+ROMTARGET +
+PAGEDCODE
+target t_wsd_dl3_xp.dll
+#include "t_wsd_dl3.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_xu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_dl3_xu.mmp
+//
+// This binary goes in rom and is unpaged
+
+ROMTARGET +
+UNPAGEDCODE
+target t_wsd_dl3_xu.dll
+#include "t_wsd_dl3.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst.mmh Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,26 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_tst.mmh
+
+targettype exe
+sourcepath ../mmu
+source t_wsd_tst.cpp
+library euser.lib
+library efsrv.lib
+capability all
+vendorid 0x70000001
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_cp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_tst_cp.mmp
+//
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET +
+PAGEDCODE
+target t_wsd_tst_cp.exe
+library t_wsd_dl1_cp.lib
+#include "t_wsd_tst.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_cu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_tst_cu.mmp
+//
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET +
+UNPAGEDCODE
+target t_wsd_tst_cu.exe
+library t_wsd_dl1_cu.lib
+#include "t_wsd_tst.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_xp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_tst_xp.mmp
+//
+// This binary goes in rom and is paged
+
+ROMTARGET +
+PAGEDCODE
+target t_wsd_tst_xp.exe
+library t_wsd_dl1_xp.lib
+#include "t_wsd_tst.mmh"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_xu.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test/group/t_wsd_tst_xu.mmp
+//
+// This binary goes in rom and is unpaged
+
+ROMTARGET +
+UNPAGEDCODE
+target t_wsd_tst_xu.exe
+library t_wsd_dl1_xu.lib
+#include "t_wsd_tst.mmh"
--- a/kerneltest/e32test/mmu/t_shbuf.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/mmu/t_shbuf.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -2819,6 +2819,11 @@
test_KErrNone(r);
r = HAL::Get(HAL::EMemoryRAM, ram);
test_KErrNone(r);
+ test_Compare(ram, >, 0);
+ // Total system RAM returned by EMemoryRAM should always be < 2GB anyway
+ TUint uram = (TUint) ram;
+ test.Printf(_L("Total system RAM: %u bytes\n"), uram);
+ test.Printf(_L("Page size: %d bytes\n"), pagesize);
RShPool pool;
{ TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
@@ -2835,9 +2840,7 @@
{ TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 4096, 10); inf.SetExclusive(); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNotSupported, r); pool.Close(); }
{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 4096, 10, 12); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNone, r); pool.Close(); }
{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 4096, 10, 12); inf.SetExclusive(); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); pool.Close(); }
-#ifndef __WINS__
- { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 128 * pagesize, (ram / (128 * pagesize)) + 1); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrNoMemory, r); }
-#endif
+ { TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 128 * pagesize, (uram / (128 * pagesize)) + 1); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrNoMemory, r); }
{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 0, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 100, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 0, 100, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_dl1.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\mmu\t_wsd_dl1.cpp
+//
+
+// MMH file will define T_WSD_DL1
+#include "t_wsd_tst.h"
+
+// Exported writable static data
+EXPORT_D TInt32 ExportedData = 0x717a1ee7;
+
+// Exported Function
+EXPORT_C TInt CheckExportedDataAddress(void* aDataAddr)
+ {
+ RDebug::Printf("CheckExportedDataAddress: ExportedData@%08x, aDataAddr %08x",
+ &ExportedData, aDataAddr);
+ return aDataAddr == (void*)&ExportedData ? KErrNone : KErrGeneral;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_dl2.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,65 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\mmu\t_wsd_dl2.cpp
+//
+
+// MMH file will define T_WSD_DL2
+#include "t_wsd_tst.h"
+
+// Ordinal 1
+EXPORT_C void** GetAddressOfDataProxy(TInt& aSize, void*& aCodeAddr, void*& aDataAddr)
+ {
+ return GetAddressOfData(aSize, aCodeAddr, aDataAddr);
+ }
+
+// Ordinal 2
+EXPORT_C TInt CheckWritableStaticData(void)
+ {
+ RDebug::Printf("CheckWritableStaticData: start");
+ TInt err = KErrNone;
+ TInt size;
+ void* codeAddr;
+ void* dataAddr;
+ const void*** dataPtrPtr = (const void***)GetAddressOfData(size, codeAddr, dataAddr);
+
+ RDebug::Printf("CheckWritableStaticData: size %d, codeAddr %08x, dataAddr %08x",
+ size, codeAddr, dataAddr);
+ RDebug::Printf("CheckWritableStaticData: dataPtrPtr %08x, PointerToStaticData is at %08x",
+ dataPtrPtr, &PointerToStaticData);
+
+ if (dataPtrPtr != (const void***)&PointerToStaticData)
+ err = KErrGeneral;
+ const void** p1 = *dataPtrPtr;
+ RDebug::Printf("CheckWritableStaticData: *dataPtrPtr %08x", p1);
+ const void* const* p2 = PointerToStaticData;
+ RDebug::Printf("CheckWritableStaticData: PointerToStaticData %08x", p2);
+ if (p1 != (const void**)p2)
+ err = KErrGeneral;
+ if (p1 != (const void**)dataAddr)
+ err = KErrGeneral;
+
+ RDebug::Printf("CheckWritableStaticData: TestDataSize is at %08x", &TestDataSize);
+ TInt sz = TestDataSize;
+ RDebug::Printf("CheckWritableStaticData: TestDataSize is %d", sz);
+ if (sz != size)
+ err = KErrGeneral;
+
+ void** p3 = WritableTestData;
+ void** p4 = PointerToWritableData;
+ if (p3 != p4)
+ err = KErrGeneral;
+
+ return err;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_dl3.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\mmu\t_wsd_dl3.cpp
+//
+
+// MMH file will define T_WSD_DL3
+#include "t_wsd_tst.h"
+
+#define C ((void*)DummyFn)
+#define D ((void*)TestData)
+#define A4W C, D, C, D // 4 words
+#define A16W A4W, A4W, A4W, A4W // 16 words
+#define A64W A16W, A16W, A16W, A16W // 64 words
+#define A256W A64W, A64W, A64W, A64W // 256 words
+#define A1KW A256W, A256W, A256W, A256W // 1Kwords
+#define A4KW A1KW, A1KW, A1KW, A1KW // 4Kwords
+
+// Non-exported dummy function whose address is put in the initialised
+// data, to check that it gets relocated correctly
+void DummyFn(void)
+ {
+ }
+
+// Non-exported const data, which should end up in the text segment
+// but doesn't on some platforms :(
+static const void* const TestData[] = { A4KW, A4KW }; // 8Kwords
+const TInt KSizeOfTestData = sizeof(TestData); // 32Kbytes
+
+// Exported Ordinals 2-5
+EXPORT_D TInt32 TestDataSize = KSizeOfTestData;
+EXPORT_D void* WritableTestData[] = { A4KW, A4KW };
+EXPORT_D const void* const* PointerToStaticData = TestData;
+EXPORT_D void** PointerToWritableData = WritableTestData;
+
+// Dummy function, just so that this DLL contains more than one page of
+// text even on platforms where the read-only data ends up in the data
+// rather than the text segment ...
+TUint AddEmUp()
+ {
+ const void* const* p = TestData;
+ TUint sum = 0;
+
+#define ADD1W { sum += (TUint)*p++; } // 1 word
+#define ADD4W { ADD1W; ADD1W; ADD1W; ADD1W; } // 4 words
+#define ADD16W { ADD4W; ADD4W; ADD4W; ADD4W; } // 16 words
+#define ADD64W { ADD16W; ADD16W; ADD16W; ADD16W; } // 64 words
+#define ADD256W { ADD64W; ADD64W; ADD64W; ADD64W; } // 256 words
+#define ADD1KW { ADD256W; ADD256W; ADD256W; ADD256W; } // 1K words
+
+ // The macro ADD1KW should expand to ~2K instructions i.e. ~8Kb of inline code
+ for (TUint i = 0; i < sizeof(TestData)/(1024*sizeof(void*)); ++i)
+ ADD1KW;
+
+ // We've added up all 8Kwords (32kb) of the test data ...
+ return sum;
+ }
+
+// Exported Ordinal 1
+EXPORT_C void** GetAddressOfData(TInt& aSize, void*& aCodeAddr, void*& aDataAddr)
+ {
+ TAny* p = User::Alloc(KSizeOfTestData);
+ aSize = AddEmUp();
+ aSize = KSizeOfTestData;
+ aCodeAddr = C;
+ aDataAddr = D;
+ User::Free(p);
+ return (void**)&PointerToStaticData;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_tst.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,466 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\mmu\t_wsd_tst.cpp
+// Test exporting and importing writable static data in DLLs.
+// This test relies on three dlls:
+// - t_wsd_dl1_[cx][pu] Which is statically linked, and exports both code & data
+// - t_wsd_dl2_[cx][pu] Which is dyanamically loaded, and imports code & writable static data from
+// - t_wsd_dl3_[cx][pu] Which exports code and writable static data
+// The [cx] suffix indicates code-in-RAM vs XIP (ROM), and [pu] indicate paged or unpaged code.
+//
+
+//! @SYMTestCaseID KBASE-T_CODEPAGING-0335
+//! @SYMTestType UT
+//! @SYMPREQ PREQ1110
+//! @SYMTestCaseDesc Demand Paging Code Paging tests.
+//! @SYMTestActions 001 Code paging tests
+//! @SYMTestExpectedResults All tests should pass.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <e32math.h>
+#include <f32file.h>
+#include <f32dbg.h>
+
+#include "mmudetect.h"
+#include "t_wsd_tst.h"
+
+// Global data /////////////////////////////////////////////////////////////////
+
+_LIT(KSearchPathTemplate, "%c:\\sys\\bin"); // drive letter
+_LIT(KLibraryName, "t_wsd_dl%d_%c%c"); // [23] [cx] [pu]
+
+TInt TheFailure = KErrNone;
+TChar CurrentDrive = 'Z';
+
+void SetCurrentDrive(TChar aDrive)
+ {
+ CurrentDrive = aDrive;
+ }
+
+class TPagingDriveInfo
+ {
+public:
+ TChar iDriveLetter;
+ TDriveInfo iDriveInfo;
+ };
+
+RArray<TPagingDriveInfo> SupportedDrives;
+
+// RTest stuff /////////////////////////////////////////////////////////////////
+
+RTest test(_L("T_WSD"));
+
+#define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); }
+#define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); }
+#define test_equal(e, a) { TInt _e = TInt(e); TInt _a = TInt(a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); }
+
+void HandleError(TInt aError, TInt aLine)
+ {
+ test.Printf(_L("Error %d\n"), aError);
+ test.operator()(EFalse, aLine);
+ }
+
+void HandleNull(TInt aLine)
+ {
+ test.Printf(_L("Null value\n"));
+ test.operator()(EFalse, aLine);
+ }
+
+void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine)
+ {
+ test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual);
+ test.operator()(EFalse, aLine);
+ }
+
+// Utility functions ///////////////////////////////////////////////////////////
+
+TPtrC16 GetMediaType(TInt aMediaType)
+ {
+ _LIT(KMediaNotPresent, "MediaNotPresent");
+ _LIT(KMediaUnknown, "MediaUnknown");
+ _LIT(KMediaFloppy, "MediaFloppy");
+ _LIT(KMediaHardDisk, "MediaHardDisk");
+ _LIT(KMediaCdRom, "MediaCdRom");
+ _LIT(KMediaRam, "MediaRam");
+ _LIT(KMediaFlash, "MediaFlash");
+ _LIT(KMediaRom, "MediaRom");
+ _LIT(KMediaRemote, "MediaRemote");
+ _LIT(KMediaNANDFlash, "MediaNANDFlash");
+ _LIT(KMediaUnKnown, "MediaUnKnown");
+
+ switch (aMediaType)
+ {
+ case EMediaNotPresent:
+ return KMediaNotPresent();
+ case EMediaUnknown:
+ return KMediaUnknown();
+ case EMediaFloppy:
+ return KMediaFloppy();
+ case EMediaHardDisk:
+ return KMediaHardDisk();
+ case EMediaCdRom:
+ return KMediaCdRom();
+ case EMediaRam:
+ return KMediaRam();
+ case EMediaFlash:
+ return KMediaFlash();
+ case EMediaRom:
+ return KMediaRom();
+ case EMediaRemote:
+ return KMediaRemote();
+ case EMediaNANDFlash:
+ return KMediaNANDFlash();
+ default:
+ return KMediaUnKnown();
+ }
+ }
+
+// Get the list of testable drives
+void GetSupportedDrives(TBool aVerbose = EFalse)
+ {
+ TUint32 memModelAttributes = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
+ TBool codePagingSupported = (memModelAttributes & EMemModelAttrCodePaging) != 0;
+ TUint32 pagingPolicy = E32Loader::PagingPolicy();
+ TBool pagingPolicyAllowsPaging = pagingPolicy != EKernelConfigCodePagingPolicyNoPaging;
+ test_Equal(codePagingSupported, pagingPolicyAllowsPaging);
+ if (codePagingSupported)
+ test.Printf(_L("Code paging is enabled.\n"));
+ else
+ test.Printf(_L("Code paging is NOT enabled.\n"));
+
+ if (aVerbose)
+ {
+ test.Printf(_L("Available drives:\n"));
+ test.Printf(_L(" Type Attr MedAttr Filesystem\n"));
+ }
+
+ RFs fs;
+ test_noError(fs.Connect());
+
+ TDriveList driveList;
+ TInt r = fs.DriveList(driveList);
+ test_noError(r);
+
+ TBool NandPageableMediaFound = EFalse;
+ for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
+ {
+ if (!driveList[drvNum])
+ continue; //-- skip unexisting drive
+
+ TDriveInfo driveInfo;
+ r = fs.Drive(driveInfo, drvNum);
+ test_noError(r);
+
+ TChar ch;
+ r = fs.DriveToChar(drvNum, ch);
+ test_noError(r);
+
+ TBuf<256> fileSystemName;
+ r = fs.FileSystemName(fileSystemName, drvNum);
+ test_noError(r);
+
+ // Decide which drives to exclude:
+ // Locked/nonwritable drives, except the Z: ROM drive
+ // Win32 drives on the emulator
+ // Remote/nonlocal, removable/noninternal, redirected, substed drives
+ // All others are included by default iff code paging is supported
+ // If not, only the Z: ROM/XIP drive is tested
+ _LIT(KWin32FS, "Win32");
+ TBool include = codePagingSupported;
+ if (driveInfo.iDriveAtt & KDriveAttRom)
+ include = (ch == 'Z');
+ else if (driveInfo.iMediaAtt & (KMediaAttWriteProtected|KMediaAttLocked))
+ include = EFalse;
+ else if (fileSystemName == KWin32FS())
+ include = EFalse;
+ else if (driveInfo.iDriveAtt & (KDriveAttRedirected|KDriveAttSubsted|KDriveAttRemovable|KDriveAttRemote))
+ include = EFalse;
+ else if ((KDriveAttInternal|KDriveAttLocal) & ~driveInfo.iDriveAtt)
+ include = EFalse;
+
+ if (include)
+ {
+ TPagingDriveInfo pagingDriveInfo;
+ pagingDriveInfo.iDriveLetter = ch;
+ pagingDriveInfo.iDriveInfo = driveInfo;
+ r = SupportedDrives.Append(pagingDriveInfo);
+ test_noError(r);
+ }
+
+ TBool pageable = EFalse;
+ if (driveInfo.iDriveAtt & KDriveAttPageable)
+ {
+ pageable = ETrue;
+ if (driveInfo.iType == EMediaNANDFlash)
+ NandPageableMediaFound = ETrue;
+ }
+
+ // If we've already found a pageable NAND drive, then assume the
+ // Z: drive is pageable too if it's got a composite file system
+ _LIT(KCompositeName,"Composite");
+ if (NandPageableMediaFound && fileSystemName == KCompositeName())
+ pageable = ETrue;
+
+ if (aVerbose)
+ {
+ TPtrC16 mediaType = GetMediaType(driveInfo.iType);
+ _LIT(KPageable, "pageable");
+ test.Printf(_L("%c %c: %16S %08x %08x %10S %S\n"),
+ include ? '*' : ' ', (TUint)ch, &mediaType,
+ driveInfo.iDriveAtt, driveInfo.iMediaAtt,
+ &fileSystemName, (pageable ? &KPageable : &KNullDesC));
+ }
+ }
+
+ fs.Close();
+ }
+
+const TDesC& LibrarySearchPath(TChar aDrive)
+ {
+ static TBuf<64> path;
+ path.Format(KSearchPathTemplate, (TUint)aDrive);
+ return path;
+ }
+
+const TDesC& LibraryName(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+ {
+ // this gives DLL#2 a different name on each drive so we can be sure we're loading the right one
+ static TBuf<64> name;
+ name.Format(KLibraryName, aLibNo, aRam ? 'c' : 'x', aPaged ? 'p' : 'u');
+ if (aLibNo == 2 && aDrive != 'Z')
+ name.AppendFormat(_L("_%c"), (TUint)aDrive);
+ return name;
+ }
+
+const TDesC& LibraryFilename(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+ {
+ static TBuf<64> filename;
+ filename = LibrarySearchPath(aDrive);
+ filename.AppendFormat(_L("\\%S.dll"), &LibraryName(aDrive, aLibNo, aRam, aPaged));
+ return filename;
+ }
+
+TInt LoadSpecificLibrary(RLibrary& aLibrary, TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+ {
+ const TDesC& path = LibrarySearchPath(aDrive);
+ const TDesC& name = LibraryName(aDrive, aLibNo, aRam, aPaged);
+ TInt err = aLibrary.Load(name, path);
+ TBuf<256> message;
+ message.Format(_L("Loading %S\\%S.dll returns %d\n"), &path, &name, err);
+ test.Printf(message);
+ return err;
+ }
+
+// Test functions //////////////////////////////////////////////////////////////
+
+void CopyDllToCurrentDrive(RFs& aFs, TBool aPaged, TInt aLibNo)
+ {
+ TBuf<64> source = LibraryFilename('Z', aLibNo, ETrue, aPaged);
+ TBuf<64> dest = LibraryFilename(CurrentDrive, aLibNo, ETrue, aPaged);
+ test.Printf(_L("Copying %S to %S\n"), &source, &dest);
+
+ TInt r = aFs.MkDirAll(dest);
+ test(r == KErrNone || r == KErrAlreadyExists);
+
+ TBuf<64> tempName(dest);
+ tempName.Append(_L(".tmp"));
+
+ RFile in, out, temp;
+ test_noError(in.Open(aFs, source, EFileRead));
+ test_noError(out.Replace(aFs, dest, EFileWrite));
+ test_noError(temp.Replace(aFs, tempName, EFileWrite));
+
+ const TInt KBufferSize = 3333;
+ TBuf8<KBufferSize> buffer;
+
+ test_noError(temp.Write(buffer));
+ test_noError(temp.Flush());
+
+ TInt size;
+ test_noError(in.Size(size));
+ TInt pos = 0;
+ while (pos < size)
+ {
+ test_noError(in.Read(buffer));
+ test_noError(out.Write(buffer));
+ test_noError(out.Flush());
+ test_noError(temp.Write(buffer));
+ test_noError(temp.Flush());
+ pos += buffer.Length();
+ }
+
+ out.SetAtt(KEntryAttNormal, KEntryAttReadOnly|
+ KEntryAttHidden|
+ KEntryAttSystem|
+ KEntryAttArchive|
+ KEntryAttXIP);
+
+ in.Close();
+ out.Close();
+ temp.Close();
+ }
+
+void CopyDllsToCurrentDrive()
+ {
+ RFs fs;
+ test_noError(fs.Connect());
+
+ CopyDllToCurrentDrive(fs, EFalse, 2); // Unpaged library 2
+ CopyDllToCurrentDrive(fs, EFalse, 3); // Unpaged library 3
+ CopyDllToCurrentDrive(fs, ETrue, 2); // Paged library 2
+ CopyDllToCurrentDrive(fs, ETrue, 3); // Paged library 3
+
+ fs.Close();
+ }
+
+void EraseDllsFromCurrentDrive()
+ {
+ RFs fs;
+ test_noError(fs.Connect());
+
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ test_notNull(cleanup);
+
+ CFileMan* fileMan = NULL;
+ TRAPD(r, fileMan = CFileMan::NewL(fs));
+ test_noError(r);
+
+ TBuf<64> libdir = LibrarySearchPath(CurrentDrive);
+ test.Printf(_L("Erasing %S\n"), &libdir);
+ fileMan->RmDir(libdir);
+
+ delete fileMan;
+ delete cleanup;
+ fs.Close();
+ }
+
+void CheckRelocatableData(RLibrary& library)
+ {
+ TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
+ test_notNull(func);
+
+ TInt size;
+ void* codeAddr;
+ void* dataAddr;
+ void*** dataPtrPtr = (void***)func(size, codeAddr, dataAddr);
+ void **dp = (void **)dataAddr;
+
+ for (TInt i = 0; i < size/4; i += 2)
+ {
+ test_equal(dp[i], codeAddr);
+ test_equal(dp[i+1], dataAddr);
+ }
+
+ test_equal(*dataPtrPtr, dp);
+ }
+
+void CheckWritableStaticData(RLibrary& library)
+ {
+ TInt (*func)(void) = (TInt (*)(void))library.Lookup(KCheckWritableStaticDataFunctionOrdinal);
+ RDebug::Printf("CheckWritableStaticData() is export %d at %08x", KCheckWritableStaticDataFunctionOrdinal, func);
+ test_notNull(func);
+ TInt err = func();
+ RDebug::Printf("CheckWritableStaticData() returned %d", err);
+ // test_noError(err);
+ if (TheFailure == KErrNone)
+ TheFailure = err;
+ }
+
+void RunPerDriveTests(TBool aPaged, TBool aRam)
+ {
+ TBuf<64> message = _L("Running ");
+ if (!aPaged)
+ message.Append(_L("un"));
+ message.AppendFormat(_L("paged R%cM tests on drive %c:"),
+ aRam ? 'A' : 'O', (TUint)CurrentDrive);
+ test.Next(message);
+
+ RFs fs;
+ test_noError(fs.Connect());
+ fs.SetDebugRegister(KFLDR);
+
+ // Explicitly loading dl2 will implicitly load dl3 as well
+ RLibrary dl2;
+ test_noError(LoadSpecificLibrary(dl2, CurrentDrive, 2, aRam, aPaged));
+ CheckRelocatableData(dl2);
+ CheckWritableStaticData(dl2);
+ dl2.Close();
+
+ fs.SetDebugRegister(0);
+ fs.Close();
+ }
+
+TInt E32Main()
+ {
+ test.Title();
+ test.Start(_L("WSD tests"));
+
+ // Check static linkage to dl1
+ test_noError(CheckExportedDataAddress(&ExportedData));
+
+ GetSupportedDrives(ETrue);
+ test(SupportedDrives.Count() > 0);
+
+ // Turn off evil lazy dll unloading
+ RLoader l;
+ test(l.Connect()==KErrNone);
+ test(l.CancelLazyDllUnload()==KErrNone);
+ l.Close();
+
+ // Make sure there aren't any DLLs left over from earlier tests
+ TInt i = SupportedDrives.Count();
+ while (--i >= 0)
+ {
+ SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+ if (CurrentDrive != 'Z')
+ EraseDllsFromCurrentDrive();
+ }
+
+ // We want to test all supported drives in order of increasing priority, so
+ // that the CurrentDrive is always the hghest priority of those tested so far.
+ // Therefore, if Z (XIP ROM, lowest priority) is a valid test drive, do it first
+ i = SupportedDrives.Count();
+ if (--i >= 0)
+ {
+ SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+ if (CurrentDrive == 'Z')
+ {
+ // ROM (XIP) tests can only be run from Z:
+ RunPerDriveTests(EFalse, EFalse); // Unpaged ROM
+ RunPerDriveTests(ETrue, EFalse); // Paged ROM
+ RunPerDriveTests(EFalse, ETrue); // Unpaged RAM
+ RunPerDriveTests(ETrue, ETrue); // Paged RAM
+ }
+ }
+
+ // Now run the RAM-based versions from each remaining drive in turn
+ for (i = 0; i < SupportedDrives.Count(); ++i)
+ {
+ SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+ if (CurrentDrive != 'Z')
+ {
+ CopyDllsToCurrentDrive();
+ RunPerDriveTests(EFalse, ETrue); // Unpaged RAM
+ RunPerDriveTests(ETrue, ETrue); // Paged RAM
+ }
+ }
+
+ test_noError(TheFailure);
+ test.End();
+ return 0;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_tst.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,74 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\mmu\t_wsd_tst.h
+//
+
+#include <e32std.h>
+#include <e32debug.h>
+
+#ifndef __T_WSD_TST_H__
+#define __T_WSD_TST_H__
+
+#if defined(__MARM_ARM4__)
+// ARM4: definition of IMPORT_D is wrong?
+#undef IMPORT_D
+#define IMPORT_D __declspec(dllimport)
+#endif // defined(__MARM_ARM4__)
+
+#if defined(__MARM_ARMV5__)
+// ARMV5: definition of IMPORT_D is wrong?
+#undef IMPORT_D
+#define IMPORT_D __declspec(dllimport)
+#endif // defined(__MARM_ARMV5__)
+
+#if defined(__MSVC6__)
+// MSVC6: definition of IMPORT_D is wrong?
+#undef IMPORT_D
+#define IMPORT_D __declspec(dllimport)
+#endif // defined(__MSVC6__)
+
+#if defined(__WINS__)
+// WINSCW: definition of IMPORT_D is wrong?
+#undef IMPORT_D
+#define IMPORT_D __declspec(dllimport)
+#endif // defined(__WINS__)
+
+// Exports of DLL1
+#ifdef T_WSD_DL1
+#else
+IMPORT_D TInt32 ExportedData;
+IMPORT_C TInt CheckExportedDataAddress(void *aDataAddr);
+#endif // T_WSD_DL1
+
+// Exports of DLL2
+#ifdef T_WSD_DL2
+#else
+typedef void** (*TGetAddressOfDataFunction)(TInt&, void*&, void*&);
+const TInt KGetAddressOfDataFunctionOrdinal = 1;
+IMPORT_C void** GetAddressOfDataProxy(TInt& aSize, void*& aCodeAddr, void*& aDataAddr);
+const TInt KCheckWritableStaticDataFunctionOrdinal = 2;
+IMPORT_C TInt CheckWritableStaticData(void);
+#endif // T_WSD_DL2
+
+// Exports of DLL3
+#ifdef T_WSD_DL3
+#else
+IMPORT_C void** GetAddressOfData(TInt& aSize, void*& aCodeAddr, void*& aDataAddr);
+IMPORT_D TInt32 TestDataSize;
+IMPORT_D void* WritableTestData[1 /* refer TestDataSize */];
+IMPORT_D const void* const* PointerToStaticData;
+IMPORT_D void** PointerToWritableData;
+#endif // T_WSD_DL3
+
+#endif // __T_WSD_TST_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of RKernelLowMemorySecuritySvrSession
+//
+//
+
+#include "r_kernel_low_memory_security_svr_session.h"
+
+void RKernelLowMemorySecuritySvrSession::FailAlloc(const TInt aCount)
+ {
+ __KHEAP_FAILNEXT(aCount);
+ }
+
+void RKernelLowMemorySecuritySvrSession::HeapReset()
+ {
+ __KHEAP_RESET;
+ }
+
+void RKernelLowMemorySecuritySvrSession::MarkHeap()
+ {
+ __KHEAP_MARK;
+ }
+
+void RKernelLowMemorySecuritySvrSession::MarkHeapEnd()
+ {
+ __KHEAP_MARKEND;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Version of security server session to enable testing of low memory conditions on kernel side
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include "r_low_memory_security_svr_session.h"
+
+class RKernelLowMemorySecuritySvrSession : public RLowMemorySecuritySvrSession
+ {
+protected:
+ void FailAlloc(const TInt aCount);
+ void HeapReset();
+ void MarkHeap();
+ void MarkHeapEnd();
+ };
+
+#endif //R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,86 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implementation of RLowMemorySecuritySvrSession
+//
+//
+
+#include "r_low_memory_security_svr_session.h"
+#include <e32debug.h>
+
+// test the effects of heap failure on global RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+ {
+ TInt failAt = 0;
+ TInt err = KErrNoMemory;
+ while(err == KErrNoMemory)
+ {
+ failAt++;
+ FailAlloc(failAt);
+ MarkHeap();
+ err = this->RSecuritySvrSession::GetList(aListId, aListData, aDataSize);
+ if(KErrNoMemory == err)
+ {
+ MarkHeapEnd();
+ }
+ HeapReset();
+ //RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(): failAt: %d, err: %d", failAt, err);
+ }
+ return err;
+ }
+
+// test the effects of heap failure on thread-specific RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const TThreadId aThreadId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+ {
+ TInt failAt = 0;
+ TInt err = KErrNoMemory;
+ while(err == KErrNoMemory)
+ {
+ failAt++;
+ FailAlloc(failAt);
+ MarkHeap();
+ err = this->RSecuritySvrSession::GetList(aThreadId, aListId, aListData, aDataSize);
+ if(KErrNoMemory == err)
+ {
+ MarkHeapEnd();
+ }
+ HeapReset();
+ //RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(TThreadId): failAt: %d, err: %d", failAt, err);
+ }
+ return err;
+ }
+
+// test the effects of heap failure on process-specific RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const TProcessId aProcessId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+ {
+ TInt failAt = 0;
+ TInt err = KErrNoMemory;
+ while(err == KErrNoMemory)
+ {
+ failAt++;
+ FailAlloc(failAt);
+ MarkHeap();
+ err = this->RSecuritySvrSession::GetList(aProcessId, aListId, aListData, aDataSize);
+ if(KErrNoMemory == err)
+ {
+ MarkHeapEnd();
+ }
+ HeapReset();
+ //RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(TProcessId): failAt: %d, err: %d", failAt, err);
+ }
+ return err;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,43 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Version of security server session to enable testing of low memory conditions
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include <rm_debug_api.h>
+
+class RLowMemorySecuritySvrSession : public Debug::RSecuritySvrSession
+ {
+public:
+ TInt GetList(const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+ TInt GetList(const TThreadId aThreadId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+ TInt GetList(const TProcessId aProcessId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+protected:
+ virtual void FailAlloc(const TInt aCount) = 0;
+ virtual void HeapReset() = 0;
+ virtual void MarkHeap() = 0;
+ virtual void MarkHeapEnd() = 0;
+ };
+
+#endif //R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,54 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// r_kernel_low_memory_security_svr_session.cpp
+// Implementation of RUserLowMemorySecuritySvrSession
+//
+//
+
+#include "r_user_low_memory_security_svr_session.h"
+#include <rm_debug_api.h>
+#ifdef _DEBUG
+#include "low_mem_requests.h"
+#endif
+
+void RUserLowMemorySecuritySvrSession::FailAlloc(const TInt aCount)
+ {
+#ifdef _DEBUG
+ TIpcArgs args(aCount);
+ SendReceive(EDebugServFailAlloc, args);
+#endif
+ }
+
+void RUserLowMemorySecuritySvrSession::HeapReset()
+ {
+#ifdef _DEBUG
+ TIpcArgs args(0);
+ SendReceive(EDebugServFailAlloc, args);
+#endif
+ }
+
+void RUserLowMemorySecuritySvrSession::MarkHeap()
+ {
+#ifdef _DEBUG
+ SendReceive(EDebugServMarkHeap);
+#endif
+ }
+
+void RUserLowMemorySecuritySvrSession::MarkHeapEnd()
+ {
+#ifdef _DEBUG
+ SendReceive(EDebugServMarkEnd);
+#endif
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Version of security server session to enable testing of low memory conditions on user side
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include "r_low_memory_security_svr_session.h"
+
+class RUserLowMemorySecuritySvrSession : public RLowMemorySecuritySvrSession
+ {
+protected:
+ void FailAlloc(const TInt aCount);
+ void HeapReset();
+ void MarkHeap();
+ void MarkHeapEnd();
+ };
+
+#endif //R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4488 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the functionality of the run mode debug device driver.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include <hal.h>
+#include <u32hal.h>
+#include <e32property.h>
+
+#include "t_rmdebug_dll.h"
+
+#include <rm_debug_api.h>
+#include "d_rmdebugthread2.h"
+#include "t_rmdebug2.h"
+#include "t_rmdebug_app.h"
+
+#ifdef __MARM_ARMV4__
+#include "d_rmdebug_step_test_armv4.h"
+#endif
+
+#ifdef __MARM_ARMV5__
+#include "d_rmdebug_step_test.h"
+#endif
+
+#include "d_demand_paging.h"
+
+#ifdef KERNEL_OOM_TESTING
+ #ifdef USER_OOM_TESTING
+ #error "Cannot define both KERNEL_OOM_TESTING and USER_OOM_TESTING"
+ #endif
+#endif
+
+_LIT8(KCrashDummyData, "This is a sample write");
+
+using namespace Debug;
+
+const TVersion securityServerVersion(0,1,1);
+
+const TVersion testVersion(2,1,0);
+
+IMPORT_C TInt StartDebugThread(RThread& aServerThread, const TDesC& aDebugThreadName);
+IMPORT_D extern TInt TestData;
+IMPORT_D extern TTestFunction FunctionChooser;
+IMPORT_D extern TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+IMPORT_C TInt TestFunction();
+IMPORT_C void TestPagedCode();
+IMPORT_C extern TInt RMDebugDemandPagingTest();
+
+// Device driver name
+_LIT(KDebugDriverFileName,"rm_debug.ldd");
+
+#ifdef SYMBIAN_STANDARDDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG2"));
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG2_OEM"));
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG2_OEM2"));
+#endif
+
+TBool gUseDelay;
+
+CRunModeAgent::CRunModeAgent()
+//
+// CRunModeAgent constructor
+//
+ {
+ FillArray();
+ RProcess thisProcess;
+ iFileName = thisProcess.FileName();
+ thisProcess.Close();
+ }
+
+CRunModeAgent* CRunModeAgent::NewL()
+//
+// CRunModeAgent::NewL
+//
+ {
+ CRunModeAgent* self = new(ELeave) CRunModeAgent();
+
+ self->ConstructL();
+
+ return self;
+ }
+
+CRunModeAgent::~CRunModeAgent()
+//
+// CRunModeAgent destructor
+//
+ {
+ User::FreeLogicalDevice(KDebugDriverFileName);
+ iServSession.Close();
+ iDebugThread.Close();
+ }
+
+void CRunModeAgent::ConstructL()
+//
+// CRunModeAgent::ConstructL
+//
+ {
+ // nothing to do here
+ }
+
+void CRunModeAgent::SetupAndAttachToDSS()
+//
+// CRunModeAgent::SetupAndAttachToDSS
+//
+ {
+ TInt err = StartDebugThread(iDebugThread, KDebugThreadName);
+
+ // get the thread id for use in the tests
+ iThreadID = iDebugThread.Id();
+
+ if (err != KErrNone)
+ {
+ User::Panic(_L("Can't start debug thread"), err);
+ }
+
+ err = iServSession.Connect(securityServerVersion);
+ if (err != KErrNone)
+ {
+ User::Panic(_L("Can't open server session"), err);
+ }
+ }
+
+CRunModeAgent *RunModeAgent;
+
+// helper function to check whether the listing of type aListId is supported for a scope of aListScope
+TBool CRunModeAgent::ListingSupported(const TListId aListId, const TListScope aListScope)
+ {
+ TTag tag = GetTag(ETagHeaderList, aListId);
+
+ return (tag.iValue) & aListScope;
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0426
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the list of XIP libraries
+//! @SYMTestActions The XIP library list should be successfully obtained
+//! @SYMTestExpectedResults The specified ldd file should be present in the obtained listing
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetXipLibrariesList()
+ {
+ test.Next(_L("TestGetXipLibrariesList\n"));
+
+ test(ListingSupported(EXipLibraries, EScopeGlobal));
+ test(!ListingSupported(EXipLibraries, EScopeProcessSpecific));
+ test(!ListingSupported(EXipLibraries, EScopeThreadSpecific));
+
+ //allocate a very small buffer so the GetList call initially fails
+ RBuf8 buffer;
+ test(KErrNone == buffer.Create(1));
+ TUint32 size = 0;
+
+ //get the list data
+ DoGetList(EXipLibraries, EScopeGlobal, buffer, size);
+
+ //search the buffer for entry corresponding to the debug kernel driver
+ //which should be in the rom
+ _LIT(KRmDebugLddName, "z:\\sys\\bin\\rm_debug.ldd");
+
+ //iterate through the buffer and set found to ETrue if we find the driver
+ TBool found = EFalse;
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TXipLibraryListEntry& xipLibrary = *(TXipLibraryListEntry*)ptr;
+
+ //get the name of the library
+ TPtr name(&xipLibrary.iName[0], xipLibrary.iNameLength, xipLibrary.iNameLength);
+ if(name.CompareF(KRmDebugLddName()) == 0)
+ {
+ //found the library but continue reading the rest of the buffer to
+ //check nothing bad happens towards the end
+ found = ETrue;
+ }
+ //move pointer on to next library
+ ptr += Align4(xipLibrary.GetSize());
+ }
+ test(found);
+
+ //do cleanup
+ buffer.Close();
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0427
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the list of executables
+//! @SYMTestActions The list of debuggable executable files should be obtained
+//! @SYMTestExpectedResults The client exe should appear in the list
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetExecutablesList()
+ {
+ test.Next(_L("TestGetExecutablesList\n"));
+
+ test(ListingSupported(EExecutables, EScopeGlobal));
+ test(!ListingSupported(EExecutables, EScopeProcessSpecific));
+ test(!ListingSupported(EExecutables, EScopeThreadSpecific));
+
+ //allocate a very small buffer so the GetList call initially fails
+ RBuf8 buffer;
+ test(KErrNone == buffer.Create(1));
+ TUint32 size = 0;
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //get the list data
+ DoGetList(EExecutables, EScopeGlobal, buffer, size);
+
+ //get this process' name
+ RProcess thisProcess;
+ TFileName thisProcessName = thisProcess.FileName();
+
+ //look through the buffer and check if the target debug thread is there
+ TBool found = EFalse;
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TExecutablesListEntry& entry = *(TExecutablesListEntry*)ptr;
+ //get name
+ TPtr name(&entry.iName[0], entry.iNameLength, entry.iNameLength);
+ if( (entry.iIsActivelyDebugged != 0) && (0 == thisProcessName.CompareF(name)) )
+ {
+ //found this process and asserted it is being actively debugged
+ found = ETrue;
+ }
+ //move pointer on to next entry
+ ptr += Align4(entry.GetSize());
+ }
+ test(found);
+
+ //clean up
+ buffer.Close();
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0428
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test error conditions for the GetList calls
+//! @SYMTestActions Multiple calls to test calling GetList with bad arguments
+//! @SYMTestExpectedResults All tests should fail with the appropriate error codes
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetListInvalidData()
+ {
+ test.Next(_L("TestGetListInvalidData\n"));
+
+ //allocate a buffer, the size should not matter as expecting all calls to fail
+ RBuf8 buffer;
+ test(KErrNone == buffer.Create(1));
+ TUint32 size = 0;
+
+ //test what happens if we ask for an unsupported list type globally
+ test(KErrNotSupported == iServSession.GetList((TListId)1234, buffer, size));
+
+ //test what happens if we ask for an unsupported list type
+ test(KErrNotSupported == iServSession.GetList(RThread().Id(), (TListId)1234, buffer, size));
+
+ //test what happens if we try to get a non-global libraries list
+ test(KErrArgument == iServSession.GetList(RThread().Id(), EXipLibraries, buffer, size));
+
+ //test what happens if we try to get a non-global executables list
+ test(KErrArgument == iServSession.GetList(RThread().Id(), EExecutables, buffer, size));
+
+ //test what happens if we try to get a non-global process list
+ test(KErrArgument == iServSession.GetList(RThread().Id(), EProcesses, buffer, size));
+
+ //check that using a process id fails
+ test(KErrArgument == iServSession.GetList(RProcess().Id(), EProcesses, buffer, size));
+
+ //check that specifying a non-existant thread id fails
+ test(KErrArgument == iServSession.GetList((TThreadId)0x12345678, EThreads, buffer, size));
+
+ //check that specifying a non-existant process id fails
+ test(KErrArgument == iServSession.GetList((TProcessId)0x12345678, EThreads, buffer, size));
+
+ //check that specifying a non-existant thread id fails
+ test(KErrArgument == iServSession.GetList((TThreadId)0x12345678, ECodeSegs, buffer, size));
+
+ //check that specifying a non-existant process id fails
+ test(KErrArgument == iServSession.GetList((TProcessId)0x12345678, ECodeSegs, buffer, size));
+
+ //cleanup
+ buffer.Close();
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0429
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the process list
+//! @SYMTestActions Get the process listing
+//! @SYMTestExpectedResults The process listing should be successfully obtained and the current process should be present in the list
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetProcessList()
+ {
+ test.Next(_L("TestGetProcessList\n"));
+
+ test(ListingSupported(EProcesses, EScopeGlobal));
+ test(!ListingSupported(EProcesses, EScopeProcessSpecific));
+ test(!ListingSupported(EProcesses, EScopeThreadSpecific));
+
+ //allocate a very small buffer so the GetList call fails
+ RBuf8 buffer;
+ test(KErrNone == buffer.Create(1));
+ TUint32 size = 0;
+
+ //get the list data
+ DoGetList(EProcesses, EScopeGlobal, buffer, size);
+
+ //initialise data about the target debug thread to compare the kernel's data against
+ RProcess thisProcess;
+ TFileName thisProcessName = thisProcess.FileName();
+ TUint32 processId = thisProcess.Id().Id();
+
+ //look through the buffer and check if the target debug thread is there
+ TBool found = EFalse;
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+ if( (RProcess().Id().Id() == entry.iProcessId) &&
+ (0 == thisProcessName.CompareF(TPtr(&(entry.iNames[0]), entry.iFileNameLength, entry.iFileNameLength))) &&
+ (0 == thisProcess.FullName().CompareF(TPtr(&(entry.iNames[0]) + entry.iFileNameLength, entry.iDynamicNameLength, entry.iDynamicNameLength))) &&
+ 0x4321bbbb /* Magic */ == entry.iUid3)
+ {
+ //if all match then we've found it
+ found = ETrue;
+ }
+ ptr += Align4(entry.GetSize());
+ }
+
+ //check whether the expected result happened
+ test(found);
+
+ //clean up
+ buffer.Close();
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0430
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the thread list
+//! @SYMTestActions Get the thread listing globally and for a specified thread or process
+//! @SYMTestExpectedResults The thread listings should all be successfully obtained and the current thread should be present in all listings
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetThreadList()
+ {
+ test.Next(_L("TestGetThreadList\n"));
+
+ test(ListingSupported(EThreads, EScopeGlobal));
+ test(ListingSupported(EThreads, EScopeProcessSpecific));
+ test(ListingSupported(EThreads, EScopeThreadSpecific));
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ //test getting the global list, ETrue as should find the target debug thread
+ DoTestGetThreadList(ETrue, EScopeGlobal);
+
+ //test getting this thread's thread list, ETrue as should find the target debug thread
+ DoTestGetThreadList(ETrue, EScopeThreadSpecific, RThread().Id().Id());
+
+ //test getting this process's thread list, ETrue as should find the target debug thread
+ DoTestGetThreadList(ETrue, EScopeProcessSpecific, RProcess().Id().Id());
+
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+void CRunModeAgent::DoTestGetThreadList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId)
+ {
+ test.Next(_L("DoTestGetThreadList\n"));
+
+ //create data to pass
+ RBuf8 buffer;
+ TUint32 size = 0;
+
+ //perform the call to get the Code segs
+ DoGetList(EThreads, aListScope, buffer, size, aTargetId);
+
+ //initialise data about the target debug thread to compare the kernel's data against
+ TFileName name = iDebugThread.FullName();
+ RProcess thisProcess;
+ TUint64 processId = thisProcess.Id();
+ TUint64 threadId = iDebugThread.Id();
+
+ //look through the buffer and check if the target debug thread is there
+ TBool found = EFalse;
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TThreadListEntry* entry = (TThreadListEntry*)ptr;
+ TPtr entryName(&(entry->iName[0]), entry->iNameLength, entry->iNameLength);
+ if( (threadId == entry->iThreadId) && (processId == entry->iProcessId) && (0 == name.CompareF(entryName)) )
+ {
+ test(entry->iSupervisorStackBaseValid);
+ test(entry->iSupervisorStackSizeValid);
+ //if all match then we've found it
+ found = ETrue;
+ }
+
+ ptr += Align4(entry->GetSize());
+ }
+
+ //check whether the expected result happened
+ test(found == aShouldPass);
+
+ //clean up
+ buffer.Close();
+
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0431
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the code segment list
+//! @SYMTestActions Get the code segment list global and for a specified thread
+//! @SYMTestExpectedResults The listings should be returned successfully
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetCodeSegsList()
+ {
+ test.Next(_L("TestGetCodeSegsList\n"));
+
+ test(ListingSupported(ECodeSegs, EScopeGlobal));
+ test(ListingSupported(ECodeSegs, EScopeProcessSpecific));
+ test(ListingSupported(ECodeSegs, EScopeThreadSpecific));
+
+ // Cannot perform this test with OEM2 debug token, as the t_rmdebug2 app
+ // needs AllFiles, and the OEM2 debug token does not authorise this.
+ // It seems reasonable to suppose that it would work anyway
+
+#ifndef SYMBIAN_OEM2DEBUG
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //test getting the global list, ETrue as should find this process' main codeSeg
+ DoTestGetCodeSegsList(ETrue, EScopeGlobal);
+
+ //test getting this process' codeSegs, ETrue as should find this process' main codeSeg
+ DoTestGetCodeSegsList(ETrue, EScopeProcessSpecific, RProcess().Id().Id());
+
+ //test getting this thread's codeSegs, ETrue as should find this process' main codeSeg
+ DoTestGetCodeSegsList(ETrue, EScopeThreadSpecific, RThread().Id().Id());
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+#endif // SYMBIAN_OEM2DEBUG
+
+ }
+
+void CRunModeAgent::DoTestGetCodeSegsList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId)
+ {
+ //create data to pass
+ RBuf8 buffer;
+ TUint32 size = 0;
+
+ //perform the call to get the Code segs
+ DoGetList(ECodeSegs, aListScope, buffer, size, aTargetId);
+
+ //create memoryInfo to contain info about this process
+ RProcess thisProcess;
+ TModuleMemoryInfo memoryInfo;
+ test(KErrNone == thisProcess.GetMemoryInfo(memoryInfo));
+
+ // check whether this process came from a file in ROM so we know whether to
+ // expect the code seg to be XIP or not.
+ RFs fs;
+ test(KErrNone == fs.Connect());
+ TBool thisFileIsInRom = EFalse;
+ if(fs.IsFileInRom(iFileName))
+ {
+ thisFileIsInRom = ETrue;
+ }
+
+ //look through the buffer to find this process' main code seg
+ TBool found = EFalse;
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TCodeSegListEntry* codeSeg = (TCodeSegListEntry*)ptr;
+
+ if( (codeSeg->iIsXip == thisFileIsInRom) && (0 == iFileName.CompareF(TPtr(&(codeSeg->iName[0]), codeSeg->iNameLength, codeSeg->iNameLength))) )
+ {
+ if( (memoryInfo.iCodeBase == codeSeg->iCodeBase) &&
+ (memoryInfo.iCodeSize == codeSeg->iCodeSize) &&
+ (memoryInfo.iConstDataSize == codeSeg->iConstDataSize) &&
+ (memoryInfo.iInitialisedDataBase == codeSeg->iInitialisedDataBase) &&
+ (memoryInfo.iInitialisedDataSize == codeSeg->iInitialisedDataSize) &&
+ (memoryInfo.iUninitialisedDataSize == codeSeg->iUninitialisedDataSize))
+ {
+ //all matched so means we've found the codeSeg we're looking for
+ found = ETrue;
+ }
+ }
+ ptr += Align4(codeSeg->GetSize());
+ }
+
+ //check whether the result was as expected
+ test(found == aShouldPass);
+
+ // only care about rm_debug.ldd if we have global scope (belongs to the system not this process)
+ if (aListScope == EScopeGlobal)
+ {
+ // Search for rm_debug.ldd library and check its UID3 is correct
+ found = EFalse;
+
+_LIT(KRMDebugDriverFileName,"Z:\\sys\bin\\rm_debug.ldd");
+
+ TFileName rmdebugFilename(KRMDebugDriverFileName);
+
+ // reset the Ptr
+ ptr = (TUint8*)buffer.Ptr();
+ ptrEnd = ptr+size;
+ while(ptr < ptrEnd)
+ {
+ TCodeSegListEntry* codeSeg = (TCodeSegListEntry*)ptr;
+
+ if( rmdebugFilename.CompareF(TPtr(&(codeSeg->iName[0]), codeSeg->iNameLength, codeSeg->iNameLength)))
+ {
+ if(codeSeg->iUid3 == 0x101f7157 /* Magic */)
+ {
+ //all matched so means we've found the codeSeg we're looking for
+ found = ETrue;
+ }
+ }
+ ptr += Align4(codeSeg->GetSize());
+ }
+ test((TUint32)found == (TUint32)ETrue);
+ }
+
+ //clean up
+ buffer.Close();
+
+ }
+
+void CRunModeAgent::DoGetList(const TListId aListId, const TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId)
+ {
+ //close the buffer in case there's stuff allocated in it
+ aBuffer.Close();
+ //initialise it to be one byte big, which will guarantee data won't fit in it
+ test(KErrNone == aBuffer.Create(1));
+ aSize = 0;
+
+ //should pass this test (assuming we've passed in sensible arguments above...)
+ if(EScopeGlobal == aListScope)
+ {
+ test(KErrTooBig == iServSession.GetList(aListId, aBuffer, aSize));
+ }
+ else if(EScopeThreadSpecific == aListScope)
+ {
+ test(KErrTooBig == iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize));
+ }
+ else if(EScopeProcessSpecific == aListScope)
+ {
+ test(KErrTooBig == iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize));
+ }
+ else
+ {
+ // unknown list scope
+ test(0);
+ }
+
+ //keep allocating larger buffers, beginning with the aSize returned by the above call,
+ //and hopefully we'll eventually make a large enough one
+ test(KErrNone == aBuffer.ReAlloc(aSize));
+
+ for(;;)
+ {
+ TInt err = KErrNone;
+ if(EScopeGlobal == aListScope)
+ {
+ err = iServSession.GetList(aListId, aBuffer, aSize);
+ }
+ else if(EScopeThreadSpecific == aListScope)
+ {
+ err = iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize);
+ }
+ else if(EScopeProcessSpecific == aListScope)
+ {
+ err = iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize);
+ }
+ else
+ {
+ // unknown list scope
+ test(0);
+ }
+ if(err == KErrTooBig)
+ {
+ //wasn't big enough so double it
+ aSize = aSize << 1;
+ err = aBuffer.ReAlloc(aSize);
+ if(err != KErrNone)
+ {
+ //print out a message if couldn't allocate memory and quit
+ test.Printf(_L("Out ot memory when attempting to allocate %d bytes."), aSize);
+ test(KErrNone == err);
+ }
+
+ //fairly arbitrary test, we don't have a max size for these calls.
+ //In reality a list would have to have many thousands of elements
+ //to break this test which shouldn't really happen
+ test(aSize <= 0x4000);
+ }
+ else
+ {
+ test(KErrNone == err);
+ test(aBuffer.Length() == aSize);
+ //break out of the loop if the list has been successfully read in
+ break;
+ }
+ }
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0432
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading and writing memory
+//! @SYMTestActions Multiple calls to read and write memory, with various sizes and at various locations.
+//! Also test that bad input values cause appropriate errors to be returned.
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestMemoryAccess()
+{
+ TInt err;
+
+ test.Next(_L("TestMemoryAccess - Read Memory\n"));
+
+ //initialise buffer
+ gMemoryAccessBytes.SetLength(0);
+ for (TInt i=0; i<SYMBIAN_RMDBG_MEMORYSIZE; i++)
+ {
+ gMemoryAccessBytes.Append(i);
+ }
+
+ TUint32 address = (TUint32)(&gMemoryAccessBytes[0]);
+ TUint32 dataSize = SYMBIAN_RMDBG_MEMORYSIZE;
+
+ //create size for buffer that is rounded up to nearest 4 bytes if not
+ //already 4 byte aligned
+ TUint32 size = dataSize;
+ if(size % 4 != 0)
+ {
+ size += (4 - (size % 4));
+ }
+
+ RBuf8 dataBlock;
+ err = dataBlock.Create(size);
+ test(err==KErrNone);
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //suspend the thread prior to memory operations
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ for (TInt i=0; i<dataSize; i++)
+ {
+ test(dataBlock.Ptr()[i] == gMemoryAccessBytes[i]);
+ }
+
+ test.Next(_L("TestMemoryAccess - Write Memory\n"));
+
+ // Now reset the buffer
+ for (TInt i=0; i<dataSize; i++)
+ {
+ gMemoryAccessBytes[i] = 0;
+ }
+
+ // Write our data into the buffer
+ err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ for (TInt i=0; i<dataSize; i++)
+ {
+ test(dataBlock.Ptr()[i] == gMemoryAccessBytes[i]);
+ }
+
+ //final test that everything's not been going wrong
+ test(gMemoryAccessBytes[5] != 0);
+
+ test.Next(_L("TestMemoryAccess - Invalid arguments\n"));
+ test.Printf(_L("This test may emit crash-like information. This is intended.\n"));
+
+ //test address that is not 32 bit aligned
+ err = iServSession.ReadMemory(iThreadID, address + 1, size, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrArgument);
+
+ //test size that is not multiple of 4 bytes
+ err = iServSession.WriteMemory(iThreadID, address, size + 2, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrArgument);
+
+ //test size > max block size
+ err = iServSession.ReadMemory(iThreadID, address, (1<<15), dataBlock, EAccess32, EEndLE8);
+ test(err == KErrArgument);
+
+ //test access size == 2 bytes
+ err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess16, EEndLE8);
+ test(err == KErrNotSupported);
+
+ //test access size == 1 byte
+ err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess8, EEndLE8);
+ test(err == KErrNotSupported);
+
+ //test endianess == EEndBE8
+ err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndBE8);
+ test(err == KErrNotSupported);
+
+ //test endianess == EEndBE32
+ err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndBE32);
+ test(err == KErrNotSupported);
+
+ //test reading off end of memory
+ err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x00000101, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrArgument);
+
+ //The following three tests check that edge conditions in the range check are handled correctly.
+ err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x000000FF, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrArgument);
+
+ err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x000000F0, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrBadDescriptor);
+
+ //Third range check test. Check that range check is handled correctly even when base + size wraps to 0.
+ err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x00000100, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrBadDescriptor);
+ //end of range check tests
+
+ //test size == 0
+ err = iServSession.WriteMemory(iThreadID, address, 0, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrArgument);
+
+ //attempt to write to address outside of process data segments,
+ //this address corresponds to the vectors so shouldn't be able to write
+ err = iServSession.WriteMemory(iThreadID, 0xffff0000, size, dataBlock, EAccess32, EEndLE8);
+ test(err == KErrBadDescriptor);
+
+ //attempt to read and write to address in process code segment
+
+ //open a handle to the thread
+ RThread debugThread;
+ test(debugThread.Open(iThreadID) == KErrNone);
+
+ //get a reference to the debug process
+ RProcess debugProcess;
+ test(debugThread.Process(debugProcess) == KErrNone);
+
+ //get the memory info for the process
+ TProcessMemoryInfo info;
+ test(debugProcess.GetMemoryInfo(info) == KErrNone);
+
+ address = info.iCodeBase;
+ if(size <= info.iCodeSize)
+ {
+ test(KErrNone == iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8));
+ test(KErrBadDescriptor == iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8));
+ }
+
+ // Some performance tests now
+ TUint32 bytesRead = 0;
+
+ // Allocate a data buffer
+ TUint32* p = (TUint32*)User::Alloc(size);
+ test(p != 0);
+
+ TInt nanokernel_tick_period;
+ HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+ test (nanokernel_tick_period != 0);
+
+ static const TInt KOneMillion = 1000000;
+
+ TInt nkTicksPerSecond = KOneMillion/nanokernel_tick_period;
+
+ TUint32 stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+ while (User::NTickCount() < stopTickCount)
+ {
+ err = iServSession.ReadMemory(iThreadID, (TUint32)p, size, dataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ // Increase the count of bytes read
+ bytesRead += size;
+ }
+
+ test(bytesRead != 0);
+ iMemoryReadKbytesPerSecond = bytesRead/1024;
+
+ // write memory test
+ TUint32 bytesWritten = 0;
+
+ stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+ while (User::NTickCount() < stopTickCount)
+ {
+ err = iServSession.WriteMemory(iThreadID, (TUint32)p, size, dataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ // Increase the count of bytes read
+ bytesWritten += size;
+ }
+
+ test (bytesWritten != 0);
+ iMemoryWriteKbytesPerSecond = bytesWritten/1024;
+
+ User::Free(p);
+
+ //resume the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+ debugThread.Close();
+ dataBlock.Close();
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0433
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test suspending and resuming threads
+//! @SYMTestActions Multiple calls to suspend and resume threads with and without attaching to the thread
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestSuspendResume()
+ {
+ TInt err;
+
+ test.Next(_L("TestSuspendResume - Suspend\n"));
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ // Suspend the thread
+ err = iServSession.SuspendThread(iThreadID);
+ test(err==KErrNone);
+ TInt localtestdata;
+ localtestdata = TestData;
+
+ // Wait 3 seconds (suspends this thread) and hopefully resumes the
+ // thread we are controlling via the iServSession.SuspendThread request
+ User::After(3000000);
+
+ // Now check data hasnt changed
+ test(localtestdata==TestData);
+
+ // Resume the thread
+ test.Next(_L("TestSuspendResume - Resume\n"));
+ err = iServSession.ResumeThread(iThreadID);
+ test(err==KErrNone);
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+ // Wait 3 seconds (suspends this thread) and hopefully resumes the
+ // thread we are controlling via the iServSession.SuspendThread request
+ User::After(3000000);
+
+ // Now check that the thread being controlled has resumed and is
+ // updating the variable
+ test(localtestdata!=TestData);
+
+ // check that agent can resume thread which it previously detached from
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+ // check that agent cannot suspend thread which it previously suspended and then detached from
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrAlreadyExists == iServSession.SuspendThread(iThreadID));
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0434
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the debug functionality from the driver
+//! @SYMTestActions Get the size and contents of the debug functionality block
+//! @SYMTestExpectedResults All tests should pass and the expected data should appear in the functionality block
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestDebugFunctionality()
+ {
+
+ TInt err;
+
+ test.Next(_L("TestDebugFunctionality - GetDebugFunctionalityBufSize\n"));
+
+ TUint32 bufsize = 0; // Safe default size
+
+ // Get functionality block size
+ err = iServSession.GetDebugFunctionalityBufSize(&bufsize);
+ test(err==KErrNone);
+ test.Next(_L("TestDebugFunctionality - GetDebugFunctionality\n"));
+
+ // Ensure we have a finite buffer size
+ test(bufsize!=0);
+
+ // Allocate space for the functionality data
+ HBufC8* dftext = HBufC8::NewLC(bufsize);
+
+ // create an empty TPtr8 refering to dftext
+ TPtr8 dftextPtr(dftext->Des());
+
+ // Get the functionality block
+ err = iServSession.GetDebugFunctionality(dftextPtr);
+ test(err==KErrNone);
+
+ // Check that the first entry is correct
+ TTagHeader RefHdr =
+ {
+ ETagHeaderIdCore,ECoreLast,
+ };
+
+ // First header passed from rm_debug.ldd
+ TTagHeader* TestHdr = (TTagHeader*)dftextPtr.Ptr();
+
+ // Check
+ test(RefHdr.iTagHdrId==TestHdr->iTagHdrId);
+ // this test might fail if the agent is used with a Debug Security Server different from
+ // the one it was compiled against. So removing it for now.
+ //test(RefHdr.iNumTags==TestHdr->iNumTags);
+
+ // read a value from the data to check it has come through as expected
+ TTagHeader* header = GetTagHdr(dftext->Des(), ETagHeaderIdApiConstants);
+ test(header != NULL);
+ TTag* tag = GetTag(header, EApiConstantsTEventInfoSize);
+ test(tag != NULL);
+ // this test might fail if the agent is used with a Debug Security Server different from
+ // the one it was compiled against. So removing it for now.
+ //test(sizeof(TEventInfo) == tag->iValue);
+
+ // Remove our temporary buffer
+ CleanupStack::PopAndDestroy(dftext);
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0435
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test setting and clearing consecutive breakpoints
+//! @SYMTestActions Set and clear consecutive breakpoints of all combinations of breakpoint types
+//! @SYMTestExpectedResults All breakpoints should be set and cleared without error
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestConsecutiveBreakPoints()
+ {
+ test.Next(_L("TestConsecutiveBreakPoints\n"));
+
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ // just a temporary structure for storing info about a breakpoint
+ struct TBreakPoint
+ {
+ public:
+ TBreakPoint()
+ :iId(0),
+ iMode((TArchitectureMode)0),
+ iAddress(0)
+ {}
+ TBreakId iId;
+ TArchitectureMode iMode;
+ TUint32 iAddress;
+ inline TInt Size() { return (EArmMode == iMode) ? 4 : 2; }
+ };
+
+ //an address in the target debug thread
+ TUint32 address = (TUint32)(&TestFunction);
+
+ // there are six orders in which three breakpoints can be set, these are looped
+ // through below to check setting and clearing consecutive breakpoints works
+ TUint8 order[6][3] =
+ {
+ {0,1,2},
+ {0,2,1},
+ {1,0,2},
+ {1,2,0},
+ {2,0,1},
+ {2,1,0}
+ };
+
+ // The following code checks that setting and clearing consecutive breakpoints works correctly:
+ // It checks that setting all combinations of three arm and thumb breakpoints succeeds, and check that the
+ // breakpoints can be set in any order, and then cleared in any order
+
+ // the 3 least significant bits of i control whether each of the three breakpoints should be arm or thumb
+ for(TInt i=0; i<8; i++)
+ {
+ // controls the order in which the breakpoints should be set
+ for(TInt j=0; j<6; j++)
+ {
+ // create the three breakpoints and set their modes
+ TBreakPoint bp[3];
+ bp[0].iMode = (i&1) ? EArmMode : EThumbMode;
+ bp[1].iMode = (i&2) ? EArmMode : EThumbMode;
+ bp[2].iMode = (i&4) ? EArmMode : EThumbMode;
+
+ // set the address of each of the breakpoints
+ bp[0].iAddress = address;
+ if(EArmMode == bp[0].iMode)
+ { // if an arm breakpoint then must be on a four byte boundary
+ bp[0].iAddress = Align4(bp[0].iAddress);
+ }
+ bp[1].iAddress = bp[0].iAddress + bp[0].Size();
+ if(EArmMode == bp[1].iMode)
+ { // if an arm breakpoint then must be on a four byte boundary
+ bp[1].iAddress = Align4(bp[1].iAddress);
+ }
+ bp[2].iAddress = bp[1].iAddress + bp[1].Size();
+ if(EArmMode == bp[2].iMode)
+ { // if an arm breakpoint then must be on a four byte boundary
+ bp[2].iAddress = Align4(bp[2].iAddress);
+ }
+ for(TInt k=0; k<6; k++)
+ {
+ // set the three breakpoints in the order defined by j and then clear them in the order defined by k
+ test(KErrNone==iServSession.SetBreak(bp[order[j][0]].iId, iThreadID, bp[order[j][0]].iAddress, bp[order[j][0]].iMode));
+ test(KErrNone==iServSession.SetBreak(bp[order[j][1]].iId, iThreadID, bp[order[j][1]].iAddress, bp[order[j][1]].iMode));
+ test(KErrNone==iServSession.SetBreak(bp[order[j][2]].iId, iThreadID, bp[order[j][2]].iAddress, bp[order[j][2]].iMode));
+ test(KErrNone==iServSession.ClearBreak(bp[order[k][0]].iId));
+ test(KErrNone==iServSession.ClearBreak(bp[order[k][1]].iId));
+ test(KErrNone==iServSession.ClearBreak(bp[order[k][2]].iId));
+ }
+ }
+ }
+
+ // resume the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0436
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test breakpoint functionality
+//! @SYMTestActions Multiple calls to set and clear breakpoints. Checking bad input produces appropriate errors.
+//! @SYMTestExpectedResults All tests should pass and the target debug thread should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakPoints()
+ {
+ TInt err;
+
+ test.Next(_L("TestBreakPoints - Set\n"));
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ TestConsecutiveBreakPoints();
+
+ //an address in the target debug thread
+ TUint32 address = (TUint32)(&TestFunction);
+
+ /*
+ * Ensure that breakpoint operations don't
+ * affect memory read/write by checking that reads/writes
+ * in locations containing breakpoints don't change behaviour
+ * because of the breakpoints.
+ */
+
+ TUint32 size = SYMBIAN_RMDBG_MEMORYSIZE;
+
+ RBuf8 originalDataBlock;
+ err = originalDataBlock.Create(size);
+ test(err==KErrNone);
+
+ //suspend the thread
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ err = iServSession.ReadMemory(iThreadID, address, size, originalDataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ // Test data block for comparison
+ RBuf8 testDataBlock;
+ err = testDataBlock.Create(size);
+ test(err==KErrNone);
+
+ /*
+ * set an arm breakpoint
+ */
+ TBreakId armBreakId = 0;
+ err = iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode);
+ test(err == KErrNone);
+
+ // Ensure that memory read is not corrupted
+ err = iServSession.ReadMemory(iThreadID, address, size, testDataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ test (testDataBlock == originalDataBlock);
+
+ /*
+ * set a thumb breakpoint
+ */
+ TBreakId thumbBreakId = 0;
+ err = iServSession.SetBreak(thumbBreakId, iThreadID, address+4, EThumbMode);
+ test(err == KErrNone);
+
+ /*
+ * set a thumb2EE breakpoint
+ */
+ TBreakId thumb2EEBreakId = 0;
+ err = iServSession.SetBreak(thumb2EEBreakId, iThreadID, address+8, EThumb2EEMode);
+ test(err == KErrNotSupported);
+
+ /*
+ * overlapping breakpoint (same address/threadId/mode)
+ */
+ TBreakId overlapBreakId = 0;
+ err = iServSession.SetBreak(overlapBreakId, iThreadID, address, EArmMode);
+ test(err == KErrAlreadyExists);
+
+ /*
+ * overlapping breakpoint (different address/same threadId/different mode)
+ *
+ * address - EArmBreakpoint
+ * address+2 - EThumbBreakpoint
+ */
+ TBreakId overlap2BreakId = 0;
+ err = iServSession.SetBreak(overlap2BreakId, iThreadID, address+2, EThumbMode);
+ test(err == KErrAlreadyExists);
+
+ /*
+ * Un-aligned address (arm)
+ */
+ TBreakId armUnalignedBreakId = 0;
+ err = iServSession.SetBreak(armUnalignedBreakId, iThreadID, address+6, EArmMode);
+ test(err == KErrArgument);
+
+ /*
+ * Un-aligned address (thumb)
+ */
+ TBreakId thumbUnalignedBreakId = 0;
+ err = iServSession.SetBreak(thumbUnalignedBreakId, iThreadID, address+7, EThumbMode);
+ test(err == KErrArgument);
+
+ /*
+ * Invalid address (arm)
+ */
+ TBreakId armBadAddressBreakId = 0;
+ err = iServSession.SetBreak(armBadAddressBreakId, iThreadID, 0 /* address */, EThumbMode);
+ test(err == KErrBadDescriptor);
+
+ /*
+ * Different thread, same address. Should fail for the same process, but succeed
+ * for a different process.
+ */
+
+ /*
+ * Invalid thread
+ */
+ TBreakId invalidThreadBreakId = 0;
+ err = iServSession.SetBreak(invalidThreadBreakId, 0xbabababa, address, EThumbMode);
+ test(err == KErrPermissionDenied);
+
+ // Clear the ARM breakpoint
+ err = iServSession.ClearBreak(armBreakId);
+ test(err == KErrNone);
+
+ // Clear the Thumb breakpoint
+ err = iServSession.ClearBreak(thumbBreakId);
+ test(err == KErrNone);
+
+ // to do : two threads at the same address
+ // to do : two processes at the same address
+
+ // Ensure that memory read is not corrupted after clearing the breakpoints
+ err = iServSession.ReadMemory(iThreadID, address, size, testDataBlock, EAccess32, EEndLE8);
+ test(err==KErrNone);
+
+ test (testDataBlock == originalDataBlock);
+
+ /*
+ * How fast can we set breakpoints?
+ *
+ * Measure the time by setting/clearing breakpoints for 1 second.
+ */
+ TInt nanokernel_tick_period;
+ HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+ test (nanokernel_tick_period != 0);
+
+ TInt nkTicksPerSecond = HelpTicksPerSecond();
+
+ TInt breaksPerSecond = 0;
+
+ TUint32 stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+ while (User::NTickCount() < stopTickCount)
+ {
+ // set the breakpoint
+ TBreakId armBreakId = 0;
+ err = iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode);
+ test(err == KErrNone);
+
+ // Clear the breakpoint
+ err = iServSession.ClearBreak(armBreakId);
+ test(err == KErrNone);
+
+ // Update the count of breakpoints
+ breaksPerSecond++;
+
+ // Gone wrong if we wrap to negative breakpoints (cannot set 2billion/second!)
+ test(breaksPerSecond >0);
+ }
+
+ // Store the results for later
+ iBreakpointsPerSecond = breaksPerSecond;
+
+ /*
+ * How many breakpoints can we set?
+ */
+
+ TBool done = EFalse;
+
+ // We assume all the breakpoints id's are issued in ascending order
+ TInt maxBreakPoints = 0;
+
+ // Temporary buffer
+ RArray<TBreakId> breakIdList;
+
+ TUint32 testAddress = address;
+
+ while(!done)
+ {
+ TBreakId breakId = 0;
+
+ // set the breakpoint
+ testAddress += 4; // ensure the addresses don't overlap
+
+ err = iServSession.SetBreak(breakId, iThreadID, testAddress, EArmMode);
+ test (err == KErrNone || err == KErrOverflow);
+ if (err != KErrNone)
+ {
+ // we've reached the limit of the number of breaks we can set
+ done = ETrue;
+ break;
+ }
+
+ // store the id of this breakpoint
+ breakIdList.Append(breakId);
+
+ // Increase the count of breakpoints
+ maxBreakPoints++;
+ test(maxBreakPoints > 0);
+ }
+
+ // How many breakpoints can we set?
+ iMaxBreakpoints = maxBreakPoints;
+
+ // now clear all those breakpoints again
+ while(breakIdList.Count() != 0)
+ {
+ // Place it into a TBreakId
+ TBreakId id = breakIdList[0];
+
+ err = iServSession.ClearBreak(id);
+ test(err == KErrNone);
+
+ // next id
+ breakIdList.Remove(0);
+ }
+
+ breakIdList.Close();
+
+ // close our temporary buffers
+ originalDataBlock.Close();
+ testDataBlock.Close();
+
+ err = iServSession.ResumeThread(iThreadID);
+ test (err == KErrNone);
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0437
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test modifying breakpoints
+//! @SYMTestActions Several calls to modify breakpoints
+//! @SYMTestExpectedResults Valid requests should result in the breakpoints being changed, invalid requests should return errors
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestModifyBreak()
+ {
+ test.Next(_L("TestModifyBreak\n"));
+
+ DoTestModifyBreak(ETrue);
+ DoTestModifyBreak(EFalse);
+ }
+
+void CRunModeAgent::DoTestModifyBreak(TBool aThreadSpecific)
+ {
+ test.Printf(_L("DoTestModifyBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+ TInt err;
+
+ RProcess process;
+ TProcessId processId = process.Id();
+ process.Close();
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //suspend the thread
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ //an address in the target debug thread
+ TUint32 address = (TUint32)(&TestFunction);
+
+ //set an arm mode break point
+ TBreakId armBreakId = 0;
+ err = aThreadSpecific
+ ? iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode)
+ : iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+ test(err == KErrNone);
+
+ /*
+ * Invalid thread
+ */
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, 0xbabababa, address, EArmMode)
+ : iServSession.ModifyProcessBreak(armBreakId, 0xbabababa, address, EArmMode);
+ test(err == KErrPermissionDenied);
+
+ /*
+ * Valid address
+ */
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, address+4, EArmMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, address+4, EArmMode);
+ test(err == KErrNone);
+
+ /*
+ * Invalid address
+ */
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, 0, EArmMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, 0, EArmMode);
+ test(err == KErrBadDescriptor);
+
+ /*
+ * Thumb mode
+ */
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, address, EThumbMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, address, EThumbMode);
+ test(err == KErrNone);
+
+ /*
+ * Thumb2EE mode
+ */
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, address, EThumb2EEMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, address, EThumb2EEMode);
+ test(err == KErrNotSupported);
+
+ /*
+ * Arm mode
+ */
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, address, EArmMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, address, EArmMode);
+ test(err == KErrNone);
+
+ // Finally, clear the breakpoint
+ err = iServSession.ClearBreak(armBreakId);
+ test(err == KErrNone);
+
+ //resume the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0438
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test extracting information about breakpoints
+//! @SYMTestActions Several calls to get information about breakpoints
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakInfo()
+ {
+ test.Next(_L("TestBreakInfo\n"));
+
+ DoTestBreakInfo(ETrue);
+ DoTestBreakInfo(EFalse);
+ }
+
+void CRunModeAgent::DoTestBreakInfo(TBool aThreadSpecific)
+ {
+ test.Printf(_L("DoTestModifyBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+ TInt err;
+
+ RProcess process;
+ TProcessId processId = process.Id();
+ process.Close();
+
+ //an address in the target debug thread
+ TUint32 address = (TUint32)(&TestFunction);
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //suspend thread
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ //set an arm mode break point
+ TBreakId armBreakId = 0;
+ err = aThreadSpecific
+ ? iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode)
+ : iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+ test(err == KErrNone);
+
+ // Read back the information and check it is correct
+ TThreadId testThreadId = TThreadId(0);
+ TProcessId testProcessId = TProcessId(0);
+ TUint32 testAddress = 0;
+ TArchitectureMode testMode = EArmMode;
+
+ err = aThreadSpecific
+ ? iServSession.BreakInfo(armBreakId,testThreadId,testAddress, testMode)
+ : iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+ test (err == KErrNone);
+ test (aThreadSpecific ? (testThreadId == iThreadID) : (testProcessId == processId));
+ test (testAddress == address);
+ test (testMode == EArmMode);
+
+ //change the address
+ TUint32 changeAddress = address + 64;
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, changeAddress,EArmMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, changeAddress, EArmMode);
+ test(err == KErrNone);
+
+ // Check the address has changed
+ err = aThreadSpecific
+ ? iServSession.BreakInfo(armBreakId,testThreadId,testAddress, testMode)
+ : iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+ test (err == KErrNone);
+ test (testAddress == changeAddress);
+
+ // change the architecture type
+ TArchitectureMode checkMode = EThumbMode;
+ err = aThreadSpecific
+ ? iServSession.ModifyBreak(armBreakId, iThreadID, address,checkMode)
+ : iServSession.ModifyProcessBreak(armBreakId, processId, address, checkMode);
+ test (err == KErrNone);
+
+ // Check the mode has changed
+ err = aThreadSpecific
+ ? iServSession.BreakInfo(armBreakId,testThreadId,testAddress,testMode)
+ : iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+ test (err == KErrNone);
+ test (testMode == checkMode);
+
+ // clear the breakpoint again
+ err = iServSession.ClearBreak(armBreakId);
+ test (err == KErrNone);
+
+ //resume thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+// Needed for the RunToBreak test
+IMPORT_C extern void RMDebug_BranchTst1();
+IMPORT_C extern void RMDebug_BranchTst2();
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0439
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test hitting various types of breakpoints
+//! @SYMTestActions Several calls to register to observe breakpoints and to hit breakpoints of different types
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestRunToBreak()
+ {
+ test.Next(_L("TestRunToBreak\n"));
+
+ DoTestRunToBreak(ETrue);
+ DoTestRunToBreak(EFalse);
+ }
+
+void CRunModeAgent::DoTestRunToBreak(TBool aThreadSpecific)
+ {
+ test.Printf(_L("DoTestRunToBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+ TInt err = KErrNone;
+
+ RProcess process;
+ TProcessId processId = process.Id();
+ process.Close();
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ // we should suspend the thread first, then set the breakpoint
+ err = iServSession.SuspendThread(iThreadID);
+ test (err == KErrNone);
+
+ // Try to set the breakpoint
+ TBreakId armBreakId;
+ TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+
+ err = aThreadSpecific
+ ? iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode)
+ : iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+ test(err == KErrNone);
+
+ err = aThreadSpecific
+ ? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionContinue)
+ : iServSession.SetEventAction(iFileName,EEventsProcessBreakPoint, EActionContinue);
+ test (err == KErrNone);
+
+ // Continue the thread
+ err = iServSession.ResumeThread(iThreadID);
+ test (err == KErrNone);
+
+ // wait for the breakpoint to be hit
+ TEventInfo info;
+ static TRequestStatus status;
+
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Wait for notification of the breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // info should now be filled with the details
+ test(info.iEventType == (aThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint));
+ test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+
+ // Not interested in breakpoint events any more
+ err = aThreadSpecific
+ ? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore)
+ : iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+ test (err == KErrNone);
+
+ // Clear the breakpoint again
+ err = iServSession.ClearBreak(armBreakId);
+ test(err == KErrNone);
+
+ // continue the thread again
+ err = iServSession.ResumeThread(iThreadID);
+ test (err == KErrNone);
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0440
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test access to target user-side registers.
+//! @SYMTestActions Suspends a target thread, and reads/writes target thread register contents
+//!
+//! @SYMTestExpectedResults KErrNone. Should access target registers without problems.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestRegisterAccess()
+ {
+ TInt err;
+
+ test.Next(_L("TestRegisterAccess - Read\n"));
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //suspend the thread to read registers
+ err = iServSession.SuspendThread(iThreadID);
+ test(err==KErrNone);
+
+ //we'll try to read/write registers ERegisterR0 - ERegisterCPSR and ERegisterR13_IRQ
+ //this way should get valid register values back, invalid ones and not supported ones, and it
+ //means that the register IDs are not completely contiguous
+
+ TInt firstRegister = 0;
+ TInt lastRegister = 17;
+ TInt numberOfRegisters = (lastRegister - firstRegister) + 1;
+
+ RBuf8 ids;
+ err = ids.Create(numberOfRegisters * sizeof(TRegisterInfo));
+ test(err == KErrNone);
+
+ for(TInt i=0; i<numberOfRegisters - 1; i++)
+ {
+ TRegisterInfo reg = (TRegisterInfo)((i + firstRegister)<<8);
+ ids.Append(reinterpret_cast<const TUint8*>(®), sizeof(TRegisterInfo));
+ }
+
+ TRegisterInfo reg = ERegisterR13Irq;
+ ids.Append(reinterpret_cast<const TUint8*>(®), sizeof(TRegisterInfo));
+
+ //create a buffer to store the register values in
+ RBuf8 originalValues;
+ err = originalValues.Create(numberOfRegisters*sizeof(TUint32));
+ test(err == KErrNone);
+
+ //create a buffer to store the register flags in
+ RBuf8 originalFlags;
+ err = originalFlags.Create(numberOfRegisters*sizeof(TUint8));
+ test(err == KErrNone);
+
+ //read register values
+ err = iServSession.ReadRegisters(iThreadID, ids, originalValues, originalFlags);
+ test(err == KErrNone);
+
+ //create a buffer containing data to write into the registers
+ RBuf8 tempValues;
+ err = tempValues.Create(numberOfRegisters*sizeof(TUint32));
+ test(err == KErrNone);
+
+ TUint cpsrId = 16;
+ for(TUint8 i=0; i<numberOfRegisters*sizeof(TUint32); i++)
+ {
+ if(i/sizeof(TUint32) == cpsrId)
+ {
+ //For the CPSR we wish to write data that makes sense - for USR mode we are
+ //allowed change all except the mode, ie. we must stay in usr mode. We try that here
+ //(allowedCPSRValue[4:0] = 10000) thus not changing the mode.
+ TUint32 allowedCPSRValue = 0x50000010;
+ tempValues.Append((TUint8*)&allowedCPSRValue, 4);
+ i += 3;
+ }
+ else
+ {
+ tempValues.Append(&i, 1);
+ }
+ }
+
+ test.Next(_L("TestRegisterAccess - Write\n"));
+
+ //create a buffer to store the register flags in
+ RBuf8 tempWriteFlags;
+ err = tempWriteFlags.Create(numberOfRegisters*sizeof(TUint8));
+ test(err == KErrNone);
+
+ //write the temp data into the registers
+ err = iServSession.WriteRegisters(iThreadID, ids, tempValues, tempWriteFlags);
+ test(err == KErrNone);
+
+ //create another buffer to store the register flags in
+ RBuf8 tempReadFlags;
+ err = tempReadFlags.Create(numberOfRegisters*sizeof(TUint8));
+ test(err == KErrNone);
+
+ RBuf8 tempReadValues;
+ err = tempReadValues.Create(numberOfRegisters*sizeof(TUint32));
+ test(err == KErrNone);
+
+ //read the temp data out again
+ err = iServSession.ReadRegisters(iThreadID, ids, tempReadValues, tempReadFlags);
+ test(err == KErrNone);
+
+ //check values are correct
+ for(TInt i=0; i<numberOfRegisters; i++)
+ {
+ TRegisterFlag writeFlag;
+ err = GetFlag(tempWriteFlags, i, writeFlag);
+ test(err == KErrNone);
+
+ TRegisterFlag readFlag;
+ err = GetFlag(tempReadFlags, i, readFlag);
+ test(err == KErrNone);
+
+ if((writeFlag == EValid) && (readFlag == EValid))
+ {
+ TUint8 offset = i * sizeof(TUint32);
+ for(TUint j = offset; j< offset + sizeof(TUint32); j++)
+ {
+ test(tempValues.Ptr()[j] == tempReadValues.Ptr()[j]);
+ }
+ }
+ }
+
+ //write the original data into the registers
+ err = iServSession.WriteRegisters(iThreadID, ids, originalValues, originalFlags);
+ test(err == KErrNone);
+
+ //read the data out again
+ err = iServSession.ReadRegisters(iThreadID, ids, tempValues, tempReadFlags);
+ test(err == KErrNone);
+
+ //check values are correct
+ for(TInt i=0; i<numberOfRegisters; i++)
+ {
+ TRegisterFlag writeFlag;
+ err = GetFlag(originalFlags, i, writeFlag);
+ test(err == KErrNone);
+
+ TRegisterFlag readFlag;
+ err = GetFlag(tempReadFlags, i, readFlag);
+ test(err == KErrNone);
+
+ if((writeFlag == EValid) && (readFlag == EValid))
+ {
+ TUint8 offset = i * sizeof(TUint32);
+ for(TUint j = offset; j< offset + sizeof(TUint32); j++)
+ {
+ test(tempValues.Ptr()[j] == originalValues.Ptr()[j]);
+ }
+ }
+ }
+
+ test.Next(_L("TestRegisterAccess - Invalid data\n"));
+
+ //create a buffer of max size 1
+ RBuf8 emptyBuffer;
+ emptyBuffer.Create(1);
+
+ //test register IDs buffer not being a multiple of sizeof(TRegisterInfo)
+ err = iServSession.ReadRegisters(iThreadID, emptyBuffer, tempValues, tempReadFlags);
+ test(err == KErrArgument);
+
+ //test register values buffer not being a multiple of sizeof(TUint32)
+ err = iServSession.ReadRegisters(iThreadID, ids, emptyBuffer, tempReadFlags);
+ test(err == KErrArgument);
+
+ //test flags buffer being representing different number of registers from other two
+ err = iServSession.ReadRegisters(iThreadID, ids, tempValues, emptyBuffer);
+ test(err == KErrArgument);
+
+ //set max length to 0
+ emptyBuffer.ReAlloc(0);
+
+ //test ids buffer being of 0 max length
+ err = iServSession.ReadRegisters(iThreadID, emptyBuffer, tempValues, tempReadFlags);
+ test(err == KErrArgument);
+
+ //do cleanup
+ emptyBuffer.Close();
+ tempValues.Close();
+ tempWriteFlags.Close();
+ tempReadFlags.Close();
+ tempReadValues.Close();
+
+ test.Next(_L("TestRegisterAccess - Setting PC value\n"));
+
+ //create buffer containing PC register ID
+ RBuf8 pcId;
+ err = pcId.Create(sizeof(TRegisterInfo));
+ test(err == KErrNone);
+ TRegisterInfo reg1 = (TRegisterInfo)0x00000f00;
+ pcId.Append(reinterpret_cast<const TUint8*>(®1), sizeof(TRegisterInfo));
+
+ //create buffer containing desired PC value
+ RBuf8 pcValue;
+ err = pcValue.Create(sizeof(TUint32));
+ test(err == KErrNone);
+ TUint32 address = (TUint32)(&TestFunction);
+ pcValue.Append(reinterpret_cast<const TUint8*>(&address), sizeof(TUint32));
+
+ //craete buffer for PC flag value
+ RBuf8 pcFlag;
+ err = pcFlag.Create(sizeof(TUint8));
+
+ //write the new PC value
+ err = iServSession.WriteRegisters(iThreadID, pcId, pcValue, pcFlag);
+ test(err==KErrNone);
+
+ //get the flag and check the PC value was written ok
+ TRegisterFlag flag = ENotSupported;
+ err = GetFlag(pcFlag, 0, flag);
+ test(err==KErrNone);
+
+ if(flag == EValid)
+ {
+ /* The PC value was changed to execute the function TestFunction.
+ * TestFunction changes the value of TestData to a given value and
+ * then calls RMDebug_BranchTst1.
+ * We place a breakpoint on RMDebug_BranchTst1 so that to we are able
+ * to test the value of TestData.
+ */
+
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend));
+ TBreakId armBreakId;
+ TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+ test(KErrNone == iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode));
+
+ // Continue the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+ // wait for the breakpoint to be hit
+ TEventInfo info;
+ static TRequestStatus status;
+
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Wait for notification of the breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // info should now be filled with the details
+ test(info.iEventType == EEventsBreakPoint);
+ test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+
+ test(KErrNone == iServSession.ClearBreak(armBreakId));
+
+ // Finally test the value
+ test(TestData == 0xffeeddcc);
+ }
+
+ //Make sure we cannot change the CPSR
+ test.Next(_L("Verifying we cannot change the CPSR mode from USR Mode"));
+
+ TUint32 disallowedCpsr = 0x50000013;
+
+ RBuf8 cpsrRegId;
+ err = cpsrRegId.Create(sizeof(TUint32));
+ test(err == KErrNone);
+
+ TRegisterInfo cpsr = (TRegisterInfo)((cpsrId + firstRegister)<<8);
+ cpsrRegId.Append(reinterpret_cast<const TUint8*>(&cpsr), sizeof(TRegisterInfo));
+
+ RBuf8 cpsrRegFlags;
+ err = cpsrRegFlags.Create(sizeof(TUint8));
+ test(err == KErrNone);
+
+ RBuf8 cpsrVal;
+ err = cpsrVal.Create(sizeof(TUint32));
+ test(err == KErrNone);
+
+ cpsrVal.Append((TUint8*)&disallowedCpsr, 4);
+
+ //attempt to write disallowed CPSR in
+ err = iServSession.WriteRegisters(iThreadID, cpsrRegId, cpsrVal, cpsrRegFlags);
+ test(err == KErrNone);
+
+ RBuf8 cpsrReadVal;
+ err = cpsrReadVal.Create(sizeof(TUint32));
+ test(err == KErrNone);
+
+ //Read back the CPSR
+ err = iServSession.ReadRegisters(iThreadID, cpsrRegId, cpsrReadVal, cpsrRegFlags);
+ test(err == KErrNone);
+
+ //Make sure we havent switched modes ie. its not what we wrote
+ TUint32* readVal = (TUint32*)cpsrReadVal.Ptr();
+ test(*readVal != disallowedCpsr);
+
+ cpsrRegId.Close();
+ cpsrRegFlags.Close();
+ cpsrVal.Close();
+ cpsrReadVal.Close();
+
+ //write the original values back into here
+ err = iServSession.WriteRegisters(iThreadID, ids, originalValues, originalFlags);
+ test(err == KErrNone);
+
+ // Resume the thread
+ err = iServSession.ResumeThread(iThreadID);
+ test(err==KErrNone);
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+ //do cleanup
+ pcId.Close();
+ pcValue.Close();
+ pcFlag.Close();
+ ids.Close();
+ originalValues.Close();
+ originalFlags.Close();
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0441
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test registration/de-registration of debug interest in target exe with the Debug Security Server
+//! @SYMTestActions As per description
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestAttachExecutable()
+ {
+
+ test.Next(_L("TestAttachExecutable - Attach\n"));
+
+ //attach to process passively
+ test(KErrNone == iServSession.AttachExecutable(iFileName, ETrue));
+
+ //make a thread id for a non-existent thread
+ TThreadId threadId(0x12345678);
+
+ //get a handle to the target thread
+ RThread targetThread;
+ TInt err = targetThread.Open(threadId);
+ test(err != KErrNone);
+
+ //not registered for this thread's process (as it doesn't exist)
+ //so should fail security check
+ err = iServSession.ResumeThread(threadId);
+ test(err==KErrPermissionDenied);
+
+ //try to attach to the same process (and fail)
+ test(KErrAlreadyExists == iServSession.AttachExecutable(iFileName, EFalse));
+
+ test.Next(_L("TestAttachExecutable - Detach\n"));
+
+ //detach from process
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+ //attach non-passively
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //not registered for this thread's process (as it doesn't exist)
+ //so should fail security check
+ err = iServSession.ResumeThread(0x12345678);
+ test(err==KErrPermissionDenied);
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0442
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests single-stepping target threads.
+//! @SYMTestActions Steps target thread assembly level instructions, mainly branch/change PC
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestStep()
+ {
+ test.Next(_L("TestStep\n"));
+
+ DoTestStep(EFalse);
+ DoTestStep(ETrue);
+ }
+
+void CRunModeAgent::DoTestStep(TBool aThreadSpecific)
+ {
+ test.Printf(_L("DoTestStep: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+ TInt err = KErrNone;
+
+ RProcess process;
+ TProcessId processId = process.Id();
+ process.Close();
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ //set the target thread to execute the stepping functions
+ test(KErrNone == SwitchTestFunction(EStepFunction));
+
+ err = iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionContinue);
+ test (err == KErrNone);
+
+ if(!aThreadSpecific)
+ {
+ err = iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionContinue);
+ test (err == KErrNone);
+ }
+
+ TUint32 startAddress;
+ TUint32 endAddress;
+
+ /*
+ * RMDebug_StepTest_Non_PC_Modifying
+ */
+ test.Next(_L("TestStep - Non-PC modifying\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying_OK);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Branch
+ */
+ test.Next(_L("TestStep - Branch\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Branch);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Branch_1);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Branch_And_Link
+ */
+ test.Next(_L("TestStep - Branch_And_Link\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Branch_And_Link_1);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Branch_And_Link_2);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_MOV_PC
+ */
+ test.Next(_L("TestStep - MOV PC,X\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_MOV_PC_1);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_MOV_PC_2);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_LDR_PC
+ */
+ test.Next(_L("TestStep - LDR PC\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_LDR_PC);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_LDR_PC_1);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+// thumb and interworking tests are not supported on armv4
+#ifdef __MARM_ARMV5__
+
+ /*
+ * RMDebug_StepTest_Thumb_Non_PC_Modifying
+ */
+ test.Next(_L("TestStep - Thumb Non PC-Modifying\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Non_PC_Modifying_1);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Non_PC_Modifying_2);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Thumb_Branch
+ */
+ test.Next(_L("TestStep - Thumb Branch\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_1);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_2);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Thumb_Branch_And_Link
+ */
+ test.Next(_L("TestStep - Thumb Branch_And_Link\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_And_Link_2);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_And_Link_3);
+
+ TInt muid=0;
+ test(HAL::Get(HAL::EMachineUid, muid)==KErrNone);
+
+ // check if running on ARMv7 core
+ if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+ {
+ // Note: ARMv7 treats BL instructions as single 32-bit instructions
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+ }
+ else
+ {
+ // Note: Due to the fact that the stepper treats BL instructions
+ // as two instructions (as the hardware does), then we must step
+ // the first half instruction first)
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ // Now we actually do the BL
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+ }
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Thumb_Back_Branch_And_Link
+ */
+ test.Next(_L("TestStep - Thumb Back_Branch_And_Link\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Back_Branch_And_Link_2);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Back_Branch_And_Link_3);
+
+ // check if running on ARMv7 core
+ if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+ {
+ // Note: ARMv7 treats BL instructions as single 32-bit instructions
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+ }
+ else
+ {
+ // Note: Due to the fact that the stepper treats BL instructions
+ // as two instructions (as the hardware does), then we must step
+ // the first half instruction first)
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ // Now we actually do the BL
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+ }
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Thumb_AddPC
+ */
+ test.Next(_L("TestStep - Thumb ADD PC, PC, R0\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Thumb_AddPC_2);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Thumb_AddPC_3);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Interwork ARM to Thumb
+ */
+ test.Next(_L("TestStep - Interworking ARM to Thumb - BLX \n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Interwork_1);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Interwork_2);
+
+ err = aThreadSpecific // nb initial breakpoint in ARM code
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+
+ test(err==KErrNone);
+
+ /*
+ * RMDebug_StepTest_Interwork Thumb to ARM
+ */
+ test.Next(_L("TestStep - Interworking Thumb to ARM - BLX\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_Interwork_2);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_Interwork_3);
+
+ // check if running on ARMv7 core
+ if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+ {
+ // ARMv7 treats BLX instructions as single 32-bit instructions
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+ }
+ else
+ {
+ // Stepper treats this as a two-stage instruction (just like the hardware)
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+ test(err == KErrNone);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+ : HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+ }
+ test(err == KErrNone);
+
+#endif // __MARM_ARMV5__
+
+ /*
+ * Test multiple-step of ARM code
+ */
+ test.Next(_L("TestStep - ARM Multiple instruction step\n"));
+
+ startAddress = (TUint32)(&RMDebug_StepTest_ARM_Step_Multiple);
+
+ endAddress = (TUint32)(&RMDebug_StepTest_ARM_Step_Multiple_1);
+
+ err = aThreadSpecific
+ ? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,5)
+ : HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,5, EFalse, processId);
+ test(err == KErrNone);
+ // stepping performance
+ test.Next(_L("TestStep - Steps per second\n"));
+
+ // run until we reach RMDebug_StepTest_Count_1
+ TBreakId stepBreakId;
+ startAddress = (TUint32)(&RMDebug_StepTest_Count_1);
+ endAddress = (TUint32)(&RMDebug_StepTest_Count_2);
+
+ err = aThreadSpecific
+ ? HelpTestStepSetBreak(stepBreakId,iThreadID,startAddress,EArmMode)
+ : HelpTestStepSetBreak(stepBreakId,iThreadID,startAddress,EArmMode,EFalse,processId);
+ test (err == KErrNone);
+
+ // wait until we hit the breakpoint
+ TEventInfo info;
+ err = HelpTestStepWaitForBreak(iFileName,info);
+ test (err == KErrNone);
+
+ // Now clear the breakpoint
+ err = iServSession.ClearBreak(stepBreakId);
+ test(err == KErrNone);
+
+ if(aThreadSpecific)
+ {
+ // now step the code
+ TInt stepsPerSecond = 0;
+
+ TUint32 stopTickCount = User::NTickCount() + HelpTicksPerSecond();
+
+ while (User::NTickCount() < stopTickCount)
+ {
+ err = iServSession.Step(iThreadID,1);
+ test (err == KErrNone);
+
+ // we need to wait now until the step completes before asking for the next step
+ {
+ TEventInfo info;
+ static TRequestStatus status;
+
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Wait for notification of the breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+ }
+
+ // Update the count of steps
+ stepsPerSecond += 1;
+
+ // Gone wrong if we do too many
+ test(stepsPerSecond < 10000);
+ }
+
+ iStepsPerSecond = stepsPerSecond;
+ test(iStepsPerSecond != 0);
+ }
+
+ // finally resume the thread
+ err = iServSession.ResumeThread(iThreadID);
+ test (err == KErrNone);
+
+ err = iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore);
+ test (err == KErrNone);
+
+ if(!aThreadSpecific)
+ {
+ err = iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+ test (err == KErrNone);
+ }
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0443
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests registration and occurrence of target thread event (in this case panic)
+//! @SYMTestActions Registers for a panic in the target thread, causes it, and catches the panic notification.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestEvents()
+ {
+ TInt err = KErrNone;
+
+ test.Next(_L("TestEvents\n"));
+
+ TInt panicReason = 12345;
+
+ test.Printf(_L("Thread t_rmdebug.exe::DebugThread should panic with reason %d.\n"), panicReason);
+
+ //attach non-passively
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ RThread threadToPanic;
+ test(KErrNone == StartDebugThread(threadToPanic, _L("EventsThread")));
+ TThreadId threadToPanicId = threadToPanic.Id();
+ TEventInfo info;
+
+ // Set things up to wait for a thread kill event
+ err = iServSession.SetEventAction(iFileName, EEventsKillThread, EActionContinue);
+ test(err==KErrNone);
+
+ // Wait for an event to occur in this process - nothing should have happened yet.
+ static TRequestStatus status;
+
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Test Request cancellation
+ err = iServSession.CancelGetEvent(iFileName);
+ test (err==KErrNone);
+
+ // Again wait for an event to occur in our process - we will provoke the
+ // thread kill event by panic'ing the test thread.
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Panic the debug thread to cause a thread kill event
+ threadToPanic.Panic(_L("t_rmdebug panic thread test"), panicReason);
+
+ // Wait for notification of the Thread Kill event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // Check we are really recieving information about the panic
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+ test(info.iProcessId==RProcess().Id());
+ test(info.iThreadId==threadToPanicId);
+ test(info.iEventType==EEventsKillThread);
+ test(info.iThreadKillInfo.iExitType==EExitPanic);
+
+ // Ignore other panic events
+ err = iServSession.SetEventAction(iFileName, EEventsKillThread, EActionIgnore);
+ test(err==KErrNone);
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0444
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests registration and occurence of target thread events in separate process.
+//! @SYMTestActions Registers for a hardware exception and kill thread events, and receives them.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestEventsForExternalProcess()
+ {
+ test.Next(_L("TestEventsForExternalProcess\n"));
+
+ for(TInt main=0; main<3; main++)
+ {
+ for(TInt extra=0; extra<3; extra++)
+ {
+ TestEventsWithExtraThreads((TKernelEventAction)main, (TKernelEventAction)extra, 0);
+ TestEventsWithExtraThreads((TKernelEventAction)main, (TKernelEventAction)extra, 2);
+ }
+ }
+ }
+
+void CRunModeAgent::TestEventsWithExtraThreads(TKernelEventAction aActionMain, TKernelEventAction aActionExtra, TUint32 aExtraThreads)
+ {
+ const TInt KNumberOfTypes = 8;
+ struct TEventStruct
+ {
+ public:
+ TDebugFunctionType iDebugFunctionType;
+ TEventType iEventType;
+ };
+
+ TEventStruct type[KNumberOfTypes] =
+ {
+ {EStackOverflowFunction, EEventsHwExc},
+ {EUserPanicFunction, EEventsKillThread},
+ {EPrefetchAbortFunction, EEventsHwExc},
+ {EDataAbortFunction, EEventsHwExc},
+ {EUndefInstructionFunction, EEventsHwExc},
+ {EDataReadErrorFunction, EEventsHwExc},
+ {EDataWriteErrorFunction, EEventsHwExc},
+ {EUserExceptionFunction, EEventsSwExc},
+ };
+
+ for(TInt j=0; j<KNumberOfTypes; j++)
+ {
+ if( gUseDelay ) User::After(500000);
+
+ RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads type: %d, main action: %d, extra action: %d, extraThreads: %d",
+ j, (TUint32)aActionMain, (TUint32)aActionExtra, aExtraThreads);
+
+ // do this check as it seems to hard to do these cases with the current set up
+ if(EEventsKillThread == type[j].iEventType)
+ {
+ if(EActionSuspend != aActionMain)
+ {
+ if(aActionMain != aActionExtra)
+ {
+ return;
+ }
+ }
+ }
+ // attach to KRMDebugTestApplication
+ test(KErrNone == iServSession.AttachExecutable(KRMDebugTestApplication, EFalse));
+
+ // Set things up to wait for the expected exception in KRMDebugTestApplication
+ test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, type[j].iEventType, aActionMain));
+
+ if(EActionSuspend != aActionMain)
+ {
+ test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsKillThread, aActionExtra));
+ }
+
+ // declare a TRequestStatus object for asynchronous calls
+ TRequestStatus status;
+
+ TEventInfo info;
+ TPtr8 infoBuffer = TPtr8((TUint8*)&info,0,sizeof(TEventInfo));
+ if(EActionIgnore != aActionMain)
+ {
+ iServSession.GetEvent(KRMDebugTestApplication(), status, infoBuffer);
+ }
+
+ // launch the target process to trigger the expected exception
+ RProcess targetProcess;
+ test(KErrNone == LaunchProcess(targetProcess, KRMDebugTestApplication(), type[j].iDebugFunctionType, 0, aExtraThreads));
+ TProcessId processId(targetProcess.Id());
+ targetProcess.Close();
+
+ if(EActionIgnore != aActionMain)
+ {
+ // wait for notification of the exception
+ User::WaitForRequest(status);
+ test(KErrNone == status.Int());
+
+ // check that this is the event we were expecting
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+ test(info.iProcessId==processId);
+ test(info.iEventType==type[j].iEventType);
+ }
+
+ if(EActionSuspend == aActionMain)
+ {
+ //RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads EActionSuspend == aActionMain, j=%d", j);
+ // read the thread list, partly to check the call works, and partly to check the thread still exists
+ test(ThreadExistsForProcess(info.iThreadId, info.iProcessId));
+
+ // register to catch all the thread kills which will occur
+ test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsKillThread, aActionExtra));
+ // we specified EActionSuspend earlier so need to call resume on this thread
+ test(KErrNone == iServSession.ResumeThread(info.iThreadId));
+ }
+
+ // find out how many threads there are in the process and catch all the thread kill events,
+ // the number of kill thread events should correspond to the number of extra threads launched,
+ // plus one if the main thread panicked with a Sw/Hw exception
+ if(EActionIgnore != aActionExtra)
+ {
+ TInt dyingThreads = aExtraThreads + ( (type[j].iEventType != EEventsKillThread) ? 1 : 0);
+ for(TInt k=0; k<dyingThreads; k++)
+ {
+ //RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads dyingThreads, k=%d, j=%d", k,j);
+ iServSession.GetEvent(KRMDebugTestApplication(), status, infoBuffer);
+
+ // wait for notification of the kill thread
+ User::WaitForRequest(status);
+ test(KErrNone == status.Int());
+
+ // check that this is the event we were expecting
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+ test(info.iProcessId==processId);
+ test(info.iEventType==EEventsKillThread);
+ if(EActionSuspend == aActionExtra)
+ {
+ // do some calls to check listings work ok at this stage
+ test(ProcessExists(info.iProcessId));
+ test(ThreadExistsForProcess(info.iThreadId, info.iProcessId));
+ // we specified EActionSuspend earlier so need to call resume on this thread
+ test(KErrNone == iServSession.ResumeThread(info.iThreadId));
+ }
+ }
+ }
+
+ if( gUseDelay ) User::After(500000);
+
+ // reset the thread kill event
+ test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication(), EEventsKillThread, EActionIgnore));
+
+ // reset events for KRMDebugTestApplication
+ test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication(), type[j].iEventType, EActionIgnore));
+
+ // finished debugging KRMDebugTestApplication so detach
+ test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication()));
+
+ // want to validate that the process has really exited, i.e. we're not accidentally keeping a handle to it...
+ TInt waitCount = 10;
+ while((waitCount-- > 0) && ProcessExists(processId))
+ {
+ /* Wait a little while and try again, just in case the process is still being removed.
+ This can happen on a very busy system or when a popup for the events is still active
+ */
+ RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads. ProcessExists(id=%d), waiting for it to exit %d",
+ I64LOW(processId), waitCount);
+ User::After(500);
+ }
+ test(!ProcessExists(processId));
+ }
+ }
+
+// helper function to check whether a thread with id aThreadId exists in the process with id aProcessId
+TBool CRunModeAgent::ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId)
+ {
+ TUint32 size;
+ RBuf8 buffer;
+ test(KErrNone == buffer.Create(1024));
+ TInt err = iServSession.GetList(aProcessId, EThreads, buffer, size);
+ while(KErrTooBig == err)
+ {
+ size*=2;
+ test(size<=16*1024);
+ test(KErrNone == buffer.ReAlloc(size));
+ err = iServSession.GetList(aProcessId, EThreads, buffer, size);
+ }
+ test(KErrNone == err);
+
+ //look through the buffer and check if the target debug thread is there
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TThreadListEntry& entry = *(TThreadListEntry*)ptr;
+ if(aThreadId.Id() == entry.iThreadId)
+ {
+ buffer.Close();
+ return ETrue;
+ }
+ ptr += Align4(entry.GetSize());
+ }
+ buffer.Close();
+ return EFalse;
+ }
+
+// helper function to check whether a process with id aProcessId exists
+TBool CRunModeAgent::ProcessExists(const TProcessId aProcessId)
+ {
+ TUint32 size;
+ RBuf8 buffer;
+ test(KErrNone == buffer.Create(1024));
+ TInt err = iServSession.GetList(EProcesses, buffer, size);
+ while(KErrTooBig == err)
+ {
+ size*=2;
+ test(size<=16*1024);
+ test(KErrNone == buffer.ReAlloc(size));
+ err = iServSession.GetList(EProcesses, buffer, size);
+ }
+ test(KErrNone == err);
+
+ //look through the buffer and check if the target debug thread is there
+ TUint8* ptr = (TUint8*)buffer.Ptr();
+ const TUint8* ptrEnd = ptr + size;
+ while(ptr < ptrEnd)
+ {
+ TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+ if(aProcessId.Id() == entry.iProcessId)
+ {
+ buffer.Close();
+ return ETrue;
+ }
+ ptr += Align4(entry.GetSize());
+ }
+ buffer.Close();
+ return EFalse;
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0445
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests basic debug functions work on demand-paged target threads
+//! @SYMTestActions Checks it can r/w memory, set breakpoints etc in a demand paged target.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestDemandPaging(void)
+ {
+ test.Next(_L("TestDemandPaging\n"));
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ // get the address of a function in code that will be paged in
+ TUint32 address = (TUint32)(&RMDebugDemandPagingTest);
+ const TUint32 armInstSize = 4;
+
+ // read the memory at &RMDebugDemandPagingTest to check that reading memory in demand paged code works
+ TUint32 demandPagedInst = 0;
+ TPtr8 demandPagedInstBuf((TUint8*)&demandPagedInst, armInstSize);
+ test(KErrNone == iServSession.ReadMemory(iThreadID, address, armInstSize, demandPagedInstBuf, EAccess32, EEndLE8));
+
+ // this is the MOVS instruction that we expect to find in RMDebugDemandPagingTest
+ TUint32 expectedDemandPagedInst = 0xe1b02000;
+
+ // check that the instruction we read is as expected
+ test(demandPagedInst == expectedDemandPagedInst);
+
+ // set event action for break points
+ test(KErrNone == iServSession.SetEventAction(RProcess().FileName(), EEventsBreakPoint, EActionContinue));
+
+ // set an arm breakpoint on RMDebugDemandPagingTest
+ TBreakId armBreakId = 0;
+ test(KErrNone == iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode));
+
+ // Ensure that after setting the breakpoint the memory read returns the correct value
+ TUint32 demandPagedInstWithBreakPoint = 0;
+ TPtr8 spinForeverInstWithBreakPointBuf((TUint8*)&demandPagedInstWithBreakPoint, armInstSize);
+ test(KErrNone == iServSession.ReadMemory(iThreadID, address, armInstSize, spinForeverInstWithBreakPointBuf, EAccess32, EEndLE8));
+ test(demandPagedInst == demandPagedInstWithBreakPoint);
+
+ // switch the target thread to run the demand paging function
+ test(KErrNone == SwitchTestFunction(EDemandPagingFunction));
+
+ // set up event watcher to catch breakpoint being hit in demand paged code
+ TEventInfo info;
+ static TRequestStatus status;
+ TPtr8 infoPtr((TUint8*)&info,sizeof(TEventInfo));
+ iServSession.GetEvent(RProcess().FileName(), status, infoPtr);
+
+ // resume the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ // wait for notification of the breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // info should now be filled with the details
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+ test(info.iEventType == EEventsBreakPoint);
+ test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+
+ // remove the break point and resume the thread
+ test(KErrNone == iServSession.ClearBreak(armBreakId));
+
+ // switch the target thread to run the default function
+ test(KErrNone == SwitchTestFunction(EDefaultFunction));
+
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurity0FileName,"z:\\sys\\bin\\t_rmdebug_security0.exe"); // Debuggable
+_LIT(KRMDebugSecurity1FileName,"z:\\sys\\bin\\t_rmdebug_security1.exe"); // Not debuggable
+_LIT(KRMDebugSecurity2FileName,"z:\\sys\\bin\\t_rmdebug_security2.exe"); // AllFiles
+_LIT(KRMDebugSecurity3FileName,"z:\\sys\\bin\\t_rmdebug_security3.exe"); // TCB AllFiles
+
+// include the test header file here
+#include "rm_debug_kerneldriver.h"
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0446
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests Debug Device Driver is locked to the SID of the Debug Security Svr.
+//! @SYMTestActions Loads rm-debug.ldd and tries to open a handle to it. This should fail.
+//!
+//! @SYMTestExpectedResults KErrPermissionDenied.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestDriverSecurity(void)
+ {
+ test.Next(_L("TestDriverSecurity\n"));
+
+ RRM_DebugDriver kernelDriver;
+
+ // Load the debug device driver
+ TInt err = User::LoadLogicalDevice( KDebugDriverFileName );
+ test((KErrNone == err) || (KErrAlreadyExists == err));
+
+ // we were allowed to load the driver, or its already loaded.
+
+ // Try to open a handle to the driver - this should return KErrPermissionDenied as we don't have the DSS SID
+ TRM_DebugDriverInfo driverInfo;
+ driverInfo.iUserLibraryEnd = 0;
+ err = kernelDriver.Open(driverInfo);
+ test((err == KErrInUse) || (err == KErrPermissionDenied));
+
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0447
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests Debug driver can only be access via the DSS. Also tests DSS cannot
+//! be subverted. Tests functionality of two representative OEM Debug Tokens.
+//! @SYMTestActions Tries to open rm_debug.ldd (should fail). Tries to debug various processes
+//! (only debuggable one should succeed).
+//!
+//! @SYMTestExpectedResults KErrPermissionDenied.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestSecurity(void)
+ {
+ // Things to test
+ //
+ // try to use debug driver directly ( should have the wrong UID/SID value!)
+ test.Next(_L("TestSecurity - Bypass Debug Security Server to Debug Device Driver - DSS running\n"));
+
+ // Things to test
+ //
+ // Load the debug device driver
+ RRM_DebugDriver kernelDriver;
+ TInt err = User::LoadLogicalDevice( KDebugDriverFileName );
+ test((KErrNone == err) || (KErrAlreadyExists == err));
+
+ // we were allowed to load the driver, or its already loaded.
+
+ // Try to open handle a to the driver - this should return KErrPermission/KErrInUse as we don't have the DSS SID
+ // and we expect the DSS to already be using it.
+ TRM_DebugDriverInfo driverInfo;
+ driverInfo.iUserLibraryEnd = 0;
+ err = kernelDriver.Open(driverInfo);
+ test(err == KErrInUse);
+
+ //
+ // Attach to the Debug Security Server (passive)
+ //
+ test.Next(_L("TestSecurity - Attach to the Debug Security Server (passive)\n"));
+
+ _LIT(KSecurityServerProcessName, "z:\\sys\\bin\\rm_debug_svr.exe");
+
+ test(KErrPermissionDenied == iServSession.AttachExecutable(KSecurityServerProcessName, ETrue));
+
+ //
+ // Attach to the Debug Security Server (active)
+ //
+ test.Next(_L("TestSecurity - Attach to the Debug Security Server (active)\n"));
+
+ test(KErrPermissionDenied == iServSession.AttachExecutable(KSecurityServerProcessName, EFalse));
+
+ //
+ // Attach to Process 0
+ //
+ // Target: Debuggable
+ //
+ test.Next(_L("TestSecurity - Attach to test process 0\n"));
+
+ // Agent can debug the target app as it is marked debuggable - ie capabilities are ignored)
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity0FileName,ETrue);
+
+ //
+ // Attach to Process - 1
+ //
+ // Target: Non-debuggable for ordinary debug agent, debuggable for OEM/OEM2 token authorised agent
+ //
+ // Note: This target app has no PlatSec capabilities
+ //
+ // Agent cannot debug the app unless it has an OEM/OEM2 Debug Token
+ test.Next(_L("TestSecurity - Attach to test process 1\n"));
+
+#ifdef SYMBIAN_STANDARDDEBUG
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,EFalse);
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,ETrue);
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,ETrue);
+#endif
+
+ //
+ // Attach to Process - 2
+ //
+ // Target: Non-debuggable for ordinary debug agent, non-debuggable for OEM2 authorised agent (insufficient caps)
+ //
+ // Note: This target app has AllFiles capability
+ //
+ // Agent cannot debug the app unless it has an OEM Debug Token
+ test.Next(_L("TestSecurity - Attach to test process 2\n"));
+
+#ifdef SYMBIAN_STANDARDDEBUG
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,EFalse);
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,ETrue);
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,EFalse);
+#endif
+
+ //
+ // Attach to Process - 3
+ //
+ // Target: Non-debuggable for ordinary debug agent, non-debuggable for OEM authorised agent (insufficient caps)
+ //
+ // Note: This target app has AllFiles and TCB and NetworkControl capabilities
+ //
+ test.Next(_L("TestSecurity - Attach to test process 3\n"));
+
+ HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity3FileName,EFalse);
+
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0543
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Validates that a dll can be built which #include's the rm_debug_api.h header, i.e. rm_debug_api.h contains no static data.
+//! @SYMTestActions Calls a dummy function in t_rmdebug_dll.dll which implies the dll has been built correctly.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestDllUsage(void)
+ {
+ test.Next(_L("TestDllUsage\n"));
+ test(KUidDebugSecurityServer == GetDSSUid());
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0812
+//! @SYMTestType
+//! @SYMPREQ PREQ1700
+//! @SYMTestCaseDesc Writes a known data to the crash flash and validates the data written
+//! using the read operation and finally erase the data. In the absence
+//! of an OEM debug token, access to the crash partition should not be allowed
+//! @SYMTestActions Invoke the flash write method in DSS and call the read method in DSS
+//! to validate the data is written correctly and then erase the written area
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestCrashFlash(void)
+ {
+#if defined (SYMBIAN_STANDARDDEBUG) || defined (SYMBIAN_OEM2DEBUG)
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-006 Testing We cannot Erase the Crash Flash with insufficient privileges"));
+
+ TUint32 size = 0;
+ TInt err = iServSession.EraseCrashLog(0, 1);
+ test(KErrPermissionDenied == err);
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-005 Testing We can't Write to the Crash Flash with insufficient privileges"));
+
+ err = iServSession.WriteCrashConfig(0, KCrashDummyData, size);
+ test(KErrPermissionDenied == err);
+ test(size == 0);
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-008 Testing We can't Read from the Crash Flash with insufficient privileges"));
+
+ TUint32 readSize = 0x10;
+ RBuf8 buf;
+ buf.CleanupClosePushL();
+ err = buf.Create(readSize);
+
+ test(err == KErrNone);
+
+ err = iServSession.ReadCrashLog(0, buf, readSize);
+ test(KErrPermissionDenied == err);
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-004 Testing Writing To an invalid location"));
+
+ TUint32 writeSize = 0;
+ err = iServSession.WriteCrashConfig(0xFFFFFFFF, KCrashDummyData, writeSize);
+
+ test(err == KErrPermissionDenied);
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-003 Testing Reading from an invalid location"));
+
+ buf.FillZ();
+ err = iServSession.ReadCrashLog(0, buf, writeSize);
+
+ test(err == KErrPermissionDenied);
+
+ CleanupStack::PopAndDestroy(&buf);
+
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+
+ TInt err = KErrNone;
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-007 Testing We can Erase the Crash Flash with sufficient privileges"));
+
+ err = iServSession.EraseCrashLog(0, 1);
+
+ // For platforms where NAND flash is not currently supported we get a KErrNotSupported - this is still a pass
+ if (KErrNotSupported == err)
+ {
+ test.Printf(_L("Nand flash not supported - continue"));
+ return;
+ }
+
+ //For platforms without a flash partition we get KErrNotFound - this is still a pass
+ if(KErrNotFound == err)
+ {
+ test.Printf(_L("Platform has no flash partition - continue"));
+ return;
+ }
+
+ test(KErrNone == err);
+
+ //Read back the start of the block to make sure its 0xFFFFFFFF
+ const TUint numBytesToCheck = 0x80; //We dont know the block size
+ TBuf8<numBytesToCheck> eraseCheck;
+ eraseCheck.SetLength(numBytesToCheck);
+
+ err = iServSession.ReadCrashLog(0, eraseCheck, numBytesToCheck);
+ test(err == KErrNone);
+
+ TBool dataIsOk = ETrue;
+ for(TUint cnt = 0; cnt < numBytesToCheck; cnt++)
+ {
+ if(eraseCheck[cnt] != 0xFF)
+ {
+ dataIsOk = EFalse;
+ }
+ }
+
+ test(dataIsOk);
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-002 Testing We can Write to the Crash Flash with sufficient privileges"));
+
+ TUint32 writeSize = 0;
+ err = iServSession.WriteCrashConfig(0, KCrashDummyData, writeSize);
+
+ test(writeSize == KCrashDummyData().Length());
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-001 Testing We can Read from the Crash Flash with sufficient privileges"));
+
+ RBuf8 buf;
+ buf.CleanupClosePushL();
+ err = buf.Create(writeSize);
+
+ test(err == KErrNone);
+
+ buf.FillZ();
+
+ err = iServSession.ReadCrashLog(0, buf, writeSize);
+
+ test(0 == buf.Compare(KCrashDummyData));
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-004 Testing Writing To an invalid location"));
+
+ writeSize = 0;
+ err = iServSession.WriteCrashConfig(0xFFFFFFFF, KCrashDummyData, writeSize);
+
+ test(err == KErrArgument);
+
+ test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-003 Testing Reading from an invalid location"));
+
+ buf.FillZ();
+ err = iServSession.ReadCrashLog(0xFFFFFFFF, buf, writeSize);
+
+ test(err == KErrArgument);
+
+ CleanupStack::PopAndDestroy(&buf);
+
+#endif
+ }
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0735
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests the Kill Process functionality. Only can kill a debuggable process.
+//! @SYMTestActions Launches a debuggable and non-debuggable process and tries to kill both.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestKillProcess(void)
+ {
+ test.Next(_L("TestKillProcess\n"));
+
+ // Kill a debuggable process
+
+ // check that killing a process is supported
+ TTag tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillProcess);
+ test(tag.iValue);
+ // check that killing a thread is not supported
+ tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillThread);
+ test(!tag.iValue);
+
+ // attach first!
+ TInt err = iServSession.AttachExecutable(KRMDebugTestApplication, EFalse /* Active */);
+ test(err == KErrNone);
+
+ // first launch a debuggable process
+ RProcess process;
+ err = LaunchProcess(process, KRMDebugTestApplication(),ESpinForever, 0, 0);
+ test (err == KErrNone);
+
+ // try to find the process in the list
+_LIT(KRMDebugAppName, "t_rmdebug_app");
+
+ TBool found = ProcessExists(KRMDebugAppName);
+ test (found);
+
+ TInt processId = process.Id();
+ process.Close();
+
+ // program now running, so try to kill it
+ err = iServSession.KillProcess(processId, 0 /* kill reason */);
+ test(err == KErrNone);
+
+ User::After(2000000); // should die within two seconds.
+
+ // can we still find it? Should be gone
+ found = ProcessExists(KRMDebugAppName);
+ test (!found);
+
+ // release the program again.
+ err = iServSession.DetachExecutable(KRMDebugTestApplication);
+ test(err == KErrNone);
+
+ // Try to kill a non-debuggable process and fail.
+
+ // first launch a non-debuggable process
+ RProcess process2;
+ err = LaunchProcess(process2, KRMDebugSecurity1FileName(),ESpinForever, 0, 0);
+ test (err == KErrNone);
+
+ // try to find the process in the list
+_LIT(KRMDebugAppName2, "t_rmdebug_security1");
+
+ TBool found2 = ProcessExists(KRMDebugAppName2);
+ test (found2);
+
+ TInt process2Id = process2.Id();
+ process2.Close();
+
+ // program now running, so try to kill it
+ err = iServSession.KillProcess(process2Id, 0 /* kill reason */);
+ test(err == KErrPermissionDenied);
+
+ User::After(2000000); // should die within two seconds if it is going to die.
+
+ // can we still find it? Should be still around!
+ found2 = ProcessExists(KRMDebugAppName2);
+ test (found2);
+
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-1388
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests the correct operation of the AddProcess and Remove Process
+//! @SYMTestActions 1. Registers for AddProcess and Remove Process events
+//! 2. Starts a test process z:\sys\bin\t_rmdebug_security0.exe
+//! 3. Wait for the AddProcess event to be reported
+//! 4. Kill the newly started test process
+//! 5. Wait for the RemoveProcess event to be reported
+//! 6. Tell the DSS it is no longer interested in AddProcess and RemoveProcess events
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestAddRemoveProcessEvents()
+ {
+ test.Next(_L("TestAddRemoveProcessEvents\n"));
+
+ // attach to a process (e.g. one of the simple security test programs)
+ // launch the security program
+ // wait for the add event
+ // continue the program.
+ // wait for the remove event
+ // detach process
+
+ test(KErrNone == iServSession.AttachExecutable(KRMDebugSecurity0FileName, EFalse));
+
+ test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsAddProcess, EActionContinue));
+
+ test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsRemoveProcess, EActionContinue));
+
+ // Creator thread ID of the current thread (to be creator of test application)
+ TInt creatorThreadId = RThread().Id();
+
+ RProcess process;
+ TInt err = process.Create(KRMDebugSecurity0FileName, KNullDesC, EOwnerProcess);
+ test (err == KErrNone);
+
+ // Rendezvous with process
+ TRequestStatus status;
+ process.Rendezvous(status);
+
+ // Start the test program
+ process.Resume();
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // Wait for the addprocess event
+ TEventInfo info;
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+ iServSession.GetEvent(KRMDebugSecurity0FileName,status,infoPtr);
+
+ // Wait for notification of the addprocess hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // Check this was the right kind of event
+ test(info.iEventType == EEventsAddProcess);
+
+ const TInt uid3offset = 2;
+
+ // Get UID3 for current process
+ TUint32 Uid3 = process.Type()[uid3offset].iUid;
+
+ // Check correct UID3 is returned from the driver
+ test(info.iAddProcessInfo.iUid3 == Uid3);
+
+ // Check correct creator ID for test application is returned from the driver
+ test(info.iAddProcessInfo.iCreatorThreadId == creatorThreadId);
+
+ // Kill the process, as we don't need it anymore
+ process.Kill(KErrNone);
+
+ // Wait for the remove process event
+ iServSession.GetEvent(KRMDebugSecurity0FileName,status,infoPtr);
+
+ // Wait for notification of the remove process hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // Check this was the right kind of event
+ test(info.iEventType == EEventsRemoveProcess);
+
+ test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsRemoveProcess, EActionIgnore));
+
+ test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsAddProcess, EActionIgnore));
+
+ test(KErrNone == iServSession.DetachExecutable(KRMDebugSecurity0FileName));
+
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0736
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Checks that process break points can be set, and that they can co-exist alongside thread breakpoints
+//! @SYMTestActions Checks that process break points can be set, and that they can co-exist alongside thread breakpoints
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestProcessBreakPoints(void)
+ {
+ test.Next(_L("TestProcessBreakPoints\n"));
+
+ // check that process breakpoints are supported
+ TTag tag = GetTag(ETagHeaderIdBreakpoints, EBreakpointProcess);
+ test(tag.iValue);
+
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ // Try to set the breakpoint
+ TBreakId breakId;
+ TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+ RProcess process;
+ TProcessId processId = process.Id();
+ process.Close();
+
+ test(KErrNone == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+ test(KErrAlreadyExists == iServSession.SetBreak(breakId, iThreadID, address, EArmMode));
+ test(KErrAlreadyExists == iServSession.SetBreak(breakId, iThreadID, address, EThumbMode));
+ test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+ test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EThumbMode));
+ test(KErrNone == iServSession.ClearBreak(breakId));
+
+ test(KErrNone == iServSession.SetBreak(breakId, iThreadID, address, EArmMode));
+ test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+ test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EThumbMode));
+ test(KErrNone == iServSession.ClearBreak(breakId));
+
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-1309
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Checks that in the case of multiple low priority events (user traces in this case) we can still receive higher
+//! priority events should the buffer reach a critical level
+//! @SYMTestActions Run to first breakpoint in our test code. Then multiple trace events are issued. We should still be able to hit
+//! the second breakpoint
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestMultipleTraceEvents(void)
+ {
+ test.Next(_L("TestMultipleTraceEvents\n"));
+
+ //attach to target debug process
+ test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ //and suspend the thread
+ test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+ //register interest in BP's & trace events and trace ignored events
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend));
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTrace, EActionContinue));
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTracesLost, EActionContinue));
+
+ // Try to set the breakpoints
+ TBreakId armBreakId;
+ TBreakId armBreakId2;
+ TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+ TUint32 address2 = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying);
+
+ test(KErrNone == iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode));
+ test(KErrNone == iServSession.SetBreak(armBreakId2,iThreadID,address2,EArmMode));
+
+ //set the target thread to execute the trace test function
+ test(KErrNone == SwitchTestFunction(EMultipleTraceCalls));
+
+ // Continue the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+ // wait for the breakpoint to be hit
+ TEventInfo info;
+ static TRequestStatus status;
+
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Wait for notification of the 1st breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // info should now be filled with the details
+ test(info.iEventType == EEventsBreakPoint);
+ test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+
+ // Continue the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+ //Now we try to hit the second breakpoint. This will occur after a number of trace calls. If we hit this breakpoint it
+ //means many trace calls are not preventing us hitting breakpoints.
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Wait for notification of the 2nd breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ TBool receivedTracesLost = EFalse;
+
+ while(info.iEventType == EEventsUserTrace || info.iEventType == EEventsUserTracesLost)
+ {
+ //ensure we get told traces are being thrown away - we generate enough to flood the buffer
+ if(info.iEventType == EEventsUserTracesLost)
+ {
+ receivedTracesLost = ETrue;
+
+ // Now stop the target thread from generating trace events
+ test(KErrNone == SwitchTestFunction(EDoNothing));
+ }
+ else
+ {
+ // Its EEventsUserTrace, so delay us in getting the next event so that it will be more
+ // likely to get a EEventsUserTracesLost next time.
+ // This is important on SMP since the platform can process lots of events, and thus
+ // withouth the delay it is difficult for this test to reproduce the abnormal situation of
+ // lost trace packets
+ User::After(200000);
+ }
+
+ iServSession.GetEvent(iFileName,status,infoPtr);
+
+ // Wait for notification of the 2nd breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+ }
+
+ //make sure we got told traces were lost
+ test(receivedTracesLost != EFalse);
+
+ // info should now be filled with the details of our breakpoint.
+ test(info.iEventType == EEventsBreakPoint);
+ test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address2);
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+
+ //dont care for breakpoints or trace events no more
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore));
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTrace, EActionIgnore));
+ test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTracesLost, EActionIgnore));
+
+ //clear the breaks we set
+ test(KErrNone == iServSession.ClearBreak(armBreakId));
+ test(KErrNone == iServSession.ClearBreak(armBreakId2));
+
+ // Continue the thread
+ test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+ //attach to target debug process
+ test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-2441
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test clearing of a process breakpoint once the process has been killed.
+//! @SYMTestActions Creates a new process then tries to set a process breakpoint and then kills the process which should clear the previously set breakpoint. Then repeat the step once again.
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestProcessKillBreakpoint(void)
+ {
+ test.Next(_L("TestProcessKillBreakpoint\n"));
+ //SID retrieved, used in Define/Attach of the property
+ iMySid.iUid = RProcess().SecureId();
+
+ static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+
+ //define a property to pass on the address from the other process we would try to debug
+ test ( KErrNone == RProperty::Define(iMySid, EMyPropertyInteger, RProperty::EInt, KAllowAllPolicy, KAllowAllPolicy));
+ //define a global semaphore to synchronise with debuggable process publishing the property
+ test ( KErrNone == iAddressGlobSem.CreateGlobal(_L("RMDebugGlobSem"), 0) );
+
+ DoTestProcessKillBreakpoint();
+ // called once again
+ // to check if we can set the breakpoint once again after the process gets killed
+ DoTestProcessKillBreakpoint();
+
+ //delete the property
+ test ( KErrNone == RProperty::Delete(iMySid, EMyPropertyInteger));
+ //close the semaphore
+ iAddressGlobSem.Close();
+ }
+
+void CRunModeAgent::DoTestProcessKillBreakpoint()
+ {
+ test.Printf(_L("\nDoTestProcessKillBreakpoint\n"));
+
+ TInt err = KErrNone;
+
+ // check that killing a process is supported
+ TTag tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillProcess);
+ test(tag.iValue);
+ // check that killing a thread is not supported
+ tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillThread);
+ test(!tag.iValue);
+
+ // attach first!
+ test ( KErrNone == iServSession.AttachExecutable(KRMDebugTestApplication, EFalse/* Active */));
+
+ // first launch a debuggable process
+ RProcess processDebug;
+ test ( KErrNone == LaunchProcess(processDebug, KRMDebugTestApplication(),ESpinForeverWithBreakPoint, 0, 0));
+
+ // try to find the process in the list
+ _LIT(KRMDebugAppName, "t_rmdebug_app");
+ TBool found = ProcessExists(KRMDebugAppName);
+ test (found);
+
+ //search for the main thread created
+ _LIT(KThreadWildCard, "t_rmdebug_app*");
+ TProcessId processDebugId = processDebug.Id();
+ TThreadId threadDebugId;
+
+ TFindThread find(KThreadWildCard);
+ TFullName name;
+ found = EFalse;
+ while(find.Next(name)==KErrNone && !found)
+ {
+ RThread thread;
+ err = thread.Open(find);
+ if (err == KErrNone)
+ {
+ RProcess process;
+ thread.Process(process);
+ if (((TUint32)process.Id() == processDebugId))
+ {
+ TFullName fullname = thread.FullName();
+ test.Printf(_L("Match Found Name %lS Process ID%ld Thread Id %ld"), &fullname, process.Id().Id(), thread.Id().Id());
+ found = ETrue;
+ threadDebugId = thread.Id();
+ }
+ process.Close();
+ }
+ thread.Close();
+ }
+
+ test (found); //check if we actually found the thread we want to debug
+
+ //get the value(property) for the breakpoint address for the process to debug
+ TInt address;
+ RProperty integerProperty;
+ test ( KErrNone == integerProperty.Attach(iMySid, EMyPropertyInteger, EOwnerThread));
+
+ //waiting on semaphore to be sure that the property is set
+ iAddressGlobSem.Wait();
+
+ test ( KErrNone == integerProperty.Get(address));
+ integerProperty.Close();
+
+ test.Printf(_L("Address retrieved to set breakpoint 0x%8x"), address);
+
+ //suspend the thread before we set a breakpoint
+ test ( KErrNone == iServSession.SuspendThread(threadDebugId));
+
+ //set a process breakpoint
+ TBreakId breakId;
+ test(KErrNone == iServSession.SetProcessBreak(breakId, processDebugId, address, EArmMode));
+
+ test(KErrNone ==iServSession.SetEventAction(KRMDebugTestApplication,EEventsProcessBreakPoint, EActionContinue));
+
+ //resume the thread now
+ test(KErrNone == iServSession.ResumeThread(threadDebugId));
+
+ // wait for the breakpoint to be hit
+ static TRequestStatus status;
+ TEventInfo info;
+ TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+ iServSession.GetEvent(KRMDebugTestApplication,status,infoPtr);
+ // Wait for notification of the breakpoint hit event
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // info should now be filled with the details
+ test(info.iEventType == EEventsProcessBreakPoint);
+ test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+ test(info.iProcessIdValid);
+ test(info.iThreadIdValid);
+
+ // Not interested in breakpoint events any more
+ test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsProcessBreakPoint, EActionIgnore));
+
+ // program now running, so try to kill it which should clear all the breakpoints
+ test(KErrNone == iServSession.KillProcess(processDebugId, 0 /* kill reason */ ));
+
+ processDebug.Close();
+ User::After(2000000); // should die within two seconds.
+
+ // can we still find it? Should be gone
+ found = ProcessExists(KRMDebugAppName);
+ test (!found);
+
+ // release the program again
+ test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication));
+
+ }
+
+void CRunModeAgent::HelpTestSecurityAttachDetachExecutable(const TDesC& aProcessName, TBool aExpectSuccess)
+ {
+ RProcess process;
+ TInt err = process.Create(aProcessName, KNullDesC, EOwnerProcess);
+ test (err == KErrNone);
+
+ // rendezvous with process
+ TRequestStatus status;
+ process.Rendezvous(status);
+
+ // start the test program
+ process.Resume();
+ User::WaitForRequest(status);
+ test(status==KErrNone);
+
+ // attach to the program (passively)
+ err = iServSession.AttachExecutable(aProcessName, EFalse);
+
+ if( gUseDelay ) User::After(500000);
+
+ // Do we expect to successfully attach
+ if (aExpectSuccess)
+ {
+ // Yes
+ test(KErrNone == err);
+
+ // Now detach again
+ test(KErrNone == iServSession.DetachExecutable(aProcessName));
+ if( gUseDelay ) User::After(500000);
+ }
+ else
+ {
+ // No
+ test(KErrPermissionDenied == err);
+
+ // Just to be sure, try active attachment
+ test(KErrPermissionDenied == iServSession.AttachExecutable(aProcessName, ETrue));
+ if( gUseDelay ) User::After(500000);
+ }
+
+ // Kill the process, as we don't need it anymore
+ process.Kill(KErrNone);
+ if( gUseDelay ) User::After(500000);
+ }
+
+void CRunModeAgent::ReportPerformance(void)
+//
+// Reports performance metrics from all the tests
+//
+ {
+ test.Printf(_L("\nPerformance\n"));
+ test.Printf(_L("========================\n"));
+
+ // Memory
+ test.Printf(_L("Memory read: %d KBytes/sec\n"),iMemoryReadKbytesPerSecond);
+ test.Printf(_L("Memory write: %d KBytes/sec\n"),iMemoryWriteKbytesPerSecond);
+
+ // Registers
+ // to do
+
+ // events
+ // to do
+
+ // Breakpoints
+ test.Printf(_L("Breakpoint set/clear: %d/sec\n"),iBreakpointsPerSecond);
+ test.Printf(_L("Maximum number of breakpoints: %d\n"),iMaxBreakpoints);
+
+ // Stepping
+ test.Printf(_L("Stepping speed: %d/sec\n"),iStepsPerSecond);
+
+ // Runtime
+ TInt ticks = HelpGetTestTicks();
+ test (ticks != 0);
+
+ TInt nkTicksPerSecond = HelpTicksPerSecond();
+ test (nkTicksPerSecond != 0);
+
+ test.Printf(_L("Total test runtime: %d seconds\n"),ticks/nkTicksPerSecond);
+
+ // Final sizes of executables/rom/ram etc
+ // to do
+
+ test.Printf(_L("\n"));
+ }
+
+/**
+ * Helper code for the stepping tests. Sets a breakpoint in a running thread.
+ * It suspends the thread, sets the breakpoint, and resumes the thread.
+ *
+ * @param aBreakId - Reference to a TBreakId which will be set when the breakpoint is set
+ * @param aThreadId - The thread id for which we should set the breakpoint.
+ * @param aBreakAddress - The address to set the breakpoint
+ * @param aMode - The architecture of the breakpoint to be set (ARM/Thumb/Thumb2EE)
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepSetBreak(TBreakId& aBreakId, TThreadId aThreadId, const TUint32 aBreakAddress, TArchitectureMode aMode, TBool aThreadSpecific, TProcessId aProcessId)
+ {
+ TInt err = KErrNone;
+
+ // Suspend the thread
+ err = iServSession.SuspendThread(aThreadId);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStepSetBreak - Failed to suspend thread\n"));
+ return err;
+ }
+
+ // Set the breakpoint
+ err = aThreadSpecific
+ ? iServSession.SetBreak(aBreakId,aThreadId,aBreakAddress,aMode)
+ : iServSession.SetProcessBreak(aBreakId, aProcessId, aBreakAddress, aMode);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStepSetBreak - Failed to set breakpoint\n"));
+ return err;
+ }
+
+ // Continue the thread
+ err = iServSession.ResumeThread(aThreadId);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStepSetBreak - Failed to resume thread\n"));
+ return err;
+ }
+
+ return KErrNone;
+ }
+
+/**
+ * Helper code for the stepping tests. Clears a breakpoint in a running thread.
+ * It suspends the thread, clears the breakpoint, and resumes the thread.
+ *
+ * @param aBreakId - Reference to a TBreakId which will be set when the breakpoint is set
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepClearBreak(TBreakId aBreakId, const TThreadId aThreadId, TBool aThreadSpecific)
+ {
+ TInt err = KErrNone;
+
+ // Find out what thread id we need to suspend
+ TThreadId threadId;
+ TProcessId processId;
+ TUint32 address;
+ TArchitectureMode mode;
+
+ err = aThreadSpecific
+ ? iServSession.BreakInfo(aBreakId, threadId, address, mode)
+ : iServSession.ProcessBreakInfo(aBreakId, processId, address, mode);
+ if (err != KErrNone )
+ {
+ test.Printf(_L("HelpTestStepClearBreak - failed to obtain information for breakpoint\n"));
+ return err;
+ }
+ if(aThreadSpecific && aThreadId != threadId)
+ {
+ test.Printf(_L("HelpTestStepClearBreak - mismatched thread Ids\n"));
+ return KErrGeneral;
+ }
+
+ // Suspend the thread
+ err = iServSession.SuspendThread(aThreadId);
+ if (!(err == KErrNone || err == KErrAlreadyExists))
+ {
+ test.Printf(_L("HelpTestStepClearBreak - failed to suspend thread\n"));
+ return err;
+ }
+
+ // Clear the breakpoint
+ err = iServSession.ClearBreak(aBreakId);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStepClearBreak - failed to clear breakpoint\n"));
+ return err;
+ }
+
+ // Continue the thread
+ err = iServSession.ResumeThread(aThreadId);
+ if (!(err == KErrNone || err == KErrNotFound))
+ {
+ test.Printf(_L("HelpTestStepClearBreak - failed to resume thread\n"));
+ return err;
+ }
+
+ return KErrNone;
+ }
+
+/**
+ * Helper code for the stepping tests. Waits for a previously set breakpoint to be hit.
+ *
+ * @param aProcessName - The name of the process in which the breakpoint is set. E.g. z:\sys\bin\app.exe
+ * @param aEventInfo - The event information block which is filled in when the breakpoint is hit.
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepWaitForBreak(const TDesC& aProcessName, TEventInfo& aEventInfo)
+ {
+ static TRequestStatus status;
+
+ TPtr8 infoPtr((TUint8*)&aEventInfo,0,sizeof(TEventInfo));
+
+ iServSession.GetEvent(aProcessName,status,infoPtr);
+
+ // Wait for notification of the breakpoint hit event
+ User::WaitForRequest(status);
+ if (status == KErrNone)
+ {
+ return KErrNone;
+ }
+ else
+ {
+ return KErrGeneral;
+ }
+ }
+
+/**
+ * Helper code for the stepping tests. Reads the current target PC for a given thread.
+ *
+ * @param aThreadId - Thread id for which to read the current target PC.
+ * @param aPc - Reference to a TUint32 which will be set to the current target PC.
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepReadPC(TThreadId aThreadId, TUint32& aPC)
+ {
+ TInt err = KErrNone;
+
+ //create buffer containing PC register ID
+ RBuf8 pcId;
+ err = pcId.Create(sizeof(TRegisterInfo));
+ if (err != KErrNone)
+ {
+ return err;
+ }
+
+ TRegisterInfo reg1 = (TRegisterInfo)0x00000f00;
+ pcId.Append(reinterpret_cast<const TUint8*>(®1), sizeof(TRegisterInfo));
+
+ //create buffer containing desired PC value
+ TPtr8 pcValue((TUint8*)&aPC,4,4);
+
+ //create buffer for PC flag value
+ RBuf8 pcFlag;
+ err = pcFlag.Create(sizeof(TUint8));
+
+ //read the new PC value
+ err = iServSession.ReadRegisters(aThreadId, pcId, pcValue, pcFlag);
+ if (err != KErrNone)
+ {
+ //delete temporary buffers
+ pcId.Close();
+ pcFlag.Close();
+ return err;
+ }
+
+ //get the flag and check the PC value was read ok
+ TRegisterFlag flag = ENotSupported;
+ err = GetFlag(pcFlag, 0, flag);
+ if (err != KErrNone)
+ {
+ //delete temporary buffers
+ pcId.Close();
+ pcFlag.Close();
+ return err;
+ }
+
+ if (flag == EValid)
+ {
+ //delete temporary buffers
+ pcId.Close();
+ pcFlag.Close();
+ return KErrNone;
+ }
+ else
+ {
+ //delete temporary buffers
+ pcId.Close();
+ pcFlag.Close();
+ return err;
+ }
+ }
+
+/**
+ * Helper code for the stepping tests. Single steps a given thread from aStartAddress to aEndAddress. Note
+ * that it reaches aStartAddress by setting a breakpoint at that address and waiting until it is hit.
+ *
+ * @param aThreadId - Thread id for which to read the current target PC.
+ * @param aStartAddress - The target address at which stepping will start.
+ * @param aEndAddress - The target address at which stepping will end.
+ * @param aMode - The architecture of the breakpoint which must be set at the start address (ARM/Thumb/Thumb2EE).
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStep(TThreadId aThreadId, TUint32 aStartAddress, TUint32 aEndAddress, TArchitectureMode aMode, TUint aNumSteps, TBool aThreadSpecific, TProcessId aProcessId)
+ {
+ TInt err = KErrNone;
+
+ // Ensure that the supplied addresses are word/half-word aligned as appropriate.
+ if (aMode == EArmMode)
+ {
+ // ARM breakpoints must be word-aligned (2 lsb must be zero)
+ aStartAddress &= 0xFFFFFFFC;
+ aEndAddress &= 0xFFFFFFFC;
+ }
+ else if (aMode == EThumbMode)
+ {
+ // Thumb breakpoints must be half-word aligned (lsb must be zero)
+ aStartAddress &= 0xFFFFFFFE;
+ aEndAddress &= 0xFFFFFFFE;
+ }
+ else if (aMode == EThumb2EEMode)
+ {
+ // Thumb2EE breakpoints are not currently supported
+ return KErrNotSupported;
+ }
+
+ // Set breakpoint at the start address
+ TBreakId tempBreakId;
+ TEventInfo info;
+
+ err = HelpTestStepSetBreak(tempBreakId,aThreadId,aStartAddress,aMode,aThreadSpecific,aProcessId);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - Failed to set breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+ return err;
+ }
+
+ // wait for the breakpoint to be hit
+ err = HelpTestStepWaitForBreak(iFileName,info);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - Failed to hit the breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+ return err;
+ }
+
+ // Check the PC == aStartAddress
+ TUint32 pc = 0;
+ err = HelpTestStepReadPC(aThreadId,pc);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - Failed to read the PC after hitting breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+ return err;
+ }
+
+ if (pc != aStartAddress)
+ {
+ test.Printf(_L("HelpTestStep - Incorrect PC value after hitting breakpoint (expected 0x%08x actual 0x%08x)\n"),aStartAddress,pc);
+ return KErrGeneral;
+ }
+
+ err = iServSession.Step(aThreadId,aNumSteps);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - Failed to do step from 0x%08x to 0x%08x\n"),aStartAddress,aEndAddress,aNumSteps);
+ return err;
+ }
+
+ // only one 'completed step' event in the buffer.
+ err = HelpTestStepWaitForBreak(iFileName,info);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - Could not read breakpoint event info after stepping"));
+ return err;
+ }
+ // end
+
+ // Check PC == aEndAddress
+ err = HelpTestStepReadPC(aThreadId,pc);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - failed read the PC after stepping\n"));
+ return err;
+ }
+ if (pc != aEndAddress)
+ {
+ test.Printf(_L("HelpTestStep - Incorrect PC value after stepping (expected 0x%08x actual 0x%08x)\n"),aEndAddress,pc);
+ return KErrGeneral;
+ }
+
+ // Clear the breakpoint
+ err = HelpTestStepClearBreak(tempBreakId, aThreadId, aThreadSpecific);
+ if (err != KErrNone)
+ {
+ test.Printf(_L("HelpTestStep - failed to clear temporary breakpoint\n"));
+ return err;
+ }
+
+ return KErrNone;
+ }
+
+/**
+ * Helper code for the stepping tests. Returns the number of nanokernel ticks in one second.
+ *
+ * @return Number of nanokernel ticks. 0 if unsuccesful.
+ */
+TInt CRunModeAgent::HelpTicksPerSecond(void)
+ {
+ TInt nanokernel_tick_period;
+ HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+ ASSERT(nanokernel_tick_period != 0);
+
+ static const TInt KOneMillion = 1000000;
+
+ return KOneMillion/nanokernel_tick_period;
+ }
+
+/**
+ Given aTestNumber runs the appropriate test inside heap markers
+
+ @param aTestNumber test to run, corresponds to an entry in iTestArray
+
+ @panic Panic if aTestNumber is not in valid range
+ */
+void CRunModeAgent::RunTest(TInt aTestNumber)
+ {
+ if( (aTestNumber<0) || (aTestNumber>=KMaxTests) )
+ {
+ User::Panic(_L("Test number out of range"), aTestNumber);
+ }
+ __UHEAP_MARK;
+ (this->*(iTestArray[aTestNumber].iFunctionPtr))();
+ __UHEAP_MARKEND;
+ }
+
+void CRunModeAgent::PrintVersion()
+ {
+ test.Printf(_L("\nt_rmdebug2.exe\nVersion: %S\n"), &(testVersion.Name()));
+ test.Printf(_L("Press any key...\n"));
+ test.Getch();
+ }
+
+void CRunModeAgent::PrintUsage()
+ {
+ test.Printf(_L("Invoke with arguments:\n"));
+ test.Printf(_L("-r: run specified tests in reverse order\n"));
+ test.Printf(_L("-h: display usage information\n"));
+ test.Printf(_L("-v: display version\n"));
+ test.Printf(_L("-d: use delays\n"));
+ test.Printf(_L("<number>: test number to run, can specify more than one from the following list:\n"));
+ test.Printf(_L("Press any key for list...\n"));
+ test.Getch();
+ // if there are too many of these they won't fit on the screen! Stick another Getch() in if there get too many
+ for(TInt i=0; i<KMaxTests; i++)
+ {
+ test.Printf(_L("%2d: %S\n"), i, &(iTestArray[i].iFunctionName));
+ }
+ test.Printf(_L("Press any key...\n"));
+ test.Getch();
+ }
+
+/**
+ Parse the command line, see CRunModeAgent::PrintUsage for syntax
+ */
+void CRunModeAgent::ParseCommandLineL(TUint32& aMode, RArray<TInt>& aTests)
+ {
+ // get the length of the command line arguments
+ TInt argc = User::CommandLineLength();
+
+ // allocate a buffer for the command line arguments and extract the data to it
+ HBufC* commandLine = HBufC::NewLC(argc);
+ TPtr commandLineBuffer = commandLine->Des();
+ User::CommandLine(commandLineBuffer);
+
+ // reset mode
+ aMode = (TTestMode)0;
+
+ // create a lexer and read through the command line
+ TLex lex(*commandLine);
+ while (!lex.Eos())
+ {
+ // expecting the first character to be a '-'
+ if (lex.Get() == '-')
+ {
+ TChar arg = lex.Get();
+ switch (arg)
+ {
+ case 'v':
+ //print out the help
+ aMode |= EModeVersion;
+ break;
+ case 'h':
+ //print out the help
+ aMode |= EModeHelp;
+ break;
+ case 'r':
+ //store the fact that we want to run in reverse
+ aMode |= EModeReverse;
+ break;
+ case 'd':
+ //store the fact that we want to run in reverse
+ gUseDelay = EFalse;
+ RDebug::Printf("Not using delays");
+ break;
+ default:
+ // unknown argument so leave
+ User::Leave(KErrArgument);
+ }
+ }
+ else
+ {
+ lex.UnGet();
+ TInt testNumber;
+ User::LeaveIfError(lex.Val(testNumber));
+ if( (testNumber<0) || (testNumber>=KMaxTests) )
+ {
+ User::Leave(KErrArgument);
+ }
+ aTests.AppendL(testNumber);
+ }
+ lex.SkipSpace();
+ }
+ // if no tests specified then run them all
+ if(aTests.Count() == 0)
+ {
+ aMode |= EModeAll;
+ }
+
+ // do clean up
+ CleanupStack::PopAndDestroy(commandLine);
+ }
+
+void CRunModeAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+ {
+ test.Start(_L("ClientAppL"));
+
+ RArray<TInt> testsToRun;
+ TUint32 testMode = 0;
+ ParseCommandLineL(testMode, testsToRun);
+
+ //if help or version mode specified then just print out the relevant stuff and quit
+ if((testMode & EModeHelp) || (testMode & EModeVersion))
+ {
+ if(testMode & EModeHelp)
+ {
+ PrintUsage();
+ }
+ if(testMode & EModeVersion)
+ {
+ PrintVersion();
+ }
+ test.End();
+ return;
+ }
+
+ if(testMode & EModeAll)
+ {
+ for(TInt i=0; i<KMaxTests; i++)
+ {
+ testsToRun.AppendL(i);
+ }
+ }
+
+ // if EModeReverse specified then reverse the array elements
+ TInt numberOfTests = testsToRun.Count();
+ if(testMode & EModeReverse)
+ {
+ for(TInt i=0; i<(numberOfTests>>1); i++)
+ {
+ TInt temp = testsToRun[i];
+ testsToRun[i] = testsToRun[numberOfTests - (i+1)];
+ testsToRun[numberOfTests - (i+1)] = temp;
+ }
+ }
+
+ __UHEAP_MARK;
+ SetupAndAttachToDSS();
+ __UHEAP_MARKEND;
+
+ HelpStartTestTimer();
+ for(TInt i=0; i<numberOfTests; i++)
+ {
+ RunTest(testsToRun[i]);
+ if( gUseDelay ) User::After(500000);
+ }
+ testsToRun.Close();
+
+ HelpStopTestTimer();
+
+ ReportPerformance();
+
+ test.End();
+ }
+
+/**
+ Fill the test array with pointers to each test.
+ */
+void CRunModeAgent::FillArray()
+ {
+ iTestArray[0].iFunctionPtr = &CRunModeAgent::TestDriverSecurity;
+ iTestArray[0].iFunctionName = _L("TestDriverSecurity");
+ iTestArray[1].iFunctionPtr = &CRunModeAgent::TestDllUsage;
+ iTestArray[1].iFunctionName = _L("TestDllUsage");
+ iTestArray[2].iFunctionPtr = &CRunModeAgent::TestSecurity;
+ iTestArray[2].iFunctionName = _L("TestSecurity");
+ iTestArray[3].iFunctionPtr = &CRunModeAgent::TestAttachExecutable;
+ iTestArray[3].iFunctionName = _L("TestAttachExecutable");
+ iTestArray[4].iFunctionPtr = &CRunModeAgent::TestGetExecutablesList;
+ iTestArray[4].iFunctionName = _L("TestGetExecutablesList");
+ iTestArray[5].iFunctionPtr = &CRunModeAgent::TestGetProcessList;
+ iTestArray[5].iFunctionName = _L("TestGetProcessList");
+ iTestArray[6].iFunctionPtr = &CRunModeAgent::TestGetXipLibrariesList;
+ iTestArray[6].iFunctionName = _L("TestGetXipLibrariesList");
+ iTestArray[7].iFunctionPtr = &CRunModeAgent::TestGetThreadList;
+ iTestArray[7].iFunctionName = _L("TestGetThreadList");
+ iTestArray[8].iFunctionPtr = &CRunModeAgent::TestGetCodeSegsList;
+ iTestArray[8].iFunctionName = _L("TestGetCodeSegsList");
+ iTestArray[9].iFunctionPtr = &CRunModeAgent::TestGetListInvalidData;
+ iTestArray[9].iFunctionName = _L("TestGetListInvalidData");
+ iTestArray[10].iFunctionPtr = &CRunModeAgent::TestMemoryAccess;
+ iTestArray[10].iFunctionName = _L("TestMemoryAccess");
+ iTestArray[11].iFunctionPtr = &CRunModeAgent::TestDebugFunctionality;
+ iTestArray[11].iFunctionName = _L("TestDebugFunctionality");
+ iTestArray[12].iFunctionPtr = &CRunModeAgent::TestSuspendResume;
+ iTestArray[12].iFunctionName = _L("TestSuspendResume");
+ iTestArray[13].iFunctionPtr = &CRunModeAgent::TestBreakPoints;
+ iTestArray[13].iFunctionName = _L("TestBreakPoints");
+ iTestArray[14].iFunctionPtr = &CRunModeAgent::TestModifyBreak;
+ iTestArray[14].iFunctionName = _L("TestModifyBreak");
+ iTestArray[15].iFunctionPtr = &CRunModeAgent::TestBreakInfo;
+ iTestArray[15].iFunctionName = _L("TestBreakInfo");
+ iTestArray[16].iFunctionPtr = &CRunModeAgent::TestRunToBreak;
+ iTestArray[16].iFunctionName = _L("TestRunToBreak");
+ iTestArray[17].iFunctionPtr = &CRunModeAgent::TestRegisterAccess;
+ iTestArray[17].iFunctionName = _L("TestRegisterAccess");
+ iTestArray[18].iFunctionPtr = &CRunModeAgent::TestStep;
+ iTestArray[18].iFunctionName = _L("TestStep");
+ iTestArray[19].iFunctionPtr = &CRunModeAgent::TestDemandPaging;
+ iTestArray[19].iFunctionName = _L("TestDemandPaging");
+ iTestArray[20].iFunctionPtr = &CRunModeAgent::TestEventsForExternalProcess;
+ iTestArray[20].iFunctionName = _L("TestEventsForExternalProcess");
+ iTestArray[21].iFunctionPtr = &CRunModeAgent::TestEvents;
+ iTestArray[21].iFunctionName = _L("TestEvents");
+ iTestArray[22].iFunctionPtr = &CRunModeAgent::TestKillProcess;
+ iTestArray[22].iFunctionName = _L("TestKillProcess");
+ iTestArray[23].iFunctionPtr = &CRunModeAgent::TestProcessBreakPoints;
+ iTestArray[23].iFunctionName = _L("TestProcessBreakPoints");
+ iTestArray[24].iFunctionPtr = &CRunModeAgent::TestMultipleTraceEvents;
+ iTestArray[24].iFunctionName = _L("TestMultipleTraceEvents");
+ iTestArray[25].iFunctionPtr = &CRunModeAgent::TestAddRemoveProcessEvents;
+ iTestArray[25].iFunctionName = _L("TestAddRemoveProcessEvents");
+ iTestArray[26].iFunctionPtr = &CRunModeAgent::TestCrashFlash;
+ iTestArray[26].iFunctionName = _L("TestCrashFlash");
+ iTestArray[27].iFunctionPtr = &CRunModeAgent::TestProcessKillBreakpoint;
+ iTestArray[27].iFunctionName = _L("TestProcessKillBreakpoint");
+ };
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+ {
+ TInt ret = KErrNone;
+
+ // client
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+ test.Title();
+ RunModeAgent = CRunModeAgent::NewL();
+ if (RunModeAgent != NULL)
+ {
+ __UHEAP_MARK;
+ TRAP(ret,RunModeAgent->ClientAppL());
+ __UHEAP_MARKEND;
+
+ delete RunModeAgent;
+ }
+
+ delete trap;
+
+ return ret;
+ }
+
+/**
+Helper function to get the aOffset'th value from aFlags
+
+@param aFlags descriptor containing TRegisterFlag type flags
+@param aOffset index of flag value to extract from aFlags
+@param aFlagValue the flag value if function returned successfully
+
+@return KErrNone if value was read successfully, KErrTooBig if aOffset is
+ greater than aFlags.Length()
+*/
+TInt CRunModeAgent::GetFlag(const TDes8& aFlags, const TUint aOffset, TRegisterFlag &aFlagValue) const
+ {
+ //get pointer to data
+ const TUint8 *ptr = aFlags.Ptr();
+
+ //check aOffset is valid
+ TUint length = aFlags.Length();
+ if(aOffset >= length)
+ return KErrTooBig;
+
+ //get flag value
+ aFlagValue = (TRegisterFlag)ptr[aOffset];
+ return KErrNone;
+ }
+
+/**
+ Helper function to set the value of FunctionChooser in the target debug thread.
+
+ @param aTestFunction TTestFunction enum to set FunctionChooser to
+
+ @return KErrNone if the value was set correctly, or one of the other system wide error codes
+ */
+TInt CRunModeAgent::SwitchTestFunction(TTestFunction aTestFunction)
+ {
+ //suspend the target thread
+ TInt suspendError = iServSession.SuspendThread(iThreadID);
+ if(! ( (suspendError == KErrNone) || (suspendError == KErrAlreadyExists) ) )
+ {
+ //the thread is not suspended so exit
+ return suspendError;
+ }
+
+ //get the address of FunctionChooser
+ TUint32 functionChooserAddress = (TUint32)&FunctionChooser;
+ //put the new value for FunctionChooser into a descriptor
+ TPtr8 functionBuf((TUint8*)&aTestFunction, sizeof(TTestFunction), sizeof(TTestFunction));
+ //write the new value into the target thread
+ TInt writeError = iServSession.WriteMemory(iThreadID, functionChooserAddress, sizeof(TTestFunction), functionBuf, EAccess32, EEndLE8);
+
+ if(KErrNone == suspendError)
+ {
+ //if this function suspended the target thread then we need to resume it
+ TInt resumeError = iServSession.ResumeThread(iThreadID);
+ if(KErrNone != resumeError)
+ {
+ //resuming failed so return the error
+ return resumeError;
+ }
+ }
+
+ //suspending and resuming was successful so return the error code from the WriteMemory call
+ return writeError;
+ }
+
+/**
+ Launch a separate process to debug.
+
+ @param aProcess the RProcess object to use to create the process
+ @param aFileName file name of the executable to create the process from
+ @param aFunctionType function that the target process should call on execution
+ @param aDelay delay before the new process should call the function represented by aFunctionType
+ @param aExtraThreads number of extra threads to create in the child process
+
+ @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt CRunModeAgent::LaunchProcess(RProcess& aProcess, const TDesC& aFileName, TDebugFunctionType aFunctionType, TUint32 aDelay, TUint32 aExtraThreads)
+ {
+ // at the moment we support two arguments, this number might have to be increased to support arguments
+ const TUint KMaxCommandLineLength = 32;
+
+ // create a command line buffer
+ RBuf commandLine;
+ commandLine.Create(KMaxCommandLineLength);
+
+ // append the command line arguments to the buffer
+ _LIT(KFArg, "-f");
+ commandLine.Append(KFArg());
+ commandLine.AppendNum(aFunctionType);
+
+ _LIT(KSpace, " ");
+ commandLine.Append(KSpace());
+
+ _LIT(KDArg, "-d");
+ commandLine.Append(KDArg());
+ commandLine.AppendNum(aDelay);
+
+ commandLine.Append(KSpace());
+
+ _LIT(KEArg, "-e");
+ commandLine.Append(KEArg());
+ commandLine.AppendNum(aExtraThreads);
+
+ // create the new process, matching on file name only, not specifying uid values
+ TInt err = aProcess.Create(aFileName, commandLine); // owned by the process
+
+ // check that there was no error raised
+ if(err != KErrNone)
+ {
+ commandLine.Close();
+ return err;
+ }
+
+ TRequestStatus status = KRequestPending;
+ aProcess.Rendezvous(status);
+
+ commandLine.Close(); // after target thread starts
+
+ if(KRequestPending != status.Int())
+ {
+ // startup failed so kill the process
+ aProcess.Kill(KErrNone);
+ return status.Int();
+ }
+ else
+ {
+ // start up succeeded so resume the process
+ aProcess.Resume();
+ User::WaitForRequest(status);
+ if(KErrNone != status.Int())
+ {
+ aProcess.Kill(KErrNone);
+ }
+ return status.Int();
+ }
+ }
+
+/**
+ Helper function to read a tag header from a debug functionality block
+
+ @param aDebugFunctionalityBlock block to read header from
+ @param aTagHdrId header type to find
+
+ @return pointer to the header, or NULL if not available
+ */
+TTagHeader* CRunModeAgent::GetTagHdr(const TDesC8& aDebugFunctionalityBlock, const TTagHeaderId aTagHdrId) const
+ {
+ TUint8* ptr = (TUint8*) aDebugFunctionalityBlock.Ptr();
+ TUint8* blockEnd = ptr + aDebugFunctionalityBlock.Size();
+
+ while(ptr < blockEnd)
+ {
+ TTagHeader* header = (TTagHeader*)ptr;
+ if(header->iTagHdrId == aTagHdrId)
+ {
+ return header;
+ }
+ ptr += sizeof(TTagHeader) + (header->iNumTags * sizeof(TTag));
+ }
+ return NULL;
+ }
+
+/**
+ Helper function to read a tag from a debug functionality block
+
+ @param aTagHdr pointer to a tag header in a debug functionality block
+ @param aElement element to return from the header's data
+
+ @return pointer to the tag, or NULL if not available
+ */
+TTag* CRunModeAgent::GetTag(const TTagHeader* aTagHdr, const TInt aElement) const
+ {
+ TUint8* ptr = (TUint8*)aTagHdr + sizeof(TTagHeader);
+ TUint8* blockEnd = ptr + (aTagHdr->iNumTags * sizeof(TTag));
+
+ while(ptr < blockEnd)
+ {
+ TTag* tag = (TTag*)ptr;
+ if(tag->iTagId == aElement)
+ {
+ return tag;
+ }
+ ptr += sizeof(TTag);
+ }
+ return NULL;
+ }
+
+TTag CRunModeAgent::GetTag(const TTagHeaderId aTagHdrId, const TInt aElement)
+ {
+ TUint32 bufsize = 0; // Safe default size
+
+ // Get functionality block size
+ test(KErrNone == iServSession.GetDebugFunctionalityBufSize(&bufsize));
+
+ // Ensure we have a finite buffer size
+ test(bufsize!=0);
+
+ // Allocate space for the functionality data
+ HBufC8* dftext = HBufC8::NewLC(bufsize);
+
+ // create an empty TPtr8 refering to dftext
+ TPtr8 dftextPtr(dftext->Des());
+
+ // Get the functionality block
+ test(KErrNone == iServSession.GetDebugFunctionality(dftextPtr));
+
+ // read a value from the data to check it has come through as expected
+ TTagHeader* header = GetTagHdr(dftext->Des(), aTagHdrId);
+ test(header != NULL);
+ TTag* tag = GetTag(header, aElement);
+ test(tag != NULL);
+
+ TTag tagToReturn = *tag;
+
+ // Remove our temporary buffer
+ CleanupStack::PopAndDestroy(dftext);
+
+ return tagToReturn;
+ }
+
+/**
+ Helper function which returns a Boolean indicating with a process with the
+ specified name is currently running.
+
+ @param aProcessName - Name of the process to find
+ @return ETrue if found, EFalse otherwise
+ */
+TBool CRunModeAgent::ProcessExists(const TDesC& aProcessName)
+ {
+ TInt err=KErrNone;
+ TBool found = FALSE;
+
+_LIT(KWildCard,"*");
+
+ TFindProcess find(KWildCard);
+ TFullName name;
+ while(find.Next(name)==KErrNone)
+ {
+ RProcess process;
+ err = process.Open(find);
+ if (err == KErrNone)
+ {
+ if (name.Find(aProcessName) != KErrNotFound)
+ {
+ found = TRUE;
+ }
+ process.Close();
+ }
+ }
+
+ return found;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,189 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_H
+#define RMDEBUG_H
+
+#include "t_rmdebug_app.h"
+#include "r_user_low_memory_security_svr_session.h"
+#include "r_kernel_low_memory_security_svr_session.h"
+
+
+class CRunModeAgent;
+
+// Create a pointer to function type
+typedef void (CRunModeAgent::*testFunction)();
+
+class TFunctionData
+ {
+public:
+ testFunction iFunctionPtr;
+ TBuf<40> iFunctionName;
+ };
+
+//number of test functions that we have
+const TInt KMaxTests = 28;
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CRunModeAgent : public CBase
+ {
+public:
+ static CRunModeAgent* NewL();
+ ~CRunModeAgent();
+ void ClientAppL();
+
+private:
+ CRunModeAgent();
+ void ConstructL();
+ void SetupAndAttachToDSS();
+
+ TInt TestStartup();
+ TInt TestShutdown();
+
+ void TestGetExecutablesList();
+ void TestGetProcessList();
+ void TestGetThreadList();
+ void TestGetCodeSegsList();
+ void TestGetXipLibrariesList();
+ void TestGetListInvalidData();
+
+ void DoTestGetThreadList(const TBool aShouldPass, const Debug::TListScope aListScope, const TUint64 aTargetId=0);
+ void DoTestGetCodeSegsList(const TBool aShouldPass, const Debug::TListScope aListScope, const TUint64 aTargetId=0);
+
+ void DoGetList(const Debug::TListId aListId, const Debug::TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId=0);
+
+ void TestMemoryAccess();
+ void TestSuspendResume();
+ void TestBreakPoints();
+ void TestConsecutiveBreakPoints();
+ void TestModifyBreak();
+ void DoTestModifyBreak(TBool aThreadSpecific);
+ void TestBreakInfo();
+ void DoTestBreakInfo(TBool aThreadSpecific);
+ void TestRunToBreak();
+ void DoTestRunToBreak(TBool aThreadSpecific);
+ void TestRegisterAccess();
+ void TestAttachExecutable();
+ void TestDebugFunctionality();
+ void TestStep();
+ void DoTestStep(TBool aThreadSpecific);
+ void TestDriverSecurity();
+ void TestSecurity();
+ void TestEvents();
+ void TestEventsForExternalProcess();
+ void TestDemandPaging();
+ void TestTraceSecurity();
+ void TestDllUsage();
+ void TestKillProcess();
+ void TestProcessBreakPoints();
+ void TestMultipleTraceEvents();
+ void TestAddRemoveProcessEvents();
+ void TestProcessKillBreakpoint();
+ void DoTestProcessKillBreakpoint();
+
+ //crash flash test functions
+ void TestCrashFlash();
+
+ TInt GetFlag(const TDes8 &aFlags, const TUint aOffset, Debug::TRegisterFlag &aFlagValue) const;
+
+ void ReportPerformance(void);
+
+ // helper functions
+ void HelpTestSecurityAttachDetachExecutable(const TDesC& aProcessName, TBool aExpectSuccess);
+
+ TInt HelpTestStepSetBreak(Debug::TBreakId& aBreakId, TThreadId aThreadId, const TUint32 aBreakAddress, Debug::TArchitectureMode aMode, TBool aThreadSpecific=ETrue, TProcessId aProcessId=0);
+ TInt HelpTestStepClearBreak(const Debug::TBreakId aBreakId, const TThreadId aThreadId, TBool aThreadSpecific);
+ TInt HelpTestStepWaitForBreak(const TDesC& aProcessName, Debug::TEventInfo& aEventInfo);
+ TInt HelpTestStepReadPC(TThreadId aThreadId, TUint32& aPC);
+ TInt HelpTestStep(TThreadId aThreadId, TUint32 aStartAddress, TUint32 aEndAddress, Debug::TArchitectureMode aMode, TUint aNumSteps, TBool aThreadSpecific=ETrue, TProcessId=0);
+
+ TInt HelpTicksPerSecond(void);
+
+ // helper functions
+ void HelpStartTestTimer(void) { iStartTick = User::NTickCount(); iStopTick = 0; };
+ void HelpStopTestTimer(void) { iStopTick = User::NTickCount(); };
+ TInt HelpGetTestTicks(void) { return (iStopTick - iStartTick); };
+ TInt SwitchTestFunction(TTestFunction aTestFunction);
+ TInt LaunchProcess(RProcess& aProcess, const TDesC& aFileName, TDebugFunctionType aFunctionType, TUint32 aDelay=0, TUint32 aExtraThreads=0);
+ Debug::TTagHeader* GetTagHdr(const TDesC8& aDebugFunctionalityBlock, const Debug::TTagHeaderId aTagHdrId) const;
+ Debug::TTag* GetTag(const Debug::TTagHeader* aTagHdr, const TInt aElement) const;
+ Debug::TTag GetTag(const Debug::TTagHeaderId aTagHdrId, const TInt aElement);
+ TBool ProcessExists(const TProcessId aProcessId);
+ TBool ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId);
+ TBool ListingSupported(const Debug::TListId aListId, const Debug::TListScope aListScope);
+ void TestEventsWithExtraThreads(Debug::TKernelEventAction aActionMain, Debug::TKernelEventAction aActionExtra, TUint32 aExtraThreads);
+ void FillArray();
+ void PrintUsage();
+ void PrintVersion();
+
+ enum TTestMode
+ {
+ //run all the tests
+ EModeAll = 1<<0,
+ //run the specified tests in reverse order
+ EModeReverse = 1<<1,
+ //print out help
+ EModeHelp = 1<<2,
+ //print out help
+ EModeVersion = 1<<3
+ };
+
+ void RunTest(TInt aTestNumber);
+ void ParseCommandLineL(TUint32& aMode, RArray<TInt>& aTests);
+
+ TBool ProcessExists(const TDesC& aProcessName);
+
+private:
+
+ TFunctionData iTestArray[KMaxTests];
+#if defined(KERNEL_OOM_TESTING)
+ RKernelLowMemorySecuritySvrSession iServSession;
+#elif defined (USER_OOM_TESTING)
+ RUserLowMemorySecuritySvrSession iServSession;
+#else
+ Debug::RSecuritySvrSession iServSession;
+#endif
+ RThread iDebugThread;
+ RProcess iDSSProcess;
+ RSemaphore iAddressGlobSem;
+ TThreadId iThreadID;
+ TFileName iFileName;
+ TUid iMySid;
+
+ // Performance data
+ TInt iMemoryReadKbytesPerSecond;
+ TInt iMemoryWriteKbytesPerSecond;
+ TInt iBreakpointsPerSecond;
+ TInt iMaxBreakpoints;
+ TInt iStepsPerSecond;
+
+ // Timing information
+ TInt iStartTick;
+ TInt iStopTick;
+ };
+
+#endif // RMDEBUG_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,32 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+#include <e32base_private.h>
+
+GLDEF_C TInt E32Main()
+ {
+ // No need to do anything, the only requirement is that
+ // this executable can be loaded and runs to completion
+ return 0;
+ }
+
+// End of file - t_rmdebug2_oemtoken.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/common/t_target_launcher.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,217 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Helper app to launch debug targets. Uses command-line parameters as follows using a + sign:
+// +n<number of applications to launch>
+// +m<number of times to launch each application>
+// +o<order of launch, 1 means launch in reverse order>
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include <hal.h>
+#include <u32hal.h>
+#include <e32property.h>
+
+#include "t_target_launcher.h"
+
+
+/**
+ Launch a process
+
+ @param aProcess The RProcess object to use to create the process
+ @param aExeName File name of the executable to create the process from
+ @param aCommandLine The command line to pass to the new process
+ @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt LaunchProcess(RProcess& aProcess, TDesC & aExeName, TPtr & aCommandLine )
+ {
+
+ TPtrC commandLine( aCommandLine );
+
+ TInt err = aProcess.Create( aExeName, commandLine );
+
+ // check that there was no error raised
+ if(err != KErrNone)
+ {
+ return err;
+ }
+
+ TRequestStatus status = KRequestPending;
+ aProcess.Rendezvous(status);
+
+ if(KRequestPending != status.Int())
+ {
+ // startup failed so kill the process
+ RDebug::Printf( "> RProcess Rendezvous() failed with %d. Killing process", status.Int() );
+ aProcess.Kill(KErrNone);
+ return status.Int();
+ }
+ else
+ {
+ // start up succeeded so resume the process
+ aProcess.Resume();
+ User::WaitForRequest(status);
+ if(KErrNone != status.Int())
+ {
+ RDebug::Printf( "> RProcess Resume() failed with %d. Killing process", status.Int() );
+ aProcess.Kill(KErrNone);
+ }
+ return status.Int();
+ }
+ }
+
+/**
+ * Read command line parameters and control the launching of targets.
+ * Create global launch semaphore KLaunchMutexName
+ */
+void MainL()
+ {
+
+ TInt numApps = KNumApps;
+ TInt numLaunches = KNumLaunches;
+ TInt launchControl = 0;
+
+ TInt argc = User::CommandLineLength();
+ HBufC* commandLine = NULL;
+ RDebug::Printf( ">Launcher Process() argc=%d", argc );
+
+ if( argc )
+ {
+ commandLine = HBufC::NewLC(argc);
+ TPtr commandLineBuffer = commandLine->Des();
+ User::CommandLine(commandLineBuffer);
+
+ RBuf printCommandLine;
+ CleanupClosePushL( printCommandLine );
+ printCommandLine.CreateL( commandLine->Des().Length() );
+ printCommandLine.Copy( commandLine->Des() );
+ printCommandLine.Collapse();
+ RDebug::Printf( ">command line = %S", &printCommandLine );
+ CleanupStack::PopAndDestroy( &printCommandLine );
+
+ // create a lexer and read through the command line
+ TLex lex(*commandLine);
+ while (!lex.Eos())
+ {
+ // only look for options with first character '+', other switches are for the targets
+ if (lex.Get() == '+')
+ {
+ TChar arg = lex.Get();
+ switch (arg)
+ {
+ case 'n':
+ lex.Val( numApps );
+ RDebug::Printf("parsed numApps as %d", numApps);
+ break;
+ case 'm':
+ lex.Val( numLaunches );
+ RDebug::Printf("parsed numLaunches as %d", numLaunches );
+ break;
+ case 'o':
+ lex.Val( launchControl );
+ RDebug::Printf("parsed launchControl as %d", launchControl);
+ break;
+ default:
+ // unknown argument ignore it
+ break;
+ }//switch
+ }// if +
+ }//while
+ }//if argc
+
+ RSemaphore launchMutex;
+ TInt ret = KErrNone;
+ CleanupClosePushL( launchMutex );
+ ret = launchMutex.CreateGlobal( KLaunchMutexName, 0 );
+ RDebug::Printf( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
+ User::LeaveIfError( ret );
+
+ ret = launchMutex.OpenGlobal( KLaunchMutexName );
+ RDebug::Printf( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
+ User::LeaveIfError( ret );
+
+ //Now launch the requested number of apps for the requested number of launches
+ for( ; numLaunches > 0; numLaunches-- )
+ {
+ for( TInt launchIndex = numApps; launchIndex > 0; launchIndex-- )
+ {
+ RDebug::Printf( ">Target Launcher: Mutex wait app %d, launch %d", launchIndex, numLaunches );
+ launchMutex.Wait();
+
+ RBuf targetName;
+ CleanupClosePushL( targetName );
+ RDebug::Printf( ">Target Launcher: targetName.Create %d, launch %d", launchIndex, numLaunches );
+ targetName.Create( KTargetExe().Length() + 2 );
+
+ if( launchControl == 1 )
+ {
+ // Reverse the order of the apps launched by reversing the index in the name
+ RDebug::Printf( ">Target Launcher: targetName.Format %d, launch %d", numApps - launchIndex + 1, numLaunches );
+ targetName.Format( KTargetExe(), numApps - launchIndex + 1 );
+ }
+ else
+ {
+ RDebug::Printf( ">Target Launcher: targetName.Format %d, launch %d", launchIndex, numLaunches );
+ targetName.Format( KTargetExe(), launchIndex );
+ }
+
+ RProcess aProc;
+ CleanupClosePushL( aProc );
+
+ RDebug::Printf( ">Target Launcher: LaunchProcess %d, launch %d", launchIndex, numLaunches );
+ RDebug::Printf( ">LaunchProcess %lS", &targetName );
+ TPtr cmdLinePtr( commandLine->Des() );
+ ret = LaunchProcess( aProc, targetName, cmdLinePtr );
+ CleanupStack::PopAndDestroy( &aProc );
+
+ RDebug::Printf( "<Target Launcher: LaunchProcess returned %d", ret );
+ CleanupStack::PopAndDestroy( &targetName );
+
+ User::LeaveIfError( ret );
+
+ //By now the add proc event should have been delivered to the
+ //test app agent.
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &launchMutex );
+
+ if( commandLine )
+ CleanupStack::PopAndDestroy( commandLine );
+
+ }
+
+
+GLDEF_C TInt E32Main()
+ {
+ RDebug::Printf( ">Launcher Process()" );
+
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+
+ TRAPD(err, MainL());
+ RDebug::Printf( "< Target launching returned %d", err);
+
+ delete trap;
+
+ return err;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/common/t_target_launcher.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,47 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for target launcher
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_TARGET_LAUNCHER_H
+#define RMDEBUG_TARGET_LAUNCHER_H
+
+// Controls how many times the target applications are launched
+const TInt KNumLaunches = 3;
+
+// Controls how many applications are attached and launched
+// If changing this, need to make sure there are enough apps
+// being built. see KTargetExe and t_rmdebug_app*
+const TInt KNumApps = 4;
+
+_LIT(KLaunchMutexName, "t_rmdebug_launch_mutex");
+_LIT(KLaunchMutexNameSearchString, "t_rmdebug_launch_mutex*");
+_LIT(KTargetExe,"z:\\sys\\bin\\t_rmdebug_app%d.exe");
+_LIT8(KTargetExeName,"t_rmdebug_app%d.exe");
+_LIT(KProcessFinder,"*t_rmdebug_app%d*");
+_LIT(KTargetOptions,"-f%d");
+
+_LIT(KZSysBin,"z:\\sys\\bin\\");
+_LIT(KLauncherExe,"z:\\sys\\bin\\t_rmdebug_target_launcher.exe");
+
+_LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+
+#endif // RMDEBUG_TARGET_LAUNCHER_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.cia Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,57 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+
+#include <u32std.h>
+
+// unused function that contains enough padding that the test function
+// RMDebugDemandPagingTest starts in a new page.
+__NAKED__ TInt RMDebugDemandPagingPaddingBefore()
+ {
+ asm("movs r2,r0");
+ asm("adds r0,r2,r1");
+ asm("bx lr");
+ // add padding to make this function 4kb in size.
+ // The 4084 corresponds to 2^12 (=4096) - 12,
+ // the 12 being the total size of the movs, adds and bx instructions.
+ asm(".space 4084");
+ }
+
+// test function which is in a page by itself
+__NAKED__ TInt RMDebugDemandPagingTest()
+ {
+ asm("movs r2,r0");
+ asm("adds r0,r2,r1");
+ asm("bx lr");
+ // add padding to make this function 4kb in size.
+ // The 4084 corresponds to 2^12 (=4096) - 12,
+ // the 12 being the total size of the movs, adds and bx instructions.
+ asm(".space 4084");
+ }
+
+// unused function that contains enough padding to ensure that no used code
+// is in the same page as RMDebugDemandPagingTest
+__NAKED__ TInt RMDebugDemandPagingPaddingAfter()
+ {
+ asm("movs r2,r0");
+ asm("adds r0,r2,r1");
+ asm("bx lr");
+ // add padding to make this function 4kb in size.
+ // The 4084 corresponds to 2^12 (=4096) - 12,
+ // the 12 being the total size of the movs, adds and bx instructions.
+ asm(".space 4084");
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// definitions of functions in d_demand_paging.cia
+//
+
+#ifndef D_DEMAND_PAGING_H
+#define D_DEMAND_PAGING_H
+
+TInt RMDebugDemandPagingTest();
+
+#endif // D_DEMAND_PAGING_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,81 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+// definitions of functions in d_rmdebug_step_tests.s
+//
+
+#ifndef D_RMDEBUG_STEP_TESTS_H
+#define D_RMDEBUG_STEP_TESTS_H
+
+extern "C"
+{
+ // ARM tests
+ unsigned int RMDebug_StepTest_Non_PC_Modifying(void);
+ unsigned int RMDebug_StepTest_Non_PC_Modifying_OK(void);
+
+ unsigned int RMDebug_StepTest_Branch(void);
+ unsigned int RMDebug_StepTest_Branch_1(void);
+
+ unsigned int RMDebug_StepTest_Branch_And_Link(void);
+ unsigned int RMDebug_StepTest_Branch_And_Link_1(void);
+ unsigned int RMDebug_StepTest_Branch_And_Link_2(void);
+
+ unsigned int RMDebug_StepTest_MOV_PC(void);
+ unsigned int RMDebug_StepTest_MOV_PC_1(void);
+ unsigned int RMDebug_StepTest_MOV_PC_2(void);
+
+ unsigned int RMDebug_StepTest_LDR_PC(void);
+ unsigned int RMDebug_StepTest_LDR_PC_1(void);
+
+ // Thumb tests
+ unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying(void);
+ unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying_1(void);
+ unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying_2(void);
+
+ unsigned int RMDebug_StepTest_Thumb_Branch(void);
+ unsigned int RMDebug_StepTest_Thumb_Branch_1(void);
+ unsigned int RMDebug_StepTest_Thumb_Branch_2(void);
+
+ unsigned int RMDebug_StepTest_Thumb_Branch_And_Link(void);
+ unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_1(void);
+ unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_2(void);
+ unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_3(void);
+
+ unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link(void);
+ unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_1(void);
+ unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_2(void);
+ unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_3(void);
+
+ unsigned int RMDebug_StepTest_Thumb_AddPC(void);
+ unsigned int RMDebug_StepTest_Thumb_AddPC_1(void);
+ unsigned int RMDebug_StepTest_Thumb_AddPC_2(void);
+ unsigned int RMDebug_StepTest_Thumb_AddPC_3(void);
+
+ // ARM<->Thumb interworking tests
+ unsigned int RMDebug_StepTest_Interwork(void);
+ unsigned int RMDebug_StepTest_Interwork_1(void);
+ unsigned int RMDebug_StepTest_Interwork_2(void);
+ unsigned int RMDebug_StepTest_Interwork_3(void);
+
+ // Stepping performance test
+ unsigned int RMDebug_StepTest_Count(void);
+ unsigned int RMDebug_StepTest_Count_1(void);
+ unsigned int RMDebug_StepTest_Count_2(void);
+
+ // Multiple step test
+ unsigned int RMDebug_StepTest_ARM_Step_Multiple(void);
+ unsigned int RMDebug_StepTest_ARM_Step_Multiple_1(void);
+
+}
+#endif // D_RMDEBUG_STEP_TESTS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.s Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,267 @@
+; Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:
+;
+;
+
+ AREA |d-rmdebug-bkpt$$Code|, CODE, READONLY, ALIGN=6
+
+ CODE32
+
+ ; ARM tests
+
+;
+; Non-PC modifying
+;
+ EXPORT RMDebug_StepTest_Non_PC_Modifying
+ EXPORT RMDebug_StepTest_Non_PC_Modifying_OK
+
+RMDebug_StepTest_Non_PC_Modifying
+ mov r0,r0 ; nop
+RMDebug_StepTest_Non_PC_Modifying_OK
+ bx lr ; should return to normal execution of the test thread
+
+;
+; Branch
+;
+ EXPORT RMDebug_StepTest_Branch
+ EXPORT RMDebug_StepTest_Branch_1
+
+RMDebug_StepTest_Branch
+ b RMDebug_StepTest_Branch_1
+ mov r0, #2 ; if the pc ends up here, we know its gone wrong
+RMDebug_StepTest_Branch_1
+ bx lr ; return
+
+;
+; Branch and Link
+;
+ EXPORT RMDebug_StepTest_Branch_And_Link
+ EXPORT RMDebug_StepTest_Branch_And_Link_1
+ EXPORT RMDebug_StepTest_Branch_And_Link_2
+
+RMDebug_StepTest_Branch_And_Link
+ mov r0, lr ; preserve lr for the moment
+RMDebug_StepTest_Branch_And_Link_1
+ bl RMDebug_StepTest_Branch_And_Link_2
+ mov r1, #1 ; insert a gap in the instruction stream so we know we branched.
+RMDebug_StepTest_Branch_And_Link_2
+ mov lr, r0 ; restore lr
+ bx lr ; should return to normal execution of the test thread
+
+;
+; MOV PC
+;
+ EXPORT RMDebug_StepTest_MOV_PC
+ EXPORT RMDebug_StepTest_MOV_PC_1
+ EXPORT RMDebug_StepTest_MOV_PC_2
+
+RMDebug_StepTest_MOV_PC
+ mov r0, #4
+RMDebug_StepTest_MOV_PC_1
+ add pc, pc, r0 ; should be a jump (bear in mind reading pc = current inst + 8bytes for arm)
+ mov r0, #1 ; Simple instructions which allow us to test where the PC really is
+ mov r0, #2 ; just by reading r0.
+RMDebug_StepTest_MOV_PC_2
+ mov r0, #3 ;
+ mov r0, #4 ;
+ bx lr ; should return to normal execution of the test thread
+
+;
+; LDR PC
+;
+ EXPORT RMDebug_StepTest_LDR_PC
+ EXPORT RMDebug_StepTest_LDR_PC_1
+
+RMDebug_StepTest_LDR_PC
+ ldr pc, =RMDebug_StepTest_LDR_PC_1
+ mov r0, #1 ; separate the branch target so we can prove it works
+RMDebug_StepTest_LDR_PC_1
+ bx lr ; should return to normal execution of the test thread
+
+;
+; ARM -> Thumb -> ARM interworking test
+;
+; Note: We always start and finish this test
+; in ARM mode.
+ EXPORT RMDebug_StepTest_Interwork
+ EXPORT RMDebug_StepTest_Interwork_1
+ EXPORT RMDebug_StepTest_Interwork_2
+ EXPORT RMDebug_StepTest_Interwork_3
+RMDebug_StepTest_Interwork
+ mov r0, lr ; preserve lr
+RMDebug_StepTest_Interwork_1
+ blx RMDebug_StepTest_Interwork_2
+
+ CODE16
+RMDebug_StepTest_Interwork_2
+ blx RMDebug_StepTest_Interwork_3
+
+ CODE32
+
+RMDebug_StepTest_Interwork_3
+ bx r0
+
+;
+; Stepping performance tests
+;
+; This counts down from 100000 to 0
+; This means that for all practical purposes
+; we can single-step as much as we like
+; in less than one second and have some likelyhood
+; that we will not step too far from our loop
+
+ EXPORT RMDebug_StepTest_Count
+ EXPORT RMDebug_StepTest_Count_1
+ EXPORT RMDebug_StepTest_Count_2
+
+RMDebug_StepTest_Count
+ ldr r2, =100000
+RMDebug_StepTest_Count_1
+ subs r2, r2, #1
+RMDebug_StepTest_Count_2
+ bne RMDebug_StepTest_Count_1
+ bx lr
+
+; Thumb tests
+
+; Thumb non-pc modifying
+;
+;
+RMDebug_StepTest_Thumb_Non_PC_Modifying
+ mov r0, lr ; preserve lr
+ blx RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+ bx r0
+
+;
+; Thumb Branch
+;
+RMDebug_StepTest_Thumb_Branch
+ mov r0, lr ; preserve lr
+ blx RMDebug_StepTest_Thumb_Branch_1
+ bx r0
+
+;
+; Thumb Branch and link
+;
+RMDebug_StepTest_Thumb_Branch_And_Link
+ mov r0, lr ; preserve lr
+ blx RMDebug_StepTest_Thumb_Branch_And_Link_1
+ bx r0
+
+;
+; Thumb Back Branch and link
+;
+RMDebug_StepTest_Thumb_Back_Branch_And_Link
+ mov r0, lr ; preserve lr
+ blx RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+ bx r0
+
+;
+; Thumb ADD PC,PC, #0
+;
+RMDebug_StepTest_Thumb_AddPC
+ mov r0, lr ; preserve lr
+ blx RMDebug_StepTest_Thumb_AddPC_1
+ bx r0
+
+ CODE16
+
+ ; Thumb tests
+ EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying
+ EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+ EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying_2
+
+ EXPORT RMDebug_StepTest_Thumb_Branch
+ EXPORT RMDebug_StepTest_Thumb_Branch_1
+ EXPORT RMDebug_StepTest_Thumb_Branch_2
+
+ EXPORT RMDebug_StepTest_Thumb_Branch_And_Link
+ EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_1
+ EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_2
+ EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_3
+
+ EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link
+ EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+ EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_2
+ EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+
+RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+ mov r0, r0 ; nop
+RMDebug_StepTest_Thumb_Non_PC_Modifying_2
+ bx lr
+
+RMDebug_StepTest_Thumb_Branch_1
+ b RMDebug_StepTest_Thumb_Branch_2
+ mov r0, r0
+RMDebug_StepTest_Thumb_Branch_2
+ bx lr
+
+RMDebug_StepTest_Thumb_Branch_And_Link_1
+ mov r1, lr
+RMDebug_StepTest_Thumb_Branch_And_Link_2
+ bl RMDebug_StepTest_Thumb_Branch_And_Link_3
+ mov r0, r0
+RMDebug_StepTest_Thumb_Branch_And_Link_3
+ bx r1
+
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+ bx r1
+
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+ mov r1, lr
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_2
+ bl RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+ bx r1
+
+;
+; ADD PC
+;
+ EXPORT RMDebug_StepTest_Thumb_AddPC
+ EXPORT RMDebug_StepTest_Thumb_AddPC_1
+ EXPORT RMDebug_StepTest_Thumb_AddPC_2
+ EXPORT RMDebug_StepTest_Thumb_AddPC_3
+
+RMDebug_StepTest_Thumb_AddPC_1
+ mov r1, lr
+ mov r2, #4
+RMDebug_StepTest_Thumb_AddPC_2
+ add pc, pc, r2 ; should arrive at RMDebug_StepTest_Thumb_AddPC_3
+ mov r0, r0
+ mov r0, r0
+ mov r0, r0
+RMDebug_StepTest_Thumb_AddPC_3
+ bx r1
+
+ ALIGN 4
+
+ CODE32
+
+;
+; ARM multiple-step ( 5 steps )
+;
+ EXPORT RMDebug_StepTest_ARM_Step_Multiple
+ EXPORT RMDebug_StepTest_ARM_Step_Multiple_1
+
+RMDebug_StepTest_ARM_Step_Multiple
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+RMDebug_StepTest_ARM_Step_Multiple_1
+ bx lr
+
+ END
+
+; End of file - d_rmdebug_bkpt.s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,50 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// definitions of functions in d_rmdebug_step_tests_armv4.s
+//
+
+#ifndef D_RMDEBUG_STEP_TESTS_H
+#define D_RMDEBUG_STEP_TESTS_H
+
+extern "C"
+{
+ // ARM tests
+ unsigned int RMDebug_StepTest_Non_PC_Modifying(void);
+ unsigned int RMDebug_StepTest_Non_PC_Modifying_OK(void);
+
+ unsigned int RMDebug_StepTest_Branch(void);
+ unsigned int RMDebug_StepTest_Branch_1(void);
+
+ unsigned int RMDebug_StepTest_Branch_And_Link(void);
+ unsigned int RMDebug_StepTest_Branch_And_Link_1(void);
+ unsigned int RMDebug_StepTest_Branch_And_Link_2(void);
+
+ unsigned int RMDebug_StepTest_MOV_PC(void);
+ unsigned int RMDebug_StepTest_MOV_PC_1(void);
+ unsigned int RMDebug_StepTest_MOV_PC_2(void);
+
+ unsigned int RMDebug_StepTest_LDR_PC(void);
+ unsigned int RMDebug_StepTest_LDR_PC_1(void);
+
+ // Stepping performance test
+ unsigned int RMDebug_StepTest_Count(void);
+ unsigned int RMDebug_StepTest_Count_1(void);
+ unsigned int RMDebug_StepTest_Count_2(void);
+
+ // Multiple step test
+ unsigned int RMDebug_StepTest_ARM_Step_Multiple(void);
+ unsigned int RMDebug_StepTest_ARM_Step_Multiple_1(void);
+
+}
+#endif // D_RMDEBUG_STEP_TESTS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.s Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,130 @@
+; Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "Eclipse Public License v1.0"
+; which accompanies this distribution, and is available
+; at the URL "http://www.eclipse.org/legal/epl-v10.html".
+;
+; Initial Contributors:
+; Nokia Corporation - initial contribution.
+;
+; Contributors:
+;
+; Description:
+;
+;
+
+ AREA |d-rmdebug-bkpt$$Code|, CODE, READONLY, ALIGN=6
+
+ CODE32
+
+ ; ARM tests
+
+;
+; Non-PC modifying
+;
+ EXPORT RMDebug_StepTest_Non_PC_Modifying
+ EXPORT RMDebug_StepTest_Non_PC_Modifying_OK
+
+RMDebug_StepTest_Non_PC_Modifying
+ mov r0,r0 ; nop
+RMDebug_StepTest_Non_PC_Modifying_OK
+ bx lr ; should return to normal execution of the test thread
+
+;
+; Branch
+;
+ EXPORT RMDebug_StepTest_Branch
+ EXPORT RMDebug_StepTest_Branch_1
+
+RMDebug_StepTest_Branch
+ b RMDebug_StepTest_Branch_1
+ mov r0, #2 ; if the pc ends up here, we know its gone wrong
+RMDebug_StepTest_Branch_1
+ bx lr ; return
+
+;
+; Branch and Link
+;
+ EXPORT RMDebug_StepTest_Branch_And_Link
+ EXPORT RMDebug_StepTest_Branch_And_Link_1
+ EXPORT RMDebug_StepTest_Branch_And_Link_2
+
+RMDebug_StepTest_Branch_And_Link
+ mov r0, lr ; preserve lr for the moment
+RMDebug_StepTest_Branch_And_Link_1
+ bl RMDebug_StepTest_Branch_And_Link_2
+ mov r1, #1 ; insert a gap in the instruction stream so we know we branched.
+RMDebug_StepTest_Branch_And_Link_2
+ mov lr, r0 ; restore lr
+ bx lr ; should return to normal execution of the test thread
+
+;
+; MOV PC
+;
+ EXPORT RMDebug_StepTest_MOV_PC
+ EXPORT RMDebug_StepTest_MOV_PC_1
+ EXPORT RMDebug_StepTest_MOV_PC_2
+
+RMDebug_StepTest_MOV_PC
+ mov r0, #4
+RMDebug_StepTest_MOV_PC_1
+ add pc, pc, r0 ; should be a jump (bear in mind reading pc = current inst + 8bytes for arm)
+ mov r0, #1 ; Simple instructions which allow us to test where the PC really is
+ mov r0, #2 ; just by reading r0.
+RMDebug_StepTest_MOV_PC_2
+ mov r0, #3 ;
+ mov r0, #4 ;
+ bx lr ; should return to normal execution of the test thread
+
+;
+; LDR PC
+;
+ EXPORT RMDebug_StepTest_LDR_PC
+ EXPORT RMDebug_StepTest_LDR_PC_1
+
+RMDebug_StepTest_LDR_PC
+ ldr pc, =RMDebug_StepTest_LDR_PC_1
+ mov r0, #1 ; separate the branch target so we can prove it works
+RMDebug_StepTest_LDR_PC_1
+ bx lr ; should return to normal execution of the test thread
+
+;
+; Stepping performance tests
+;
+; This counts down from 100000 to 0
+; This means that for all practical purposes
+; we can single-step as much as we like
+; in less than one second and have some likelyhood
+; that we will not step too far from our loop
+
+ EXPORT RMDebug_StepTest_Count
+ EXPORT RMDebug_StepTest_Count_1
+ EXPORT RMDebug_StepTest_Count_2
+
+RMDebug_StepTest_Count
+ ldr r2, =100000
+RMDebug_StepTest_Count_1
+ subs r2, r2, #1
+RMDebug_StepTest_Count_2
+ bne RMDebug_StepTest_Count_1
+ bx lr
+
+;
+; ARM multiple-step ( 5 steps )
+;
+ EXPORT RMDebug_StepTest_ARM_Step_Multiple
+ EXPORT RMDebug_StepTest_ARM_Step_Multiple_1
+
+RMDebug_StepTest_ARM_Step_Multiple
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+ mov r0,r0 ; nop
+RMDebug_StepTest_ARM_Step_Multiple_1
+ bx lr
+
+ END
+
+; End of file - d_rmdebug_step_test_armv4.s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,106 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements a debug thread for testing.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include "d_rmdebugthread.h"
+
+EXPORT_C TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+extern void RMDebug_BranchTst1();
+
+EXPORT_C TInt TestData;
+
+CDebugServThread::CDebugServThread()
+//
+// Empty constructor
+//
+ {
+ }
+
+GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*)
+//
+// Generic thread function for testing
+//
+ {
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ if (cleanup == NULL)
+ {
+ User::Leave(KErrNoMemory);
+ }
+
+ RThread::Rendezvous(KErrNone);
+
+ TestData = 1;
+
+ while(1)
+ {
+ RMDebug_BranchTst1();
+
+ TestData++;
+
+ // Wait half a second (suspends this thread)
+ User::After(500000);
+
+ if (TestData == 0xFFFFFFFF)
+ {
+ break;
+ }
+ }
+
+ delete cleanup;
+
+ return (KErrNone);
+ }
+
+EXPORT_C TInt StartDebugThread(RThread& aDebugThread)
+//
+// Starts the test thread
+//
+{
+ TInt res=KErrNone;
+
+ // Create the thread
+ res = aDebugThread.Create( KDebugThreadName,
+ CDebugServThread::ThreadFunction,
+ KDefaultStackSize,
+ KDebugThreadDefaultHeapSize,
+ KDebugThreadDefaultHeapSize,
+ NULL
+ );
+
+ // Check that the creation worked
+ if (res == KErrNone)
+ {
+ TRequestStatus rendezvousStatus;
+
+ aDebugThread.SetPriority(EPriorityNormal);
+ // Make a request for a rendezvous
+ aDebugThread.Rendezvous(rendezvousStatus);
+ // Set the thread as ready for execution
+ aDebugThread.Resume();
+ // Wait for the resumption
+ User::WaitForRequest(rendezvousStatus);
+ }
+ else
+ {
+ // Close the handle.
+ aDebugThread.Close();
+ }
+
+ return res;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// t_rmdebugthread.h
+// Definitions for the run mode debug test thread.
+//
+//
+
+#ifndef RMDEBUGSVRTHRD_H
+#define RMDEBUGSVRTHRD_H
+
+#define SYMBIAN_RMDBG_MEMORYSIZE 1024*4
+
+// Thread name
+_LIT(KDebugThreadName,"DebugThread");
+
+const TUint KDebugThreadDefaultHeapSize=0x10000;
+
+class CDebugServThread : public CBase
+ {
+ public:
+ CDebugServThread();
+ static TInt ThreadFunction(TAny* aStarted);
+
+ public:
+ };
+
+#endif // RMDEBUGSVRTHRD_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,214 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements a debug thread for testing.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32debug.h>
+#include "d_rmdebugthread2.h"
+
+#include "d_rmdebug_step_test.h"
+#include "d_demand_paging.h"
+
+EXPORT_C TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+IMPORT_C extern void RMDebug_BranchTst1();
+IMPORT_C extern TInt RMDebugDemandPagingTest();
+
+EXPORT_C TInt TestData;
+EXPORT_C TTestFunction FunctionChooser;
+
+const TInt KNumberOfTraceCalls = 50;
+
+EXPORT_C TInt TestFunction()
+ {
+ // Set TestData to an arbitrary value that can be checked by a tester
+ TestData = 0xffeeddcc;
+ RMDebug_BranchTst1();
+
+ // Code here may not be executed because tests can change the PC value
+ // at any time, typically once the test passes
+ return 0;
+ }
+
+/**
+ Wrapper around RMDebugDemandPagingTest, need to pause for a short time to
+ allow time in t_rmdebug.cpp to issue a User::WaitForRequest to catch the break point
+ */
+EXPORT_C void TestPagedCode()
+ {
+ User::After(100000);
+
+ // call the function in paged code
+ RMDebugDemandPagingTest();
+ }
+
+EXPORT_C void TestMultipleTraceCalls()
+ {
+ //arbitrary function to set a BP on
+ RMDebug_BranchTst1();
+
+ // The tester will change FunctionChooser once it gets what it needs out of the test
+ for(TInt cnt = KNumberOfTraceCalls; cnt>0 && (FunctionChooser==EMultipleTraceCalls); cnt--)
+ {
+ RDebug::Printf("T");
+ RDebug::Printf("R");
+ RDebug::Printf("A");
+ RDebug::Printf("C");
+ RDebug::Printf("E");
+ }
+
+ //another arbitrary function to set a BP on
+ RMDebug_StepTest_Non_PC_Modifying();
+ }
+
+CDebugServThread::CDebugServThread()
+//
+// Empty constructor
+//
+ {
+ }
+
+GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*)
+//
+// Generic thread function for testing
+//
+ {
+ // set FunctionChooser to run the default function
+ FunctionChooser = EDefaultFunction;
+
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ if (cleanup == NULL)
+ {
+ User::Leave(KErrNoMemory);
+ }
+
+ RThread::Rendezvous(KErrNone);
+
+ TestData = 1;
+
+ /* Beware of adding printf or other debug-generating events in this loop because
+ * they interfere with the tests
+ */
+ while(TestData != 0xFFFFFFFF)
+ {
+ switch(FunctionChooser)
+ {
+ case EDemandPagingFunction:
+ TestPagedCode();
+ break;
+ case EDefaultFunction:
+ // the default function is the stepping test functions
+ case EStepFunction:
+ {
+ RMDebug_BranchTst1();
+
+ // Single stepping test support code
+
+ // ARM tests
+ RMDebug_StepTest_Non_PC_Modifying();
+
+ RMDebug_StepTest_Branch();
+
+ RMDebug_StepTest_Branch_And_Link();
+
+ RMDebug_StepTest_MOV_PC();
+
+ RMDebug_StepTest_LDR_PC();
+
+// thumb/interworking tests not supported on armv4
+#ifdef __MARM_ARMV5__
+
+ // Thumb tests
+ RMDebug_StepTest_Thumb_Non_PC_Modifying();
+
+ RMDebug_StepTest_Thumb_Branch();
+
+ RMDebug_StepTest_Thumb_Branch_And_Link();
+
+ RMDebug_StepTest_Thumb_Back_Branch_And_Link();
+
+ // ARM <-> Thumb interworking tests
+ RMDebug_StepTest_Interwork();
+
+ RMDebug_StepTest_Thumb_AddPC();
+
+#endif // __MARM_ARMV5__
+
+ // Single-stepping performance
+ RMDebug_StepTest_Count();
+
+ // multiple step test
+ RMDebug_StepTest_ARM_Step_Multiple();
+
+ TestData++;
+
+ // Wait 50mSecs. // (suspends this thread)
+ User::After(50000);
+
+ break;
+ }
+ case EMultipleTraceCalls:
+ TestMultipleTraceCalls();
+ break;
+ default:
+ //do nothing
+ break;
+ }
+ }
+
+ delete cleanup;
+
+ return (KErrNone);
+ }
+
+EXPORT_C TInt StartDebugThread(RThread& aDebugThread, const TDesC& aDebugThreadName)
+//
+// Starts a test thread
+//
+{
+ TInt res=KErrNone;
+
+ // Create the thread
+ res = aDebugThread.Create( aDebugThreadName,
+ CDebugServThread::ThreadFunction,
+ KDefaultStackSize,
+ KDebugThreadDefaultHeapSize,
+ KDebugThreadDefaultHeapSize,
+ NULL
+ );
+
+ // Check that the creation worked
+ if (res == KErrNone)
+ {
+ TRequestStatus rendezvousStatus;
+
+ aDebugThread.SetPriority(EPriorityNormal);
+ // Make a request for a rendezvous
+ aDebugThread.Rendezvous(rendezvousStatus);
+ // Set the thread as ready for execution
+ aDebugThread.Resume();
+ // Wait for the resumption
+ User::WaitForRequest(rendezvousStatus);
+ }
+ else
+ {
+ // Close the handle.
+ aDebugThread.Close();
+ }
+
+ return res;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,51 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug test thread.
+//
+//
+
+#ifndef RMDEBUGSVRTHRD_H
+#define RMDEBUGSVRTHRD_H
+
+#define SYMBIAN_RMDBG_MEMORYSIZE 1024*4
+
+// Thread name
+_LIT(KDebugThreadName,"DebugThread");
+
+const TUint KDebugThreadDefaultHeapSize=0x10000;
+
+// enumeration of functions which the target debug thread can call, the
+// debugger can choose to switch the thread to a different function by
+// writing the appropriate enumeration value into FunctionChooser, the
+// target thread will finish executing the function it is currently running
+// then execute the chosen function.
+enum TTestFunction
+ {
+ EDefaultFunction = 0,
+ EStepFunction = 1,
+ EDemandPagingFunction = 2,
+ EMultipleTraceCalls = 3,
+ EDoNothing = 4
+ };
+
+class CDebugServThread : public CBase
+ {
+ public:
+ CDebugServThread();
+ static TInt ThreadFunction(TAny* aStarted);
+
+ public:
+ };
+
+#endif // RMDEBUGSVRTHRD_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm.cia Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,32 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// d_rmdebugthreadasm.h
+// Assembler file for debug thread testing.
+//
+//
+
+//#include <e32cia.h>
+//#include <e32base.h>
+//#include <e32cons.h>
+//#include "d_rmdebugthread.h"
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+//
+//
+{
+ asm("mov r0, #0 "); // aResult==KErrNone
+ asm("bx lr "); // Return
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// d_rmdebugthreadasm2.h
+// Assembler file for debug thread testing.
+//
+//
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+//
+//
+{
+ asm("mov r0, #0 "); // aResult==KErrNone
+ asm("bx lr "); // Return
+}
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst2( void )
+//
+//
+//
+{
+ asm("mov r0, #0 "); // aResult==KErrNone
+ asm("bx lr "); // Return
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,380 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <e32debug.h>
+#include <e32property.h>
+#include <u32hal.h>
+#include <f32file.h>
+
+
+
+#include "t_rmdebug_app.h"
+
+IMPORT_C extern void RMDebug_BranchTst2();
+
+LOCAL_C void ParseCommandLineL(TInt32& aFunctionType, TUint& aDelay, TUint& aExtraThreads, TInt32& aCpuNumber)
+ {
+ // get the length of the command line arguments
+ TInt argc = User::CommandLineLength();
+ RDebug::Printf(" t_rmdebug_app: ParseCommandLineL argc=%d", argc);
+
+ // allocate a buffer for the command line arguments and extract the data to it
+ HBufC* commandLine = HBufC::NewLC(argc);
+ TPtr commandLineBuffer = commandLine->Des();
+ User::CommandLine(commandLineBuffer);
+
+ // create a lexer and read through the command line
+ TLex lex(*commandLine);
+ while (!lex.Eos())
+ {
+ // expecting the first character to be a '-'
+ if (lex.Get() == '-')
+ {
+ TChar arg = lex.Get();
+ switch (arg)
+ {
+ case 'f':
+ // the digits following '-f' give the function type
+ User::LeaveIfError(lex.Val(aFunctionType));
+ RDebug::Printf(" t_rmdebug_app: setting aFunctionType=%d", aFunctionType);
+ break;
+ case 'd':
+ // the digits following '-d' give the delay
+ User::LeaveIfError(lex.Val(aDelay));
+ RDebug::Printf(" t_rmdebug_app: setting aDelay=%d", aDelay);
+ break;
+ case 'e':
+ // the digits following '-e' give the number of extra threads to launch
+ User::LeaveIfError(lex.Val(aExtraThreads));
+ RDebug::Printf(" t_rmdebug_app: setting aExtraThreads=%d", aExtraThreads);
+ break;
+
+ case 'a':
+ // the digits following '-a' gives the cpu on which this thread will execute on
+ User::LeaveIfError(lex.Val(aCpuNumber));
+ RDebug::Printf(" t_rmdebug_app: CPU Number=%d", aCpuNumber);
+ break;
+
+ default:
+ // unknown argument so leave
+ User::Leave(KErrArgument);
+ }
+ lex.SkipSpace();
+ }
+ else
+ {
+ // unknown argument so leave
+ User::Leave(KErrArgument);
+ }
+ }
+
+ // do clean up
+ CleanupStack::PopAndDestroy(commandLine);
+ }
+
+typedef void (*TPfun)();
+
+// test function to call corresponding to EPrefetchAbortFunction
+void PrefetchAbort()
+ {
+ TPfun f = NULL;
+ f();
+ }
+
+// test function to call corresponding to EUserPanicFunction
+void UserPanic()
+ {
+ User::Panic(KUserPanic, KUserPanicCode);
+ }
+
+// calls self repeatedly until stack is used up. Slightly convoluted to prevent UREL optimising this out...
+TUint32 StackOverFlowFunction(TUint32 aInt=0)
+ {
+ TUint32 unusedArray[150];
+ for(TInt i=0; i<150; i++)
+ {
+ unusedArray[i] = StackOverFlowFunction(i);
+ }
+ return unusedArray[0];
+ }
+
+void DataAbort()
+ {
+ TInt* r = (TInt*) 0x1000;
+ *r = 0x42;
+ }
+
+void UndefInstruction()
+ {
+ TUint32 undef = 0xE6000010;
+ TPfun f = (TPfun) &undef;
+ f();
+ }
+
+TInt DataRead()
+ {
+ TInt* r = (TInt*) 0x1000;
+ TInt rr = (TInt)*r;
+ //include the following line to ensure that rr doesn't get optimised out
+ RDebug::Printf("Shouldn't see this being printed out: %d", rr);
+
+ // Stop compilation warning. Should not get here anyway.
+ rr++;
+ return rr;
+ }
+
+void DataWrite()
+ {
+ TInt* r = (TInt*) 0x1000;
+ *r = 0x42;
+ }
+
+void UserException()
+ {
+ User::RaiseException(EExcGeneral);
+ }
+
+void SpinForeverWithBreakPoint()
+ {
+
+ // finding the process t_rmdebug2/t_rmdebug2_oem/t_rmdebug2_oem2
+ // we find the process.SID to attach to the property
+ _LIT(KThreadWildCard, "t_rmdebug2*");
+
+ TInt err = KErrNone;
+ TUid propertySid = KNullUid;
+ TFindThread find(KThreadWildCard);
+ TFullName name;
+ TBool found = EFalse;
+ while(find.Next(name)==KErrNone && !found)
+ {
+ RThread thread;
+ err = thread.Open(find);
+ if (err == KErrNone)
+ {
+ RProcess process;
+ thread.Process(process);
+ TFullName fullname = thread.FullName();
+ //RDebug::Printf("SID Search Match Found Name %lS Process ID%ld Thread Id %ld", &fullname, process.Id().Id(), thread.Id().Id());
+ found = ETrue;
+ //SID saved so that the property can be attached to
+ propertySid = process.SecureId();
+ process.Close();
+ }
+ thread.Close();
+ }
+
+ //attach to the property to publish the address of the RMDebug_BranchTst2 with the correct SID value
+ RProperty integerProperty;
+ err = integerProperty.Attach(propertySid, EMyPropertyInteger, EOwnerThread);
+ if(KErrNone != err)
+ RDebug::Printf("Error Attach to the property %d", err);
+
+ TInt address = (TInt)&RMDebug_BranchTst2;
+
+ // publish the address where the breakpoint would be set
+ err = integerProperty.Set(address);
+ if(KErrNone != err)
+ RDebug::Printf("Error Set of the property %d", err);
+ integerProperty.Close();
+
+ //open semaphore to signal the fact we have reached the point where we have to set the property
+ RSemaphore globsem;
+ globsem.OpenGlobal(_L("RMDebugGlobSem"));
+ globsem.Signal();
+ globsem.Close();
+
+ RProcess thisProcess;
+ TFileName thisProcessName = thisProcess.FileName();
+ RDebug::Printf("App Process Name %lS process id %ld thread id %ld", &thisProcessName, thisProcess.Id().Id(), RThread().Id().Id());
+
+ TInt i=0;
+ RThread::Rendezvous(KErrNone);
+ while(i<0xffffffff)
+ {
+ RMDebug_BranchTst2();
+ User::After(10000);
+ }
+ }
+
+void SpinForever()
+ {
+ TInt i=0;
+ RThread::Rendezvous(KErrNone);
+ while(i<0xffffffff)
+ {
+ User::After(10000);
+ }
+ }
+
+void NormalExit()
+ {
+ RDebug::Printf("Target app: NormalExit() function. Returning to MainL" );
+ }
+
+void LaunchThreads(TUint aNumber)
+ {
+ _LIT(KDebugThreadName, "DebugThread");
+ const TUint KDebugThreadDefaultHeapSize=0x10000;
+ for(TInt i=0; i<aNumber; i++)
+ {
+ RThread thread;
+ RBuf threadName;
+ threadName.Create(KDebugThreadName().Length()+10); // the 10 is for appending i to the end of the name
+ threadName.Append(KDebugThreadName());
+ threadName.AppendNum(i);
+ TInt err = thread.Create(threadName, (TThreadFunction)SpinForever, KDefaultStackSize, KDebugThreadDefaultHeapSize, KDebugThreadDefaultHeapSize, NULL);
+ if(err != KErrNone)
+ {
+ RDebug::Printf("Couldn't create thread %d", err);
+ threadName.Close();
+ thread.Close();
+ break;
+ }
+ thread.SetPriority(EPriorityNormal);
+ TRequestStatus status;
+ thread.Rendezvous(status);
+ thread.Resume();
+ User::WaitForRequest(status);
+ thread.Close();
+ threadName.Close();
+ }
+ }
+
+void WaitFiveSecondsThenExit(void)
+ {
+ // wait for 5 seconds
+ User::After(5000000);
+ }
+
+TInt NumberOfCpus()
+ {
+ TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
+ return r;
+ }
+
+TInt SetCpuAffinity(TInt aCpuNumber)
+ {
+ TInt TestCpuCount = NumberOfCpus();
+ RDebug::Printf("SetCpuAffinity --> TestCpuCount = %d\n", TestCpuCount);
+ TUint32 cpu = 0;
+
+ if ((aCpuNumber % TestCpuCount) != 0)
+ cpu = (TUint32)(aCpuNumber % TestCpuCount);
+
+ RDebug::Printf("SetCpuAffinity --> Setting cpu %3d\n", cpu);
+ TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
+ return r;
+ }
+
+// call the function corresponding to aFunctionType
+LOCAL_C void CallFunction(TDebugFunctionType aFunctionType, TUint aDelay, TUint aExtraThreads, TInt32 aCpuNumber)
+ {
+ // pause for aDelay microseconds
+ User::After(aDelay);
+
+ // set cpu on which this thread should execute on
+ if (aCpuNumber)
+ SetCpuAffinity(aCpuNumber);
+
+ // launch the extra threads
+ LaunchThreads(aExtraThreads);
+
+ // call appropriate function
+ switch( aFunctionType )
+ {
+ case EPrefetchAbortFunction:
+ PrefetchAbort();
+ break;
+ case EUserPanicFunction:
+ UserPanic();
+ break;
+ case EStackOverflowFunction:
+ StackOverFlowFunction();
+ break;
+ case EDataAbortFunction:
+ DataAbort();
+ break;
+ case EUndefInstructionFunction:
+ UndefInstruction();
+ break;
+ case EDataReadErrorFunction:
+ DataRead();
+ break;
+ case EDataWriteErrorFunction:
+ DataWrite();
+ break;
+ case EUserExceptionFunction:
+ UserException();
+ break;
+ case EWaitFiveSecondsThenExit:
+ WaitFiveSecondsThenExit();
+ break;
+ case ESpinForever:
+ SpinForever();
+ break;
+ case ESpinForeverWithBreakPoint:
+ SpinForeverWithBreakPoint();
+ break;
+ case ENormalExit:
+ NormalExit();
+ break;
+ case EDefaultDebugFunction:
+ default:
+ break;
+ }
+ }
+
+void PrintHelp()
+ {
+ RDebug::Printf("Invoke with arguments:\n");
+ RDebug::Printf("\t-d<delay>\n\t: delay in microseconds before calling target function\n");
+ RDebug::Printf("\t-f<function-number>\n\t: enumerator from TDebugFunctionType representing function to call\n");
+ RDebug::Printf("\t-e<number>\n\t: number of extra threads to launch, these threads run endlessly\n");
+ }
+
+
+TInt E32Main()
+ {
+ // setup heap checking and clean up trap
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ RThread().SetPriority(EPriorityNormal);
+ RProcess::Rendezvous(KErrNone);
+
+ // read arguments from command line
+ TUint delay = 0;
+ TInt32 functionTypeAsTInt32 = (TInt32)EDefaultDebugFunction;
+ TUint extraThreads = 0;
+ TInt32 aCpuNumber = -1;
+
+ TRAPD(err, ParseCommandLineL(functionTypeAsTInt32, delay, extraThreads, aCpuNumber));
+
+ if(KErrNone == err)
+ {
+ // if the command line arguments were successfully read then call the appropriate function
+ CallFunction((TDebugFunctionType)functionTypeAsTInt32, delay, extraThreads, aCpuNumber);
+ }
+
+ // perform clean up and return any error which was recorded
+ delete cleanup;
+ __UHEAP_MARKEND;
+ return err;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#ifndef T_RMDEBUG_APP_H
+#define T_RMDEBUG_APP_H
+
+_LIT(KRMDebugTestApplication, "z:\\sys\\bin\\t_rmdebug_app.exe");
+_LIT(KUserPanic, "UserPanic");
+const TInt KUserPanicCode = 0x1234ABCD;
+enum TMyPropertyKeys {EMyPropertyInteger};
+
+
+// enumeration of functions to call in test debug application
+enum TDebugFunctionType
+ {
+ EDefaultDebugFunction,
+ EPrefetchAbortFunction,
+ EUserPanicFunction,
+ EStackOverflowFunction,
+ EDataAbortFunction,
+ EUndefInstructionFunction,
+ EDataReadErrorFunction,
+ EDataWriteErrorFunction,
+ EUserExceptionFunction,
+ EWaitFiveSecondsThenExit,
+ ESpinForever,
+ ESpinForeverWithBreakPoint,
+ ENormalExit
+ };
+
+#endif //T_RMDEBUG_APP_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,25 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32std.h>
+#include <e32std_private.h>
+#include <rm_debug_api.h>
+#include "t_rmdebug_dll.h"
+
+EXPORT_C TUid GetDSSUid()
+ {
+ return Debug::KUidDebugSecurityServer;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32std.h>
+
+/**
+ This is a simple function that uses an element from rm_debug_api.h.
+ If the e32tests can be built and run then this is 'proof' that the
+ rm_debug_api.h header file can be #include'd into a dll
+ */
+IMPORT_C TUid GetDSSUid();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,100 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged by t_rmdebug.exe when testing
+// security restrictions. This application is built with various
+// capabilities by the t_rmdebug_securityX.mmp files. This allows
+// the t_rmdebug2 program to ensure that security restrictions are
+// properly enforced by the DSS/DDD subsystem.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include "t_rmdebug_security.h"
+
+CRunModeApp* CRunModeApp::NewL()
+//
+// CRunModeApp::NewL
+//
+ {
+ CRunModeApp* self = new(ELeave) CRunModeApp();
+
+ self->ConstructL();
+
+ return self;
+ }
+
+CRunModeApp::CRunModeApp()
+//
+// CRunModeApp constructor
+//
+ {
+ }
+
+CRunModeApp::~CRunModeApp()
+//
+// CRunModeApp destructor
+//
+ {
+ }
+
+void CRunModeApp::ConstructL()
+//
+// CRunModeApp::ConstructL
+//
+ {
+ }
+
+void CRunModeApp::TestWaitDebug()
+//
+// CRunModeApp::TestWaitDebug
+//
+ {
+ RProcess::Rendezvous(KErrNone);
+
+ // Wait a 3secs then quit (long enough to test, but not hang around forever)
+ User::After(3000000);
+ }
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug app test program
+//
+ {
+ TInt ret = KErrNone;
+
+ // client
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+
+ CRunModeApp* myApp = CRunModeApp::NewL();
+ if (myApp != NULL)
+ {
+ __UHEAP_MARK;
+ TRAP(ret,myApp->TestWaitDebug());
+ __UHEAP_MARKEND;
+
+ delete myApp;
+ }
+
+ delete trap;
+
+ return ret;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged by t_rmdebug2.exe when testing
+// security restrictions. This application is built with various
+// capabilities by the t_rmdebug_securityX.mmp files. This allows
+// the t_rmdebug2 program to ensure that security restrictions are
+// properly enforced by the DSS/DDD subsystem.
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef T_RMDEBUG_SECURITY_H
+#define T_RMDEBUG_SECURITY_H
+
+class CRunModeApp : public CBase
+{
+public:
+ static CRunModeApp* NewL();
+ ~CRunModeApp();
+
+ void TestWaitDebug();
+
+private:
+ CRunModeApp();
+ void ConstructL();
+};
+
+#endif // T_RMDEBUG_SECURITY_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_crashmonitor_lib.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the functionality of the System Crash Monitor libraries
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype exe
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude ../../../../kernel/eka/debug/crashMonitor/inc
+sourcepath ../crashmonitor
+
+source t_crashmonitor.cpp
+
+library euser.lib
+library hal.lib
+staticlibrary scmusr_lib.lib
+
+target t_crashmonitor_lib.exe
+
+UID 0x0 0x4321bbbc
+SECUREID 0x2000B26F
+
+capability none
+
+VENDORID 0x70000001
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_multi_agent_launcher.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that launches multiple agents which in-turn test the ability of
+// the run mode debug component to debug several targets
+//
+//
+
+targettype exe
+target t_multi_agent_launcher.exe
+
+library euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude ../debug_targets
+userinclude ../common
+userinclude ../multi_agent_tests
+
+sourcepath ../multi_agent_tests
+source t_multi_agent_launcher.cpp
+
+UID 0x0 0x4321bbbc
+SECUREID 0x1234aaab
+VENDORID 0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_rmdebug.exe
+targettype exe
+
+sourcepath ../metro_trk
+source d_rmdebugserver.cpp
+source d_rmdebugthread.cpp
+source t_rmdebug.cpp
+sourcepath ../common
+source d_rmdebugthreadasm.cia
+
+library euser.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID 0x100039CE 0x101F7159
+SECUREID 0x101F7159
+VENDORID 0x70000001
+
+CAPABILITY ALL -TCB
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2.mmh Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,65 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype exe
+
+sourcepath ..\debug_targets
+
+source d_rmdebugthread2.cpp
+source d_rmdebugthreadasm2.cia
+
+#if defined(MARM_ARMV5)
+source d_rmdebug_step_test.s
+#endif
+
+#if defined(MARM_ARMV4)
+source d_rmdebug_step_test_armv4.s
+#endif
+
+source d_demand_paging.cia
+
+library euser.lib
+library hal.lib
+library efsrv.lib
+library t_rmdebug_dll.lib
+
+userinclude ..\..\..\..\kernel\eka\include\drivers
+userinclude ..\..\..\..\kernel\eka\debug\securityserver\inc
+userinclude ..\debug_targets
+
+
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+SYMBIAN_BASE_SYSTEMINCLUDE(drivers)
+SYMBIAN_BASE_SYSTEMINCLUDE(kernel)
+#endif
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+PAGED
+
+// To test heap allocation failure uncomment one or other of the following macros.
+// NOTE: Do not uncomment both, the tests will panic if both are defined!
+
+// To test heap allocation failure in the Debug Device Driver uncomment this macro
+//macro KERNEL_OOM_TESTING
+
+// To test heap allocation failure in the Debug Security Server uncomment this macro
+//macro USER_OOM_TESTING
+
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+#include "t_rmdebug2.mmh"
+
+target t_rmdebug2.exe
+
+sourcepath ../basic_tests
+source t_rmdebug2.cpp
+source r_low_memory_security_svr_session.cpp
+source r_kernel_low_memory_security_svr_session.cpp
+source r_user_low_memory_security_svr_session.cpp
+
+UID 0x0 0x4321bbbb
+SECUREID 0x1234aaaa
+VENDORID 0x70000001
+
+CAPABILITY READUSERDATA POWERMGMT ALLFILES
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oem.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Same tests as t_rmdebug2.mmp but with OEM rights conferred
+// by the OEMDebug_F123ABCD.exe token file.
+//
+//
+
+#include "t_rmdebug2.mmh"
+
+target t_rmdebug2_oem.exe
+
+sourcepath ../basic_tests
+source t_rmdebug2.cpp
+source r_low_memory_security_svr_session.cpp
+source r_kernel_low_memory_security_svr_session.cpp
+source r_user_low_memory_security_svr_session.cpp
+
+UID 0x0 0x4321bbbb
+SECUREID 0xF123abcd
+VENDORID 0x70000001
+
+CAPABILITY READUSERDATA POWERMGMT ALLFILES
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token
+macro SYMBIAN_OEMDEBUG
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oem2.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Same tests as t_rmdebug2.mmp but with some OEM rights conferred
+// by the OEMDebug_F1234567.exe token file.
+//
+//
+
+#include "t_rmdebug2.mmh"
+
+target t_rmdebug2_oem2.exe
+
+sourcepath ../basic_tests
+source t_rmdebug2.cpp
+source r_low_memory_security_svr_session.cpp
+source r_kernel_low_memory_security_svr_session.cpp
+source r_user_low_memory_security_svr_session.cpp
+
+UID 0x0 0x4321bbbb
+SECUREID 0xF1234567
+VENDORID 0x70000001
+
+CAPABILITY READUSERDATA POWERMGMT
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token with AllFiles only capability
+macro SYMBIAN_OEM2DEBUG
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target OEMDebug_F123ABCD.exe
+targettype exe
+
+sourcepath ../basic_tests
+
+source t_rmdebug2_oemtoken.cpp
+
+library euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability PowerMgmt AllFiles Tcb ReadUserData WriteUserData
+
+UID 0x0 0x0
+SECUREID 0x0
+VENDORID 0x70000001
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken2.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,37 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target OEMDebug_F1234567.exe
+targettype exe
+
+sourcepath ../basic_tests
+
+source t_rmdebug2_oemtoken.cpp
+
+library euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+// Token requires AllFiles
+capability AllFiles ReadUserData PowerMgmt
+
+UID 0x0 0x0
+SECUREID 0x0
+VENDORID 0x70000001
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+target t_rmdebug_app.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app1.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app1.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app10.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app10.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app2.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app2.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app3.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app3.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app4.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app4.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app5.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app5.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app6.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app6.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app7.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app7.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app8.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app8.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app9.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Target application to be debugged
+//
+//
+
+target t_rmdebug_app9.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_app.cpp
+source d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library euser.lib hal.lib
+
+uid 0x0 0x0
+capability none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_dll.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_rmdebug_dll.dll
+targettype dll
+
+DEFFILE ../../~/t_rmdebug_dll.def
+
+sourcepath ../debug_targets
+
+source t_rmdebug_dll.cpp
+
+library euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability PowerMgmt AllFiles ReadUserData
+
+UID 0x0 0x0
+SECUREID 0x0
+VENDORID 0x70000001
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_multi_agent.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that tests the ability of the run mode debug component
+// to debug multiple targets
+//
+//
+
+targettype exe
+target t_rmdebug_multi_agent.exe
+
+library euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude ../debug_targets
+userinclude ../common
+userinclude ../multi_agent_tests
+
+sourcepath ../multi_agent_tests
+source t_multi_agent.cpp t_agent_eventhandler.cpp
+
+UID 0x0 0x4321bbbc
+SECUREID 0x1234aaab
+VENDORID 0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_multi_target.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,43 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that tests the ability of the run mode debug component
+// to debug several targets
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype exe
+target t_rmdebug_multi_target.exe
+
+library euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude ../debug_targets
+userinclude ../common
+userinclude ../multi_target_tests
+
+sourcepath ../multi_target_tests
+source t_multi_target.cpp
+
+UID 0x0 0x4321bbbc
+SECUREID 0x1234aaab
+VENDORID 0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security0.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_rmdebug_security0.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_security.cpp
+
+library euser.lib hal.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID 0x100039CE 0xbaaaf00d
+SECUREID 0x101F7159
+VENDORID 0x70000001
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security1.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_rmdebug_security1.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_security.cpp
+
+library euser.lib hal.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID 0x100039CE 0xdeadbaaa
+SECUREID 0x101F7159
+VENDORID 0x70000001
+
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security2.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_rmdebug_security2.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_security.cpp
+
+library euser.lib hal.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability AllFiles
+
+UID 0x100039CE 0xdeadbaaa
+SECUREID 0x101F7159
+VENDORID 0x70000001
+
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security3.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_rmdebug_security3.exe
+targettype exe
+
+sourcepath ../debug_targets
+source t_rmdebug_security.cpp
+
+library euser.lib hal.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability TCB AllFiles NetworkControl
+
+UID 0x100039CE 0xdeadbaaa
+SECUREID 0x101F7159
+VENDORID 0x70000001
+
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_target_launcher.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Application that test the ability of the run mode debug component
+// to handle several target applications
+//
+//
+
+target t_rmdebug_target_launcher.exe
+targettype exe
+
+library euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude ../common
+sourcepath ../common
+source t_target_launcher.cpp
+
+UID 0x0 0x4321bbbd
+SECUREID 0x1234aaac
+VENDORID 0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_trkdummyapp.mmp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// t_trkdummyapp.mmp
+//
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target t_trkdummyapp.exe
+targettype exe
+
+sourcepath ../trk_blocking
+
+source t_trkdummyapp.cpp
+
+library euser.lib
+library hal.lib
+library efsrv.lib
+library t_rmdebug_dll.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID 0x0 0x0
+SECUREID 0x0
+VENDORID 0x70000001
+
+CAPABILITY none
+
+
+
+
+SMPSAFE
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/d_rmdebugclient.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,100 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// t_rmdebugclient.h
+// Definitions for the run mode debug agent client side sessions.
+//
+//
+
+#ifndef RMDEBUGCLIENT_H
+#define RMDEBUGCLIENT_H
+
+class TProcessInfo
+ {
+ public:
+ TUint iProcessID;
+ TInt iAttributes;
+ TUint32 iPriority;
+ TBuf<KMaxName> iName;
+ };
+
+class TThreadInfo
+ {
+ public:
+ TUint iThreadID;
+ TUint8 iPriority;
+ TUint8 iThreadType;
+ TBuf<KMaxName> iName;
+ TUint iOwningProcessID;
+
+ // Probably would want a state element here, under debug control, stopped etc
+ // such that additional information could be provided which was only valid for
+ // stopped threads.
+
+ };
+
+class TExecReq
+ {
+ public:
+ TUint32 iRequest; // Step, Step into, step threads
+ TUint32 iStartAddress;
+ TUint32 iStopAddress;
+
+ };
+
+class TMemoryInfo
+ {
+ public:
+ TUint32 iAddress;
+ TUint32 iSize;
+ TPtr8* iDataPtr;
+ };
+
+
+// Client Side session
+class RDebugServSession : public RSessionBase
+ {
+ public:
+ RDebugServSession();
+ TVersion Version() const;
+
+ TInt Open();
+ TInt Close();
+
+ TInt ReadMemory(const TUint32 aThreadId, TMemoryInfo* aInfo);
+ TInt WriteMemory(const TUint32 aThreadId, TMemoryInfo* aInfo);
+
+// TInt ReadThreadInfo(const TInt aIndex, const TInt aOwningProc, TThreadInfo* aInfo);
+// TInt ReadProcessInfo(const TInt aIndex, TProcessInfo* aInfo);
+ TInt SuspendThread(const TInt ThreadID);
+ TInt ResumeThread(const TInt ThreadID);
+
+ private:
+ RThread iServerThread;
+ };
+
+// Function codes (opcodes) used in message passing between client and server
+enum TDebugServRqst
+ {
+ EDebugServOpen = 1,
+ EDebugServClose,
+
+ EDebugServSuspendThread,
+ EDebugServResumeThread,
+// EDebugServReadProcessInfo,
+// EDebugServReadThreadInfo,
+ EDebugServReadMemory,
+ EDebugServWriteMemory,
+ };
+
+#endif // RMDEBUGCLIENT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,453 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Provides the debug agent server implementation.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <trkkerneldriver.h>
+#include "d_rmdebugserver.h"
+#include "d_rmdebugclient.h"
+#include "t_rmdebug.h"
+
+
+CDebugServServer::CDebugServServer(CActive::TPriority aActiveObjectPriority)
+ : CServer2(aActiveObjectPriority)
+//
+// Server constructor
+//
+ {
+ }
+
+CSession2* CDebugServServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
+//
+// Session constructor
+//
+ {
+ // make sure the kernel side device driver is not already loaded
+ TInt err;
+ err = User::LoadLogicalDevice(KDebugDriverFileName);
+ if ((KErrNone == err) || (KErrAlreadyExists == err))
+ {
+ return new(ELeave) CDebugServSession();
+ }
+ else
+ {
+ return (NULL);
+ }
+ }
+
+CDebugServSession::CDebugServSession()
+// Session implementation
+ {
+ TInt err;
+ TMetroTrkDriverInfo info;
+ info.iUserLibraryEnd = 0;
+ err = iKernelDriver.Open(info);
+ if (KErrNone != err)
+ {
+ User::Leave(err);
+ }
+ }
+
+CDebugServSession::~CDebugServSession()
+//
+// Session destructor
+//
+ {
+ // stop the kernel side driver
+ iKernelDriver.Close();
+
+ User::FreeLogicalDevice(KDebugDriverName);
+ }
+
+
+void CDebugServSession::ServiceL(const RMessage2& aMessage)
+//
+// Session service handler
+//
+ {
+ TInt res = KErrNone;
+
+ switch(aMessage.Function())
+ {
+ case EDebugServResumeThread:
+ res = ResumeThread(aMessage);
+ break;
+
+ case EDebugServSuspendThread:
+ res = SuspendThread(aMessage);
+ break;
+
+// case EDebugServReadProcessInfo:
+// res = ReadProcessInfo(aMessage);
+// break;
+//
+// case EDebugServReadThreadInfo:
+// res = ReadThreadInfo(aMessage);
+// break;
+
+ case EDebugServReadMemory:
+ res = ReadMemory(aMessage);
+ break;
+
+ case EDebugServWriteMemory:
+ res = WriteMemory(aMessage);
+ break;
+
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ aMessage.Complete(res);
+ }
+
+
+
+TInt CDebugServSession::SuspendThread(const RMessage2& aMessage)
+//
+// Session suspend thread
+//
+ {
+ TInt err;
+
+ err = iKernelDriver.SuspendThread(aMessage.Int0());
+
+ return err;
+ }
+
+TInt CDebugServSession::ResumeThread(const RMessage2& aMessage)
+//
+// Server resume thread
+//
+ {
+ TInt err;
+
+ err = iKernelDriver.ResumeThread(aMessage.Int0());
+
+ return err;
+ }
+
+//TInt CDebugServSession::ReadProcessInfo(const RMessage2& aMessage)
+////
+//// Server read process information
+////
+// {
+// TInt err;
+// TProcessInfo procinfo;
+// TMetroTrkTaskInfo processInfo(0);
+//
+// err = iKernelDriver.GetProcessInfo(aMessage.Int0(), processInfo);
+//
+// if (KErrNone == err)
+// {
+// procinfo.iProcessID = processInfo.iId;
+// procinfo.iPriority = processInfo.iPriority;
+// procinfo.iName.Copy(processInfo.iName);
+//
+// TPckgBuf<TProcessInfo> p(procinfo);
+// aMessage.WriteL(1,p);
+// }
+//
+// return err;
+// }
+//
+//TInt CDebugServSession::ReadThreadInfo(const RMessage2& aMessage)
+////
+//// Server read thread information
+////
+// {
+// TInt err;
+// TThreadInfo thrdinfo;
+// TMetroTrkTaskInfo threadInfo(aMessage.Int1()); // Sets OtherID to the second input parameter in aMessage
+//
+// // aMessage.Int0 is the index into the thread list for the process
+// err = iKernelDriver.GetThreadInfo(aMessage.Int0(), threadInfo);
+//
+// if (KErrNone == err)
+// {
+// thrdinfo.iThreadID = threadInfo.iId;
+// thrdinfo.iPriority = threadInfo.iPriority;
+// thrdinfo.iName.Copy(threadInfo.iName);
+// thrdinfo.iOwningProcessID = threadInfo.iOtherId;
+//
+// TPckgBuf<TThreadInfo> p(thrdinfo);
+//
+// // Write out the results to the third argument passed in (pointer to the threadinfo structure)
+// aMessage.WriteL(2,p);
+// }
+//
+// return err;
+// }
+
+TInt CDebugServSession::ReadMemory(const RMessage2& aMessage)
+//
+// Server read process memory
+//
+ {
+ TInt err;
+ TUint32 threadId = aMessage.Int0();
+ TPckgBuf<TMemoryInfo> pckg = *(TPckgBuf<TMemoryInfo> *)(aMessage.Ptr1());
+ TMemoryInfo* InputMemoryInfo = &pckg();
+
+ TPtr8 *ptrtst = InputMemoryInfo->iDataPtr;
+
+ err = iKernelDriver.ReadMemory(threadId, InputMemoryInfo->iAddress, InputMemoryInfo->iSize, *ptrtst);
+
+ return err;
+ }
+
+TInt CDebugServSession::WriteMemory(const RMessage2& aMessage)
+//
+// Server write process memory
+//
+ {
+ TInt err;
+ TUint32 threadId = aMessage.Int0();
+ TPckgBuf<TMemoryInfo> pckg = *(TPckgBuf<TMemoryInfo> *)(aMessage.Ptr1());
+ TMemoryInfo* InputMemoryInfo = &pckg();
+
+ TPtr8 *ptrtst = InputMemoryInfo->iDataPtr;
+
+ err = iKernelDriver.WriteMemory(threadId, InputMemoryInfo->iAddress, InputMemoryInfo->iSize, *ptrtst);
+
+ return err;
+ }
+
+
+GLDEF_C TInt CDebugServServer::ThreadFunction(TAny*)
+//
+// Server thread function, continues until active scheduler stops
+//
+ {
+ CTrapCleanup* cleanup=CTrapCleanup::New();
+ if (cleanup == NULL)
+ {
+ User::Leave(KErrNoMemory);
+ }
+
+ CActiveScheduler *pA=new CActiveScheduler;
+ CDebugServServer *pS=new CDebugServServer(EPriorityStandard);
+
+ CActiveScheduler::Install(pA);
+
+ TInt err = pS->Start(KDebugServerName);
+ if (err != KErrNone)
+ {
+ User::Leave(KErrNone);
+ }
+
+ RThread::Rendezvous(KErrNone);
+
+ CActiveScheduler::Start();
+
+ delete pS;
+ delete pA;
+ delete cleanup;
+
+ return (KErrNone);
+ }
+
+
+
+EXPORT_C TInt StartThread(RThread& aServerThread)
+//
+// Start the server thread
+//
+ {
+ TInt res=KErrNone;
+
+ TFindServer finddebugserver(KDebugServerName);
+ TFullName name;
+
+ if (finddebugserver.Next(name) != KErrNone)
+ {
+ res = aServerThread.Create( KDebugServerName,
+ CDebugServServer::ThreadFunction,
+ KDefaultStackSize,
+ KDefaultHeapSize,
+ KDefaultHeapSize,
+ NULL
+ );
+
+ if (res == KErrNone)
+ {
+ TRequestStatus rendezvousStatus;
+
+ aServerThread.SetPriority(EPriorityNormal);
+ aServerThread.Rendezvous(rendezvousStatus);
+ aServerThread.Resume();
+ User::WaitForRequest(rendezvousStatus);
+ }
+ else
+ {
+ aServerThread.Close();
+ }
+ }
+
+ return res;
+ }
+
+
+
+RDebugServSession::RDebugServSession()
+//
+// Server session constructor
+//
+ {
+ }
+
+TInt RDebugServSession::Open()
+//
+// Session open
+//
+ {
+ TInt r = StartThread(iServerThread);
+ if (r == KErrNone)
+ {
+ r=CreateSession(KDebugServerName, Version(), KDefaultMessageSlots);
+ }
+
+ return r;
+ }
+
+
+TVersion RDebugServSession::Version(void) const
+//
+// Session version
+//
+ {
+ return (TVersion(KDebugServMajorVersionNumber, KDebugServMinorVersionNumber, KDebugServBuildVersionNumber));
+ }
+
+TInt RDebugServSession::SuspendThread(const TInt aThreadID)
+//
+// Session suspend thread request
+//
+ {
+ TIpcArgs args(aThreadID);
+ TInt res;
+ res = SendReceive(EDebugServSuspendThread, args);
+
+ return res;
+ }
+
+TInt RDebugServSession::ResumeThread(const TInt aThreadID)
+//
+// Session resume thread request
+//
+ {
+ TIpcArgs args(aThreadID);
+ TInt res;
+ res = SendReceive(EDebugServResumeThread, args);
+
+ return res;
+ }
+
+
+//TInt RDebugServSession::ReadProcessInfo(const TInt aIndex, TProcessInfo* aInfo)
+////
+//// Session read process information request
+////
+// {
+// TPckgBuf<TProcessInfo> pckg;
+// pckg = *aInfo;
+//
+// TIpcArgs args(aIndex, &pckg);
+//
+// TInt res;
+//
+// res = SendReceive(EDebugServReadProcessInfo, args);
+//
+// *aInfo = pckg();
+//
+// return res;
+//
+// }
+//
+//TInt RDebugServSession::ReadThreadInfo(const TInt aIndex, const TInt aProc, TThreadInfo* aInfo)
+////
+//// Session read thread information request
+////
+// {
+// TPckgBuf<TThreadInfo> pckg;
+// pckg = *aInfo;
+//
+// TIpcArgs args(aIndex, aProc, &pckg);
+//
+// TInt res;
+//
+// res = SendReceive(EDebugServReadThreadInfo, args);
+//
+// *aInfo = pckg();
+//
+// return res;
+//
+// }
+
+
+TInt RDebugServSession::ReadMemory(const TUint32 aThreadID, TMemoryInfo* aInfo)
+//
+// Session read thread memory request
+//
+ {
+ TPckgBuf<TMemoryInfo> pckg;
+ pckg = *aInfo;
+
+ TIpcArgs args(aThreadID, &pckg);
+
+ TInt res;
+
+ res = SendReceive(EDebugServReadMemory, args);
+
+ *aInfo = pckg();
+
+ return res;
+
+ }
+
+
+TInt RDebugServSession::WriteMemory(const TUint32 aThreadID, TMemoryInfo* aInfo)
+//
+// Session write thread memory request
+//
+ {
+ TPckgBuf<TMemoryInfo> pckg;
+ pckg = *aInfo;
+
+ TIpcArgs args(aThreadID, &pckg);
+
+ TInt res;
+
+ res = SendReceive(EDebugServWriteMemory, args);
+
+ return res;
+ }
+
+
+
+TInt RDebugServSession::Close()
+//
+// Session close the session and thread
+//
+ {
+ RSessionBase::Close();
+ iServerThread.Close();
+
+ return KErrNone;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,73 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// t_rmdebugserver.h
+// Definitions for the run mode debug agent server side session.
+//
+//
+
+#ifndef RMDEBUGSVR_H
+#define RMDEBUGSVR_H
+
+// Server name
+_LIT(KDebugServerName,"DebugServer");
+_LIT(KDebugDriverName,"MetroTrk Driver");
+_LIT(KDebugDriverFileName,"trkdriver.ldd");
+
+// A version must be specifyed when creating a session with the server
+const TUint KDebugServMajorVersionNumber=0;
+const TUint KDebugServMinorVersionNumber=1;
+const TUint KDebugServBuildVersionNumber=1;
+const TUint KDefaultMessageSlots=4;
+const TUint KDefaultHeapSize=0x10000;
+
+class CDebugServSession;
+
+
+// Server
+class CDebugServServer : public CServer2
+ {
+ public:
+ CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
+ public:
+ static TInt ThreadFunction(TAny* aStarted);
+ protected:
+ CDebugServServer(CActive::TPriority aActiveObjectPriority);
+ };
+
+// Server side session
+class CDebugServSession : public CSession2
+ {
+ public:
+ CDebugServSession();
+ ~CDebugServSession();
+ void ConstructL ( void );
+ void ServiceL(const RMessage2& aMessage);
+
+ TInt ReadMemory(const RMessage2& aMessage);
+ TInt WriteMemory(const RMessage2& aMessage);
+
+// TInt ReadProcessInfo(const RMessage2& aMessage);
+// TInt ReadThreadInfo(const RMessage2& aMessage);
+
+ TInt ResumeThread(const RMessage2& aMessage);
+ TInt SuspendThread(const RMessage2& aMessage);
+
+ public:
+ RMetroTrkDriver iKernelDriver;
+
+ private:
+ };
+
+
+#endif // RMDEBUGSVR_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,347 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the functionality of the run mode debug device driver.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <f32dbg.h>
+#include "d_rmdebugclient.h"
+#include "d_rmdebugthread.h"
+#include "t_rmdebug.h"
+
+IMPORT_C TInt StartDebugThread(RThread& aServerThread);
+IMPORT_D extern TInt TestData;
+IMPORT_D extern TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+
+LOCAL_D RTest test(_L("T_RMDEBUG"));
+
+CRunModeAgent::CRunModeAgent()
+//
+// CRunModeAgent constructor
+//
+ {
+ }
+
+CRunModeAgent* CRunModeAgent::NewL()
+//
+// CRunModeAgent::NewL
+//
+ {
+ CRunModeAgent* self = new(ELeave) CRunModeAgent();
+
+ self->ConstructL();
+
+ if (self->iState != ERunModeAgentRunning)
+ {
+ delete self;
+ self = NULL;
+ }
+ return self;
+ }
+
+CRunModeAgent::~CRunModeAgent()
+//
+// CRunModeAgent destructor
+//
+ {
+ iServSession.Close();
+ iDebugThread.Close();
+ iState = ERunModeAgentUnInit;
+ }
+
+void CRunModeAgent::ConstructL()
+//
+// CRunModeAgent::ConstructL
+//
+ {
+ TInt err;
+ err = StartDebugThread(iDebugThread);
+
+ if (err == KErrNone)
+ {
+ if (iServSession.Open() == KErrNone)
+ {
+ iState = ERunModeAgentRunning;
+ }
+ else
+ {
+ iState = ERunModeAgentUnInit;
+ }
+ }
+ else
+ {
+ User::Panic(_L("Can't start debug thread"), err);
+ }
+}
+
+
+
+CRunModeAgent *RunModeAgent;
+
+// Test process names
+_LIT(ProcessName1,"T_RMDEBUG");
+_LIT(ProcessName1a,"t_rmdebug");
+//_LIT(ProcessName2,"ekern");
+//_LIT(ProcessName3,"efile");
+_LIT(KWildCard,"*");
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0185
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading process list
+//! @SYMTestActions Several calls to read the process list
+//! @SYMTestExpectedResults KErrNone and the owning process ID set
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestProcessList()
+ {
+ TInt err=KErrNone;
+ TBool found = FALSE;
+
+ test.Next(_L("TestProcessList - Read Process List\n"));
+
+ TFindProcess find(KWildCard);
+ TFullName name;
+ while(find.Next(name)==KErrNone)
+ {
+ RProcess process;
+ err = process.Open(find);
+ if (err == KErrNone)
+ {
+ if ((name.Find(ProcessName1) != KErrNotFound) ||
+ (name.Find(ProcessName1a) != KErrNotFound))
+ {
+ iProcessID = process.Id();
+ found = TRUE;
+ }
+ process.Close();
+ }
+ }
+ test(found== TRUE);
+ }
+
+// Test thread name
+_LIT(ThreadName1,"DebugThread");
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0186
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading thread list
+//! @SYMTestActions Several calls to read the thread list
+//! @SYMTestExpectedResults KErrNone and the debug thread ID set
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestThreadList()
+ {
+ TInt err=KErrNone;
+ TBool found = FALSE;
+
+ test.Next(_L("TestThreadList - Read Thread List\n"));
+
+ TFindThread find(KWildCard);
+ TFullName name;
+ while(find.Next(name)==KErrNone)
+ {
+ RThread thread;
+ err = thread.Open(find);
+ if (err == KErrNone)
+ {
+ RProcess process;
+ thread.Process(process);
+ if (((TUint32)process.Id() == iProcessID) &&
+ (name.Find(ThreadName1) != KErrNotFound))
+ {
+ found = TRUE;
+ iThreadID = thread.Id();
+ }
+ }
+ thread.Close();
+ }
+
+ test(found==TRUE);
+ }
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0187
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading and writing thread memory
+//! @SYMTestActions Several call to read and write blocks of thread memory
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestMemoryAccess()
+{
+ TInt err=KErrNone;
+ TMemoryInfo MemoryInfo;
+ TInt i;
+
+ test.Next(_L("TestMemoryAccess - Read Memory\n"));
+
+ for (i = 0; i < SYMBIAN_RMDBG_MEMORYSIZE; i++)
+ {
+ gMemoryAccessBytes.Append(i);
+ }
+
+ MemoryInfo.iAddress = (TUint32)(&gMemoryAccessBytes[0]);
+ MemoryInfo.iSize = SYMBIAN_RMDBG_MEMORYSIZE;
+
+ HBufC8 *data = HBufC8::NewLC(SYMBIAN_RMDBG_MEMORYSIZE);
+ TPtr8 ptr_memread(data->Des());
+ MemoryInfo.iDataPtr = &ptr_memread;
+
+// test.Printf(_L("Read address = 0x%x Read size = 0x%x\n"),MemoryInfo.iAddress,MemoryInfo.iSize);
+
+ err = iServSession.ReadMemory(iThreadID, &MemoryInfo);
+
+ for (i = 0; i < MemoryInfo.iSize; i++)
+ {
+ if (ptr_memread.Ptr()[i] != gMemoryAccessBytes[i])
+ {
+ err = KErrCorrupt;
+ }
+ }
+
+
+ // Test out writing memory.
+ test.Next(_L("TestMemoryAccess - Write Memory\n"));
+// test.Printf(_L("Write address = 0x%x Write size = 0x%x\n"),MemoryInfo.iAddress,MemoryInfo.iSize);
+ if (err== KErrNone)
+ {
+ // Now reset the buffer
+ for (i = 0; i < SYMBIAN_RMDBG_MEMORYSIZE; i++)
+ {
+ gMemoryAccessBytes[i] = 0;
+ }
+
+ // Write our data into the buffer
+ err = iServSession.WriteMemory(iThreadID, &MemoryInfo);
+
+ for (i = 0; i < MemoryInfo.iSize; i++)
+ {
+ if (ptr_memread.Ptr()[i] != gMemoryAccessBytes[i])
+ {
+ err = KErrCorrupt;
+ }
+ }
+
+ }
+
+ if (gMemoryAccessBytes[5] == 0)
+ {
+ err = KErrCorrupt;
+ }
+
+ CleanupStack::PopAndDestroy(data);
+ test(err==KErrNone);
+ }
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0188
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test suspending and resuming a task
+//! @SYMTestActions Suspends a thread checks the contents of a variable then waits and tests it hasnt changed
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestSuspendResume()
+ {
+ TInt err;
+
+ test.Next(_L("TestSuspendResume - Suspend\n"));
+ // Suspend the thread
+ err = iServSession.SuspendThread(iThreadID);
+ test(err==KErrNone);
+ TInt localtestdata;
+ localtestdata = TestData;
+
+ // Wait 3 seconds (suspends this thread) and hopefully resumes the
+ // thread we are controlling via the iServSession.SuspendThread request
+ User::After(3000000);
+
+ // Now check data hasnt changed
+ test(localtestdata==TestData);
+
+ // Resume the thread
+ test.Next(_L("TestSuspendResume - Resume\n"));
+ err = iServSession.ResumeThread(iThreadID);
+ test(err==KErrNone);
+
+ // Wait 3 seconds (suspends this thread) and hopefully resumes the
+ // thread we are controlling via the iServSession.SuspendThread request
+ User::After(3000000);
+
+ // Now check that the thread being controlled has resumed and is
+ // updating the variable
+ test(localtestdata!=TestData);
+ }
+
+void CRunModeAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+ {
+ test.Start(_L("ClientAppL"));
+
+ TestProcessList();
+ TestThreadList();
+ TestMemoryAccess();
+ TestSuspendResume();
+ test.End();
+ }
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+ {
+ TInt ret = KErrNone;
+
+ // client
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+
+ RunModeAgent = CRunModeAgent::NewL();
+ if (RunModeAgent != NULL)
+ {
+ test.Title();
+
+ __UHEAP_MARK;
+ TRAPD(r,RunModeAgent->ClientAppL());
+ ret = r;
+ __UHEAP_MARKEND;
+
+ delete RunModeAgent;
+ }
+
+ delete trap;
+
+ return ret;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,61 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+//
+//
+
+#ifndef RMDEBUG_H
+#define RMDEBUG_H
+
+// Function codes (opcodes) used in message passing between client and server
+enum TRunModeAgentState
+ {
+ ERunModeAgentUnInit,
+ ERunModeAgentRunning,
+ };
+
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CRunModeAgent : public CBase
+ {
+ public:
+ static CRunModeAgent* NewL();
+ ~CRunModeAgent();
+ void ClientAppL();
+
+ private:
+ CRunModeAgent();
+ void ConstructL();
+
+ TInt TestStartup();
+ TInt TestShutdown();
+
+ void TestProcessList();
+ void TestThreadList();
+ void TestMemoryAccess();
+ void TestSuspendResume();
+
+ private:
+ RDebugServSession iServSession;
+ RThread iDebugThread;
+ TInt iProcessID;
+ TInt iThreadID;
+ TInt iState;
+ };
+
+#endif // RMDEBUG_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,124 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Implements the handling of run mode events for a particular target executable
+//
+
+#include <e32base.h>
+#include <e32property.h>
+#include <e32test.h>
+
+#include "t_rmdebug_app.h"
+#include "t_agent_eventhandler.h"
+#include "t_multi_agent.h"
+#include "t_debug_logging.h"
+
+using namespace Debug;
+
+CAgentAsyncEvent::CAgentAsyncEvent(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig):
+ CActive(EPriorityStandard), iDriver(aDriver)
+ {
+ }
+
+CAgentAsyncEvent* CAgentAsyncEvent::NewLC(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig)
+ {
+ CAgentAsyncEvent* self = new(ELeave) CAgentAsyncEvent(aDriver, aExeName, aExeConfig);
+ CleanupStack::PushL(self);
+ self->ConstructL(aExeName, aExeConfig);
+ return self;
+ }
+
+CAgentAsyncEvent* CAgentAsyncEvent::NewL(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig)
+ {
+ CAgentAsyncEvent* self = CAgentAsyncEvent::NewLC(aDriver, aExeName, aExeConfig);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+void CAgentAsyncEvent::ConstructL(const TDesC& aExeName, const TDesC& aExeConfig)
+ {
+ iExeName.CreateL(aExeName);
+ iExeConfig.CreateL(aExeConfig);
+ CActiveScheduler::Add(this);
+ }
+
+CAgentAsyncEvent::~CAgentAsyncEvent()
+ {
+ LOG_MSG2("~CAgentAsyncEvent(), this = 0x%08x", this);
+
+ iSEventInfo.iEventInfoBuf.Delete(0, sizeof(TEventInfo));
+ iExeName.Close();
+ iExeConfig.Close();
+ iProc.Close();
+ Cancel(); // Cancel any request, if outstanding
+ }
+
+/*
+ * Issue request to DSS and notify the active scheduler
+ */
+void CAgentAsyncEvent::Watch()
+ {
+ LOG_MSG2("ENTER: CAgentAsyncEvent::Watch, this = 0x%08x", this);
+ iDriver.DebugDriver().GetEvent(GetExecutable(), iStatus, iSEventInfo.iEventInfoBuf);
+
+ if (!IsActive())
+ {
+ LOG_MSG("CAgentAsyncEvent::Watch(): SetActive()");
+ SetActive();
+ }
+
+ LOG_MSG("EXIT: CAgentAsyncEvent::Watch");
+ }
+
+void CAgentAsyncEvent::RunL()
+ {
+ LOG_MSG4("ENTER: CAgentAsyncEvent::RunL iDebugType=%d, iStatus.Int() %d, this 0x%x08",
+ iSEventInfo.iEventInfo.iEventType, iStatus.Int(), this);
+
+ LOG_MSG2("%S", &TPtr8((TUint8*)GetExecutable().Ptr(), 2*GetExecutable().Length(), 2*GetExecutable().Length()));
+ iDriver.HandleEvent(iSEventInfo.iEventInfo);
+
+ LOG_MSG2("iDriver.GetNumApps() %d: ", iDriver.GetNumApps());
+ LOG_MSG2("iDriver.iLaunchCompleted %d: ", iDriver.GetLaunchCompleted());
+
+ if (iDriver.GetLaunchCompleted() < iDriver.GetNumApps())
+ {
+ // Do not call Watch() if target has run to completion but test is still on going
+ if (iSEventInfo.iEventInfo.iEventType != EEventsRemoveProcess)
+ {
+ LOG_MSG("CAgentAsyncEvent::RunL Setting Watch()");
+ Watch();
+ }
+ }
+ else
+ {
+ // Stop event handling for all targets
+ LOG_MSG("CAgentAsyncEvent::RunL CActiveScheduler::Stop() & Cancel");
+ CActiveScheduler::Stop();
+ }
+
+ LOG_MSG2("EXIT: CAgentAsyncEvent::RunL", KNullDesC);
+ }
+
+void CAgentAsyncEvent::DoCancel()
+ {
+ LOG_MSG("CAgentAsyncEvent::DoCancel");
+ }
+
+TInt CAgentAsyncEvent::RunError(TInt aError)
+ {
+ LOG_MSG3(" RunL() has left with error %d, this 0x%08X", aError, this);
+ return aError;
+ // Can we handle this error? Not at the moment!
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,90 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for event handling via the DSS and target specific information
+//
+//
+
+#ifndef RMDEBUG_AGENT_EVENTHANDLER_H
+#define RMDEBUG_AGENT_EVENTHANDLER_H
+
+#include "t_multi_agent.h"
+
+using namespace Debug;
+
+class CMultiAgent;
+
+/**
+ Class for gathering event data from the run-mode driver
+ */
+class TAgentEventInfo
+{
+public:
+ TAgentEventInfo() :
+ iEventInfoBuf((TUint8*)&iEventInfo, sizeof(TEventInfo), sizeof(TEventInfo))
+ {
+ }
+
+public:
+ // This is the underlying class for event interaction with the Run Mode debug API
+ TEventInfo iEventInfo;
+
+ // A convenience handle for iEventInfo used across the Debug::GetEvent() method
+ TPtr8 iEventInfoBuf;
+};
+
+/**
+ Active object class used to trap asynchronous events
+ Also, contains target specific parameters
+ */
+class CAgentAsyncEvent : public CActive
+ {
+public:
+ // Close buffers and Cancel and destroy
+ ~CAgentAsyncEvent();
+
+ // Two-phased constructor
+ static CAgentAsyncEvent* NewLC(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+
+ // Two-phased constructor
+ static CAgentAsyncEvent* NewL(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+
+ // set up ASP and issue another request
+ void Watch();
+
+ TDesC& GetExecutable() { return iExeName; }
+ TDesC& GetExeConfig() { return iExeConfig; }
+ RProcess& GetProcHandle() { return iProc; }
+
+protected:
+ // from CActive
+ virtual void RunL();
+ virtual void DoCancel();
+ virtual TInt RunError(TInt aError);
+
+private:
+ CAgentAsyncEvent(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+ void ConstructL(const TDesC& aExeName, const TDesC& aExeConfig);
+
+private:
+ RBuf iExeName;
+ RBuf iExeConfig;
+ RProcess iProc;
+
+ CMultiAgent& iDriver;
+ TAgentEventInfo iSEventInfo;
+ };
+
+#endif // RMDEBUG_AGENT_EVENTHANDLER_H
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_debug_logging.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,52 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Logging macros for use in debug subsystem
+//
+//
+
+#ifndef RMDEBUG_MULTI_AGENT_LOGGING_H
+#define RMDEBUG_MULTI_AGENT_LOGGING_H
+
+/* Debug messages
+ *
+ * Debug messages are only generated for debug builds.
+ *
+ * As user mode use RDebug::Printf().
+ *
+ */
+
+// Uncomment if logging of multi agent test required
+// #define MULTI_AGENT_DEBUG_LOGGING
+
+#ifdef MULTI_AGENT_DEBUG_LOGGING
+
+ #include <e32debug.h>
+
+ #define LOG_MSG( a ) RDebug::Printf( a )
+ #define LOG_MSG2( a, b ) RDebug::Printf( a, b )
+ #define LOG_MSG3( a, b, c ) RDebug::Printf( a, b, c )
+ #define LOG_MSG4( a, b, c, d ) RDebug::Printf( a, b, c, d )
+ #define LOG_MSG5( a, b, c, d, e ) RDebug::Printf( a, b, c, d, e )
+
+#else
+
+ #define LOG_MSG( a )
+ #define LOG_MSG2( a, b )
+ #define LOG_MSG3( a, b, c )
+ #define LOG_MSG4( a, b, c, d )
+ #define LOG_MSG5( a, b, c, d, e )
+
+#endif
+
+#endif //RMDEBUG_MULTI_AGENT_LOGGING_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,432 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Tests the run mode debug device component by launching multiple targets
+// on different CPUs. On a single core the targets run on the same CPU.
+//
+
+#include <e32base.h>
+#include <e32property.h>
+#include <hal.h>
+#include <e32test.h>
+#include <e32def.h>
+
+#include "t_rmdebug_app.h"
+#include "t_multi_agent.h"
+#include "t_agent_eventhandler.h"
+#include "t_debug_logging.h"
+
+const TVersion securityServerVersion(0,1,1);
+
+/**
+ * First phase constructor
+ */
+CMultiAgent* CMultiAgent::NewL()
+ {
+ CMultiAgent* self = new(ELeave) CMultiAgent();
+ self->ConstructL();
+ return self;
+ }
+
+/**
+ * Destructor
+ */
+CMultiAgent::~CMultiAgent()
+ {
+ LOG_MSG("~CMultiTargetAgent\n");
+ iServSession.Close();
+ }
+
+/**
+ * Constructor
+ */
+CMultiAgent::CMultiAgent()
+ {
+ }
+
+/**
+ * Second phase constructor
+ */
+void CMultiAgent::ConstructL()
+ {
+ }
+
+/**
+ Parse the command line, set agent cpu affinity and call main test function
+ */
+void CMultiAgent::ClientAppL()
+ {
+ LOG_MSG("ENTER: CMultiTargetAgent::ClientAppL");
+
+ iNumApps = KNumApps;
+ iAgentCpuNo = KAgentCpu;
+ iTargetNameOffset = KTargetOffset;
+
+ TInt argc = User::CommandLineLength();
+ HBufC* commandLine = NULL;
+ LOG_MSG2(">Launcher Process() argc=%d", argc);
+
+ if(argc)
+ {
+ commandLine = HBufC::NewLC(argc);
+ TPtr commandLineBuffer = commandLine->Des();
+ User::CommandLine(commandLineBuffer);
+
+ RBuf printCommandLine;
+ CleanupClosePushL(printCommandLine);
+ printCommandLine.CreateL(commandLine->Des().Length());
+ printCommandLine.Copy(commandLine->Des());
+ printCommandLine.Collapse();
+ LOG_MSG2(">command line = %S", &printCommandLine );
+ CleanupStack::PopAndDestroy( &printCommandLine );
+
+ // create a lexer and read through the command line
+ TLex lex(*commandLine);
+
+ while (!lex.Eos())
+ {
+ // only look for options with first character '-'
+ if (lex.Get() == '-')
+ {
+ TChar arg = lex.Get();
+
+ switch ( arg )
+ {
+ case 'n':
+ lex.Val( iNumApps );
+ LOG_MSG2("parsed numApps as %d", iNumApps);
+ break;
+
+ case 'a':
+ lex.Val( iAgentCpuNo );
+ LOG_MSG2("parsed agentCpuNo as %d", iAgentCpuNo);
+ break;
+
+ case 'o':
+ lex.Val( iTargetNameOffset );
+ LOG_MSG2("parsed iTargetNameOffset as %d", iTargetNameOffset);
+ break;
+
+ default:
+ LOG_MSG("Bad argument from user");
+ break;
+ }
+ }
+ }
+ }
+ // Create active scheduler (to run active objects)
+ CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ if (iAgentCpuNo)
+ {
+ LOG_MSG2("CMultiAgent::ClientAppL() - setting agent to cpu %d", iAgentCpuNo);
+ UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)iAgentCpuNo, 0);
+ }
+
+ TInt err = iServSession.Connect(securityServerVersion);
+
+ if (err != KErrNone)
+ {
+ User::Panic(_L("Can't open server session"), err);
+ }
+
+ StartTest();
+
+ // Note: below is a workaround to overcome an issue with RTest server crashing
+ // when writing to the windows console from different agents (on different CPUs
+ // at the same time). To overcome this we signal the launcher using a global
+ // semaphore to indicate a RTest complete instead
+ RSemaphore launchSemaphore;
+ CleanupClosePushL(launchSemaphore);
+
+ TFindSemaphore launchSemFinder(KLaunchSemaphoreSearchString);
+ TFullName semaphoreResult;
+ TInt ret = launchSemFinder.Next(semaphoreResult);
+ LOG_MSG3( "> Find Launch Semaphote.Next ret=%d, %lS", ret, &semaphoreResult);
+
+ ret = launchSemaphore.OpenGlobal(semaphoreResult);
+ LOG_MSG2( ">OpenGlobal semaphore ret=%d", ret );
+
+ LOG_MSG( ">Signalling semaphore" );
+ launchSemaphore.Signal();
+ CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore
+
+ // Delete active scheduler
+ CleanupStack::PopAndDestroy(scheduler);
+
+ if (commandLine)
+ CleanupStack::PopAndDestroy(commandLine);
+
+ LOG_MSG( "EXIT: CMultiTargetAgent::ClientAppL");
+ }
+
+/**
+ Launch a process
+ @param aProcess the RProcess object used to create the process
+ @param aFileName file name of the executable used to create the process
+ @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt CMultiAgent::LaunchProcess(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine)
+ {
+ LOG_MSG( "ENTER: CMultiAgent::LaunchProcess");
+ LOG_MSG2("%S", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length()));
+
+ // wait for 0.5 seconds due to issue with creating several processes in smp quickly
+ User::After(500000);
+
+ TInt err = aProcess.Create( aExeName, aCommandLine );
+ LOG_MSG2( "CMultiAgent::LaunchProcess, aProcess.Create err = %d", err);
+
+ // check that there was no error raised
+ if (err != KErrNone)
+ return err;
+
+ // rendezvous with process
+ TRequestStatus status = KRequestPending;
+ aProcess.Rendezvous(status);
+
+ if (KRequestPending != status.Int())
+ {
+ // startup failed so kill the process
+ LOG_MSG2( "> RProcess Rendezvous() failed with %d. Killing process", status.Int() );
+ aProcess.Kill(KErrNone);
+ LOG_MSG( "EXIT: CMultiAgent::LaunchProcess");
+ return status.Int();
+ }
+ else
+ {
+ // start the test target
+ aProcess.Resume();
+ User::WaitForRequest(status);
+
+ LOG_MSG2( "> CMultiAgent::LaunchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int() );
+
+ if(KErrNone != status.Int())
+ {
+ LOG_MSG2( "> RProcess Resume() failed with %d. Killing process", status.Int() );
+ aProcess.Kill(KErrNone);
+ }
+
+ LOG_MSG( "EXIT: CMultiAgent::LaunchProcess");
+ return status.Int();
+ }
+ }
+
+/**
+ Handle Event
+ @param aEventInfo object containing event information from the DSS
+ */
+void CMultiAgent::HandleEvent(TEventInfo& aEventInfo)
+ {
+ LOG_MSG( "ENTER: CMultiAgent::HandleEvent" );
+ TInt ret = KErrNone;
+ const TInt idValid = 1;
+
+ switch ( aEventInfo.iEventType )
+ {
+ case EEventsAddProcess:
+ {
+ LOG_MSG(">> EEventsAddProcess");
+ TPtrC8 exeNamePtr8(aEventInfo.iAddProcessInfo.iFileName, aEventInfo.iAddProcessInfo.iFileNameLength);
+
+ RBuf8 exeName8;
+ CleanupClosePushL(exeName8);
+ exeName8.CreateL(exeNamePtr8);
+ LOG_MSG2("From event: exeName8=%S", &exeName8);
+ CleanupStack::PopAndDestroy(&exeName8);
+ LOG_MSG("Testing if event process id is valid");
+
+ LOG_MSG2("Got aEventInfo.iProcessId=%d", I64LOW( aEventInfo.iProcessId));
+ __ASSERT_ALWAYS((aEventInfo.iProcessIdValid==idValid), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+
+ RProcess targetProc;
+ ret = targetProc.Open(TProcessId(aEventInfo.iProcessId));
+ LOG_MSG2("RProcess open ret=%d", ret);
+ targetProc.Close();
+
+ __ASSERT_ALWAYS((ret == KErrNone), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+ break;
+ }
+
+ case EEventsStartThread:
+ {
+ LOG_MSG(">> EEventsStartThread");
+ TPtrC8 exeNamePtr8(aEventInfo.iStartThreadInfo.iFileName, aEventInfo.iStartThreadInfo.iFileNameLength);
+ RBuf8 exe8Name;
+ CleanupClosePushL(exe8Name);
+ exe8Name.CreateL(exeNamePtr8);
+ LOG_MSG2("From event: exeName8=%S", &exe8Name);
+ CleanupStack::PopAndDestroy(&exe8Name);
+
+ LOG_MSG("Testing if event process id is valid" );
+
+ __ASSERT_ALWAYS((aEventInfo.iProcessIdValid==idValid), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+
+ LOG_MSG2("Got aEventInfo.iProcessId=%d", I64LOW(aEventInfo.iProcessId));
+
+ LOG_MSG("Testing if event thread id is valid");
+
+ __ASSERT_ALWAYS((aEventInfo.iThreadIdValid==idValid), User::Panic(_L("ThreadId Invalid"), aEventInfo.iThreadIdValid));
+
+ LOG_MSG2("Got aEventInfo.iThreadId=%d", I64LOW(aEventInfo.iThreadId));
+ break;
+ }
+
+ case EEventsUserTrace:
+ {
+ LOG_MSG(">> EEventsUserTrace");
+ break;
+ }
+
+ case EEventsRemoveProcess:
+ {
+ LOG_MSG( ">> EEventsRemoveProcess");
+ iLaunchCompleted++;
+ break;
+ }
+
+ default:
+ {
+ LOG_MSG( ">> Unknown event - probably due to DSS busy?");
+ break;
+ }
+ }
+
+ LOG_MSG("EXIT: CMultiAgent::HandleEvent");
+ }
+
+/**
+ * Main test function which launches several targets and stresses the DSS
+ */
+TInt CMultiAgent::StartTest()
+ {
+ LOG_MSG("ENTER: CMultiTargetAgent::StartTest");
+
+ for( TInt i = 0; i < iNumApps; i++ )
+ {
+ RBuf targetName;
+ RBuf launcherOptions;
+
+ CleanupClosePushL(targetName);
+ CleanupClosePushL(launcherOptions);
+
+ targetName.CreateL( KTargetExe().Length() + 2 );
+ targetName.Format( KTargetExe(), i + iTargetNameOffset + 1 );
+
+ LOG_MSG2("App %d: ", i+1);
+ LOG_MSG2("%S", &TPtr8((TUint8*)targetName.Ptr(), 2*targetName.Length(), 2*targetName.Length()));
+
+ launcherOptions.CreateL( KTargetOptions().Length() + 2 );
+ launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit, (i+1) );
+
+ LOG_MSG( "AppOptions : ");
+ LOG_MSG2("%S", &TPtr8((TUint8*)launcherOptions.Ptr(), 2*launcherOptions.Length(), 2*launcherOptions.Length()));
+
+ // Add each test target to array
+ iTargetList.AppendL(CAgentAsyncEvent::NewL(*this, targetName, launcherOptions));
+ CleanupStack::PopAndDestroy(2, &targetName );
+ }
+
+ iLaunchCompleted = 0;
+ TInt err = KErrNone;
+
+ for (TInt i = 0; i < iNumApps; i++)
+ {
+ // Attach to process non-passively
+ LOG_MSG2( ">AttachExecutable app %d ", i + iTargetNameOffset + 1 );
+ LOG_MSG2("%S", &TPtr8((TUint8*)iTargetList[i]->GetExecutable().Ptr(), 2*iTargetList[i]->GetExecutable().Length(),
+ 2*iTargetList[i]->GetExecutable().Length()));
+
+ err = iServSession.AttachExecutable( iTargetList[i]->GetExecutable(), EFalse);
+ __ASSERT_ALWAYS((err == KErrNone), User::Panic(_L("DSS Attach failed"), err));
+
+ // Continue on interested event actions
+ LOG_MSG2( ">SetEventAction app %d, EEventsStartThread EAcionContinue", i + iTargetNameOffset + 1);
+
+ err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsStartThread, EActionContinue);
+ __ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+ LOG_MSG2(">SetEventAction app %d, EEventsAddProcess EActionContinue", i + iTargetNameOffset + 1);
+ err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsAddProcess, EActionContinue);
+ __ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+ LOG_MSG2(">SetEventAction app %d, EEventsUserTrace EActionContinue", i + iTargetNameOffset + 1);
+ err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsUserTrace, EActionContinue);
+ __ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+ LOG_MSG2(">SetEventAction app %d, EEventsRemoveProcess EActionContinue", i + iTargetNameOffset + 1);
+ err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsRemoveProcess, EActionContinue);
+ __ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+ // Add target object to active schedular
+ iTargetList[i]->Watch();
+ }
+
+ for (TInt i= 0; i< iNumApps; i++)
+ {
+ LOG_MSG( ">Calling LaunchProcess function");
+ err = LaunchProcess(iTargetList[i]->GetProcHandle(), iTargetList[i]->GetExecutable(), iTargetList[i]->GetExeConfig());
+ __ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("LaunchProcess failed"), err));
+ }
+
+ LOG_MSG( ">CActiveScheduler::Start()");
+ CActiveScheduler::Start();
+
+ for (TInt i= 0; i < iNumApps; i++)
+ {
+ // Now detach again
+ LOG_MSG( "Before iServSession.DetachExecutable" );
+ err = iServSession.DetachExecutable(iTargetList[i]->GetExecutable());
+ __ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("DetachExecutable failed"), err));
+ }
+
+ // Free all the memory
+ iTargetList.ResetAndDestroy();
+ LOG_MSG( "EXIT: CMultiTargetAgent::StartTest" );
+
+ return KErrNone;
+ }
+
+/**
+ * Entry point for run mode debug driver test
+ */
+GLDEF_C TInt E32Main()
+ {
+ LOG_MSG( "ENTER: Multi_agent E32Main ");
+ __UHEAP_MARK;
+
+ TInt ret = KErrNone;
+ RProcess::Rendezvous(KErrNone);
+
+ CTrapCleanup* trap = CTrapCleanup::New();
+
+ if (!trap)
+ return KErrNoMemory;
+
+ CMultiAgent *runModeAgent = CMultiAgent::NewL();
+
+ if (runModeAgent != NULL)
+ {
+ TRAP(ret,runModeAgent->ClientAppL());
+ LOG_MSG2( "ClientAppL returned %d", ret );
+ delete runModeAgent;
+ }
+
+ delete trap;
+ __UHEAP_MARKEND;
+ LOG_MSG( "EXIT: Multi_agent E32Main ");
+ return ret;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,110 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_AGENT_H
+#define RMDEBUG_MULTI_AGENT_H
+
+#include <u32hal.h>
+#include <f32file.h>
+#include <rm_debug_api.h>
+
+using namespace Debug;
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreSearchString, "t_rmdebug_launch_semaphore*");
+
+// Currently the targets are instances of t_rmdebug_app.exe
+_LIT(KTargetExe,"z:\\sys\\bin\\t_rmdebug_app%d.exe");
+
+_LIT(KTargetOptions,"-f%d -a%d");
+
+// If changing this, make sure there are enough apps built/in the rom
+const TInt KNumApps = 5;
+
+// Default CPU execution for Agent
+const TInt KAgentCpu = 0;
+
+// Workaround to ensure we have the same agent binary when running multiple agents
+const TInt KTargetOffset = 0;
+
+class CAgentAsyncEvent;
+
+/**
+ @Class CRunModeAgent
+
+ The basic run mode agent
+ */
+class CMultiAgent : public CBase
+ {
+ public:
+ static CMultiAgent* NewL();
+ ~CMultiAgent();
+ void ClientAppL();
+ RSecuritySvrSession& DebugDriver() { return iServSession; };
+ void HandleEvent(TEventInfo& aSEventInfo);
+
+ public:
+ TInt GetLaunchCompleted() const { return iLaunchCompleted; }
+ TInt GetNumApps() const { return iNumApps; }
+ TInt GetTargetOffset() const { return iTargetNameOffset; }
+
+ private:
+ CMultiAgent();
+ void ConstructL();
+ TInt StartTest();
+ TInt LaunchProcess(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine);
+
+ private:
+
+ /**
+ * CPU agent executes on; by default this is 0
+ */
+ TInt iAgentCpuNo;
+
+ /*
+ * Offset for running multiple targets using the same agent
+ */
+ TInt iTargetNameOffset;
+
+ /**
+ * Number of applications/targets per agent
+ */
+ TInt iNumApps;
+
+ /**
+ * Flag used for terminating the event handling for a target
+ */
+ TInt iLaunchCompleted;
+
+ /*
+ * Handle to DSS
+ */
+ RSecuritySvrSession iServSession;
+
+ /**
+ * Array to target parameters required by the agent
+ */
+ RPointerArray<CAgentAsyncEvent> iTargetList;
+ };
+
+#endif // RMDEBUG_MULTI_AGENT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,229 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Helper app to launch debug targets
+//
+//
+
+#include "t_multi_agent_launcher.h"
+
+#include "t_debug_logging.h"
+
+/**
+ * Launch a process
+ * @param aProcess the RProcess object used for creating the process
+ * @param aExeName the name of the executable to run
+ * @param aCommandLine command line parameters to pass when creating the process
+ * @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt LaunchProcess(RProcess& aProcess, TDesC& aExeName, TDesC& aCommandLine )
+ {
+ LOG_MSG("ENTER: t_multi_agent_launcher: launchProcess");
+
+ LOG_MSG2("aExeName %S ", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length()));
+ LOG_MSG2("aCommandLine %S", &TPtr8((TUint8*)aCommandLine.Ptr(), 2*aCommandLine.Length(), 2*aCommandLine.Length()));
+
+ TInt err = aProcess.Create( aExeName, aCommandLine );
+ LOG_MSG2("t_multi_agent_launcher launchProcess, aProcess.Create err = %d", err);
+
+ // check that there was no error raised
+ if(err != KErrNone)
+ {
+ return err;
+ }
+
+ // rendezvous with process
+ TRequestStatus status = KRequestPending;
+ aProcess.Rendezvous(status);
+
+ if(KRequestPending != status.Int())
+ {
+ // startup failed so kill the process
+ LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Rendezvous() failed with %d. Killing process", status.Int());
+ aProcess.Kill(KErrNone);
+ return status.Int();
+ }
+ else
+ {
+ aProcess.Resume();
+ User::WaitForRequest(status);
+
+ LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int());
+
+ if(KErrNone != status.Int())
+ {
+ LOG_MSG2("t_multi_agent_launcher: RProcess Resume() failed with %d. Killing process", status.Int());
+ aProcess.Kill(KErrNone);
+ }
+
+ LOG_MSG("EXIT: t_multi_agent_launcher launchProcess");
+ return status.Int();
+ }
+ }
+
+/**
+ * Read command line parameters and control the launching of the agents.
+ */
+void MainL()
+ {
+ LOG_MSG( "ENTER: t_multi_agent_launcher MainL()");
+
+ TInt ret = KErrNone;
+ TInt numAgents = KNumAgents;
+ TInt numTargets = KNumTargets;
+ TInt numTestRuns = KNumTestRuns;
+
+ TInt argc = User::CommandLineLength();
+ HBufC* commandLine = NULL;
+ LOG_MSG2("t_multi_agent_launcher: MainL(): argc=%d", argc);
+
+ if(argc)
+ {
+ commandLine = HBufC::NewLC(argc);
+ TPtr commandLineBuffer = commandLine->Des();
+ User::CommandLine(commandLineBuffer);
+
+ RBuf printCommandLine;
+ CleanupClosePushL( printCommandLine );
+ printCommandLine.CreateL( commandLine->Des().Length() );
+ printCommandLine.Copy( commandLine->Des() );
+ printCommandLine.Collapse();
+ LOG_MSG2("t_multi_agent_launcher: command line = %S", &printCommandLine);
+ CleanupStack::PopAndDestroy( &printCommandLine );
+
+ // create a lexer and read through the command line
+ TLex lex(*commandLine);
+ while (!lex.Eos())
+ {
+ // only look for options with first character '-'
+ if (lex.Get() == '-')
+ {
+ TChar arg = lex.Get();
+ switch ( arg )
+ {
+ case 'n':
+ lex.Val( numAgents );
+ LOG_MSG2("t_multi_agent_launcher: parsed numAgents as %d", numAgents);
+ break;
+ case 'm':
+ lex.Val( numTargets );
+ LOG_MSG2("t_multi_agent_launcher: parsed numTargets as %d", numTargets);
+ break;
+ case 't':
+ lex.Val( numTestRuns );
+ LOG_MSG2("t_multi_agent_launcher: parsed numTestRuns as %d", numTestRuns);
+ break;
+ default:
+ LOG_MSG("t_multi_agent_launcher: unknown argument ignoring it");
+ break;
+ }
+ }
+ }
+ }
+
+ // Note: below is a workaround to overcome an issue with RTest server crashing
+ // when writing to the windows console from different agents (on different CPUs
+ // at the same time). To overcome this we get signaled by the agents when they have
+ // completed their tests so that we can do a RTest complete
+ RSemaphore launchSemaphore;
+ CleanupClosePushL(launchSemaphore);
+ ret = launchSemaphore.CreateGlobal(KLaunchSemaphoreName, 0);
+ LOG_MSG2( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
+ User::LeaveIfError( ret );
+
+ ret = launchSemaphore.OpenGlobal(KLaunchSemaphoreName);
+ LOG_MSG2( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
+ User::LeaveIfError( ret );
+
+ //Now launch the requested number of apps for the requested number of test runs
+ for( TInt j = 0; j < numTestRuns; j++ )
+ {
+ for( TInt i = 0; i < numAgents; i++ )
+ {
+ RBuf targetName;
+ targetName.CleanupClosePushL();
+ targetName.CreateL(KAgentExe());
+
+ RProcess aProc;
+ CleanupClosePushL(aProc);
+ RBuf launcherOptions;
+ CleanupClosePushL(launcherOptions);
+ const TInt additionalWords = 2;
+ launcherOptions.CreateL( KAgentOptions().Length() + additionalWords );
+
+ // Apply offset: launcherOptions.Format( .., .., i * numTargets, ..)
+ // workaround to ensure we have the same binary for multiple agents.
+ // e.g. So if offset = 0, agent attaches to app1, app2, app3, app4, app5
+ // if offset = 5, agent attached to app6, app7, app8, app9, app10 etc.
+ // Note: apps need to be in rom otherwise the agent will fail on an assert
+ // (with KErrNotFound)
+ launcherOptions.Format( KAgentOptions(), (TUint)numTargets, i * numTargets, 0);
+
+ ret = LaunchProcess( aProc, targetName, launcherOptions );
+ CleanupStack::PopAndDestroy(3,&targetName);
+ User::LeaveIfError(ret);
+ }
+ }
+
+ // Wait for all agents to do their testing before checking the semaphore
+ User::After(12000000);
+
+ LOG_MSG( ">Target Launcher: Semaphore wait");
+
+ for (TInt i = 0; i < numAgents; i ++)
+ {
+ //We need this delay just in case an agent crashes and never signals the sem
+ ret = launchSemaphore.Wait(100000);
+ if( ret != KErrNone )
+ {
+ LOG_MSG3("launchSemaphore.Wait ret %d for agent %d", ret, i);
+ break;
+ }
+ }
+
+ LOG_MSG2( "testing for Semaphore ret %d", ret);
+
+ // We only want to have one RTest instance at any one time since otherwise RTest can panic
+ RTest test(_L("T_MULTI_AGENT_LAUNCHER"));
+ test.Start(_L("t_multi_agent_launcher Check for agents finishing correctly"));
+ test(ret == KErrNone);
+ test.End();
+ test.Close();
+
+ CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore
+
+ if( commandLine )
+ CleanupStack::PopAndDestroy(commandLine);
+
+ LOG_MSG("EXIT: t_multi_agent_launcher MainL()");
+ }
+
+GLDEF_C TInt E32Main()
+ {
+ LOG_MSG("ENTER: Multi_agent_launcher E32Main()");
+ __UHEAP_MARK;
+
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+
+ TRAPD(err, MainL());
+ LOG_MSG2("Multi_agent_launcher: returning from MainL(), err = %d", err);
+
+ delete trap;
+ LOG_MSG("EXIT: Multi_agent_launcher E32Main()");
+ __UHEAP_MARKEND;
+
+ return err;
+ }
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,45 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for agent launcher
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_AGENT_LAUNCHER_H
+#define RMDEBUG_MULTI_AGENT_LAUNCHER_H
+
+#include <e32test.h>
+
+// Default test runs
+const TInt KNumTestRuns = 1;
+
+// Default number of targets per agent
+const TInt KNumTargets = 5;
+
+// Default number of agents, if changing this make sure there are enough apps being built
+const TInt KNumAgents = 2;
+
+_LIT(KAgentExe,"z:\\sys\\bin\\t_rmdebug_multi_agent.exe");
+_LIT(KAgentOptions,"-n%d -o%d -a%d");
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreSearchString, "t_rmdebug_launch_semaphore*");
+
+#endif // RMDEBUG_MULTI_AGENT_LAUNCHER_H
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,402 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Test the ability of the debug system to handle events from several debug targets
+//
+//
+
+#include <e32base.h>
+#include <e32property.h>
+
+#include <hal.h>
+#include <e32test.h>
+
+#include "t_multi_target.h"
+#include "t_target_launcher.h"
+#include "t_rmdebug_app.h"
+
+#ifdef KERNEL_OOM_TESTING
+ #ifdef USER_OOM_TESTING
+ #error "Cannot define both KERNEL_OOM_TESTING and USER_OOM_TESTING"
+ #endif
+#endif
+
+
+using namespace Debug;
+
+const TVersion securityServerVersion(0,1,1);
+
+const TVersion testVersion(2,1,0);
+
+#ifdef SYMBIAN_STANDARDDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET"));
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET_OEM"));
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET_OEM2"));
+#endif
+
+
+
+CMultiTargetAgent* CMultiTargetAgent::NewL()
+//
+// CMultiTargetAgent::NewL
+//
+ {
+ CMultiTargetAgent* self = new(ELeave) CMultiTargetAgent();
+
+ self->ConstructL();
+
+ return self;
+ }
+
+
+CMultiTargetAgent::~CMultiTargetAgent()
+//
+// CMultiTargetAgent destructor
+//
+ {
+ RDebug::Printf("~CMultiTargetAgent\n");
+ iServSession.Close();
+ }
+
+
+CMultiTargetAgent::CMultiTargetAgent() :
+ iEventPtr( (TUint8*)&iEventInfo, sizeof(TEventInfo) )
+ {
+ }
+
+
+void CMultiTargetAgent::ConstructL()
+//
+// CMultiTargetAgent::ConstructL
+//
+ {
+ }
+
+/**
+ * Helper code for the stepping tests. Returns the number of nanokernel ticks in one second.
+ *
+ * @return Number of nanokernel ticks. 0 if unsuccesful.
+ */
+TInt CMultiTargetAgent::HelpTicksPerSecond(void)
+ {
+ TInt nanokernel_tick_period;
+ HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+ ASSERT(nanokernel_tick_period != 0);
+
+ static const TInt KOneMillion = 1000000;
+
+ return KOneMillion/nanokernel_tick_period;
+ }
+
+void CMultiTargetAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+ {
+ TInt err = iServSession.Connect(securityServerVersion);
+ if (err != KErrNone)
+ {
+ User::Panic(_L("Can't open server session"), err);
+ }
+
+ LaunchTargetsInOrderL();
+ RDebug::Printf( "returning from CMultiTargetAgent::ClientAppL" );
+ }
+
+/**
+ Launch a process
+
+ @param aProcess The RProcess object to use to create the process
+ @param aExeName File name of the executable to create the process from
+ @param aCommandLine The command line to pass to the new process
+ @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt CMultiTargetAgent::LaunchProcess(RProcess& aProcess, TDesC & aExeName, TDesC & aCommandLine )
+ {
+ TInt err = aProcess.Create( aExeName, aCommandLine );
+ if(err != KErrNone)
+ {
+ RDebug::Printf( "aProcess.Create ret %d", err);
+ return err;
+ }
+
+ TRequestStatus status = KRequestPending;
+ aProcess.Rendezvous(status);
+ if(KRequestPending != status.Int())
+ {
+ // startup failed so kill the process
+ aProcess.Kill(KErrNone);
+ return status.Int();
+ }
+ else
+ {
+ // start up succeeded so resume the process
+ aProcess.Resume();
+ // Give the process a chance to run
+ User::After( 500000 );
+ return KErrNone;
+ }
+ }
+
+void CMultiTargetAgent::SetupDebugServerL()
+ {
+ RDebug::Printf( "CMultiTargetAgent::SetupDebugServerL" );
+
+ iTargets.ReserveL( KNumApps );
+
+ RBuf targetName;
+ CleanupClosePushL( targetName );
+
+ for( TInt numApps = 0; numApps < KNumApps; numApps++ )
+ {
+ iTargets.AppendL( targetName );
+ RDebug::Printf( "Attach to DSS for app %d ", numApps );
+
+ iTargets[numApps].CreateL( KTargetExe().Length() + 2 );
+ iTargets[numApps].Format( KTargetExe(), numApps+1 );
+
+ TInt ret = iServSession.AttachExecutable( iTargets[numApps], EFalse );
+ test( ret == KErrNone );
+
+ RDebug::Printf( ">SetEventAction app %d, EEventsStartThread EActionSuspend", numApps );
+ ret = iServSession.SetEventAction( iTargets[numApps], EEventsStartThread, EActionSuspend );
+ test( ret == KErrNone );
+
+ RDebug::Printf( ">SetEventAction app %d, EEventsAddProcess EActionContinue", numApps );
+ ret = iServSession.SetEventAction( iTargets[numApps], EEventsAddProcess, EActionContinue );
+ test( ret == KErrNone );
+
+ RDebug::Printf( ">SetEventAction app %d, EEventsRemoveProcess EActionContinue", numApps );
+ ret = iServSession.SetEventAction( iTargets[numApps], EEventsRemoveProcess, EActionContinue );
+ test( ret == KErrNone );
+ }
+
+ CleanupStack::PopAndDestroy( &targetName ); // targetName
+
+ }
+
+
+
+TInt CMultiTargetAgent::LaunchTargetsInOrderL()
+ {
+ RDebug::Printf( "CMultiTargetAgent::LaunchTargetsInOrderL" );
+
+ RBuf launcher;
+ CleanupClosePushL( launcher );
+ launcher.CreateL( KLauncherExe() );
+
+ RBuf launcherOptions;
+ CleanupClosePushL( launcherOptions );
+ launcherOptions.CreateL( KTargetOptions().Length() + 2 );
+ launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit );
+
+ RDebug::Printf( ">LaunchProcess()" );
+ RProcess launcherProc;
+ CleanupClosePushL( launcherProc );
+
+ TInt ret = LaunchProcess( launcherProc, launcher, launcherOptions );
+ RDebug::Printf( "<LaunchProcess() ret %d", ret );
+
+ CleanupStack::PopAndDestroy( &launcherProc ); // launcherProc
+ CleanupStack::PopAndDestroy( &launcherOptions ); // launcherOptions
+ CleanupStack::PopAndDestroy( &launcher ); //launcher
+
+ test( ret == KErrNone );
+
+ RSemaphore launchSemaphore;
+ CleanupClosePushL( launchSemaphore );
+
+ TFindSemaphore launchSemFinder( KLaunchMutexNameSearchString );
+ TFullName mutexResult;
+ ret = launchSemFinder.Next(mutexResult);
+ RDebug::Printf( "> Find Launch Semaphote.Next ret=%d, %lS", ret, &mutexResult );
+ test( ret == KErrNone );
+
+ ret = launchSemaphore.OpenGlobal( mutexResult );
+ RDebug::Printf( "> OpenGlobal mutex ret=%d", ret );
+ test( ret == KErrNone );
+
+ TBool thisLaunchCompleted;
+
+ SetupDebugServerL();
+
+ for( TInt numLaunches = KNumLaunches; numLaunches > 0; numLaunches-- )
+ {
+ for( TInt numApps = KNumApps; numApps > 0; numApps-- )
+ {
+ thisLaunchCompleted = EFalse;
+ // This will trigger the launcher app to launch the next target
+ RDebug::Printf( " >Mutex.Signal app=%d, launch=%d", numApps, numLaunches);
+ launchSemaphore.Signal();
+
+ RBuf8 tgt8Name;
+ CleanupClosePushL( tgt8Name );
+
+ RBuf tgtCollapseName;
+ CleanupClosePushL( tgtCollapseName );
+
+ tgtCollapseName.CreateL( iTargets[numApps-1] );
+ tgt8Name.CreateL( tgtCollapseName.Collapse() );
+
+
+ while( ! thisLaunchCompleted )
+ {
+ RDebug::Printf( ">GetEvent app %d for %S", numApps, &tgt8Name );
+ iServSession.GetEvent( iTargets[numApps-1], iStatus, iEventPtr );
+
+ // Wait for the target to get started.
+ RDebug::Printf( " >Wait for event from target app=%d, launch=%d\n", numApps, numLaunches);
+ User::WaitForRequest( iStatus );
+ RDebug::Printf( " <Wait for request returned with status %d", iStatus.Int() );
+ test( iStatus==KErrNone );
+
+ RDebug::Printf( " > Got iEventType =%d, app=%d", iEventInfo.iEventType, numApps );
+ switch( iEventInfo.iEventType )
+ {
+ case EEventsAddProcess:
+ {
+ RDebug::Printf( "Got EEventsAddProcess" );
+ TPtrC8 exeNamePtr8( iEventInfo.iAddProcessInfo.iFileName, iEventInfo.iAddProcessInfo.iFileNameLength );
+
+ RBuf8 exeName8;
+ CleanupClosePushL( exeName8 );
+ exeName8.CreateL( exeNamePtr8 );
+ RDebug::Printf( " from event: exeName8=%S", &exeName8 );
+ CleanupStack::PopAndDestroy( &exeName8 );
+
+ RBuf8 compareName8;
+ CleanupClosePushL( compareName8 );
+ compareName8.CreateL( KTargetExeName().Length() + 10 );
+ compareName8.Format( KTargetExeName(), numApps );
+ RDebug::Printf( " comparing to: compareName8=%S", &compareName8 );
+
+ test( compareName8.CompareC( exeNamePtr8 ) == 0 );
+ CleanupStack::PopAndDestroy( &compareName8 );
+
+ RDebug::Printf( "Testing if event process id is valid" );
+ test( iEventInfo.iProcessIdValid );
+ RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) );
+
+ RProcess targetProc;
+ ret = targetProc.Open( TProcessId( iEventInfo.iProcessId ) );
+ RDebug::Printf( "RProcess open ret=%d",ret );
+ targetProc.Close();
+ test( ret == KErrNone );
+
+ break;
+ }//EEventsAddProcess
+
+ case EEventsStartThread:
+ {
+ RDebug::Printf( "Got EEventsStartThread" );
+
+ TPtrC8 exeNamePtr8( iEventInfo.iStartThreadInfo.iFileName, iEventInfo.iStartThreadInfo.iFileNameLength );
+ RBuf8 exe8Name;
+ CleanupClosePushL( exe8Name );
+ exe8Name.CreateL( exeNamePtr8 );
+ RDebug::Printf( " from event: exeName8=%S", &exe8Name );
+ CleanupStack::PopAndDestroy( &exe8Name );
+
+ test( tgt8Name.CompareC( exeNamePtr8 ) == 0 );
+
+ RDebug::Printf( "Testing if event process id is valid" );
+ test( iEventInfo.iProcessIdValid );
+ RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) );
+
+ RDebug::Printf( "Testing if event thread id is valid" );
+ test( iEventInfo.iThreadIdValid );
+ RDebug::Printf( "Got iEventInfo.iThreadId=%d", I64LOW( iEventInfo.iThreadId ) );
+
+ RThread targetThread;
+ CleanupClosePushL( targetThread );
+
+ ret = targetThread.Open( TThreadId( iEventInfo.iThreadId ) );
+ RDebug::Printf( "RThread open ret=%d", ret );
+ test( ret == KErrNone );
+
+ test( iEventInfo.iThreadId == targetThread.Id() );
+
+ RDebug::Printf( "Resuming thread for app=%d, id=%d", numApps, I64LOW( targetThread.Id() ));
+ ret = iServSession.ResumeThread( iEventInfo.iThreadId );
+ CleanupStack::PopAndDestroy( &targetThread );
+
+ test( ret == KErrNone );
+
+ ret = iServSession.ResumeThread( iEventInfo.iThreadId );
+ break;
+ }//case EEventsStartThread
+
+ case ( EEventsRemoveProcess ):
+ {
+ RDebug::Printf( "*** Got EEventsRemoveProcess. app%d has exited. Moving on to next app", numApps );
+ thisLaunchCompleted = ETrue;
+ break;
+ }
+
+ default :
+ RDebug::Printf( "Got unknown event" );
+ test( EFalse );
+ break;
+ }
+ }//while
+
+ CleanupStack::PopAndDestroy( &tgtCollapseName ); // tgtCollapseName
+ CleanupStack::PopAndDestroy( &tgt8Name ); // tgt8Name
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &launchSemaphore ); // launchSemaphore
+
+ for( TInt i = iTargets.Count()-1; i>=0; i-- )
+ {
+ RDebug::Printf( "Closing target %d", i );
+ iTargets[ i ].Close();
+ }
+
+ iTargets.Close();
+
+ return KErrNone;
+ }
+
+
+GLDEF_C TInt E32Main()
+ {
+ TInt ret = KErrNone;
+
+
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+ test.Title();
+
+ CMultiTargetAgent *runModeAgent = CMultiTargetAgent::NewL();
+ if (runModeAgent != NULL)
+ {
+ __UHEAP_MARK;
+ TRAP(ret,runModeAgent->ClientAppL());
+ __UHEAP_MARKEND;
+
+ RDebug::Printf( "ClientAppL returned %d", ret );
+ delete runModeAgent;
+ }
+
+ delete trap;
+ return ret;
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Definitions for the run mode debug tests
+//
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_TARGET_H
+#define RMDEBUG_MULTI_TARGET_H
+
+#include "t_rmdebug_app.h"
+
+#include <rm_debug_api.h>
+
+class CMultiTargetAgent;
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CMultiTargetAgent : public CBase
+ {
+public:
+ static CMultiTargetAgent* NewL();
+ ~CMultiTargetAgent();
+ void ClientAppL();
+
+ TInt LaunchProcess(RProcess& aProcess, TDesC & aExeName, TDesC & aCommandLine );
+
+private:
+ CMultiTargetAgent();
+ void ConstructL();
+
+ void ReportPerformance(void);
+
+ TInt HelpTicksPerSecond(void);
+
+ enum TTestMode
+ {
+ //run all the tests
+ EModeAll = 1<<0,
+ //run the specified tests in reverse order
+ EModeReverse = 1<<1,
+ //print out help
+ EModeHelp = 1<<2,
+ //print out help
+ EModeVersion = 1<<3
+ };
+
+ TInt LaunchTargetsInOrderL();
+ void SetupDebugServerL();
+
+private:
+
+#if defined(KERNEL_OOM_TESTING)
+ RKernelLowMemorySecuritySvrSession iServSession;
+#elif defined (USER_OOM_TESTING)
+ RUserLowMemorySecuritySvrSession iServSession;
+#else
+ Debug::RSecuritySvrSession iServSession;
+#endif
+ RSemaphore iAddressGlobSem;
+
+ TUid iMySid;
+
+ // Timing information
+ TInt iStartTick;
+ TInt iStopTick;
+
+ RArray<RBuf> iTargets;
+ TRequestStatus iStatus;
+ Debug::TEventInfo iEventInfo;
+ TPtr8 iEventPtr;
+ };
+
+#endif // RMDEBUG_MULTI_TARGET_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,532 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Ensure that old insecure Trk debug agent cannot be installed
+// as it should be blocked from SWInstall'ing by a trkdummyapp.exe contained within
+// the base OS with the same SID as the insecure Trk.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include "t_trkdummyapp.h"
+
+LOCAL_D RTest test(_L("T_TRKDUMMYAPP"));
+
+CTrkDummyAppTest::CTrkDummyAppTest()
+//
+// CTrkDummyAppTest constructor
+//
+ {
+ // nothing to do
+ }
+
+CTrkDummyAppTest* CTrkDummyAppTest::NewL()
+//
+// CRunModeAgent::NewL
+//
+ {
+ CTrkDummyAppTest* self = new(ELeave) CTrkDummyAppTest();
+
+ self->ConstructL();
+
+ return self;
+ }
+
+CTrkDummyAppTest::~CTrkDummyAppTest()
+//
+// CTrkDummyAppTest destructor
+//
+ {
+ // Nothing to do
+ }
+
+void CTrkDummyAppTest::ConstructL()
+//
+// CTrkDummyAppTest::ConstructL
+//
+ {
+ // nothing to do here
+ }
+
+
+CTrkDummyAppTest *TrkDummyTest;
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-TRKDUMMYAPP-0792
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests that a known insecure debug agent trkapp.sis cannot be installed
+//! by ensuring the existence of a Symbian OS common app called trkdummyapp.exe
+//! already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions
+//!
+//! 1. Calls RProcess.Create() on z:\sys\bin\trkdummyapp.exe. Fail if unsuccessful.
+//!
+//! 2. Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp.exe.
+//!
+//! 3. Close the process derived from z:\sys\bin\trkdummyapp.exe.
+//!
+//! @SYMTestExpectedResults
+//!
+//! 1. Fails if unable to create a process from z:\sys\bin\trkdummyapp.exe.
+//!
+//! 2. The Secure ID of trkdummyapp.exe has the Secure ID 0x101F7159. Fail otherwise.
+//!
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp,"z:\\sys\\bin\\trkdummyapp.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent(void)
+ {
+
+ test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent, SID 0x101F7159\n"));
+
+ RProcess process;
+ TInt err = process.Create(KRMDebugSecurityTrkDummyApp, KNullDesC, EOwnerProcess);
+ test (err == KErrNone);
+
+ // rendezvous with process
+ TRequestStatus status;
+ process.Rendezvous(status);
+
+ // obtain the secure ID for the process
+ TSecurityInfo secInfo(process);
+
+ static const TSecureId KTrkDummyAppSID = 0x101F7159;
+
+ test(secInfo.iSecureId.iId == KTrkDummyAppSID);
+
+ // Kill the process, as we don't need it anymore
+ process.Kill(KErrNone);
+
+ process.Close();
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-TRKDUMMYAPP-0793
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests that a known insecure debug agent trkapp.sis cannot be installed
+//! by ensuring the existence of a Symbian OS common app called trkdummyapp.exe
+//! already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions
+//!
+//! 1. Calls RProcess.Create() on z:\sys\bin\trkdummyapp2.exe. Fail if unsuccessful.
+//!
+//! 2. Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp2.exe.
+//!
+//! 3. Close the process derived from z:\sys\bin\trkdummyapp2.exe.
+//!
+//! @SYMTestExpectedResults
+//!
+//! 1. Fails if unable to create a process from z:\sys\bin\trkdummyapp2.exe.
+//!
+//! 2. The Secure ID of trkdummyapp.exe has the Secure ID 0x2000a7dd. Fail otherwise.
+//!
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp2,"z:\\sys\\bin\\trkdummyapp2.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent2(void)
+ {
+
+ test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent2, SID 0x2000a7dd\n"));
+
+ RProcess process;
+ TInt err = process.Create(KRMDebugSecurityTrkDummyApp2, KNullDesC, EOwnerProcess);
+ test (err == KErrNone);
+
+ // rendezvous with process
+ TRequestStatus status;
+ process.Rendezvous(status);
+
+ // obtain the secure ID for the process
+ TSecurityInfo secInfo(process);
+
+ static const TSecureId KTrkDummyAppSID2 = 0x2000a7dd;
+
+ test(secInfo.iSecureId.iId == KTrkDummyAppSID2);
+
+ // Kill the process, as we don't need it anymore
+ process.Kill(KErrNone);
+
+ process.Close();
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-TRKDUMMYAPP-2396
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests that a known insecure debug agent trkapp.sis cannot be installed
+//! by ensuring the existence of a Symbian OS common app called trkdummyapp200159D8.exe
+//! already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions
+//!
+//! 1. Calls RProcess.Create() on z:\sys\bin\trkdummyapp200159D8.exe. Fail if unsuccessful.
+//!
+//! 2. Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp200159D8.exe.
+//!
+//! 3. Close the process derived from z:\sys\bin\trkdummyapp200159D8.exe.
+//!
+//! @SYMTestExpectedResults
+//!
+//! 1. Fails if unable to create a process from z:\sys\bin\trkdummyapp200159D8.exe.
+//!
+//! 2. The Secure ID of trkdummyapp200159D8.exe has the Secure ID 0x200159D8. Fail otherwise.
+//!
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp200159D8,"z:\\sys\\bin\\trkdummyapp200159D8.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent200159D8(void)
+ {
+ test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent, SID 0x200159D8\n"));
+
+ RProcess process;
+ TInt err = process.Create(KRMDebugSecurityTrkDummyApp200159D8, KNullDesC, EOwnerProcess);
+ test (err == KErrNone);
+
+ // rendezvous with process
+ TRequestStatus status;
+ process.Rendezvous(status);
+
+ // obtain the secure ID for the process
+ TSecurityInfo secInfo(process);
+
+ static const TSecureId KTrkDummyAppSID2 = 0x200159D8;
+
+ test(secInfo.iSecureId.iId == KTrkDummyAppSID2);
+
+ // Kill the process, as we don't need it anymore
+ process.Kill(KErrNone);
+
+ process.Close();
+ }
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-TRKDUMMYAPP-2397
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Tests that a known insecure debug agent trkapp.sis cannot be installed
+//! by ensuring the existence of a Symbian OS common app called trkdummyapp200170BC.exe
+//! already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions
+//!
+//! 1. Calls RProcess.Create() on z:\sys\bin\trkdummyapp200170BC.exe. Fail if unsuccessful.
+//!
+//! 2. Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp200170BC.exe.
+//!
+//! 3. Close the process derived from z:\sys\bin\trkdummyapp200170BC.exe.
+//!
+//! @SYMTestExpectedResults
+//!
+//! 1. Fails if unable to create a process from z:\sys\bin\trkdummyapp200170BC.exe.
+//!
+//! 2. The Secure ID of trkdummyapp.exe has the Secure ID 0x200170BC. Fail otherwise.
+//!
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp200170BC,"z:\\sys\\bin\\trkdummyapp200170BC.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent200170BC(void)
+ {
+
+ test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent, SID 0x200170BC\n"));
+
+ RProcess process;
+ TInt err = process.Create(KRMDebugSecurityTrkDummyApp200170BC, KNullDesC, EOwnerProcess);
+ test (err == KErrNone);
+
+ // rendezvous with process
+ TRequestStatus status;
+ process.Rendezvous(status);
+
+ // obtain the secure ID for the process
+ TSecurityInfo secInfo(process);
+
+ static const TSecureId KTrkDummyAppSID2 = 0x200170BC;
+
+ test(secInfo.iSecureId.iId == KTrkDummyAppSID2);
+
+ // Kill the process, as we don't need it anymore
+ process.Kill(KErrNone);
+
+ process.Close();
+ }
+
+void CTrkDummyAppTest::ClientAppL()
+//
+// Performs each test in turn
+//
+ {
+ test.Start(_L("ClientAppL"));
+
+ TestSecurityCheckPreventInsecureTrkDebugAgent();
+
+ TestSecurityCheckPreventInsecureTrkDebugAgent2();
+
+ TestSecurityCheckPreventInsecureTrkDebugAgent200159D8();
+
+ TestSecurityCheckPreventInsecureTrkDebugAgent200170BC();
+
+ test.End();
+ }
+
+
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+ {
+ TInt ret = KErrNone;
+
+ // client
+ CTrapCleanup* trap = CTrapCleanup::New();
+ if (!trap)
+ return KErrNoMemory;
+
+ test.Title();
+ TrkDummyTest = CTrkDummyAppTest::NewL();
+ if (TrkDummyTest != NULL)
+ {
+ __UHEAP_MARK;
+ TRAP(ret,TrkDummyTest->ClientAppL());
+ __UHEAP_MARKEND;
+
+ delete TrkDummyTest;
+ }
+
+ delete trap;
+
+ return ret;
+ }
+
+// End of file - t_trkdummyapp.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.h Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,59 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Ensure that old insecure Trk debug agent cannot be installed
+// as it should be blocked from SWInstall'ing by a trkdummyapp.exe contained within
+// the base OS with the same SID as the insecure Trk.
+//
+//
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+#ifndef T_TRKDUMMYAPP_H
+#define T_TRKDUMMYAPP_H
+
+class CTrkDummyAppTest;
+
+//
+// class CTrkDummyAppTest
+//
+// Basic test of the existence of the TrkDummyApp.
+//
+class CTrkDummyAppTest : public CBase
+ {
+public:
+ static CTrkDummyAppTest* NewL();
+ ~CTrkDummyAppTest();
+ void ClientAppL();
+
+ void TestSecurityCheckPreventInsecureTrkDebugAgent(void);
+
+ void TestSecurityCheckPreventInsecureTrkDebugAgent2(void);
+
+ void TestSecurityCheckPreventInsecureTrkDebugAgent200159D8(void);
+
+ void TestSecurityCheckPreventInsecureTrkDebugAgent200170BC(void);
+
+private:
+ CTrkDummyAppTest();
+ void ConstructL();
+
+ void TestTrkDummyAppExists();
+
+ };
+
+#endif // T_TRKDUMMYAPP_H
--- a/kerneltest/f32test/filesystem/fat/b_fat32.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/b_fat32.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -63,15 +63,16 @@
const TInt KMaxFatEntries = 2048;
const TInt KMaxFatSize = KMaxFatEntries * 4;
-const TInt KDirAttrReadOnly = 0x01;
-const TInt KDirAttrHidden = 0x02;
-const TInt KDirAttrSystem = 0x04;
-const TInt KDirAttrVolumeId = 0x08;
-const TInt KDirAttrDirectory = 0x10;
-const TInt KDirAttrArchive = 0x20;
-const TInt KDirAttrLongName = KDirAttrReadOnly | KDirAttrHidden | KDirAttrSystem | KDirAttrVolumeId;
-const TInt KDirAttrLongMask = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive;
-const TInt KDirLastLongEntry = 0x40;
+
+const TUint KDirAttrReadOnly = 0x01;
+const TUint KDirAttrHidden = 0x02;
+const TUint KDirAttrSystem = 0x04;
+const TUint KDirAttrVolumeId = 0x08;
+const TUint KDirAttrDirectory = 0x10;
+const TUint KDirAttrArchive = 0x20;
+const TUint KDirAttrLongName = KDirAttrReadOnly | KDirAttrHidden | KDirAttrSystem | KDirAttrVolumeId;
+const TUint KDirAttrLongMask = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive;
+const TUint KDirLastLongEntry = 0x40;
void CreateFatEntry(const TDesC& aDir, TBool aVFatEntry, TDes *apFileName=NULL);
@@ -1495,7 +1496,7 @@
}
-static void TestMakeDir(const TDesC& aName,TInt aNewClust,TInt aParentClust)
+static void TestMakeDir(const TDesC& aName, TUint aNewClust, TUint aParentClust)
//
// Test make dir
//
@@ -1526,7 +1527,7 @@
pE++;
if (pE->Name()[0]!='.' || pE->Name()[1]!='.')
Error(_L("Second entry is not '..'"),KErrNone);
- if (pE->StartCluster() != ((aParentClust==gRootCluster)?0:aParentClust))
+ if (pE->StartCluster() != ((aParentClust==(TUint)gRootCluster)?0:aParentClust))
Error(_L("Start cluster of .. is not parent directory"),KErrNone);
}
--- a/kerneltest/f32test/filesystem/fat/t_compat32.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/t_compat32.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -156,7 +156,7 @@
// Replace a 8.3 filename with upper and lower case letters which is, actually out of FAT specs.
// I.e. VFAT entries are valid, but DOS entry has a lower case symbol, which is wrong.
//
-LOCAL_C void Test1(TNameCase aCase)
+static void Test1(TNameCase aCase)
{
test.Next(_L("Replace a file with a wrong DOS entry"));
QuickFormat();
@@ -190,7 +190,7 @@
// Renaming a 8.3 filename with upper and lower case letters which is, actually out of FAT specs.
// I.e. VFAT entries are valid, but DOS entry has a lower case symbol, which is wrong.
//
-LOCAL_C void Test2(TNameCase aCase)
+static void Test2(TNameCase aCase)
{
test.Next(_L("Rename a file with a wrong DOS entry"));
QuickFormat();
@@ -520,11 +520,89 @@
}
+//---------------------------------------------
+/**
+ Test that the created VFAT entryset corresponds to what Windows creates in the
+ same situation
+*/
+void TestVFatEntryInterop()
+{
+ test.Next(_L("Testind VFAT entries interoperability\n"));
+ QuickFormat();
-GLDEF_C void CallTestsL()
-//
-// Call tests that may leave
-//
+ TInt nRes;
+ _LIT(KFName, "\\longfilename12345678");
+
+ //-- 1. create a file with long FN that isn't multiple of 13 (max unicode characters in VFAT entry)
+ const TUint KFileSize = 24;
+ nRes = CreateEmptyFile(TheFs, KFName, KFileSize);
+ test(nRes == KErrNone);
+
+ //-- 2. verify that the dir. entries are the same what Windows creates.
+ nRes = TheDisk.Open(TheFs,CurrentDrive());
+ test(nRes == KErrNone);
+
+ //-- read 1st dir. entry from the root dir and check it.
+ //-- this is the rest of the LFN
+ TInt64 posEntry = gBootSector.RootDirStartSector() << KDefaultSectorLog2; //-- dir entry1 position
+
+ TFatDirEntry fatEntry;
+ TPtr8 ptrEntry((TUint8*)&fatEntry, KSizeOfFatDirEntry);
+
+ nRes = TheDisk.Read(posEntry, ptrEntry);
+ test(nRes == KErrNone);
+
+ //-- the expected entry #1 contents (what Windows places there).
+ const TUint8 KEntry1[KSizeOfFatDirEntry] = {0x42, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x0F, 0x00, 0xF7, 0x37, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ nRes = Mem::Compare(fatEntry.iData, KSizeOfFatDirEntry, KEntry1, KSizeOfFatDirEntry);
+ test(nRes == KErrNone);
+
+ //-- read 2nd dir. entry from the root dir and check it.
+ //-- this is the beginning of the LFN
+
+ posEntry += KSizeOfFatDirEntry;
+ nRes = TheDisk.Read(posEntry, ptrEntry);
+ test(nRes == KErrNone);
+
+ //-- the expected entry #2 contents (what Windows places there).
+ const TUint8 KEntry2[KSizeOfFatDirEntry] = { 0x01, 0x6C, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x66, 0x00, 0x0F, 0x00, 0xF7, 0x69, 0x00,
+ 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x65, 0x00, 0x31, 0x00 };
+
+ nRes = Mem::Compare(fatEntry.iData, KSizeOfFatDirEntry, KEntry2, KSizeOfFatDirEntry);
+ test(nRes == KErrNone);
+
+ //-- read the last, 3rd entry from the root dir and check it.
+ //-- this is the DOS entry
+
+ posEntry += KSizeOfFatDirEntry;
+ nRes = TheDisk.Read(posEntry, ptrEntry);
+ test(nRes == KErrNone);
+
+ //-- first 13 bytes of DOS entry SFN, attributes and DIR_NTRes field
+ const TUint8 KEntry3[13] = {'L','O','N','G','F','I','~','1',' ',' ',' ', 0x20, 0x00 };
+ nRes = Mem::Compare(fatEntry.iData, 13, KEntry3, 13);
+ test(nRes == KErrNone);
+
+ //-- skip file time stamps, they are not consistent
+
+ //-- test file size and start cluster of the file
+ test(fatEntry.StartCluster() != gBootSector.RootClusterNum() && fatEntry.StartCluster() != 0);
+ test(fatEntry.Size() == KFileSize);
+
+ //-- goto the next entry, this must be the end of directory
+ posEntry += KSizeOfFatDirEntry;
+ nRes = TheDisk.Read(posEntry, ptrEntry);
+ test(nRes == KErrNone);
+ test(fatEntry.IsEndOfDirectory());
+
+ TheDisk.Close();
+
+}
+
+
+void CallTestsL()
{
TInt drvNum;
@@ -546,6 +624,8 @@
GetBootInfo();
+ TestVFatEntryInterop();
+
Test1(EUpper); // Test directory entries with 8.3 uppercase (no VFAT entries expected)
Test1(ELower); // Test directory entries with 8.3 lowercase ( VFAT entries expected)
Test1(EMixed); // Test directory entries with 8.3 mixed ( VFAT entries expected)
@@ -559,7 +639,6 @@
TestPDEF116912();
TestReplaceByShortName();
-
}
--- a/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -597,7 +597,7 @@
RDebug::Print(_L("%5d: ------------- end of directory"), aNum);
return EFalse;
}
- else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+ else if (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
{
TBuf16<15> name;
ExtractNameString(name, aEntry);
@@ -795,7 +795,7 @@
TheRawDisk.Close();
RDebug::Print(_L("Cluster %d @ 0x%08X:"), aCluster, ClusterToByte(aCluster));
TFatDirEntry* d = (TFatDirEntry*)ptr.Ptr() + aEntry;
- while ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName && aEntry < gEntriesPerCluster)
+ while (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName && aEntry < gEntriesPerCluster)
{
if (d->IsErased() || d->IsEndOfDirectory())
break;
@@ -807,7 +807,7 @@
start = -1;
else if (d->IsEndOfDirectory())
start = -1;
- else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+ else if (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
start = -1;
else if (!IsValidDirEntry(d))
start = -1;
--- a/kerneltest/f32test/filesystem/fat/t_tscan32.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/t_tscan32.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -563,7 +563,7 @@
}
else if (d->IsEndOfDirectory())
return EFalse;
- else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+ else if (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
{
TBuf16<15> name;
ExtractNameString(name, aEntry);
--- a/kerneltest/f32test/fileutils/inc/fat_utils.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/fileutils/inc/fat_utils.h Mon Mar 15 12:45:50 2010 +0200
@@ -77,22 +77,22 @@
//-----------------------------------------------------------------------------
-const TInt KFatFirstSearchCluser =2; ///< FAT usable clusters start from 2; FAT[0] and FAT[1] are reserved
+const TUint KFatFirstSearchCluser =2; ///< FAT usable clusters start from 2; FAT[0] and FAT[1] are reserved
const TInt KFatDirNameSize =11; ///< Dos directory/File name length
-const TInt KFatDirReserved1Size =8; ///< Size of reserved area one in a directory enrty
+const TUint KFatDirReserved1Size =8; ///< Size of reserved area one in a directory enrty
const TInt KVolumeLabelSize =11; ///< Volume lable size
const TInt KFileSysTypeSize =8; ///< File system type parameter size
const TInt KVendorIdSize =8; ///< Vendor ID parameter size
-const TInt KVFatEntryAttribute =0x0F; ///< VFat entry attribute setting
-const TInt KBootSectorSignature =0xAA55;///< File system Boot sector signiture
+const TUint KVFatEntryAttribute =0x0F; ///< VFat entry attribute setting
+const TUint KBootSectorSignature =0xAA55;///< File system Boot sector signiture
const TUint8 KDotEntryByte =0x2e; ///< Dot value for self and parent pointer directory entries
const TUint8 KBlankSpace =0x20; ///< Blank space in a directory entry
-const TInt KSizeOfFatDirEntry =32; ///< Size in bytes of a Fat directry entry
-const TInt KSizeOfFatDirEntryLog2 =5; ///< Log2 of size in bytes of a Fat directry entry
-const TInt KFat16VolumeLabelPos =43; ///< Position of volume lable in BPB for Fat12/16
-const TInt KFat32VolumeLabelPos =71; ///< Position of volume lable in BPB for Fat32
-const TInt KReservedIdOldEntry =1; ///< used for TFatDirEntry::SetReserved2(..)
-const TInt KReservedIdNewEntry =0;
+const TUint KSizeOfFatDirEntry =32; ///< Size in bytes of a Fat directry entry
+const TUint KSizeOfFatDirEntryLog2 =5; ///< Log2 of size in bytes of a Fat directry entry
+const TUint KFat16VolumeLabelPos =43; ///< Position of volume lable in BPB for Fat12/16
+const TUint KFat32VolumeLabelPos =71; ///< Position of volume lable in BPB for Fat32
+const TUint KReservedIdOldEntry =1; ///< used for TFatDirEntry::SetReserved2(..)
+const TUint KReservedIdNewEntry =0;
const TInt KSizeOfFatBootSector =90; ///< Size in bytes of Boot sector parameter block (BPB)
const TUint32 KBootSectorNum =0; ///< Main Boot Sector number (always 0)
@@ -325,9 +325,9 @@
void InitZ();
const TPtrC8 Name() const;
- TInt Attributes() const;
+ TUint Attributes() const;
TTime Time() const;
- TInt StartCluster() const;
+ TUint32 StartCluster() const;
TUint32 Size() const;
TBool IsErased() const;
TBool IsCurrentDirectory() const;
@@ -335,10 +335,10 @@
TBool IsEndOfDirectory() const;
TBool IsGarbage() const;
void SetName(const TDesC8& aDes);
- void SetAttributes(TInt anAtt);
+ void SetAttributes(TUint anAtt);
void SetTime(TTime aTime);
void SetCreateTime(TTime aTime);
- void SetStartCluster(TInt aStartCluster);
+ void SetStartCluster(TUint32 aStartCluster);
void SetSize(TUint32 aFilesize);
void SetErased();
void SetCurrentDirectory();
--- a/kerneltest/f32test/fileutils/src/fat_utils.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/fileutils/src/fat_utils.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -1149,7 +1149,7 @@
{return TPtrC8((TUint8*)&(pDir->iName),KFatDirNameSize);}
/** @return The attributes for the Directory entry */
-TInt TFatDirEntry::Attributes() const
+TUint TFatDirEntry::Attributes() const
{return pDir->iAttributes;}
/** @return Time of file creation */
@@ -1157,7 +1157,7 @@
{return DosTimeToTTime(pDir->iTime,pDir->iDate);}
/** @return The Start cluster for the file or directory for this entry */
-TInt TFatDirEntry::StartCluster() const
+TUint32 TFatDirEntry::StartCluster() const
{
const TUint16 KStClustMaskHi = 0x0FFF;
return ((pDir->iStartClusterHi&KStClustMaskHi)<<16) | pDir->iStartClusterLo;
@@ -1198,7 +1198,7 @@
Set the file or directory attributes for this entry
@param anAtts The file or directory attributes
*/
-void TFatDirEntry::SetAttributes(TInt anAtts)
+void TFatDirEntry::SetAttributes(TUint anAtts)
{
ASSERT(!(anAtts&~KMaxTUint8));
pDir->iAttributes=(TUint8)anAtts;
@@ -1224,7 +1224,7 @@
Set the start cluster number of the file or directory refered to by the entry
@param aStartCluster The start cluster number
*/
-void TFatDirEntry::SetStartCluster(TInt aStartCluster)
+void TFatDirEntry::SetStartCluster(TUint32 aStartCluster)
{
const TUint32 KHalfWordMask = 0x0000FFFF;
pDir->iStartClusterLo=(TUint16)(aStartCluster & KHalfWordMask);
--- a/kerneltest/f32test/server/t_main.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/server/t_main.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -680,10 +680,8 @@
r = controlIo(TheFs,theDrive, KControlIoCacheCount, orgValues);
test_KErrNone(r);
- test.Printf(_L("Requests on close queue at start=%d\n"),orgValues.iCloseCount);
- test.Printf(_L("Requests on free queue at start=%d\n"),orgValues.iFreeCount);
- test.Printf(_L("Requests dynamically allocated at start=%d\n"),orgValues.iAllocated);
- test.Printf(_L("Requests in total at start=%d\n"),orgValues.iTotalCount);
+ test.Printf(_L("Requests at start: CloseQ %d FreeQ %d total %d peak %d\n"),
+ orgValues.iCloseCount, orgValues.iFreeCount, orgValues.iTotalCount, orgValues.iRequestCountPeak);
// File cache
@@ -793,10 +791,10 @@
r = controlIo(TheFs,theDrive, KControlIoCacheCount, values);
test_KErrNone(r);
- test.Printf(_L("Requests on close queue at end=%d\n"),values.iCloseCount);
- test.Printf(_L("Requests on free queue at end=%d\n"),values.iFreeCount);
- test.Printf(_L("Requests dynamically allocated at end=%d\n"),values.iAllocated);
- test.Printf(_L("Requests in total at end=%d\n"),values.iTotalCount);
+ test.Printf(_L("Requests at end: CloseQ %d FreeQ %d total %d peak %d\n"),
+ values.iCloseCount, values.iFreeCount, values.iTotalCount, values.iRequestCountPeak);
+ test.Printf(_L("Operations at end: FreeQ %d total %d peak=%d\n"),
+ values.iOpFreeCount, values.iOpRequestCount, values.iOpRequestCountPeak);
test(orgValues.iCloseCount==values.iCloseCount);
test(orgValues.iAllocated == values.iAllocated);
--- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/cmassstoragemountcb.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/cmassstoragemountcb.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -220,280 +220,6 @@
delete hDes;
}
-/**
-Make sure that the file system is fat.
-*/
-TBool CMassStorageMountCB::ValidateBootSector()
- {
- __FNLOG("CMassStorageMountCB::ValidateBootSector");
-
- TFatBootSector bootSector;
- TInt r=ReadBootSector(bootSector);
- __PRINT1(_L("CMassStorageMountCB::MountL - ReadBootSector returned %d"),r);
- if (r != KErrNone)
- {
- return EFalse;
- }
-
- __PRINT(_L("\nBootSector info"));
- __PRINT8BIT1(_L("FAT type = %S"),bootSector.FileSysType());
- __PRINT8BIT1(_L("Vendor ID = %S"),bootSector.VendorId());
- __PRINT1(_L("BytesPerSector %d"),bootSector.BytesPerSector());
- __PRINT1(_L("SectorsPerCluster %d"),bootSector.SectorsPerCluster());
- __PRINT1(_L("ReservedSectors %d"),bootSector.ReservedSectors());
- __PRINT1(_L("NumberOfFats %d"),bootSector.NumberOfFats());
- __PRINT1(_L("RootDirEntries %d"),bootSector.RootDirEntries());
- __PRINT1(_L("Total Sectors = %d"),bootSector.TotalSectors());
- __PRINT1(_L("MediaDescriptor = 0x%x"),bootSector.MediaDescriptor());
- __PRINT1(_L("FatSectors %d"),bootSector.FatSectors());
- __PRINT1(_L("SectorsPerTrack %d"),bootSector.SectorsPerTrack());
- __PRINT1(_L("NumberOfHeads %d"),bootSector.NumberOfHeads());
- __PRINT1(_L("HugeSectors %d"),bootSector.HugeSectors());
- __PRINT1(_L("Fat32 Sectors %d"),bootSector.FatSectors32());
- __PRINT1(_L("Fat32 Flags %d"),bootSector.FATFlags());
- __PRINT1(_L("Fat32 Version Number %d"),bootSector.VersionNumber());
- __PRINT1(_L("Root Cluster Number %d"),bootSector.RootClusterNum());
- __PRINT1(_L("FSInfo Sector Number %d"),bootSector.FSInfoSectorNum());
- __PRINT1(_L("Backup Boot Rec Sector Number %d"),bootSector.BkBootRecSector());
- __PRINT1(_L("PhysicalDriveNumber %d"),bootSector.PhysicalDriveNumber());
- __PRINT1(_L("ExtendedBootSignature %d"),bootSector.ExtendedBootSignature());
- __PRINT1(_L("UniqueID %d"),bootSector.UniqueID());
- __PRINT8BIT1(_L("VolumeLabel %S"),bootSector.VolumeLabel());
- __PRINT8BIT1(_L("FileSysType %S\n"),bootSector.FileSysType());
-
- iUniqueID=bootSector.UniqueID();
- iIs16BitFat=bootSector.Is16BitFat();
-
- iIs32BitFat=bootSector.Is32BitFat();
- switch (DetermineFatType(bootSector))
- {
- case 12:
- iIs16BitFat = EFalse;
- iIs32BitFat = EFalse;
- break;
- case 16:
- iIs16BitFat = ETrue;
- iIs32BitFat = EFalse;
- break;
- case 32:
- iIs16BitFat = EFalse;
- iIs32BitFat = ETrue;
- break;
- default:
- return EFalse;
- }
-
- TInt sectorsPerCluster=bootSector.SectorsPerCluster();
- if (!IsPowerOfTwo(sectorsPerCluster))
- return EFalse;
-
- TInt sectorSizeLog2=Log2(bootSector.BytesPerSector());
- if (sectorSizeLog2<0 || !IsPowerOfTwo(bootSector.BytesPerSector()))
- return EFalse;
-
- TInt firstFatSector=bootSector.ReservedSectors();
- if (firstFatSector<1)
- return EFalse;
-
- TInt fatSizeInBytes;
- if(iIs32BitFat)
- {
- fatSizeInBytes=bootSector.FatSectors32()*bootSector.BytesPerSector();
- if (fatSizeInBytes<bootSector.BytesPerSector())
- return EFalse;
- }
- else
- {
- fatSizeInBytes=bootSector.FatSectors()*bootSector.BytesPerSector();
- if (fatSizeInBytes<bootSector.BytesPerSector())
- return EFalse;
-
- TInt rootDirectorySector=firstFatSector+bootSector.FatSectors()*bootSector.NumberOfFats();
- if (rootDirectorySector<3)
- return EFalse;
-
- TInt rootDirSizeInBytes=bootSector.RootDirEntries()*KSizeOfFatDirEntry;
- TInt numOfRootDirSectors=(rootDirSizeInBytes+(1<<sectorSizeLog2)-1)>>sectorSizeLog2;
- TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<<sectorSizeLog2;
- if (rootDirEnd<(4<<sectorSizeLog2))
- return EFalse;
- }
-
-
- TInt totalSectors=bootSector.TotalSectors();
- if (totalSectors==0)
- totalSectors=bootSector.HugeSectors();
- if (totalSectors<5)
- return EFalse;
-
- TInt numberOfFats=bootSector.NumberOfFats();
- if (numberOfFats<1)
- return EFalse;
-
- return ETrue;
- }
-
-/**
-Read non aligned boot data from media into TFatBootSector structure
-
-@param aBootSector refrence to TFatBootSector populate
-@return Media read error code
-*/
-TInt CMassStorageMountCB::ReadBootSector(TFatBootSector& aBootSector)
- {
- __FNLOG("CMassStorageMountCB::ReadBootSector");
- TInt pos=0;
- TUint8 data[KSizeOfFatBootSector];
- TPtr8 buf(&data[0],KSizeOfFatBootSector);
- TInt r=LocalDrive()->Read(0,KSizeOfFatBootSector,buf);
- if (r!=KErrNone)
- {
- __PRINT1(_L("LocalDrive::Read() failed - %d"),r);
- return(r);
- }
-// 0 TUint8 iJumpInstruction[3]
- Mem::Copy(&aBootSector.iJumpInstruction,&data[pos],3);
- pos+=3;
-// 3 TUint8 iVendorId[KVendorIdSize]
- Mem::Copy(&aBootSector.iVendorId,&data[pos],KVendorIdSize);
- pos+=KVendorIdSize;
-// 11 TUint16 iBytesPerSector
- Mem::Copy(&aBootSector.iBytesPerSector,&data[pos],2);
- pos+=2;
-// 13 TUint8 sectorsPerCluster
- Mem::Copy(&aBootSector.iSectorsPerCluster,&data[pos],1);
- pos+=1;
-// 14 TUint16 iReservedSectors
- Mem::Copy(&aBootSector.iReservedSectors,&data[pos],2);
- pos+=2;
-// 16 TUint8 numberOfFats
- Mem::Copy(&aBootSector.iNumberOfFats,&data[pos],1);
- pos+=1;
-// 17 TUint16 iRootDirEntries
- Mem::Copy(&aBootSector.iRootDirEntries,&data[pos],2);
- pos+=2;
-// 19 TUint16 totalSectors
- Mem::Copy(&aBootSector.iTotalSectors,&data[pos],2);
- pos+=2;
-// 21 TUint8 iMediaDescriptor
- Mem::Copy(&aBootSector.iMediaDescriptor,&data[pos],1);
- pos+=1;
-// 22 TUint16 iFatSectors
- Mem::Copy(&aBootSector.iFatSectors,&data[pos],2);
- pos+=2;
-// 24 TUint16 iSectorsPerTrack
- Mem::Copy(&aBootSector.iSectorsPerTrack,&data[pos],2);
- pos+=2;
-// 26 TUint16 iNumberOfHeads
- Mem::Copy(&aBootSector.iNumberOfHeads,&data[pos],2);
- pos+=2;
-// 28 TUint32 iHiddenSectors
- Mem::Copy(&aBootSector.iHiddenSectors,&data[pos],4);
- pos+=4;
-// 32 TUint32 iHugeSectors
- Mem::Copy(&aBootSector.iHugeSectors,&data[pos],4);
- pos+=4;
-
- if(aBootSector.iRootDirEntries == 0) //indicates we have FAT32 volume
- {
- __PRINT(_L("\nFile system thinks Fat32"));
-
- //36 TUint32 iFatSectors32
- Mem::Copy(&aBootSector.iFatSectors32, &data[pos],4);
- pos+=4;
- //40 TUint16 iFATFlags
- Mem::Copy(&aBootSector.iFATFlags, &data[pos],2);
- pos+=2;
- //42 TUint16 iVersionNumber
- Mem::Copy(&aBootSector.iVersionNumber, &data[pos],2);
- pos+=2;
- //44 TUint32 iRootClusterNum
- Mem::Copy(&aBootSector.iRootClusterNum, &data[pos],4);
- pos+=4;
- //48 TUint16 iFSInfoSectorNum
- Mem::Copy(&aBootSector.iFSInfoSectorNum, &data[pos],2);
- pos+=2;
- //50 TUint16 iBkBootRecSector
- Mem::Copy(&aBootSector.iBkBootRecSector, &data[pos],2);
- pos+=(2+12);//extra 12 for the reserved bytes
- }
-
-// 36|64 TUint8 iPhysicalDriveNumber
- Mem::Copy(&aBootSector.iPhysicalDriveNumber,&data[pos],1);
- pos+=1;
-// 37|65 TUint8 iReserved
- Mem::Copy(&aBootSector.iReserved,&data[pos],1);
- pos+=1;
-// 38|66 TUint8 iExtendedBootSignature
- Mem::Copy(&aBootSector.iExtendedBootSignature,&data[pos],1);
- pos+=1;
-// 39|67 TUint32 iUniqueID
- Mem::Copy(&aBootSector.iUniqueID,&data[pos],4);
- pos+=4;
-// 43|71 TUint8 iVolumeLabel[KVolumeLabelSize]
- Mem::Copy(&aBootSector.iVolumeLabel,&data[pos],KVolumeLabelSize);
- pos+=KVolumeLabelSize;
-// 54|82 TUint8 iFileSysType[KFileSysTypeSize]
- Mem::Copy(&aBootSector.iFileSysType,&data[pos],KFileSysTypeSize);
-// 62|90
-
- return(KErrNone);
- }
-
-/**
-Work out if we have a FAT12|16|32 volume.
-Returns 12, 16 or 32 as appropriate.
-Returns 0 if can't be calculated (invalid values)
-*/
-TInt CMassStorageMountCB::DetermineFatType(TFatBootSector& aBootSector)
- {
- TUint32 ressectors = aBootSector.ReservedSectors();
-
- if (aBootSector.SectorsPerCluster() < 1)
- return 0;
-
- if (aBootSector.RootDirEntries() != 0)
- {
- TUint32 rootdirbytes;
- rootdirbytes = aBootSector.RootDirEntries() * 32 + aBootSector.BytesPerSector() - 1;
- ressectors += rootdirbytes / aBootSector.BytesPerSector();
- }
-
- if (aBootSector.FatSectors() != 0)
- ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors();
- else
- ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors32();
-
- TUint32 totalsectors;
- if (aBootSector.TotalSectors() != 0)
- totalsectors = aBootSector.TotalSectors();
- else
- totalsectors = aBootSector.HugeSectors();
-
- if (ressectors < 1 || totalsectors < 1)
- return 0;
-
- TUint32 datasec;
- datasec = totalsectors - ressectors;
-
- TUint32 countofclusters;
- countofclusters = datasec / aBootSector.SectorsPerCluster();
-
- __PRINT1(_L("CFatMountCB: Count of clusters = %d\n"), countofclusters);
-
- if (countofclusters < 4085)
- {
- return 12;
- }
- else if (countofclusters < 65525)
- {
- return 16;
- }
- else
- {
- return 32;
- }
- }
TInt CMassStorageMountCB::ReMount()
{
--- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragefilesystem.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragefilesystem.h Mon Mar 15 12:45:50 2010 +0200
@@ -35,7 +35,6 @@
};
-
/**
Mass Storage Filesystem class.
Only supports creating a new mount. Calling NewFileL, NewDirL and NewFormatL
@@ -82,8 +81,6 @@
CUsbMassStorageController* iMassStorageController;
TBool iRunning;
TLunToDriveMap iDriveMap;
-
-
};
#endif // __CMASSSTORAGEFILESYSTEM_H__
--- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragemountcb.h Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragemountcb.h Mon Mar 15 12:45:50 2010 +0200
@@ -25,7 +25,6 @@
#ifndef __CMASSSTORAGEMOUNTCB_H__
#define __CMASSSTORAGEMOUNTCB_H__
-#include <f32fsys.h>
/**
Mass Storage Mount.
@@ -34,7 +33,6 @@
ControlIO is also supported for debug builds and returns KErrNotSupported for Release builds.
@internalTechnology
*/
-class TFatBootSector;
class CMassStorageMountCB : public CLocDrvMountCB
{
public:
@@ -65,208 +63,14 @@
CMassStorageMountCB(const TLunToDriveMap& aDriveMapping);
void WritePasswordData();
TInt DriveNumberToLun(TInt aDriveNumber);
- TBool ValidateBootSector();
- TInt ReadBootSector(TFatBootSector& aBootSector);
- TInt DetermineFatType(TFatBootSector& aBootSector);
TInt CheckDriveNumberL();
TBool IsPowerOfTwo(TInt aNum);
TInt Log2(TInt aNum);
private:
- TBool iIs16BitFat;
- TBool iIs32BitFat;
const TLunToDriveMap& iDriveMapping;
};
-const TInt KSizeOfFatBootSector = 90;
-const TInt KVendorIdSize = 8;
-const TInt KVolumeLabelSize = 11;
-const TInt KFileSysTypeSize = 8;
-const TInt KBootSectorSignature = 0xAA55;
-const TInt KSizeOfFatDirEntry = 32;
-
-/**
-Boot sector parameter block, enables access to all file system parameters.
-Data is populated at mount time from the BPB sector
-@internalTechnology
-*/
-class TFatBootSector
- {
-public:
- inline const TPtrC8 VendorId() const;
- inline TUint16 BytesPerSector() const;
- inline TInt SectorsPerCluster() const;
- inline TInt ReservedSectors() const;
- inline TInt NumberOfFats() const;
- inline TInt RootDirEntries() const;
- inline TInt TotalSectors() const;
- inline TUint8 MediaDescriptor() const;
- inline TInt FatSectors() const;
- inline TInt SectorsPerTrack() const;
- inline TInt NumberOfHeads() const;
- inline TInt HiddenSectors() const;
- inline TInt HugeSectors() const;
- inline TInt PhysicalDriveNumber() const;
- inline TInt ExtendedBootSignature() const;
- inline TUint32 UniqueID() const;
- inline const TPtrC8 VolumeLabel() const;
- inline const TPtrC8 FileSysType() const;
- inline TInt BootSectorSignature() const;
- inline void SetJumpInstruction();
- inline void SetVendorID(const TDesC8& aDes);
- inline void SetBytesPerSector(TInt aBytesPerSector);
- inline void SetSectorsPerCluster(TInt aSectorsPerCluster);
- inline void SetReservedSectors(TInt aReservedSectors);
- inline void SetNumberOfFats(TInt aNumberOfFats);
- inline void SetRootDirEntries(TInt aRootDirEntries);
- inline void SetTotalSectors(TInt aTotalSectors);
- inline void SetMediaDescriptor(TUint8 aMediaDescriptor);
- inline void SetFatSectors(TInt aFatSectors);
- inline void SetSectorsPerTrack(TInt aSectorsPerTrack);
- inline void SetNumberOfHeads(TInt aNumberOfHeads);
- inline void SetHiddenSectors(TUint32 aHiddenSectors);
- inline void SetHugeSectors(TUint32 aTotalSectors);
- inline void SetPhysicalDriveNumber(TInt aPhysicalDriveNumber);
- inline void SetReservedByte(TUint8 aReservedByte);
- inline void SetExtendedBootSignature(TInt anExtendedBootSignature);
- inline void SetUniqueID(TUint32 anUniqueID);
- inline void SetVolumeLabel(const TDesC8& aDes);
- inline void SetFileSysType(const TDesC8& aDes);
-
- inline void SetFatSectors32(TUint32 aFatSectors32);
- inline void SetFATFlags(TUint16 aFATFlags);
- inline void SetVersionNumber(TUint16 aVersionNumber);
- inline void SetRootClusterNum(TUint32 aRootCusterNum);
- inline void SetFSInfoSectorNum(TUint16 aFSInfoSectorNum);
- inline void SetBkBootRecSector(TUint16 aBkBootRecSector);
- inline TUint32 FatSectors32() const;
- inline TUint16 FATFlags() const;
- inline TUint16 VersionNumber() const;
- inline TUint32 RootClusterNum() const;
- inline TUint16 FSInfoSectorNum() const;
- inline TUint16 BkBootRecSector() const;
-public:
- inline TBool Is16BitFat();
- inline TBool Is32BitFat();
- inline TInt FirstFatSectorPos();
- inline TInt RootDirStartSector();
- inline TInt FirstFreeSector();
-public:
- /**
- Jump instruction used for bootable volumes
- */
- TUint8 iJumpInstruction[3];
- /**
- Vendor ID of the file system that formatted the volume
- */
- TUint8 iVendorId[KVendorIdSize];
- /**
- Bytes per sector
- */
- TUint16 iBytesPerSector;
- /**
- Sectors per cluster ratio
- */
- TUint8 iSectorsPerCluster;
- /**
- Number of reserved sectors on the volume
- */
- TUint16 iReservedSectors;
- /**
- Number of Fats on the volume
- */
- TUint8 iNumberOfFats;
- /**
- Number of entries allowed in the root directory, specific to Fat12/16, zero for FAT32
- */
- TUint16 iRootDirEntries;
- /**
- Total sectors on the volume, zero for FAT32
- */
- TUint16 iTotalSectors;
- /**
- Media descriptor
- */
- TUint8 iMediaDescriptor;
- /**
- Sectors used for the Fat table, zero for FAT32
- */
- TUint16 iFatSectors;
- /**
- Sectors per track
- */
- TUint16 iSectorsPerTrack;
- /**
- Number of heads
- */
- TUint16 iNumberOfHeads;
- /**
- Number of hidden sectors in the volume
- */
- TUint32 iHiddenSectors;
- /**
- Total sectors in the volume, Used if totalSectors > 65535
- */
- TUint32 iHugeSectors;
-
- /**
- Start of additional elements @ offset 36 for FAT32
- Sectors in Fat table for 32 bit volume
- */
- TUint32 iFatSectors32;
- /**
- Fat flags
- */
- TUint16 iFATFlags;
- /**
- Version number of the file system
- */
- TUint16 iVersionNumber;
- /**
- Cluster number of the root directory
- */
- TUint32 iRootClusterNum;
- /**
- Sector number containing the FSIInfo structure
- */
- TUint16 iFSInfoSectorNum;
- /**
- Backup boot sector
- */
- TUint16 iBkBootRecSector;
- /**
- Reserved space
- End of Fat32 Only parameters section
- */
- TUint8 iReserved2[12];
-
- /**
- Physical drive number, not used in Symbian OS
- */
- TUint8 iPhysicalDriveNumber;
- /**
- Reserved byte
- */
- TUint8 iReserved;
- /**
- Extended boot signiture
- */
- TUint8 iExtendedBootSignature;
- /**
- Unique volume ID
- */
- TUint32 iUniqueID;
- /**
- The volume's label
- */
- TUint8 iVolumeLabel[KVolumeLabelSize];
- /**
- File system type
- */
- TUint8 iFileSysType[KFileSysTypeSize];
- };
-
-#include "tfatbootsector.inl"
#endif //__CMASSSTORAGEMOUNTCB_H__
--- a/kerneltest/f32test/smassstorage/src/t_ms_fsunit.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/smassstorage/src/t_ms_fsunit.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -21,11 +21,8 @@
*/
#include <f32file.h>
+#include <f32fsys.h>
#include <e32test.h>
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32svr.h>
-#include <hal.h>
#include "t_ms_main.h"
#include "t_ms_common.h"
#include "cmassstoragefilesystem.h"
@@ -268,7 +265,6 @@
EXPORT_C CLocDrvMountCB::~CLocDrvMountCB()
{
- __PRINT1(_L("CLocDrvMountCB::~CLocDrvMountCB() 0x%x"),this);
if(iProxyDrive)
delete(iProxyDrive);
}
--- a/userlibandfileserver/fileserver/group/release.txt Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/group/release.txt Mon Mar 15 12:45:50 2010 +0200
@@ -1,3 +1,30 @@
+Version 2.00.2039
+=================
+(Made by vfebvre 23/02/2010)
+
+1. niccox
+ 1. DEF144323 remove redundant bootsector code from smassstorage
+
+
+Version 2.00.2038
+=================
+(Made by vfebvre 18/02/2010)
+
+1. famustaf
+ 1. PDEF144438 Optimise TParseBase::AddDir() to not use TFileName
+
+2. migubarr
+ 1. DEF144407: File Server request cache is not big enough for S60
+
+
+Version 2.00.2037
+=================
+(Made by vfebvre 11/02/2010)
+
+1. dlyokhin
+ 1. DEF144356 VFAT interoperability: LFN entries padding is wrong
+
+
Version 2.00.2036
=================
(Made by vfebvre 09/02/2010)
--- a/userlibandfileserver/fileserver/inc/f32dbg.h Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/inc/f32dbg.h Mon Mar 15 12:45:50 2010 +0200
@@ -194,10 +194,17 @@
class TIOCacheValues
{
public:
- TInt iFreeCount; // number of requests on free queue
- TInt iCloseCount; // number of requests on close queue
- TInt iAllocated; // number of dynamically allocated requests
- TInt iTotalCount; // number of permanently & dynamically allocated requests
+ TInt iFreeCount; // current number of requests on free queue
+ TInt iCloseCount; // current number of requests on close queue
+ TInt iAllocated; // no longer used
+ TInt iTotalCount; // current number of requests
+ TInt iRequestCountPeak; // peak number of requests, i.e. peak value reached by iTotalCount
+
+
+ // the same again but for the OperationAllocator
+ TInt iOpFreeCount;
+ TInt iOpRequestCount;
+ TInt iOpRequestCountPeak;
};
class TFileCacheStats
--- a/userlibandfileserver/fileserver/inc/f32ver.h Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/inc/f32ver.h Mon Mar 15 12:45:50 2010 +0200
@@ -58,6 +58,6 @@
@see TVersion
*/
-const TInt KF32BuildVersionNumber=2036;
+const TInt KF32BuildVersionNumber=2039;
//
#endif
--- a/userlibandfileserver/fileserver/sfile/sf_debug.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_debug.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -450,8 +450,15 @@
TIOCacheValues cacheValues;
cacheValues.iCloseCount= RequestAllocator::CloseCount();
cacheValues.iFreeCount= RequestAllocator::FreeCount();
- cacheValues.iAllocated= RequestAllocator::AllocatedCount();
- cacheValues.iTotalCount= RequestAllocator::TotalCount();
+ cacheValues.iAllocated= 0; // no longer used
+ cacheValues.iTotalCount= RequestAllocator::RequestCount();
+ cacheValues.iRequestCountPeak = RequestAllocator::RequestCountPeak();
+
+ cacheValues.iOpFreeCount= OperationAllocator::FreeCount();
+ cacheValues.iOpRequestCount= OperationAllocator::RequestCount();
+ cacheValues.iOpRequestCountPeak = OperationAllocator::RequestCountPeak();
+
+
TPckgBuf<TIOCacheValues> pkgBuf(cacheValues);
// ensure we only write what the client buffer can hold -
--- a/userlibandfileserver/fileserver/sfile/sf_lepoc.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_lepoc.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -202,14 +202,33 @@
#ifdef _DEBUG
__IF_DEBUG(Printf("processed reloc table (size=%d,pageCount=%d)", iCodeRelocTableSize, pageCount));
- // dump the import fixup table if loader tracing enabled
- const TUint16* table16 = (const TUint16*)table;
- const TInt halfWordsInTable = iCodeRelocTableSize / 2;
- for(i = 0; i < halfWordsInTable; i += 4)
+ // Dump the processed reloc table if loader tracing enabled. The dump is in
+ // two parts; first, the page indexes (1 word per page), then the entries
+ // describing the items to be relocated on each of these pages, formatted
+ // with up to 8 entries per line but starting a new line for each page.
+ // Each of these entries has the relocation type in the first nibble, and
+ // the offset within the page in the remaining 3 nibbles.
+ const TUint32* table32 = (const TUint32*)table;
+ for (i = 0; i <= pageCount; ++i)
+ __IF_DEBUG(Printf("%04x: %08x", i*4, table32[i]));
+
+ for (i = 0; i < pageCount; ++i)
{
- __IF_DEBUG(Printf(
- "reloc %04x: %04x %04x %04x %04x",
- i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
+ TUint start = table32[i];
+ TInt nbytes = table32[i+1] - start;
+ while (nbytes)
+ {
+ TBuf8<0x100> buf;
+ buf.Format(_L8("%04x:"), start);
+
+ const TUint16* p = (const TUint16*)(table+start);
+ TInt n = nbytes <= 16 ? nbytes : 16;
+ for (nbytes -= n, start += n; n > 0; n -= 2)
+ buf.AppendFormat(_L8(" %04x"), *p++);
+
+ buf.AppendFormat(_L8("\r\n"));
+ __IF_DEBUG(RawPrint(buf));
+ }
}
#endif
return KErrNone;
@@ -268,6 +287,18 @@
}
}
+// A version that will work in user or supervisor mode
+void MyPrintf(const char* aFmt, ...)
+ {
+ VA_LIST list;
+ VA_START(list, aFmt);
+ TPtrC8 fmt((const TText8*)aFmt);
+ TBuf8<0x100> buf;
+ buf.AppendFormatList(fmt, list);
+ buf.AppendFormat(_L8("\r\n"));
+ RDebug::RawPrint(buf);
+ VA_END(list);
+ }
/**
Arguments for svRelocateSection.
@@ -340,29 +371,80 @@
/**
Fix up the export directory
-Only performed on PE images. ELF image's exports are marked
-as relocatable and therefore relocated by svRelocateSection when the
-text section is relocated up
+Only performed on PE images. ELF image's exports are marked as relocatable
+and therefore relocated by svRelocateSection along with the text section
*/
TInt svRelocateExports(TAny* aPtr)
{
- E32Image* pI=(E32Image*)aPtr;
- TUint32* destExport=(TUint32*)pI->iExportDirLoad;
- TInt i=pI->iExportDirCount;
- TUint32 codeBase=pI->iCodeRunAddress;
- while (i-->0)
- *destExport+++=codeBase;
+ E32Image& exporter = *(E32Image*)aPtr;
+
+ // Dump everything potentially useful that we know about the exporter ...
+ __LDRTRACE(MyPrintf("RelocateExports: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
+ exporter.iUseCodePaging, exporter.iRomImageHeader, exporter.iHeader));
+ __LDRTRACE(MyPrintf(" iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
+ exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
+ exporter.iCodeSize, exporter.iTextSize))
+ __LDRTRACE(MyPrintf(" iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
+ exporter.iDataLoadAddress, exporter.iDataRunAddress,
+ exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
+ __LDRTRACE(MyPrintf(" iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
+ exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
+
+ // It turns out that very little of the exporter info is useful! For
+ // example, the required code and data deltas are NOT those provided
+ // by the exporter, nor are the load addresses relevant ... :(
+ //
+ // In the case of a PE-derived image, the entries in the export table
+ // are expressed in terms of offsets into the image file, rather than
+ // locations in memory. Each therefore needs to be relocated by the
+ // difference between its file offset and its run address.
+ //
+ // It is assumed that the code segment appears before the data segment
+ // in the file; therefore, export table entries with values between 0
+ // and (exporter.iCodeSize) refer to the text segment, while higher
+ // values represent references to data addresses. Since the run addresses
+ // of code and data segments may be different, each type of export must
+ // be relocated with respect to the correct section.
+ //
+ // The following express the start and finish of each section in terms of
+ // file offsets and then derive the required adjustments to the entries
+ // in the export table ...
+ TUint32 codeStart = 0; // compiler whinges if this is 'const' :(
+ const TUint32 codeFinish = codeStart + exporter.iCodeSize;
+ const TUint32 dataStart = codeFinish;
+ const TUint32 dataFinish = dataStart + exporter.iTotalDataSize;
+ const TUint32 codeDelta = exporter.iCodeRunAddress - codeStart;
+ const TUint32 dataDelta = exporter.iDataRunAddress - dataStart;
+
+ TUint32* destExport = (TUint32*)exporter.iExportDirLoad;
+ for (TInt i = exporter.iExportDirCount; --i >= 0; )
+ {
+ TUint32 relocAddr = *destExport;
+ TUint32 newValue;
+ if (relocAddr >= codeStart && relocAddr < codeFinish)
+ newValue = relocAddr + codeDelta; // points to text/rdata section
+ else if (relocAddr >= dataStart && relocAddr < dataFinish)
+ newValue = relocAddr + dataDelta; // points to data/bss section
+ else
+ newValue = relocAddr; // unknown - just leave it alone
+ *destExport++ = newValue;
+
+ __LDRTRACE(MyPrintf("RelocateExports: export %d %08x => %08x %c",
+ exporter.iExportDirCount-i, relocAddr, newValue,
+ (relocAddr >= codeStart && relocAddr < codeFinish) ? 'C' :
+ (relocAddr >= dataStart && relocAddr < dataFinish) ? 'D' : 'X'));
+ }
+
return 0;
}
struct SFixupImportAddressesInfo
{
- TUint32* iIat;
- TUint32* iExportDir;
- TUint32 iExportDirEntryDelta;
- TInt iNumImports;
- E32Image* iExporter;
+ TUint32* iIat; // Next part of IAT to be fixed up
+ E32Image* iExporter; // Module from which we're importing
+ TInt iNumImports; // Number of imports from this exporter
+
/**
For demand paging, this points to the buffer which is populated
so each page can be fixed up as it is loaded in.
@@ -378,52 +460,104 @@
Fix up the import address table, used for 'PE derived' executables.
@param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
SFixupImportAddressesInfo::iIat is updated by this function.
+
+For a given importer, this function will be called once for each image from which
+objects are imported, and each time it will update the relevant portion of the
+importer's IAT, until all imports from all exporters have been processed.
*/
TInt svFixupImportAddresses(TAny* aPtr)
{
SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
-
- TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
- TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
-
- TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
- TUint32 exp_delta = info.iExportDirEntryDelta;
+ E32Image& exporter = *info.iExporter;
+
+#ifdef _DEBUG
+ __LDRTRACE(MyPrintf(">svFixupImportAddresses %d imports, code@%08x, fixup@%08x exporter@%08x",
+ info.iNumImports, info.iCodeLoadAddress, info.iFixup64, info.iExporter));
+
+ // Dump everything potentially useful that we know about the exporter ...
+ __LDRTRACE(MyPrintf("%S: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
+ &exporter.iFileName, exporter.iUseCodePaging,
+ exporter.iRomImageHeader, exporter.iHeader));
+ __LDRTRACE(MyPrintf("iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
+ exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
+ exporter.iCodeSize, exporter.iTextSize))
+ __LDRTRACE(MyPrintf("iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
+ exporter.iDataLoadAddress, exporter.iDataRunAddress,
+ exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
+ __LDRTRACE(MyPrintf("iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
+ exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
+
+ if (exporter.iRomImageHeader)
+ {
+ const TRomImageHeader& rh = *exporter.iRomImageHeader;
+ __LDRTRACE(MyPrintf("ROM: iCodeAddress %08x, iCodeSize %x, iTextSize %x",
+ rh.iCodeAddress, rh.iCodeSize, rh.iTextSize));
+ __LDRTRACE(MyPrintf("ROM: iDataAddress %08x, iDataSize %x, iBssSize %x",
+ rh.iDataAddress, rh.iDataSize, rh.iBssSize));
+ __LDRTRACE(MyPrintf("ROM: iDataBssLinearBase %08x, iTotalDataSize %x",
+ rh.iDataBssLinearBase, rh.iTotalDataSize));
+ }
+
+ if (exporter.iHeader)
+ {
+ const E32ImageHeader& ih = *exporter.iHeader;
+ __LDRTRACE(MyPrintf("HEAD: iCodeBase %08x, iCodeSize %x, iTextSize %x",
+ ih.iCodeBase, ih.iCodeSize, ih.iTextSize));
+ __LDRTRACE(MyPrintf("HEAD: iDataBase %08x, iDataSize %x, iBssSize %x",
+ ih.iDataBase, ih.iDataSize, ih.iBssSize));
+ }
+#endif // _DEBUG
+
+ // 'exportDir' points to the address of the 0th ordinal (symbol name data);
+ // ordinary exports start from ordinal 1
+ const TUint32* const exportDir = (TUint32*)exporter.iExportDirLoad - KOrdinalBase;
+ const TUint32 maxOrdinal = (TUint32)exporter.iExportDirCount;
+ const TUint32 absentOrdinal = (TUint32)exporter.iFileEntryPoint;
TUint32* iat = info.iIat;
- TUint32* iatE = iat+info.iNumImports;
- for(; iat<iatE; ++iat)
+ TUint32* const iatEnd = iat + info.iNumImports;
+ for (; iat < iatEnd; ++iat)
{
- TUint32 imp = *iat;
- if(imp>maxOrdinal)
+ // Each IAT slot contains the ordinal number of the export to be imported from
+ // the exporter. We use that index to locate the address of the export itself.
+ TUint32 ordinal = *iat;
+ if (ordinal > maxOrdinal)
return KErrNotSupported;
- TUint32 writeValue;
- if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
- {
- // attempt to import ordinal zero (symbol name data) from an executable
- // which doesn't export this information, use NULL for imported value in this case...
- writeValue = NULL;
- }
- else
+ // If the import number is 0 (symbol name data), and the exporter doesn't provide
+ // this, we don't regard it as an error; we just skip this block, leaving the
+ // address set to 0. For all other valid cases, we index the export directory to
+ // find the exported object's address (which has already been relocated) ...
+ TUint32 newValue = 0;
+ if (ordinal > 0 || (exporter.iAttr & ECodeSegAttNmdExpData))
{
- // get imported value from exporter...
- TUint32 exp_addr = exp_dir[imp];
- if(exp_addr==0 || exp_addr==absentOrdinal)
+ TUint32 expAddr = exportDir[ordinal];
+ if (expAddr == 0 || expAddr == absentOrdinal)
return KErrNotSupported;
- writeValue = exp_addr + exp_delta;
+ // The new value is just the address of the export, no adjustment needed
+ newValue = expAddr;
}
- // if not code paging then directly fix up the import...
- if (info.iFixup64 == 0)
- *iat = writeValue;
+ __LDRTRACE(MyPrintf("svFixupImportAddresses: import[%d]@%08x is export[%d] == %08x",
+ iat - info.iIat, iat, ordinal, newValue));
+
+ // In non-paged code, we can simply replace the ordinals in the IAT with the
+ // object addresses to which they refer once and for all. However, in a code
+ // paging system, the IAT may be thrown away and later reloaded from the code
+ // image; therefore, we need to save the updates in the buffer pointed to by
+ // 'iFixup64' so that they can be reapplied each time the code page(s)
+ // containing (parts of the) IAT are reloaded. The fixup entries are in the
+ // form of 64-bit words, with the 32-bit address-to-be-fixed-up in the upper
+ // half and the value-to-be-stored-there in the lower half -- the multiple
+ // casts are needed to stop some compilers whinging about converting a
+ // pointer to a 64-bit integral type :(
+ if (!info.iFixup64)
+ *iat = newValue;
else
- // ...otherwise defer until the page is fixed up
- {
- TUint64 iat64 = reinterpret_cast<TUint64>(iat);
- *info.iFixup64++ = (iat64 << 32) | writeValue;
- }
+ *info.iFixup64++ = ((TUint64)(TUintPtr)iat << 32) | newValue;
}
+ // Finally, update 'info.iIat' to show which imports have been processed
info.iIat = iat;
return KErrNone;
}
@@ -436,50 +570,155 @@
TInt svElfDerivedFixupImportAddresses(TAny* aPtr)
{
SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
- TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
- TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
-
- TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
- TUint32 exp_delta = info.iExportDirEntryDelta;
- TUint32 code = info.iCodeLoadAddress;
+ E32Image& exporter = *info.iExporter;
+
+#ifdef _DEBUG
+ __LDRTRACE(MyPrintf(">svElfDerivedFixupImportAddresses %d imports, code@%08x, fixup@%08x exporter@%08x",
+ info.iNumImports, info.iCodeLoadAddress, info.iFixup64, info.iExporter));
+
+ // Dump everything potentially useful that we know about the exporter ...
+ __LDRTRACE(MyPrintf("%S: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
+ &exporter.iFileName, exporter.iUseCodePaging,
+ exporter.iRomImageHeader, exporter.iHeader));
+ __LDRTRACE(MyPrintf("iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
+ exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
+ exporter.iCodeSize, exporter.iTextSize))
+ __LDRTRACE(MyPrintf("iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
+ exporter.iDataLoadAddress, exporter.iDataRunAddress,
+ exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
+ __LDRTRACE(MyPrintf("iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
+ exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
+
+ if (exporter.iRomImageHeader)
+ {
+ const TRomImageHeader& rh = *exporter.iRomImageHeader;
+ __LDRTRACE(MyPrintf("ROM: iCodeAddress %08x, iCodeSize %x, iTextSize %x",
+ rh.iCodeAddress, rh.iCodeSize, rh.iTextSize));
+ __LDRTRACE(MyPrintf("ROM: iDataAddress %08x, iDataSize %x, iBssSize %x",
+ rh.iDataAddress, rh.iDataSize, rh.iBssSize));
+ __LDRTRACE(MyPrintf("ROM: iDataBssLinearBase %08x, iTotalDataSize %x",
+ rh.iDataBssLinearBase, rh.iTotalDataSize));
+ }
+
+ if (exporter.iHeader)
+ {
+ const E32ImageHeader& ih = *exporter.iHeader;
+ __LDRTRACE(MyPrintf("HEAD: iCodeBase %08x, iCodeSize %x, iTextSize %x",
+ ih.iCodeBase, ih.iCodeSize, ih.iTextSize));
+ __LDRTRACE(MyPrintf("HEAD: iDataBase %08x, iDataSize %x, iBssSize %x",
+ ih.iDataBase, ih.iDataSize, ih.iBssSize));
+ }
+#endif // _DEBUG
+
+ // Here we calculate the bounds of each section of the exporter, as
+ // code and data exports may have to be offset by different amounts.
+ // Unfortunately, the required information seems to be in several
+ // different places, depending on whether the code is ROM or RAM, etc
+ TUint32 codeStart = exporter.iCodeRunAddress;
+ TUint32 codeEnd = codeStart + exporter.iCodeSize;
+ TUint32 dataStart = exporter.iDataRunAddress;
+ TUint32 dataEnd = dataStart + exporter.iTotalDataSize;
+
+ if (exporter.iRomImageHeader)
+ {
+ const TRomImageHeader& rh = *exporter.iRomImageHeader;
+ codeStart = rh.iCodeAddress;
+ codeEnd = codeStart + rh.iCodeSize;
+ dataStart = rh.iDataBssLinearBase;
+ dataEnd = dataStart + rh.iTotalDataSize;
+ }
+
+ if (exporter.iHeader)
+ {
+ const E32ImageHeader& ih = *exporter.iHeader;
+ codeStart = ih.iCodeBase;
+ codeEnd = codeStart + ih.iCodeSize;
+ dataStart = ih.iDataBase;
+ dataEnd = dataStart + ih.iDataSize + ih.iBssSize;
+ }
+
+ // 'exportDir' points to the address of the 0th ordinal (symbol name data);
+ // ordinary exports start from ordinal 1
+ const TUint32* const exportDir = (TUint32*)exporter.iExportDirLoad - KOrdinalBase;
+ const TUint32 maxOrdinal = (TUint32)exporter.iExportDirCount;
+ const TUint32 absentOrdinal = (TUint32)exporter.iFileEntryPoint;
+
+ const TUint32 codeDelta = exporter.iCodeDelta;
+ const TUint32 dataDelta = exporter.iDataDelta;
+ const TUint32 dirDelta = exporter.iExportDirEntryDelta;
+ TUint8* const codeBase = (TUint8*)info.iCodeLoadAddress;
TUint32* iol = info.iImportOffsetList;
- TUint32* iolE = iol+info.iNumImports;
- for(; iol<iolE; ++iol)
+ TUint32* const iolEnd = iol + info.iNumImports;
+ for(; iol < iolEnd; ++iol)
{
- TUint32* impPtr = (TUint32*)(code+*iol);
- TUint32 impd = *impPtr;
- TUint32 imp = impd & 0xffff;
- TUint32 offset = impd >> 16;
- if(imp>maxOrdinal)
+ // Whereas the PE format's IAT contains ordinals to be imported, the ELF IOL
+ // (Import Offset List) is a list of offsets (within the importer's code) of
+ // the locations that contain references to imported objects.
+ //
+ // At the start of this process, each such location contains a composite value,
+ // of which the low 16 bits indicate the ordinal to be imported from the
+ // exporter's directory, and the upper 16 provide an optional adjustment to
+ // be added to the imported value.
+ //
+ // This composite value has to be replaced by the actual address of the
+ // object being imported (plus the adjustment factor, if any).
+ TUint32 codeOffset = *iol;
+ TUint32* codePtr = (TUint32*)(codeBase+codeOffset);
+ TUint32 importInfo = *codePtr;
+ TUint32 ordinal = importInfo & 0xffff;
+ TUint32 adjustment = importInfo >> 16;
+ if(ordinal > maxOrdinal)
return KErrNotSupported;
- TUint32 writeValue;
- if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
+ // If the import number is 0 (symbol name data), and the exporter doesn't provide
+ // this, we don't regard it as an error; we just skip this block, leaving the
+ // address set to 0. For all other valid cases, we index the export directory to find
+ // the exported object's address (which may OR MAY NOT have already been relocated)
+ TUint32 expAddr = 0;
+ TUint32 newValue = 0;
+ if (ordinal > 0 || (exporter.iAttr & ECodeSegAttNmdExpData))
{
- // attempt to import ordinal zero (symbol name data) from an executable
- // which doesn't export this information, use NULL for imported value in this case...
- writeValue = NULL;
+ expAddr = exportDir[ordinal];
+ if(expAddr == 0 || expAddr == absentOrdinal)
+ return KErrNotSupported;
+
+ // If the exporter does not use code paging, then the entries in the export
+ // table will already have been relocated along with its text section. In
+ // the paged case, however, the relocation will have been deferred until the
+ // relevant pages are (re)loaded; therefore, we have to deduce here whether
+ // each export is code or data so that we can apply the correct delta ...
+ TUint32 sectionDelta;
+ if (!exporter.iUseCodePaging)
+ sectionDelta = dirDelta;
+ else if (expAddr >= codeStart && expAddr < codeEnd)
+ sectionDelta = codeDelta; // points to text/rdata section
+ else if (expAddr >= dataStart && expAddr < dataEnd)
+ sectionDelta = dataDelta; // points to data/bss section
+ else
+ sectionDelta = dirDelta; // unknown - assume nonpaged?
+ newValue = expAddr + sectionDelta + adjustment;
}
+
+ __LDRTRACE(MyPrintf("svElfDerivedFixupImportAddresses: import[%d] (%08x:%08x) is export[%d] %08x+%08x => %08x",
+ iol - info.iImportOffsetList, codePtr, importInfo, ordinal, expAddr, adjustment, newValue));
+
+ // In non-paged code, we can simply replace the ordinals in the IAT with the
+ // object addresses to which they refer once and for all. However, in a code
+ // paging system, the IAT may be thrown away and later reloaded from the code
+ // image; therefore, we need to save the updates in the buffer pointed to by
+ // 'iFixup64' so that they can be reapplied each time the code page(s)
+ // containing (parts of the) IAT are reloaded. The fixup entries are in the
+ // form of 64-bit words, with the 32-bit address-to-be-fixed-up in the upper
+ // half and the value-to-be-stored-there in the lower half -- the multiple
+ // casts are needed to stop some compilers whinging about converting a
+ // pointer to a 64-bit integral type :(
+ if (!info.iFixup64)
+ *codePtr = newValue;
else
- {
- // get imported value from exporter...
- TUint32 exp_addr = exp_dir[imp];
- if(exp_addr==0 || exp_addr==absentOrdinal)
- return KErrNotSupported;
- writeValue = exp_addr + exp_delta + offset;
- }
-
- // if not code paging then directly fix up the import...
- if (info.iFixup64 == 0)
- *impPtr = writeValue;
- // ...otherwise defer until the page is fixed up
- else
- {
- TUint64 impPtr64 = reinterpret_cast<TUint64>(impPtr);
- *info.iFixup64++ = (impPtr64 << 32) | writeValue;
- }
+ *info.iFixup64++ = ((TUint64)(TUintPtr)codePtr << 32) | newValue;
}
+
return KErrNone;
}
@@ -2834,8 +3073,9 @@
// on "new" dlls
if (e->iDepCount && !e->iAlreadyLoaded && e->iIsDll)
{
- __IF_DEBUG(Printf("****Go recursive****"));
+ __IF_DEBUG(Printf("****Going recursive****"));
r = e->LoadDlls(aArray);
+ __IF_DEBUG(Printf("****Returned from recursion****"));
if (r!=KErrNone)
{
return r;
@@ -2956,8 +3196,6 @@
r = exp->ReadExportDirLoad();
if (r != KErrNone)
return r;
- info.iExportDir = (TUint32*)exp->iExportDirLoad;
- info.iExportDirEntryDelta = exp->iExportDirEntryDelta;
info.iNumImports = block->iNumberOfImports;
info.iExporter = exp;
@@ -2976,10 +3214,14 @@
if (impfmt == KImageImpFmt_ELF)
{
info.iImportOffsetList = (TUint32*)(block+1);
+ __IF_DEBUG(Printf("Import format ELF (%08x); info@%08x", impfmt, &info));
r = ExecuteInSupervisorMode(&svElfDerivedFixupImportAddresses, &info);
}
else
+ {
+ __IF_DEBUG(Printf("Import format PE (%08x); info@%08x", impfmt, &info));
r = ExecuteInSupervisorMode(&svFixupImportAddresses, &info);
+ }
if (r != KErrNone)
{
@@ -3058,7 +3300,18 @@
*/
TInt E32Image::BuildImportFixupTable()
{
- __IF_DEBUG(Printf(">BuildImportFixupTable,0x%08x,%d", iFixups, iFixupCount));
+ __IF_DEBUG(Printf(">BuildImportFixupTable,%d@%08x,%08x", iFixupCount, iFixups, iCodeLoadAddress));
+
+#ifdef _DEBUG
+ // Dump the incoming fixup table if loader tracing enabled. Each item is an
+ // (address, value) pair, where the address and the value are 32 bits each.
+ TInt i;
+ for (i = 0; i < iFixupCount; ++i)
+ {
+ TUint64 x = iFixups[i];
+ __IF_DEBUG(Printf("%04x: %08x %08x", i*sizeof(TUint64), I64HIGH(x), I64LOW(x)));
+ }
+#endif // DEBUG
// sort the array in address order, to organize by page
RArray<TUint64> fixup64ToSort(sizeof(TUint64), iFixups, iFixupCount);
@@ -3070,7 +3323,7 @@
// to the word at offset XXX. (See PREQ1110 Design Sketch v1.0 S3.1.1.2.3.2.)
TUint32 pageCount = SizeToPageCount(iCodeSize);
- iImportFixupTableSize = (pageCount+1) * sizeof(TUint32) + iFixupCount * 3 * sizeof(TUint16);
+ iImportFixupTableSize = (pageCount+1)*sizeof(TUint32) + 3*iFixupCount*sizeof(TUint16);
iImportFixupTable = (TUint32*) User::Alloc(iImportFixupTableSize);
__IF_DEBUG(Printf("iImportFixupTable=0x%08x", iImportFixupTable));
if (iImportFixupTable == 0)
@@ -3121,18 +3374,20 @@
while (++lastPage <= pageCount)
iImportFixupTable[lastPage] = iImportFixupTableSize;
- __IF_DEBUG(Printf("processed table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
-
#ifdef _DEBUG
- // dump the import fixup table if loader tracing enabled
+ __IF_DEBUG(Printf("processed fixup table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
+
+ // Dump the processed fixup table if loader tracing enabled. The dump is in two
+ // parts; first, the page indexes (1 word per page), then the entries describing
+ // the items to be relocated, each of which is a 16-bit offset-within-page and a
+ // 32-bit value to be stored there.
+ for (i = 0; i <= (TInt)pageCount; ++i)
+ __IF_DEBUG(Printf("%04x: %08x", i*4, iImportFixupTable[i]));
+
const TUint16* table16 = (const TUint16*)iImportFixupTable;
const TInt halfWordsInTable = iImportFixupTableSize / 2;
- for (TInt i = 0; i < halfWordsInTable; i += 4)
- {
- __IF_DEBUG(Printf(
- "%04x: %04x %04x %04x %04x",
- i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
- }
+ for (i *= 2; i < halfWordsInTable; i += 3)
+ __IF_DEBUG(Printf("%04x: %04x %04x%04x", i*2, table16[i+0], table16[i+2], table16[i+1]));
#endif
User::Free(iFixups);
--- a/userlibandfileserver/fileserver/sfile/sf_main.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_main.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -474,7 +474,9 @@
KernHeapAllocFailCount=-1;
#endif
- TInt r= RequestAllocator::iCacheLock.CreateLocal();
+ TInt r = RequestAllocator::Initialise();
+ __ASSERT_ALWAYS(r==KErrNone,Fault(EFsCacheLockFailure));
+ r = OperationAllocator::Initialise();
__ASSERT_ALWAYS(r==KErrNone,Fault(EFsCacheLockFailure));
// initialise the TParse pool lock object
@@ -492,7 +494,6 @@
r=FsThreadManager::CreateDisconnectThread();
__ASSERT_ALWAYS(r==KErrNone,Fault(EMainDisconnectThread));
- RequestAllocator::Initialise();
//
// Install a trap handler
--- a/userlibandfileserver/fileserver/sfile/sf_request.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_request.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -27,81 +27,25 @@
CFsClientMessageRequest* RequestAllocator::iFreeHead;
CFsClientMessageRequest* RequestAllocator::iCloseHead;
-TInt RequestAllocator::iAllocNum;
-TInt RequestAllocator::iAllocNumOperation;
-TMsgOperation* RequestAllocator::iFreeHeadSupOp;
-
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-TInt RequestAllocator::iAllocated;
-#endif
+TInt RequestAllocator::iRequestCount;
+TInt RequestAllocator::iFreeCount;
+TInt RequestAllocator::iRequestCountPeak;
RFastLock RequestAllocator::iCacheLock;
-void RequestAllocator::Initialise()
- {
- iFreeHead=NULL;
- iCloseHead=NULL;
- iAllocNum=0;
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- iAllocated=0;
-#endif
- iAllocNumOperation=0;
- iFreeHeadSupOp=NULL;
- }
+TMsgOperation* OperationAllocator::iFreeHead;
+TInt OperationAllocator::iRequestCount;
+TInt OperationAllocator::iFreeCount;
+TInt OperationAllocator::iRequestCountPeak;
+RFastLock OperationAllocator::iCacheLock;
-TInt RequestAllocator::AllocRequest(TInt aNum)
-//
-// Allocates a group of request objects
-//
- {
- TInt i;
- if(iAllocNum < KMaxRequestAllocated)
- {
- __CACHE_PRINT(_L("RequestAllocator::AllocRequest() Not reached the limit"));
- CFsClientMessageRequest* list;
- CFsClientMessageRequest* start;
- list = new CFsClientMessageRequest[KAllocReqBlock];
- start = list;
- if(!list)
- return KErrNoMemory;
-
- // Make sure the constructors are called for every element in the array
- // - some compilers don't do this
- for(TInt j=0; j<KAllocReqBlock; j++)
- {
- CFsClientMessageRequest* request = &list[j];
- new(request) CFsClientMessageRequest();
- }
-
- iAllocNum += KAllocReqBlock;
- CFsClientMessageRequest* last;
- for(i=1;i<KAllocReqBlock;i++)
- {
- last = list;
- list++;
- last->iNext = list;
- }
- list->iNext = iFreeHead;
- iFreeHead = start;
- return KErrNone;
- }
- else
- {
- __CACHE_PRINT1(_L("RequestAllocator::AllocRequest() Limit exceeded Count = %d"),aNum);
- CFsClientMessageRequest* request;
- for(i=0;i<aNum;i++)
- {
- request=new CFsClientMessageRequest;
- if(!request)
- return KErrNoMemory;
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- iAllocated++;
-#endif
- request->SetAllocated();
- request->iNext=iFreeHead;
- iFreeHead=request;
- }
- return KErrNone;
- }
+TInt RequestAllocator::Initialise()
+ {
+ iFreeHead = NULL;
+ iCloseHead = NULL;
+ iRequestCount = 0;
+ iFreeCount = 0;
+ iRequestCountPeak = 0;
+ return iCacheLock.CreateLocal();
}
void RequestAllocator::FreeRequest(CFsClientMessageRequest* aRequest)
@@ -109,28 +53,28 @@
//free request
//
{
- __CACHE_PRINT1(_L("PLUGIN: RequestAllocator::FreeRequest for %x"), aRequest);
- if(aRequest->IsAllocated())
+ __CACHE_PRINT1(_L("RequestAllocator::FreeRequest for %x"), aRequest);
+ ASSERT(aRequest != NULL);
+ iCacheLock.Wait();
+ if (iFreeCount >= KFreeCountMax)
{
- __CACHE_PRINT(_L("RequestAllocator::FreeRequest() Allocated request"));
- delete(aRequest);
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- iAllocated--;
-#endif
- return;
+ delete aRequest;
+ ASSERT(iRequestCount > 0);
+ iRequestCount--;
}
-
- __CACHE_PRINT(_L("RequestAllocator::FreeRequest() returning to free list"));
- iCacheLock.Wait();
- aRequest->iNext = iFreeHead;
- iFreeHead=aRequest;
- aRequest->SetSubstedDrive(NULL);
+ else
+ {
+ aRequest->SetSubstedDrive(NULL);
+ aRequest->iNext = iFreeHead;
+ iFreeHead=aRequest;
+ iFreeCount++;
+ }
iCacheLock.Signal();
}
void RequestAllocator::OpenSubFailed(CSessionFs* aSession)
//
-// Move requst from closed list to free list
+// Move request from closed list to free list
//
{
__ASSERT_DEBUG(iCloseHead!=NULL,Fault(ERequestAllocatorOpenSubFailed)); // On arriving here Close Queue is supposed to be empty
@@ -142,34 +86,39 @@
iCacheLock.Wait();
CFsClientMessageRequest* rp = iCloseHead;
iCloseHead = rp->iNext;
+ iCacheLock.Signal();
// dec the number of closed requests owned by this session
aSession->CloseRequestCountDec();
- rp->iNext = NULL;
- if(rp->IsAllocated())
+ __CACHE_PRINT1(_L("RequestAllocator::OpenSubFailed() IsAllocated %d"), rp->IsAllocated());
+ FreeRequest(rp);
+ }
+
+CFsClientMessageRequest* RequestAllocator::GetRequest()
+//
+// Get request from the free queue
+//
+ {
+ CFsClientMessageRequest* request;
+ if (iFreeHead == NULL)
{
- __CACHE_PRINT(_L("RequestAllocator::OpenSubFailed() Allocated request"));
- delete(rp);
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- iAllocated--;
-#endif
+ request = new CFsClientMessageRequest;
+ if (request)
+ {
+ iRequestCount++;
+ iRequestCountPeak = Max(iRequestCountPeak, iRequestCount);
+ }
}
else
{
- __CACHE_PRINT(_L("RequestAllocator::OpenSubFailed()"));
- if(iFreeHead)
- {
- rp->iNext = iFreeHead;
- }
- else
- {
- rp->iNext = NULL;
- }
-
- iFreeHead = rp;
+ request = iFreeHead;
+ iFreeHead = iFreeHead->iNext;
+ request->iNext = NULL;
+ iFreeCount--;
+ ASSERT(iFreeCount >= 0);
}
- iCacheLock.Signal();
+ return request;
}
TInt RequestAllocator::GetMessageRequest(const TOperation& aOperation,const RMessage2& aMessage,CFsClientMessageRequest* &aRequest)
@@ -181,27 +130,20 @@
{
__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() Open sub-sess"));
iCacheLock.Wait();
- if(iFreeHead == NULL || iFreeHead->iNext == NULL)
- {
- if(AllocRequest(2)!= KErrNone)
- {
- iCacheLock.Signal();
- return KErrNoMemory;
- }
- }
- aRequest= iFreeHead; //get our request from free head
- iFreeHead = iFreeHead->iNext->iNext; //set next but one as new free head read for next
- aRequest->iNext->iNext = NULL; //seperate our request and close from free list
- CFsClientMessageRequest* CRp = aRequest->iNext;
- aRequest->iNext = NULL;
- if(iCloseHead)
+ aRequest = GetRequest();
+ CFsClientMessageRequest* closeRequest = GetRequest();
+
+ if (aRequest == NULL || closeRequest == NULL)
{
- CRp->iNext = iCloseHead; //set second one as a reserved (tail) close request
- iCloseHead = CRp;
+ delete aRequest;
+ delete closeRequest;
+ iCacheLock.Signal();
+ return KErrNoMemory;
}
- else
- iCloseHead = CRp;
+
+ closeRequest->iNext = iCloseHead; //set second one as a reserved (tail) close request
+ iCloseHead = closeRequest;
((CSessionFs*) aMessage.Session())->CloseRequestCountInc();
}
@@ -272,6 +214,7 @@
}
iCacheLock.Wait();
+ ASSERT(iCloseHead);
aRequest = iCloseHead;
iCloseHead = aRequest->iNext;
((CSessionFs*) aMessage.Session())->CloseRequestCountDec();
@@ -289,17 +232,12 @@
{
__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() "));
iCacheLock.Wait();
- if(!iFreeHead)
+ aRequest = GetRequest();
+ if (aRequest == NULL)
{
- if(AllocRequest(1) != KErrNone)
- {
- iCacheLock.Signal();
- return KErrNoMemory;
- }
+ iCacheLock.Signal();
+ return KErrNoMemory;
}
- aRequest = iFreeHead;
- iFreeHead = aRequest->iNext;
- aRequest->iNext= NULL;
}
aRequest->Init();
@@ -322,126 +260,103 @@
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
TInt RequestAllocator::CloseCount()
{TInt count=0;
+ iCacheLock.Wait();
+
CFsClientMessageRequest* list=iCloseHead;
while(list!=NULL)
{
count++;
list=list->iNext;
}
+
+ iCacheLock.Signal();
return(count);
}
TInt RequestAllocator::FreeCount()
{
TInt count=0;
+ iCacheLock.Wait();
CFsClientMessageRequest* list=iFreeHead;
while(list!=NULL)
{
count++;
list=list->iNext;
}
- return(count);}
+ ASSERT(count == iFreeCount);
+ iCacheLock.Signal();
+ return(count);
+ }
#endif
-TInt RequestAllocator::AllocOperation()
-//
-// Allocates a group of TMsgOperation objects
+TInt OperationAllocator::Initialise()
+ {
+ iFreeHead = NULL;
+ iRequestCount = 0;
+ iFreeCount = 0;
+ return iCacheLock.CreateLocal();
+ }
+
+void OperationAllocator::FreeOperation(TMsgOperation* aOperation)
//
-// Must be called with iCacheLock held
+// free Operation
+//
{
- TInt i;
- if(iAllocNumOperation < KMaxOperationAllocated)
+ __CACHE_PRINT1(_L("RequestAllocator::FreeOperation() returning %x to free list"), aOperation);
+ ASSERT(aOperation != NULL);
+ iCacheLock.Wait();
+ if (iFreeCount >= KFreeCountMax)
{
- __CACHE_PRINT(_L("RequestAllocator::AllocOperation() Not reached the limit"));
- TMsgOperation* list;
- TMsgOperation* start;
- list = new TMsgOperation[KAllocReqBlock];
- start = list;
- if(!list)
- return KErrNoMemory;
-
- for(TInt j=0; j<KAllocReqBlock; j++)
- {
- TMsgOperation* request = &list[j];
- request->iIsAllocated = EFalse;
- }
-
- iAllocNumOperation += KAllocReqBlock;
- TMsgOperation* last;
- for(i=1;i<KAllocReqBlock;i++)
- {
- last = list;
- list++;
- last->iNext = list;
- }
- list->iNext = iFreeHeadSupOp;
- iFreeHeadSupOp = start;
- return KErrNone;
+ delete aOperation;
+ ASSERT(iRequestCount > 0);
+ iRequestCount--;
}
else
{
- __CACHE_PRINT(_L("RequestAllocator::AllocOperation() Limit exceeded"));
- TMsgOperation* request;
+ aOperation->iNext = iFreeHead;
+ iFreeHead = aOperation;
+ iFreeCount++;
+ }
- request=new TMsgOperation;
- if(!request)
- return KErrNoMemory;
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- iAllocated++;
-#endif
- request->iIsAllocated = ETrue;
- request->iNext=iFreeHeadSupOp;
- iFreeHeadSupOp=request;
+ iCacheLock.Signal();
+ }
- return KErrNone;
- }
- }
-TInt RequestAllocator::GetOperation(TMsgOperation* &aOperation)
+TInt OperationAllocator::GetOperation(TMsgOperation* &aOperation)
//
// tries to get a pre allocated subop from the cache. Failing that allocates one individualy
//
{
__CACHE_PRINT(_L("RequestAllocator::GetOperation() "));
+
iCacheLock.Wait();
- if(!iFreeHeadSupOp)
+
+ TInt r = KErrNone;
+ if (iFreeHead == NULL)
{
- if(AllocOperation() != KErrNone)
+ aOperation = new TMsgOperation;
+ if (aOperation == NULL)
+ r = KErrNoMemory;
+ else
{
- iCacheLock.Signal();
- return KErrNoMemory;
+ iRequestCount++;
+ iRequestCountPeak = Max(iRequestCountPeak, iRequestCount);
}
}
- aOperation = iFreeHeadSupOp;
- iFreeHeadSupOp = aOperation->iNext;
- aOperation->iNext = aOperation->iPrev = NULL;
+ else
+ {
+ aOperation = iFreeHead;
+ iFreeHead = iFreeHead->iNext;
+ iFreeCount--;
+ ASSERT(iFreeCount >= 0);
+ }
+
+ if (aOperation)
+ aOperation->iNext = aOperation->iPrev = NULL;
iCacheLock.Signal();
- return KErrNone;
+ return r;
}
-void RequestAllocator::FreeOperation(TMsgOperation* aOperation)
-//
-// free Operation
-//
- {
- if(aOperation->iIsAllocated)
- {
- __CACHE_PRINT(_L("RequestAllocator::FreeOperation() Allocated subop"));
- delete(aOperation);
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- iAllocated--;
-#endif
- return;
- }
-
- __CACHE_PRINT(_L("RequestAllocator::FreeOperation() returning to free list"));
- iCacheLock.Wait();
- aOperation->iNext = iFreeHeadSupOp; // NB backward link only used when request in in use
- iFreeHeadSupOp = aOperation;
-
- iCacheLock.Signal();
- }
-
CFsRequest::CFsRequest()
//
@@ -1821,7 +1736,7 @@
TInt CFsMessageRequest::PushOperation(TFsRequestFunc aCallback, TInt aNextState, TInt aFunction)
{
TMsgOperation* nextOperation;
- TInt r = RequestAllocator::GetOperation(nextOperation);
+ TInt r = OperationAllocator::GetOperation(nextOperation);
if (r != KErrNone)
return r;
@@ -1949,7 +1864,7 @@
SetOperationFunc(iCurrentOperation->iFunction);
}
- RequestAllocator::FreeOperation(currentOperation);
+ OperationAllocator::FreeOperation(currentOperation);
}
TMsgOperation& CFsMessageRequest::CurrentOperation()
--- a/userlibandfileserver/fileserver/sfile/sf_std.h Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_std.h Mon Mar 15 12:45:50 2010 +0200
@@ -1398,9 +1398,10 @@
TRequestStatus iStatus;
TBool iIsAllocated;
};
-const TInt KMaxRequestAllocated = 45;
-const TInt KMaxOperationAllocated = KMaxRequestAllocated * 2;
-const TInt KAllocReqBlock=15;
+
+// If the number of requests on the free queue reaches this value then completed requests
+// are returned to the heap rather than being added to thefree queue
+const TInt KFreeCountMax = 64;
class TParseCon
{
@@ -1413,34 +1414,53 @@
class RequestAllocator
{
public:
+ static TInt Initialise();
+
static TInt GetMessageRequest(const TOperation& aOperation,const RMessage2& aMessage,CFsClientMessageRequest* &aRequest);
- static void FreeRequest(CFsClientMessageRequest* aRequest); // Use the one from cache
+ static void FreeRequest(CFsClientMessageRequest* aRequest);
static void OpenSubFailed(CSessionFs* aSession);
- static TInt AllocRequest(TInt aNum);
+
+#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
+ inline static TInt RequestCount();
+ inline static TInt RequestCountPeak();
+ static TInt CloseCount();
+ static TInt FreeCount();
+#endif
+
+private:
+ static CFsClientMessageRequest* GetRequest();
- static TInt AllocOperation();
+private:
+ static RFastLock iCacheLock;
+ static CFsClientMessageRequest* iFreeHead;
+ static CFsClientMessageRequest* iCloseHead;
+
+ static TInt iRequestCount; // current number of requests
+ static TInt iFreeCount; // current number of requests on free queue
+ static TInt iRequestCountPeak; // maximum value of requests reached
+ };
+
+class OperationAllocator
+ {
+public:
+ static TInt Initialise();
+
static TInt GetOperation(TMsgOperation* &aOperation);
static void FreeOperation(TMsgOperation* aOperation);
-
- static void Initialise();
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
- inline static TInt TotalCount();
- static TInt CloseCount();
- static TInt FreeCount();
- inline static TInt AllocatedCount();
-private:
- static TInt iAllocated;
+ inline static TInt RequestCount();
+ inline static TInt RequestCountPeak();
+ inline static TInt FreeCount();
#endif
-public:
- static RFastLock iCacheLock;
+
private:
- static TInt iAllocNum;
- static CFsClientMessageRequest* iFreeHead;
- static CFsClientMessageRequest* iCloseHead;
+ static RFastLock iCacheLock;
+ static TMsgOperation* iFreeHead;
- static TInt iAllocNumOperation;
- static TMsgOperation* iFreeHeadSupOp;
+ static TInt iRequestCount; // current number of requests
+ static TInt iFreeCount; // current number of requests on free queue
+ static TInt iRequestCountPeak; // maximum value of requests reached
};
--- a/userlibandfileserver/fileserver/sfile/sf_std.inl Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_std.inl Mon Mar 15 12:45:50 2010 +0200
@@ -310,12 +310,19 @@
#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
// Class RequestAllocator
-/** returns number of dynamically allocated requests */
-TInt RequestAllocator::AllocatedCount()
-{ return iAllocated;}
/** returns number of permanently & dynamically allocated requests */
-TInt RequestAllocator::TotalCount()
-{ return iAllocated + iAllocNum;}
+TInt RequestAllocator::RequestCount()
+ { return iRequestCount;}
+TInt RequestAllocator::RequestCountPeak()
+ { return iRequestCountPeak;}
+
+TInt OperationAllocator::FreeCount()
+ { return iFreeCount;}
+TInt OperationAllocator::RequestCount()
+ { return iRequestCount;}
+TInt OperationAllocator::RequestCountPeak()
+ { return iRequestCountPeak;}
+
#endif
//---------------------------------------------------------------------------------------------------------------------
--- a/userlibandfileserver/fileserver/sfsrv/cl_parse.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfsrv/cl_parse.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -302,9 +302,9 @@
TInt pos=aName.Locate(KPathDelimiter);
if (pos!=KErrNotFound)
return(KErrBadName);
- TFileName n=aName;
- n.Append(KPathDelimiter);
- NameBuf().Insert(iField[EName].pos,n);
+
+ NameBuf().Insert(iField[EName].pos,aName);
+ NameBuf().Insert(iField[EName].pos + aName.Length(),TPtrC16((const TUint16*)(&KPathDelimiter),1));
iField[EPath].len=(TUint8)(iField[EPath].len+len);
iField[EName].pos=(TUint8)(iField[EName].pos+len);
iField[EExt].pos=(TUint8)(len+iField[EExt].pos);
--- a/userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -21,6 +21,8 @@
*/
#include <f32file.h>
+#include <f32ver.h>
+#include "cusbmassstoragecontroller.h"
#include "cmassstoragefilesystem.h"
#include "cmassstoragemountcb.h"
#include "massstoragedebug.h"
--- a/userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp Mon Mar 15 12:45:50 2010 +0200
@@ -23,10 +23,9 @@
#include <f32fsys.h>
#include <f32file.h>
#include "cmassstoragemountcb.h"
+#include "cusbmassstoragecontroller.h"
#include "cmassstoragefilesystem.h"
-#include "drivemanager.h"
#include "massstoragedebug.h"
-#include "massstorageutil.h"
CMassStorageMountCB::CMassStorageMountCB(const RArray<TInt>& aDriveMapping)
: iDriveMapping(aDriveMapping)
@@ -214,281 +213,6 @@
delete hDes;
}
-/**
-Make sure that the file system is fat.
-*/
-TBool CMassStorageMountCB::ValidateBootSector()
- {
- __FNLOG("CMassStorageMountCB::ValidateBootSector");
-
- TFatBootSector bootSector;
- TInt r=ReadBootSector(bootSector);
- __PRINT1(_L("CMassStorageMountCB::MountL - ReadBootSector returned %d"),r);
- if (r != KErrNone)
- {
- return EFalse;
- }
-
- __PRINT(_L("\nBootSector info"));
- __PRINT8BIT1(_L("FAT type = %S"),bootSector.FileSysType());
- __PRINT8BIT1(_L("Vendor ID = %S"),bootSector.VendorId());
- __PRINT1(_L("BytesPerSector %d"),bootSector.BytesPerSector());
- __PRINT1(_L("SectorsPerCluster %d"),bootSector.SectorsPerCluster());
- __PRINT1(_L("ReservedSectors %d"),bootSector.ReservedSectors());
- __PRINT1(_L("NumberOfFats %d"),bootSector.NumberOfFats());
- __PRINT1(_L("RootDirEntries %d"),bootSector.RootDirEntries());
- __PRINT1(_L("Total Sectors = %d"),bootSector.TotalSectors());
- __PRINT1(_L("MediaDescriptor = 0x%x"),bootSector.MediaDescriptor());
- __PRINT1(_L("FatSectors %d"),bootSector.FatSectors());
- __PRINT1(_L("SectorsPerTrack %d"),bootSector.SectorsPerTrack());
- __PRINT1(_L("NumberOfHeads %d"),bootSector.NumberOfHeads());
- __PRINT1(_L("HugeSectors %d"),bootSector.HugeSectors());
- __PRINT1(_L("Fat32 Sectors %d"),bootSector.FatSectors32());
- __PRINT1(_L("Fat32 Flags %d"),bootSector.FATFlags());
- __PRINT1(_L("Fat32 Version Number %d"),bootSector.VersionNumber());
- __PRINT1(_L("Root Cluster Number %d"),bootSector.RootClusterNum());
- __PRINT1(_L("FSInfo Sector Number %d"),bootSector.FSInfoSectorNum());
- __PRINT1(_L("Backup Boot Rec Sector Number %d"),bootSector.BkBootRecSector());
- __PRINT1(_L("PhysicalDriveNumber %d"),bootSector.PhysicalDriveNumber());
- __PRINT1(_L("ExtendedBootSignature %d"),bootSector.ExtendedBootSignature());
- __PRINT1(_L("UniqueID %d"),bootSector.UniqueID());
- __PRINT8BIT1(_L("VolumeLabel %S"),bootSector.VolumeLabel());
- __PRINT8BIT1(_L("FileSysType %S\n"),bootSector.FileSysType());
-
- iUniqueID=bootSector.UniqueID();
- iIs16BitFat=bootSector.Is16BitFat();
-
- iIs32BitFat=bootSector.Is32BitFat();
- switch (DetermineFatType(bootSector))
- {
- case 12:
- iIs16BitFat = EFalse;
- iIs32BitFat = EFalse;
- break;
- case 16:
- iIs16BitFat = ETrue;
- iIs32BitFat = EFalse;
- break;
- case 32:
- iIs16BitFat = EFalse;
- iIs32BitFat = ETrue;
- break;
- default:
- return EFalse;
- }
-
- TInt sectorsPerCluster=bootSector.SectorsPerCluster();
- if (!IsPowerOfTwo(sectorsPerCluster))
- return EFalse;
-
- TInt sectorSizeLog2=Log2(bootSector.BytesPerSector());
- if (sectorSizeLog2<0 || !IsPowerOfTwo(bootSector.BytesPerSector()))
- return EFalse;
-
- TInt firstFatSector=bootSector.ReservedSectors();
- if (firstFatSector<1)
- return EFalse;
-
- TInt fatSizeInBytes;
- if(iIs32BitFat)
- {
- fatSizeInBytes=bootSector.FatSectors32()*bootSector.BytesPerSector();
- if (fatSizeInBytes<bootSector.BytesPerSector())
- return EFalse;
- }
- else
- {
- fatSizeInBytes=bootSector.FatSectors()*bootSector.BytesPerSector();
- if (fatSizeInBytes<bootSector.BytesPerSector())
- return EFalse;
-
- TInt rootDirectorySector=firstFatSector+bootSector.FatSectors()*bootSector.NumberOfFats();
- if (rootDirectorySector<3)
- return EFalse;
-
- TInt rootDirSizeInBytes=bootSector.RootDirEntries()*KSizeOfFatDirEntry;
- TInt numOfRootDirSectors=(rootDirSizeInBytes+(1<<sectorSizeLog2)-1)>>sectorSizeLog2;
- TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<<sectorSizeLog2;
- if (rootDirEnd<(4<<sectorSizeLog2))
- return EFalse;
- }
-
-
- TInt totalSectors=bootSector.TotalSectors();
- if (totalSectors==0)
- totalSectors=bootSector.HugeSectors();
- if (totalSectors<5)
- return EFalse;
-
- TInt numberOfFats=bootSector.NumberOfFats();
- if (numberOfFats<1)
- return EFalse;
-
- return ETrue;
- }
-
-/**
-Read non aligned boot data from media into TFatBootSector structure
-
-@param aBootSector refrence to TFatBootSector populate
-@return Media read error code
-*/
-TInt CMassStorageMountCB::ReadBootSector(TFatBootSector& aBootSector)
- {
- __FNLOG("CMassStorageMountCB::ReadBootSector");
- TInt pos=0;
- TUint8 data[KSizeOfFatBootSector];
- TPtr8 buf(&data[0],KSizeOfFatBootSector);
- TInt r=LocalDrive()->Read(0,KSizeOfFatBootSector,buf);
- if (r!=KErrNone)
- {
- __PRINT1(_L("LocalDrive::Read() failed - %d"),r);
- return(r);
- }
-// 0 TUint8 iJumpInstruction[3]
- Mem::Copy(&aBootSector.iJumpInstruction,&data[pos],3);
- pos+=3;
-// 3 TUint8 iVendorId[KVendorIdSize]
- Mem::Copy(&aBootSector.iVendorId,&data[pos],KVendorIdSize);
- pos+=KVendorIdSize;
-// 11 TUint16 iBytesPerSector
- Mem::Copy(&aBootSector.iBytesPerSector,&data[pos],2);
- pos+=2;
-// 13 TUint8 sectorsPerCluster
- Mem::Copy(&aBootSector.iSectorsPerCluster,&data[pos],1);
- pos+=1;
-// 14 TUint16 iReservedSectors
- Mem::Copy(&aBootSector.iReservedSectors,&data[pos],2);
- pos+=2;
-// 16 TUint8 numberOfFats
- Mem::Copy(&aBootSector.iNumberOfFats,&data[pos],1);
- pos+=1;
-// 17 TUint16 iRootDirEntries
- Mem::Copy(&aBootSector.iRootDirEntries,&data[pos],2);
- pos+=2;
-// 19 TUint16 totalSectors
- Mem::Copy(&aBootSector.iTotalSectors,&data[pos],2);
- pos+=2;
-// 21 TUint8 iMediaDescriptor
- Mem::Copy(&aBootSector.iMediaDescriptor,&data[pos],1);
- pos+=1;
-// 22 TUint16 iFatSectors
- Mem::Copy(&aBootSector.iFatSectors,&data[pos],2);
- pos+=2;
-// 24 TUint16 iSectorsPerTrack
- Mem::Copy(&aBootSector.iSectorsPerTrack,&data[pos],2);
- pos+=2;
-// 26 TUint16 iNumberOfHeads
- Mem::Copy(&aBootSector.iNumberOfHeads,&data[pos],2);
- pos+=2;
-// 28 TUint32 iHiddenSectors
- Mem::Copy(&aBootSector.iHiddenSectors,&data[pos],4);
- pos+=4;
-// 32 TUint32 iHugeSectors
- Mem::Copy(&aBootSector.iHugeSectors,&data[pos],4);
- pos+=4;
-
- if(aBootSector.iRootDirEntries == 0) //indicates we have FAT32 volume
- {
- __PRINT(_L("\nFile system thinks Fat32"));
-
- //36 TUint32 iFatSectors32
- Mem::Copy(&aBootSector.iFatSectors32, &data[pos],4);
- pos+=4;
- //40 TUint16 iFATFlags
- Mem::Copy(&aBootSector.iFATFlags, &data[pos],2);
- pos+=2;
- //42 TUint16 iVersionNumber
- Mem::Copy(&aBootSector.iVersionNumber, &data[pos],2);
- pos+=2;
- //44 TUint32 iRootClusterNum
- Mem::Copy(&aBootSector.iRootClusterNum, &data[pos],4);
- pos+=4;
- //48 TUint16 iFSInfoSectorNum
- Mem::Copy(&aBootSector.iFSInfoSectorNum, &data[pos],2);
- pos+=2;
- //50 TUint16 iBkBootRecSector
- Mem::Copy(&aBootSector.iBkBootRecSector, &data[pos],2);
- pos+=(2+12);//extra 12 for the reserved bytes
- }
-
-// 36|64 TUint8 iPhysicalDriveNumber
- Mem::Copy(&aBootSector.iPhysicalDriveNumber,&data[pos],1);
- pos+=1;
-// 37|65 TUint8 iReserved
- Mem::Copy(&aBootSector.iReserved,&data[pos],1);
- pos+=1;
-// 38|66 TUint8 iExtendedBootSignature
- Mem::Copy(&aBootSector.iExtendedBootSignature,&data[pos],1);
- pos+=1;
-// 39|67 TUint32 iUniqueID
- Mem::Copy(&aBootSector.iUniqueID,&data[pos],4);
- pos+=4;
-// 43|71 TUint8 iVolumeLabel[KVolumeLabelSize]
- Mem::Copy(&aBootSector.iVolumeLabel,&data[pos],KVolumeLabelSize);
- pos+=KVolumeLabelSize;
-// 54|82 TUint8 iFileSysType[KFileSysTypeSize]
- Mem::Copy(&aBootSector.iFileSysType,&data[pos],KFileSysTypeSize);
-// 62|90
-
- return(KErrNone);
- }
-
-/**
-Work out if we have a FAT12|16|32 volume.
-Returns 12, 16 or 32 as appropriate.
-Returns 0 if can't be calculated (invalid values)
-*/
-TInt CMassStorageMountCB::DetermineFatType(TFatBootSector& aBootSector)
- {
- TUint32 ressectors = aBootSector.ReservedSectors();
-
- if (aBootSector.SectorsPerCluster() < 1)
- return 0;
-
- if (aBootSector.RootDirEntries() != 0)
- {
- TUint32 rootdirbytes;
- rootdirbytes = aBootSector.RootDirEntries() * 32 + aBootSector.BytesPerSector() - 1;
- ressectors += rootdirbytes / aBootSector.BytesPerSector();
- }
-
- if (aBootSector.FatSectors() != 0)
- ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors();
- else
- ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors32();
-
- TUint32 totalsectors;
- if (aBootSector.TotalSectors() != 0)
- totalsectors = aBootSector.TotalSectors();
- else
- totalsectors = aBootSector.HugeSectors();
-
- if (ressectors < 1 || totalsectors < 1)
- return 0;
-
- TUint32 datasec;
- datasec = totalsectors - ressectors;
-
- TUint32 countofclusters;
- countofclusters = datasec / aBootSector.SectorsPerCluster();
-
- __PRINT1(_L("CFatMountCB: Count of clusters = %d\n"), countofclusters);
-
- if (countofclusters < 4085)
- {
- return 12;
- }
- else if (countofclusters < 65525)
- {
- return 16;
- }
- else
- {
- return 32;
- }
- }
-
TInt CMassStorageMountCB::ReMount()
{
return KErrNotReady;
--- a/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragefilesystem.h Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragefilesystem.h Mon Mar 15 12:45:50 2010 +0200
@@ -23,11 +23,9 @@
#ifndef __CMASSSTORAGEFILESYSTEM_H__
#define __CMASSSTORAGEFILESYSTEM_H__
-#include <f32fsys.h>
-#include <f32ver.h>
-#include <f32file.h>
-#include "cusbmassstoragecontroller.h"
+//Forward Declaration
+class CUsbMassStorageController;
/**
Mass Storage Filesystem class.
@@ -75,8 +73,6 @@
CUsbMassStorageController* iMassStorageController;
TBool iRunning;
RArray<TInt> iMsDrives;
-
-
};
#endif // __CMASSSTORAGEFILESYSTEM_H__
--- a/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragemountcb.h Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragemountcb.h Mon Mar 15 12:45:50 2010 +0200
@@ -23,7 +23,6 @@
#ifndef __CMASSSTORAGEMOUNTCB_H__
#define __CMASSSTORAGEMOUNTCB_H__
-#include <f32fsys.h>
/**
Mass Storage Mount.
@@ -32,7 +31,6 @@
ControlIO is also supported for debug builds and returns KErrNotSupported for Release builds.
@internalTechnology
*/
-class TFatBootSector;
class CMassStorageMountCB : public CLocDrvMountCB
{
public:
@@ -63,205 +61,11 @@
CMassStorageMountCB(const RArray<TInt>& aDriveMapping);
void WritePasswordData();
TInt DriveNumberToLun(TInt aDriveNumber);
- TBool ValidateBootSector();
- TInt ReadBootSector(TFatBootSector& aBootSector);
- TInt DetermineFatType(TFatBootSector& aBootSector);
TInt CheckDriveNumberL();
private:
- TBool iIs16BitFat;
- TBool iIs32BitFat;
const RArray<TInt>& iDriveMapping;
};
-const TInt KSizeOfFatBootSector = 90;
-const TInt KVendorIdSize = 8;
-const TInt KVolumeLabelSize = 11;
-const TInt KFileSysTypeSize = 8;
-const TInt KBootSectorSignature = 0xAA55;
-const TInt KSizeOfFatDirEntry = 32;
-
-/**
-Boot sector parameter block, enables access to all file system parameters.
-Data is populated at mount time from the BPB sector
-@internalTechnology
-*/
-class TFatBootSector
- {
-public:
- inline const TPtrC8 VendorId() const;
- inline TUint16 BytesPerSector() const;
- inline TInt SectorsPerCluster() const;
- inline TInt ReservedSectors() const;
- inline TInt NumberOfFats() const;
- inline TInt RootDirEntries() const;
- inline TInt TotalSectors() const;
- inline TUint8 MediaDescriptor() const;
- inline TInt FatSectors() const;
- inline TInt SectorsPerTrack() const;
- inline TInt NumberOfHeads() const;
- inline TInt HiddenSectors() const;
- inline TInt HugeSectors() const;
- inline TInt PhysicalDriveNumber() const;
- inline TInt ExtendedBootSignature() const;
- inline TUint32 UniqueID() const;
- inline const TPtrC8 VolumeLabel() const;
- inline const TPtrC8 FileSysType() const;
- inline TInt BootSectorSignature() const;
- inline void SetJumpInstruction();
- inline void SetVendorID(const TDesC8& aDes);
- inline void SetBytesPerSector(TInt aBytesPerSector);
- inline void SetSectorsPerCluster(TInt aSectorsPerCluster);
- inline void SetReservedSectors(TInt aReservedSectors);
- inline void SetNumberOfFats(TInt aNumberOfFats);
- inline void SetRootDirEntries(TInt aRootDirEntries);
- inline void SetTotalSectors(TInt aTotalSectors);
- inline void SetMediaDescriptor(TUint8 aMediaDescriptor);
- inline void SetFatSectors(TInt aFatSectors);
- inline void SetSectorsPerTrack(TInt aSectorsPerTrack);
- inline void SetNumberOfHeads(TInt aNumberOfHeads);
- inline void SetHiddenSectors(TUint32 aHiddenSectors);
- inline void SetHugeSectors(TUint32 aTotalSectors);
- inline void SetPhysicalDriveNumber(TInt aPhysicalDriveNumber);
- inline void SetReservedByte(TUint8 aReservedByte);
- inline void SetExtendedBootSignature(TInt anExtendedBootSignature);
- inline void SetUniqueID(TUint32 anUniqueID);
- inline void SetVolumeLabel(const TDesC8& aDes);
- inline void SetFileSysType(const TDesC8& aDes);
-
- inline void SetFatSectors32(TUint32 aFatSectors32);
- inline void SetFATFlags(TUint16 aFATFlags);
- inline void SetVersionNumber(TUint16 aVersionNumber);
- inline void SetRootClusterNum(TUint32 aRootCusterNum);
- inline void SetFSInfoSectorNum(TUint16 aFSInfoSectorNum);
- inline void SetBkBootRecSector(TUint16 aBkBootRecSector);
- inline TUint32 FatSectors32() const;
- inline TUint16 FATFlags() const;
- inline TUint16 VersionNumber() const;
- inline TUint32 RootClusterNum() const;
- inline TUint16 FSInfoSectorNum() const;
- inline TUint16 BkBootRecSector() const;
-public:
- inline TBool Is16BitFat();
- inline TBool Is32BitFat();
- inline TInt FirstFatSectorPos();
- inline TInt RootDirStartSector();
- inline TInt FirstFreeSector();
-public:
- /**
- Jump instruction used for bootable volumes
- */
- TUint8 iJumpInstruction[3];
- /**
- Vendor ID of the file system that formatted the volume
- */
- TUint8 iVendorId[KVendorIdSize];
- /**
- Bytes per sector
- */
- TUint16 iBytesPerSector;
- /**
- Sectors per cluster ratio
- */
- TUint8 iSectorsPerCluster;
- /**
- Number of reserved sectors on the volume
- */
- TUint16 iReservedSectors;
- /**
- Number of Fats on the volume
- */
- TUint8 iNumberOfFats;
- /**
- Number of entries allowed in the root directory, specific to Fat12/16, zero for FAT32
- */
- TUint16 iRootDirEntries;
- /**
- Total sectors on the volume, zero for FAT32
- */
- TUint16 iTotalSectors;
- /**
- Media descriptor
- */
- TUint8 iMediaDescriptor;
- /**
- Sectors used for the Fat table, zero for FAT32
- */
- TUint16 iFatSectors;
- /**
- Sectors per track
- */
- TUint16 iSectorsPerTrack;
- /**
- Number of heads
- */
- TUint16 iNumberOfHeads;
- /**
- Number of hidden sectors in the volume
- */
- TUint32 iHiddenSectors;
- /**
- Total sectors in the volume, Used if totalSectors > 65535
- */
- TUint32 iHugeSectors;
-
- /**
- Start of additional elements @ offset 36 for FAT32
- Sectors in Fat table for 32 bit volume
- */
- TUint32 iFatSectors32;
- /**
- Fat flags
- */
- TUint16 iFATFlags;
- /**
- Version number of the file system
- */
- TUint16 iVersionNumber;
- /**
- Cluster number of the root directory
- */
- TUint32 iRootClusterNum;
- /**
- Sector number containing the FSIInfo structure
- */
- TUint16 iFSInfoSectorNum;
- /**
- Backup boot sector
- */
- TUint16 iBkBootRecSector;
- /**
- Reserved space
- End of Fat32 Only parameters section
- */
- TUint8 iReserved2[12];
-
- /**
- Physical drive number, not used in Symbian OS
- */
- TUint8 iPhysicalDriveNumber;
- /**
- Reserved byte
- */
- TUint8 iReserved;
- /**
- Extended boot signiture
- */
- TUint8 iExtendedBootSignature;
- /**
- Unique volume ID
- */
- TUint32 iUniqueID;
- /**
- The volume's label
- */
- TUint8 iVolumeLabel[KVolumeLabelSize];
- /**
- File system type
- */
- TUint8 iFileSysType[KFileSysTypeSize];
- };
-
-#include "tfatbootsector.inl"
#endif //__CMASSSTORAGEMOUNTCB_H__