# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1268649950 -7200 # Node ID e7d2d738d3c2dfcd6c80657f216005e2cbd1c2b8 # Parent 597aaf25e343874b26a197d5f2130e45faab65a8 Revision: 201010 Kit: 201010 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/debug/securityServer/inc/c_security_svr_async.h --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/debug/securityServer/inc/c_security_svr_session.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" diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/debug/securityServer/src/c_process_pair.cpp --- 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; } diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/debug/securityServer/src/c_security_svr_async.cpp --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/debug/securityServer/src/c_security_svr_session.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. diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp --- 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; iiEventQueueLock, _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; iClose(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* 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* 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_debug_agent.h --- 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 #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* aAsyncGetValueRequest, Debug::TEventInfo* aEventInfo, DThread* aClientThread); + void GetEvent(TClientDataRequest* 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 iEventQueue; // ring buffer. + /** + * Object used to write events back to DSS thread + * @see TEventInfo + */ TClientDataRequest* 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 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_debug_agent.inl --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_list_manager.cpp --- 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; diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_process_tracker.cpp --- 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;indexProcessName() ); 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;iRemoveAgent(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= KMaxPath) { return 0; // not found - }; + } // Can we find this in the array? - TInt i; TBool found = EFalse; DTargetProcess* foundProcess = 0; - for(i=0;iProcessName() ); - - 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; iProcessName().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; iProcessName().CompareF(*name) == 0) { @@ -421,7 +424,8 @@ void DProcessTracker::FSWait() { - for(TInt i=0; iFSWait(); } @@ -447,7 +451,8 @@ } //iterate through the processes trying to match the name, try to resume the thread if found - for(TInt i=0; iProcessName().CompareF(*name) == 0) { diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_rmd_stepping.cpp --- 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 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; } // diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/d_target_process.cpp --- 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 @@ -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; iiOwningThread == 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++) { diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/rm_debug_eventhandler.cpp --- 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) diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp --- 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; iiCodeSeg; @@ -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<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; } diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/dma/dmapil.cpp --- 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. diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/media/base_e32_drivers_media.mrp --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/pbus/spbus.cpp --- 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. diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/usbc/d_usbc.cpp --- 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(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++; diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/drivers/usbcc/ps_usbc.cpp --- 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); } diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/include/drivers/rm_debug_eventhandler.h --- 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; diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/include/e32ver.h --- 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; diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/include/nkern/nk_priv.h --- 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) diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/include/nkernsmp/nk_priv.h --- 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) diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/kernel/server.cpp --- 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(); } diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/kernel/sutils.cpp --- 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) diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/memmodel/emul/win32/mprocess.cpp --- 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); } } diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp --- 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(); } diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/nkern/win32/ncsched.cpp --- 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 +// Uncomment the following line to turn on tracing when we examine the call stack +// #define DUMP_STACK_BACKTRACE + +#ifdef DUMP_STACK_BACKTRACE + +#include + +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]; diff -r 597aaf25e343 -r e7d2d738d3c2 kernel/eka/release.txt --- 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) diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bmarm/t_wsd_dl1.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bmarm/t_wsd_dl2.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bmarm/t_wsd_dl3.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bwins/t_wsd_dl1.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bwins/t_wsd_dl2.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bwins/t_wsd_dl3.def --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bx86/t_wsd_dl1.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bx86/t_wsd_dl2.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/bx86/t_wsd_dl3.def --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/debug/context.cia --- 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} "); diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/dma/d_dma.cpp --- 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; iClose(); - for (i=0; iDestroy(); @@ -302,6 +304,23 @@ iBufMgr.FreeAll(); } +void DDmaTestChannel::FreeDmaRequests() + { + for (TInt i=0; iQueue(); + __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); } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/dma/t_dma.cpp --- 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; diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/eabi/t_wsd_dl1.def --- /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) + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/eabi/t_wsd_dl2.def --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/eabi/t_wsd_dl3.def --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/bld.inf --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl1.mmh --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl1_cp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl1_cu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl1_xp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl1_xu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl2.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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl2_cp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl2_cu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl2_xp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl2_xu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl3.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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl3_cp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl3_cu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl3_xp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_dl3_xu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_tst.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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_tst_cp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_tst_cu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_tst_xp.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/group/t_wsd_tst_xu.mmp --- /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" diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/mmu/t_shbuf.cpp --- 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); } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/mmu/t_wsd_dl1.cpp --- /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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/mmu/t_wsd_dl2.cpp --- /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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/mmu/t_wsd_dl3.cpp --- /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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/mmu/t_wsd_tst.cpp --- /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 +#include +#include +#include + +#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 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 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 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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/mmu/t_wsd_tst.h --- /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 +#include + +#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__ diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp --- /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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/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_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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp --- /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 + +// 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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/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_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 + +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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp --- /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 +#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 + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/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/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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "t_rmdebug_dll.h" + +#include +#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 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 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 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(®), sizeof(TRegisterInfo)); + } + + TRegisterInfo reg = ERegisterR13Irq; + ids.Append(reinterpret_cast(®), 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(®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(&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(&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 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 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(®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(": 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& 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 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>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; iClientAppL()); + __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; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.h --- /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& 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp --- /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 +#include + +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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/common/t_target_launcher.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 +// +m +// +o +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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( "Launcher Process()" ); + + CTrapCleanup* trap = CTrapCleanup::New(); + if (!trap) + return KErrNoMemory; + + TRAPD(err, MainL()); + RDebug::Printf( "< Target launching returned %d", err); + + delete trap; + + return err; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/common/t_target_launcher.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.cia --- /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 + +// 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"); + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.s --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.s --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.cpp --- /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 +#include +#include +#include "d_rmdebugthread.h" + +EXPORT_C TBuf8 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; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.cpp --- /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 +#include +#include +#include +#include "d_rmdebugthread2.h" + +#include "d_rmdebug_step_test.h" +#include "d_demand_paging.h" + +EXPORT_C TBuf8 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; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm.cia --- /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 +//#include +//#include +//#include "d_rmdebugthread.h" + +EXPORT_C __NAKED__ void RMDebug_BranchTst1( void ) +// +// +// +{ + asm("mov r0, #0 "); // aResult==KErrNone + asm("bx lr "); // Return +} + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia --- /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 +} diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include + + + +#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 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\n\t: delay in microseconds before calling target function\n"); + RDebug::Printf("\t-f\n\t: enumerator from TDebugFunctionType representing function to call\n"); + RDebug::Printf("\t-e\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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.h --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.cpp --- /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 +#include +#include +#include "t_rmdebug_dll.h" + +EXPORT_C TUid GetDSSUid() + { + return Debug::KUidDebugSecurityServer; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.h --- /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 + +/** + 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(); diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.cpp --- /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 +#include +#include +#include +#include +#include +#include +#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; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_crashmonitor_lib.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_multi_agent_launcher.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug2.mmh --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug2.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug2_oem.mmp --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug2_oem2.mmp --- /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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken2.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app1.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app10.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app2.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app3.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app4.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app5.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app6.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app7.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app8.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_app9.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_dll.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_multi_agent.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_multi_target.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_security0.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_security1.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_security2.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_security3.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_rmdebug_target_launcher.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/group/t_trkdummyapp.mmp --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/metro_trk/d_rmdebugclient.h --- /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 iName; + }; + +class TThreadInfo + { + public: + TUint iThreadID; + TUint8 iPriority; + TUint8 iThreadType; + TBuf 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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.cpp --- /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 +#include +#include +#include +#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 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 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 pckg = *(TPckgBuf *)(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 pckg = *(TPckgBuf *)(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 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 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 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 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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.cpp --- /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 +#include +#include +#include +#include +#include +#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 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; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp --- /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 +#include +#include + +#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! + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.h --- /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 + + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_debug_logging.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 + + #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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.cpp --- /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 +#include +#include +#include +#include + +#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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.h --- /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 +#include +#include + +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 iTargetList; + }; + +#endif // RMDEBUG_MULTI_AGENT_H diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp --- /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; + } + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.h --- /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 + +// 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 + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.cpp --- /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 +#include + +#include +#include + +#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( " 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( " 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; + } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.h --- /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 + +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 iTargets; + TRequestStatus iStatus; + Debug::TEventInfo iEventInfo; + TPtr8 iEventPtr; + }; + +#endif // RMDEBUG_MULTI_TARGET_H diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.h --- /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 diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/filesystem/fat/b_fat32.cpp --- 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); } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/filesystem/fat/t_compat32.cpp --- 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(); - } diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp --- 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; diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/filesystem/fat/t_tscan32.cpp --- 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); diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/fileutils/inc/fat_utils.h --- 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(); diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/fileutils/src/fat_utils.cpp --- 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); diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/server/t_main.cpp --- 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); diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/cmassstoragemountcb.cpp --- 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>sectorSizeLog2; - TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<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() { diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragefilesystem.h --- 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__ diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragemountcb.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 /** 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__ diff -r 597aaf25e343 -r e7d2d738d3c2 kerneltest/f32test/smassstorage/src/t_ms_fsunit.cpp --- 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 +#include #include -#include -#include -#include -#include #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); } diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/group/release.txt --- 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) diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/inc/f32dbg.h --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/inc/f32ver.h --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfile/sf_debug.cpp --- 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 pkgBuf(cacheValues); // ensure we only write what the client buffer can hold - diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfile/sf_lepoc.cpp --- 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(; iatmaxOrdinal) + // 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(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> 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(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 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); diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfile/sf_main.cpp --- 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 diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfile/sf_request.cpp --- 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; jiNext = list; - } - list->iNext = iFreeHead; - iFreeHead = start; - return KErrNone; - } - else - { - __CACHE_PRINT1(_L("RequestAllocator::AllocRequest() Limit exceeded Count = %d"),aNum); - CFsClientMessageRequest* request; - for(i=0;iSetAllocated(); - 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; jiIsAllocated = EFalse; - } - - iAllocNumOperation += KAllocReqBlock; - TMsgOperation* last; - for(i=1;iiNext = 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() diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfile/sf_std.h --- 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 }; diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfile/sf_std.inl --- 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 //--------------------------------------------------------------------------------------------------------------------- diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/sfsrv/cl_parse.cpp --- 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); diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp --- 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 +#include +#include "cusbmassstoragecontroller.h" #include "cmassstoragefilesystem.h" #include "cmassstoragemountcb.h" #include "massstoragedebug.h" diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp --- 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 #include #include "cmassstoragemountcb.h" +#include "cusbmassstoragecontroller.h" #include "cmassstoragefilesystem.h" -#include "drivemanager.h" #include "massstoragedebug.h" -#include "massstorageutil.h" CMassStorageMountCB::CMassStorageMountCB(const RArray& 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>sectorSizeLog2; - TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<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; diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/smassstorage/inc/cmassstoragefilesystem.h --- 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 -#include -#include -#include "cusbmassstoragecontroller.h" +//Forward Declaration +class CUsbMassStorageController; /** Mass Storage Filesystem class. @@ -75,8 +73,6 @@ CUsbMassStorageController* iMassStorageController; TBool iRunning; RArray iMsDrives; - - }; #endif // __CMASSSTORAGEFILESYSTEM_H__ diff -r 597aaf25e343 -r e7d2d738d3c2 userlibandfileserver/fileserver/smassstorage/inc/cmassstoragemountcb.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 /** 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& 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& 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__