debugsrv/runmodedebug/rmdriver/src/d_debug_functionality.cpp
branchRCL_3
changeset 20 ca8a1b6995f6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugsrv/runmodedebug/rmdriver/src/d_debug_functionality.cpp	Tue Aug 31 16:45:49 2010 +0300
@@ -0,0 +1,426 @@
+// 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:
+// Defines the DebugFunctionality class. This is responsible for
+// providing configuration data needed by a host debugger to be able
+// to correctly use the functionality provided by the run-mode debug subsystem.
+// 
+
+#include <e32def.h>
+#include <e32def_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <u32std.h>
+#include <kernel/kernel.h>
+#include <rm_debug_api.h>
+#include "d_rmd_breakpoints.h"
+#include "rm_debug_kerneldriver.h"
+#include "d_debug_functionality.h"
+
+using namespace Debug;
+
+// Core
+const TTag DebugFunctionalityCoreInfo[] =
+	{
+	{ECoreEvents,ETagTypeBoolean,0,ETrue},
+	{ECoreStartStop,ETagTypeBoolean,0,ETrue},
+	{ECoreMemory,ETagTypeBoolean,0,ETrue},
+	{ECoreRegister,ETagTypeBoolean,0,ETrue},
+	{ECoreBreakpoint,ETagTypeBoolean,0,ETrue},
+	{ECoreStepping,ETagTypeBoolean,0,ETrue},
+	{ECoreLists,ETagTypeBoolean,0,ETrue},
+	{ECoreLogging,ETagTypeBoolean,0,EFalse},
+	{ECoreHardware,ETagTypeBoolean,0,EFalse},
+	{ECoreApiConstants,ETagTypeBoolean,0,ETrue},
+	{ECoreKillObjects,ETagTypeBoolean,0,ETrue},
+	{ECoreSecurity,ETagTypeBoolean,0,ETrue},	
+	};
+
+const TSubBlock DebugFunctionalityCore[] =
+	{
+	ETagHeaderIdCore,ECoreLast,
+	(TTag*)DebugFunctionalityCoreInfo
+	};
+
+// Memory
+const TTag DebugFunctionalityMemoryInfo[] =
+	{
+	{EMemoryRead,ETagTypeBoolean,0,ETrue}, 
+	{EMemoryWrite,ETagTypeBoolean,0,ETrue},
+	{EMemoryAccess64,ETagTypeBoolean,0,EFalse},
+	{EMemoryAccess32,ETagTypeBoolean,0,ETrue},
+	{EMemoryAccess16,ETagTypeBoolean,0,EFalse},
+	{EMemoryAccess8,ETagTypeBoolean,0,EFalse},
+	{EMemoryBE8,ETagTypeBoolean,0,EFalse},
+	{EMemoryBE32,ETagTypeBoolean,0,EFalse},
+	{EMemoryLE8,ETagTypeBoolean,0,ETrue},
+	{EMemoryMaxBlockSize,ETagTypeTUint32,0,16 * KKilo /* 16Kbytes */}	// binaryMax size of memory requests in bytes
+	};
+
+const TSubBlock DebugFunctionalityMemory[]=
+	{
+	ETagHeaderIdMemory,EMemoryLast,
+	(TTag*)DebugFunctionalityMemoryInfo
+	};
+
+// Kill Objects
+const TTag DebugFunctionalityKillObjectsInfo[] =
+	{
+	{EFunctionalityKillThread,ETagTypeBoolean,0,EFalse}, 
+	{EFunctionalityKillProcess,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalityKillObjects[]=
+	{
+	ETagHeaderIdKillObjects,EFunctionalityKillObjectLast,
+	(TTag*)DebugFunctionalityKillObjectsInfo
+	};
+
+// Core Registers
+const TTag DebugFunctionalityRegistersCoreInfo[] =
+	{
+	{ERegisterR0,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR1,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR2,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR3,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR4,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR5,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR6,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR7,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR8,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR9,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR10,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR11,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR12,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR13,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR14,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR15,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterCpsr,ETagTypeEnum, 4,EAccessReadWrite},
+	{ERegisterR13Svc,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Svc,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrSvc,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Abt,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Abt,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrAbt,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Und,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Und,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrUnd,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Irq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Irq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrIrq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR8Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR9Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR10Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR11Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR12Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR13Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterR14Fiq,ETagTypeEnum, 4,EAccessNone},
+	{ERegisterSpsrFiq, ETagTypeEnum, 4,EAccessNone}
+	};
+
+const TSubBlock DebugFunctionalityRegistersCore[] =
+	{
+	ETagHeaderIdRegistersCore, ERegisterLast,
+	(TTag*)DebugFunctionalityRegistersCoreInfo
+	};
+
+// Co-processor registers
+const TTag DebugFunctionalityRegistersCoProInfo[]=
+	{
+	//this is the DACR register
+	{0x00300f01, ETagTypeTUint32, 4, EAccessReadWrite} 
+	};
+
+const TSubBlock DebugFunctionalityRegistersCoPro[]=
+	{
+	ETagHeaderIdCoProRegisters,1,
+	(TTag*)DebugFunctionalityRegistersCoProInfo
+	};
+
+// Breakpoints
+const TTag DebugFunctionalityBreakpointsInfo[]=
+	{
+	{EBreakpointThread,ETagTypeBoolean,0,ETrue},
+	{EBreakpointProcess,ETagTypeBoolean,0,ETrue},
+	{EBreakpointSystem,ETagTypeBoolean,0,EFalse},
+	{EBreakpointArm,ETagTypeBoolean,0,ETrue},
+	{EBreakpointThumb,ETagTypeBoolean,0,ETrue},
+	{EBreakpointT2EE,ETagTypeBoolean,0,ETrue},
+	{EBreakpointArmInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointThumbInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointT2EEInst,ETagTypeBoolean,0,ETrue},
+	{EBreakpointSetArmInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointSetThumbInst,ETagTypeBoolean,0,EFalse},
+	{EBreakpointSetT2EEInst,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalityBreakpoints[] =
+	{
+	ETagHeaderIdBreakpoints, EBreakpointLast,
+	(TTag*)DebugFunctionalityBreakpointsInfo
+	};
+
+// Stepping
+const TTag DebugFunctionalitySteppingInfo[]=
+	{
+	{EStep,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalityStepping[] =
+	{
+	ETagHeaderIdStepping, EStepLast,
+	(TTag*)DebugFunctionalitySteppingInfo
+	};
+
+// Execution Control
+const TTag DebugFunctionalityExecutionInfo[]=
+	{
+	{EExecThreadSuspendResume,ETagTypeBoolean,0,ETrue},
+	{EExecProcessSuspendResume,ETagTypeBoolean,0,EFalse},
+	{EExecSystemSuspendResume,ETagTypeBoolean,0,EFalse},
+	};
+
+const TSubBlock DebugFunctionalityExecution[]=
+	{
+	ETagHeaderIdExecution, EExecLast,
+	(TTag*)DebugFunctionalityExecutionInfo
+	};
+
+// Events
+const TTag DebugFunctionalityEventsInfo[]=
+	{
+	{EEventsBreakPoint,ETagTypeEnum,0,EActionSuspend},
+	{EEventsProcessBreakPoint,ETagTypeEnum,0,EActionSuspend},
+	{EEventsSwExc,ETagTypeEnum,0,EActionSuspend},
+	{EEventsHwExc,ETagTypeEnum,0,EActionSuspend},
+	{EEventsKillThread,ETagTypeEnum,0,EActionContinue},
+	{EEventsAddLibrary,ETagTypeEnum,0,EActionSuspend},
+	{EEventsRemoveLibrary,ETagTypeEnum,0,EActionSuspend},
+	{EEventsUserTrace,ETagTypeEnum,0,EActionSuspend},
+	{EEventsStartThread,ETagTypeEnum,0,EActionSuspend},
+	{EEventsBufferFull,ETagTypeEnum,0,EActionContinue},
+	{EEventsUnknown,ETagTypeEnum,0,EActionContinue},
+	{EEventsUserTracesLost, ETagTypeEnum, 0, EActionContinue},
+	{EEventsAddProcess,ETagTypeEnum,0,EActionContinue},
+	{EEventsRemoveProcess,ETagTypeEnum,0,EActionContinue}
+	};
+
+const TSubBlock DebugFunctionalityEvents[] =
+	{
+	ETagHeaderIdEvents, EEventsLast,
+	(TTag*)DebugFunctionalityEventsInfo
+	};
+
+// API Constants
+const TTag DebugFunctionalityApiConstantsInfo[]=
+	{
+	{EApiConstantsTEventInfoSize,ETagTypeTUint32,0,sizeof(TEventInfo)},
+	};
+
+const TSubBlock DebugFunctionalityApiConstants[] =
+	{
+	ETagHeaderIdApiConstants, EApiConstantsLast,
+	(TTag*)DebugFunctionalityApiConstantsInfo
+	};
+
+// Listings
+const TTag DebugFunctionalityListInfo[] =
+	{
+	{EProcesses,ETagTypeBitField,0,EScopeGlobal},
+	{EThreads,ETagTypeBitField,0,EScopeGlobal|EScopeProcessSpecific|EScopeThreadSpecific},
+	{ECodeSegs,ETagTypeBitField,0,EScopeGlobal|EScopeProcessSpecific|EScopeThreadSpecific},
+	{EXipLibraries,ETagTypeBitField,0,EScopeGlobal},
+	{EExecutables,ETagTypeBitField,0,EScopeGlobal},
+	{ELogicalDevices,ETagTypeBitField,0,EScopeNone},
+	{EMutexes,ETagTypeBitField,0,EScopeNone},
+	{EServers,ETagTypeBitField,0,EScopeNone},
+	{ESessions,ETagTypeBitField,0,EScopeNone},
+	{ESemaphores,ETagTypeBitField,0,EScopeNone},
+	{EChunks,ETagTypeBitField,0,EScopeNone},
+	{EBreakpoints,ETagTypeBitField,0,EScopeNone},
+	{ESetBreak,ETagTypeBitField,0,EScopeNone},
+	{ERemoveBreak,ETagTypeBitField,0,EScopeNone},
+	{EModifyBreak,ETagTypeBitField,0,EScopeNone},
+	};
+
+const TSubBlock DebugFunctionalityList[] =
+	{
+	ETagHeaderList, EListLast,
+	(TTag*)DebugFunctionalityListInfo
+	};
+
+// Security
+const TTag DebugFunctionalitySecurityInfo[]=
+	{
+	{ESecurityOEMDebugToken,ETagTypeBoolean,0,ETrue}
+	};
+
+const TSubBlock DebugFunctionalitySecurity[] =
+	{
+	ETagHeaderIdSecurity, ESecurityLast,
+	(TTag*)DebugFunctionalitySecurityInfo
+	};
+
+TUint32 TDebugFunctionality::GetDebugFunctionalityBufSize(void)
+	{
+	TUint32 df_size = 0;
+
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityCore);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityMemory);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityRegistersCore);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityRegistersCoPro);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityBreakpoints);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityStepping);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityExecution);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityEvents);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityApiConstants);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityList);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityKillObjects);
+	df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalitySecurity);
+	
+	return df_size;
+	}
+
+TBool TDebugFunctionality::GetDebugFunctionality(TDes8& aDFBlock)
+	{
+	if (aDFBlock.MaxLength() < GetDebugFunctionalityBufSize() )
+		{
+		// Insufficient space to contain the debug functionality block
+		return EFalse;
+		}
+
+	AppendBlock((const TSubBlock&)DebugFunctionalityCore,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityMemory,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityRegistersCore,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityRegistersCoPro,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityBreakpoints,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityStepping,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityExecution,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityEvents,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityApiConstants,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityList,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalityKillObjects,aDFBlock);
+	AppendBlock((const TSubBlock&)DebugFunctionalitySecurity,aDFBlock);
+
+	return ETrue;
+	}
+
+/**
+ * Get the register information associated with aRegisterInfo. If aRegisterInfo is
+ * an unsupported register then an entry of the form:
+ *   {aRegisterInfo, x, 0, EAccessUnknown}
+ *   will be returned where x is an arbitrary value.
+ *   
+ *   @param aRegisterInfo register id information
+ *   @param aTag The functionality information for this register.
+ *   @return One of the system wide error codes
+ */
+TInt TDebugFunctionality::GetRegister(const TRegisterInfo aRegisterInfo, TTag& aTag)
+	{
+	if(Register::IsCoreReg(aRegisterInfo))
+		{
+		for(TInt i=0; i<ERegisterLast; i++)
+			{
+			if(Register::GetCoreRegId(DebugFunctionalityRegistersCoreInfo[i].iTagId) == Register::GetCoreRegId(aRegisterInfo))
+				{
+				aTag = DebugFunctionalityRegistersCoreInfo[i];
+				return KErrNone;
+				}
+			}
+		}
+	else if(Register::IsCoproReg(aRegisterInfo))
+		{
+		//get aRegisterInfo's details
+		TUint32 crn = Register::GetCRn(aRegisterInfo);
+		TUint32 crm = Register::GetCRm(aRegisterInfo);
+		TUint32 opcode1 = Register::GetOpcode1(aRegisterInfo);
+		TUint32 opcode2 = Register::GetOpcode2(aRegisterInfo);
+		TUint32 coproNum = Register::GetCoproNum(aRegisterInfo);
+
+		for(TInt i=0; i<sizeof(DebugFunctionalityRegistersCoProInfo)/sizeof(TTag); i++)
+			{
+			TUint32 tagId = DebugFunctionalityRegistersCoProInfo[i].iTagId;
+
+			//if this entry is the DACR
+			if((Register::GetCRm(tagId) == 3) && (Register::GetCoproNum(tagId) == 15))
+				{
+				if((crm == 3) && (coproNum == 15))
+					{
+					aTag = DebugFunctionalityRegistersCoProInfo[i];
+					return KErrNone;
+					}
+				}
+			//each coprocessor register that is supported will need logic adding here
+			}
+		}
+	else // in the future there could be other types of register supported
+		{
+		//for now just fall through to unsupported case
+		}
+
+	//found an unsupported register so just return EAccessUnknown as the access level
+	aTag.iTagId = aRegisterInfo;
+	aTag.iSize = 0;
+	aTag.iValue = EAccessUnknown;
+
+	return KErrNotSupported;
+	}
+
+/**
+ * Returns the maximum memory block size which can be read or written.
+ * @return the maximum memory block size which can be read or written
+*/
+TUint32 TDebugFunctionality::GetMemoryOperationMaxBlockSize()
+	{
+	return DebugFunctionalityMemoryInfo[EMemoryMaxBlockSize].iValue;
+	}
+
+/**
+ * Helper function to append a DebugFunctionalityXXX SubBlock 
+ * into a TDes buffer
+ */
+void TDebugFunctionality::AppendBlock(const TSubBlock& aDFSubBlock, TDes8& aDFBlock)
+	{
+	// Copy the aSubDFBlock.header into aDFBlock (Note we don't put in a TSubBlock structure
+	// as the block is just that - a flat block so the pointer is not required)
+	TPtr8 SubDFBlockHdrPtr((TUint8*)&aDFSubBlock.iHeader,sizeof(TTagHeader),sizeof(TTagHeader));
+
+	aDFBlock.Append(SubDFBlockHdrPtr);
+
+	// Append all the Tags
+	for (TUint i=0; i<aDFSubBlock.iHeader.iNumTags; i++)
+		{
+		TPtr8 tmpPtr((TUint8*)&aDFSubBlock.iTagArray[i],sizeof(TTag),sizeof(TTag));
+
+		aDFBlock.Append(tmpPtr);
+		}
+	}
+
+/**
+ * Computes the size in bytes of aDFBlock
+ * @param aDFSubBlock
+ * @return TUint32 size of sub block
+ */
+TUint32 TDebugFunctionality::ComputeBlockSize(const TSubBlock& aDFSubBlock)
+	{
+	TUint32 size = 0;
+
+	// Header size
+	size += sizeof(TTagHeader);
+
+	// size of all the tags within the header:
+	size += aDFSubBlock.iHeader.iNumTags * sizeof(TTag); 
+
+	return size;
+	}
+