sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Stop-mode debug interface implementation as defined in sm_debug_api.h sl@0: // sl@0: sl@0: /** sl@0: * @file sl@0: * @internalComponent sl@0: * @prototype sl@0: */ sl@0: sl@0: #ifdef __LAUNCH_AS_EXTENSION__ sl@0: sl@0: #include sl@0: #include sl@0: #include "d_rmd_breakpoints.h" sl@0: sl@0: using namespace Debug; sl@0: sl@0: /** sl@0: * Stop Mode routine to retrieve the code seg list and place it in the response buffer sl@0: * @param aItem List item describing the list sl@0: * @return One of the system wide error codes sl@0: */ sl@0: TInt StopModeDebug::GetCodeSegList(const TListItem* aItem, bool aCheckConsistent) sl@0: { sl@0: if(aCheckConsistent) sl@0: { sl@0: DMutex* codeMutex = Kern::CodeSegLock(); sl@0: if(!codeMutex || codeMutex->iHoldCount) sl@0: { sl@0: return ExitPoint(KErrNotReady); sl@0: } sl@0: } sl@0: sl@0: TUint8* bufferInitial = (TUint8*)aItem->iBufferAddress; sl@0: TUint8* buffer = (TUint8*)aItem->iBufferAddress + 12; sl@0: TUint32 bufferSize = aItem->iBufferSize; sl@0: sl@0: TUint32* buffer32 = (TUint32*)aItem->iBufferAddress; sl@0: *buffer32 = (TUint32)aItem; sl@0: TUint32* size = buffer32+1; sl@0: *size = 12; sl@0: TUint32* nextElementSize = buffer32+2; sl@0: *nextElementSize = 0; sl@0: TUint32 start = aItem->iStartElement; sl@0: sl@0: while(1) sl@0: { sl@0: DEpocCodeSeg* codeSeg = GetNextCodeSeg(start, aItem->iListScope, aItem->iScopeData); sl@0: if(!codeSeg) sl@0: { sl@0: *size = buffer-bufferInitial; sl@0: return KErrNone; // we're done sl@0: } sl@0: start = (TUint32)codeSeg + 1; sl@0: sl@0: TInt ret = ProcessCodeSeg(buffer, bufferSize, codeSeg); sl@0: if(KErrNone != ret) sl@0: { sl@0: if(ret > 0) sl@0: { sl@0: Kern::Printf("Next element is %d bytes big\n", ret); sl@0: *nextElementSize = ret; sl@0: ret = KErrTooBig; sl@0: } sl@0: *size = buffer-bufferInitial; sl@0: return ret; sl@0: } sl@0: } sl@0: } sl@0: sl@0: DEpocCodeSeg* StopModeDebug::GetNextCodeSeg(const TUint32 aStart, const TListScope aListScope, const TUint64 aScopeData) sl@0: { sl@0: switch(aListScope) sl@0: { sl@0: case EScopeGlobal: sl@0: return GetNextGlobalCodeSeg(aStart); sl@0: case EScopeThreadSpecific: sl@0: return GetNextThreadSpecificCodeSeg(aStart, aScopeData); sl@0: default: sl@0: return NULL; sl@0: } sl@0: } sl@0: sl@0: DEpocCodeSeg* StopModeDebug::GetNextThreadSpecificCodeSeg(const TUint32 aStart, const TUint64 aThreadId) sl@0: { sl@0: return NULL; sl@0: } sl@0: sl@0: DEpocCodeSeg* StopModeDebug::GetNextGlobalCodeSeg(const TUint32 aStart) sl@0: { sl@0: //get global code seg list sl@0: SDblQue* codeSegList = Kern::CodeSegList(); sl@0: sl@0: DEpocCodeSeg* codeSeg = NULL; sl@0: for (SDblQueLink* codeSegPtr= codeSegList->First(); codeSegPtr!=(SDblQueLink*) (codeSegList); codeSegPtr=codeSegPtr->iNext) sl@0: { sl@0: DEpocCodeSeg* tempCodeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iLink); sl@0: if((TUint32)tempCodeSeg >= aStart) sl@0: { sl@0: if(!codeSeg || tempCodeSeg < codeSeg) sl@0: { sl@0: codeSeg = tempCodeSeg; sl@0: } sl@0: } sl@0: } sl@0: return codeSeg; sl@0: } sl@0: sl@0: TInt StopModeDebug::ProcessCodeSeg(TUint8*& aBuffer, TUint32& aBufferSize, DEpocCodeSeg* aCodeSeg) sl@0: { sl@0: //create a memory info object for use in the loop sl@0: TModuleMemoryInfo memoryInfo; sl@0: sl@0: //get the memory info sl@0: TInt err = aCodeSeg->GetMemoryInfo(memoryInfo, NULL); sl@0: if(err != KErrNone) sl@0: { sl@0: //there's been an error so return it sl@0: return err; sl@0: } sl@0: //calculate data values sl@0: TFileName fileName(aCodeSeg->iFileName->Ptr()); sl@0: TBool isXip = (aCodeSeg->iXIP) ? ETrue : EFalse; sl@0: sl@0: //get the code seg type sl@0: TCodeSegType type = sl@0: aCodeSeg->IsExe() ? EExeCodeSegType : sl@0: aCodeSeg->IsDll() ? EDllCodeSegType : sl@0: EUnknownCodeSegType; sl@0: sl@0: //append data to buffer sl@0: return AppendCodeSegData(aBuffer, aBufferSize, memoryInfo, isXip, type, fileName, aCodeSeg); sl@0: } sl@0: sl@0: TInt StopModeDebug::AppendCodeSegData(TUint8*& aBuffer, TUint32& aBufferSize, const TModuleMemoryInfo& aMemoryInfo, const TBool aIsXip, const TCodeSegType aCodeSegType, const TDesC8& aFileName, DEpocCodeSeg* aCodeSeg) sl@0: { sl@0: //get some data elements to put in buffer sl@0: TUint16 fileNameLength = aFileName.Length(); sl@0: sl@0: //calculate the resultant size sl@0: TUint dataSize = Align4(sizeof(TCodeSegListEntry) + (2*fileNameLength) - sizeof(TUint16)); sl@0: if(dataSize > aBufferSize) sl@0: { sl@0: // data won't fit in the buffer so quit sl@0: return dataSize; sl@0: } sl@0: //Create a TCodeSegListEntry which references the buffer. sl@0: TCodeSegListEntry& entry = *(TCodeSegListEntry*)aBuffer; sl@0: entry.iCodeBase = aMemoryInfo.iCodeBase; sl@0: entry.iCodeSize = aMemoryInfo.iCodeSize; sl@0: entry.iConstDataSize = aMemoryInfo.iConstDataSize; sl@0: entry.iInitialisedDataBase = aMemoryInfo.iInitialisedDataBase; sl@0: entry.iInitialisedDataSize = aMemoryInfo.iInitialisedDataSize; sl@0: entry.iUninitialisedDataSize = aMemoryInfo.iUninitialisedDataSize; sl@0: entry.iIsXip = aIsXip; sl@0: entry.iCodeSegType = aCodeSegType; sl@0: entry.iNameLength = fileNameLength; sl@0: //entry.iSpare1 = (TUint32)aCodeSeg; sl@0: sl@0: //have to convert the stored name to 16 bit Unicode sl@0: TPtr name = TPtr((TUint8*)&(entry.iName[0]), fileNameLength*2, fileNameLength*2); sl@0: TInt err = CopyAndExpandDes(aFileName, name); sl@0: if(err != KErrNone) sl@0: { sl@0: return KErrGeneral; sl@0: } sl@0: sl@0: //increase length sl@0: aBufferSize-=dataSize; sl@0: aBuffer+=dataSize; sl@0: return KErrNone; sl@0: } sl@0: sl@0: #endif sl@0: