1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Defines the DebugFunctionality class. This is responsible for |
|
15 // providing configuration data needed by a host debugger to be able |
|
16 // to correctly use the functionality provided by the run-mode debug subsystem. |
|
17 // |
|
18 |
|
19 #include <e32def.h> |
|
20 #include <e32def_private.h> |
|
21 #include <e32cmn.h> |
|
22 #include <e32cmn_private.h> |
|
23 #include <u32std.h> |
|
24 #include <kernel/kernel.h> |
|
25 #include <rm_debug_api.h> |
|
26 #include "d_rmd_breakpoints.h" |
|
27 #include "rm_debug_kerneldriver.h" |
|
28 #include "d_debug_functionality.h" |
|
29 |
|
30 using namespace Debug; |
|
31 |
|
32 // Core |
|
33 const TTag DebugFunctionalityCoreInfo[] = |
|
34 { |
|
35 {ECoreEvents,ETagTypeBoolean,0,ETrue}, |
|
36 {ECoreStartStop,ETagTypeBoolean,0,ETrue}, |
|
37 {ECoreMemory,ETagTypeBoolean,0,ETrue}, |
|
38 {ECoreRegister,ETagTypeBoolean,0,ETrue}, |
|
39 {ECoreBreakpoint,ETagTypeBoolean,0,ETrue}, |
|
40 {ECoreStepping,ETagTypeBoolean,0,ETrue}, |
|
41 {ECoreLists,ETagTypeBoolean,0,ETrue}, |
|
42 {ECoreLogging,ETagTypeBoolean,0,EFalse}, |
|
43 {ECoreHardware,ETagTypeBoolean,0,EFalse}, |
|
44 {ECoreApiConstants,ETagTypeBoolean,0,ETrue}, |
|
45 {ECoreKillObjects,ETagTypeBoolean,0,ETrue}, |
|
46 {ECoreSecurity,ETagTypeBoolean,0,ETrue}, |
|
47 }; |
|
48 |
|
49 const TSubBlock DebugFunctionalityCore[] = |
|
50 { |
|
51 ETagHeaderIdCore,ECoreLast, |
|
52 (TTag*)DebugFunctionalityCoreInfo |
|
53 }; |
|
54 |
|
55 // Memory |
|
56 const TTag DebugFunctionalityMemoryInfo[] = |
|
57 { |
|
58 {EMemoryRead,ETagTypeBoolean,0,ETrue}, |
|
59 {EMemoryWrite,ETagTypeBoolean,0,ETrue}, |
|
60 {EMemoryAccess64,ETagTypeBoolean,0,EFalse}, |
|
61 {EMemoryAccess32,ETagTypeBoolean,0,ETrue}, |
|
62 {EMemoryAccess16,ETagTypeBoolean,0,EFalse}, |
|
63 {EMemoryAccess8,ETagTypeBoolean,0,EFalse}, |
|
64 {EMemoryBE8,ETagTypeBoolean,0,EFalse}, |
|
65 {EMemoryBE32,ETagTypeBoolean,0,EFalse}, |
|
66 {EMemoryLE8,ETagTypeBoolean,0,ETrue}, |
|
67 {EMemoryMaxBlockSize,ETagTypeTUint32,0,16 * KKilo /* 16Kbytes */} // binaryMax size of memory requests in bytes |
|
68 }; |
|
69 |
|
70 const TSubBlock DebugFunctionalityMemory[]= |
|
71 { |
|
72 ETagHeaderIdMemory,EMemoryLast, |
|
73 (TTag*)DebugFunctionalityMemoryInfo |
|
74 }; |
|
75 |
|
76 // Kill Objects |
|
77 const TTag DebugFunctionalityKillObjectsInfo[] = |
|
78 { |
|
79 {EFunctionalityKillThread,ETagTypeBoolean,0,EFalse}, |
|
80 {EFunctionalityKillProcess,ETagTypeBoolean,0,ETrue} |
|
81 }; |
|
82 |
|
83 const TSubBlock DebugFunctionalityKillObjects[]= |
|
84 { |
|
85 ETagHeaderIdKillObjects,EFunctionalityKillObjectLast, |
|
86 (TTag*)DebugFunctionalityKillObjectsInfo |
|
87 }; |
|
88 |
|
89 // Core Registers |
|
90 const TTag DebugFunctionalityRegistersCoreInfo[] = |
|
91 { |
|
92 {ERegisterR0,ETagTypeEnum, 4,EAccessReadWrite}, |
|
93 {ERegisterR1,ETagTypeEnum, 4,EAccessReadWrite}, |
|
94 {ERegisterR2,ETagTypeEnum, 4,EAccessReadWrite}, |
|
95 {ERegisterR3,ETagTypeEnum, 4,EAccessReadWrite}, |
|
96 {ERegisterR4,ETagTypeEnum, 4,EAccessReadWrite}, |
|
97 {ERegisterR5,ETagTypeEnum, 4,EAccessReadWrite}, |
|
98 {ERegisterR6,ETagTypeEnum, 4,EAccessReadWrite}, |
|
99 {ERegisterR7,ETagTypeEnum, 4,EAccessReadWrite}, |
|
100 {ERegisterR8,ETagTypeEnum, 4,EAccessReadWrite}, |
|
101 {ERegisterR9,ETagTypeEnum, 4,EAccessReadWrite}, |
|
102 {ERegisterR10,ETagTypeEnum, 4,EAccessReadWrite}, |
|
103 {ERegisterR11,ETagTypeEnum, 4,EAccessReadWrite}, |
|
104 {ERegisterR12,ETagTypeEnum, 4,EAccessReadWrite}, |
|
105 {ERegisterR13,ETagTypeEnum, 4,EAccessReadWrite}, |
|
106 {ERegisterR14,ETagTypeEnum, 4,EAccessReadWrite}, |
|
107 {ERegisterR15,ETagTypeEnum, 4,EAccessReadWrite}, |
|
108 {ERegisterCpsr,ETagTypeEnum, 4,EAccessReadWrite}, |
|
109 {ERegisterR13Svc,ETagTypeEnum, 4,EAccessNone}, |
|
110 {ERegisterR14Svc,ETagTypeEnum, 4,EAccessNone}, |
|
111 {ERegisterSpsrSvc,ETagTypeEnum, 4,EAccessNone}, |
|
112 {ERegisterR13Abt,ETagTypeEnum, 4,EAccessNone}, |
|
113 {ERegisterR14Abt,ETagTypeEnum, 4,EAccessNone}, |
|
114 {ERegisterSpsrAbt,ETagTypeEnum, 4,EAccessNone}, |
|
115 {ERegisterR13Und,ETagTypeEnum, 4,EAccessNone}, |
|
116 {ERegisterR14Und,ETagTypeEnum, 4,EAccessNone}, |
|
117 {ERegisterSpsrUnd,ETagTypeEnum, 4,EAccessNone}, |
|
118 {ERegisterR13Irq,ETagTypeEnum, 4,EAccessNone}, |
|
119 {ERegisterR14Irq,ETagTypeEnum, 4,EAccessNone}, |
|
120 {ERegisterSpsrIrq,ETagTypeEnum, 4,EAccessNone}, |
|
121 {ERegisterR8Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
122 {ERegisterR9Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
123 {ERegisterR10Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
124 {ERegisterR11Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
125 {ERegisterR12Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
126 {ERegisterR13Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
127 {ERegisterR14Fiq,ETagTypeEnum, 4,EAccessNone}, |
|
128 {ERegisterSpsrFiq, ETagTypeEnum, 4,EAccessNone} |
|
129 }; |
|
130 |
|
131 const TSubBlock DebugFunctionalityRegistersCore[] = |
|
132 { |
|
133 ETagHeaderIdRegistersCore, ERegisterLast, |
|
134 (TTag*)DebugFunctionalityRegistersCoreInfo |
|
135 }; |
|
136 |
|
137 // Co-processor registers |
|
138 const TTag DebugFunctionalityRegistersCoProInfo[]= |
|
139 { |
|
140 //this is the DACR register |
|
141 {0x00300f01, ETagTypeTUint32, 4, EAccessReadWrite} |
|
142 }; |
|
143 |
|
144 const TSubBlock DebugFunctionalityRegistersCoPro[]= |
|
145 { |
|
146 ETagHeaderIdCoProRegisters,1, |
|
147 (TTag*)DebugFunctionalityRegistersCoProInfo |
|
148 }; |
|
149 |
|
150 // Breakpoints |
|
151 const TTag DebugFunctionalityBreakpointsInfo[]= |
|
152 { |
|
153 {EBreakpointThread,ETagTypeBoolean,0,ETrue}, |
|
154 {EBreakpointProcess,ETagTypeBoolean,0,ETrue}, |
|
155 {EBreakpointSystem,ETagTypeBoolean,0,EFalse}, |
|
156 {EBreakpointArm,ETagTypeBoolean,0,ETrue}, |
|
157 {EBreakpointThumb,ETagTypeBoolean,0,ETrue}, |
|
158 {EBreakpointT2EE,ETagTypeBoolean,0,ETrue}, |
|
159 {EBreakpointArmInst,ETagTypeBoolean,0,EFalse}, |
|
160 {EBreakpointThumbInst,ETagTypeBoolean,0,EFalse}, |
|
161 {EBreakpointT2EEInst,ETagTypeBoolean,0,ETrue}, |
|
162 {EBreakpointSetArmInst,ETagTypeBoolean,0,EFalse}, |
|
163 {EBreakpointSetThumbInst,ETagTypeBoolean,0,EFalse}, |
|
164 {EBreakpointSetT2EEInst,ETagTypeBoolean,0,ETrue} |
|
165 }; |
|
166 |
|
167 const TSubBlock DebugFunctionalityBreakpoints[] = |
|
168 { |
|
169 ETagHeaderIdBreakpoints, EBreakpointLast, |
|
170 (TTag*)DebugFunctionalityBreakpointsInfo |
|
171 }; |
|
172 |
|
173 // Stepping |
|
174 const TTag DebugFunctionalitySteppingInfo[]= |
|
175 { |
|
176 {EStep,ETagTypeBoolean,0,ETrue} |
|
177 }; |
|
178 |
|
179 const TSubBlock DebugFunctionalityStepping[] = |
|
180 { |
|
181 ETagHeaderIdStepping, EStepLast, |
|
182 (TTag*)DebugFunctionalitySteppingInfo |
|
183 }; |
|
184 |
|
185 // Execution Control |
|
186 const TTag DebugFunctionalityExecutionInfo[]= |
|
187 { |
|
188 {EExecThreadSuspendResume,ETagTypeBoolean,0,ETrue}, |
|
189 {EExecProcessSuspendResume,ETagTypeBoolean,0,EFalse}, |
|
190 {EExecSystemSuspendResume,ETagTypeBoolean,0,EFalse}, |
|
191 }; |
|
192 |
|
193 const TSubBlock DebugFunctionalityExecution[]= |
|
194 { |
|
195 ETagHeaderIdExecution, EExecLast, |
|
196 (TTag*)DebugFunctionalityExecutionInfo |
|
197 }; |
|
198 |
|
199 // Events |
|
200 const TTag DebugFunctionalityEventsInfo[]= |
|
201 { |
|
202 {EEventsBreakPoint,ETagTypeEnum,0,EActionSuspend}, |
|
203 {EEventsProcessBreakPoint,ETagTypeEnum,0,EActionSuspend}, |
|
204 {EEventsSwExc,ETagTypeEnum,0,EActionSuspend}, |
|
205 {EEventsHwExc,ETagTypeEnum,0,EActionSuspend}, |
|
206 {EEventsKillThread,ETagTypeEnum,0,EActionContinue}, |
|
207 {EEventsAddLibrary,ETagTypeEnum,0,EActionSuspend}, |
|
208 {EEventsRemoveLibrary,ETagTypeEnum,0,EActionSuspend}, |
|
209 {EEventsUserTrace,ETagTypeEnum,0,EActionSuspend}, |
|
210 {EEventsStartThread,ETagTypeEnum,0,EActionSuspend}, |
|
211 {EEventsBufferFull,ETagTypeEnum,0,EActionContinue}, |
|
212 {EEventsUnknown,ETagTypeEnum,0,EActionContinue}, |
|
213 {EEventsUserTracesLost, ETagTypeEnum, 0, EActionContinue}, |
|
214 {EEventsAddProcess,ETagTypeEnum,0,EActionContinue}, |
|
215 {EEventsRemoveProcess,ETagTypeEnum,0,EActionContinue} |
|
216 }; |
|
217 |
|
218 const TSubBlock DebugFunctionalityEvents[] = |
|
219 { |
|
220 ETagHeaderIdEvents, EEventsLast, |
|
221 (TTag*)DebugFunctionalityEventsInfo |
|
222 }; |
|
223 |
|
224 // API Constants |
|
225 const TTag DebugFunctionalityApiConstantsInfo[]= |
|
226 { |
|
227 {EApiConstantsTEventInfoSize,ETagTypeTUint32,0,sizeof(TEventInfo)}, |
|
228 }; |
|
229 |
|
230 const TSubBlock DebugFunctionalityApiConstants[] = |
|
231 { |
|
232 ETagHeaderIdApiConstants, EApiConstantsLast, |
|
233 (TTag*)DebugFunctionalityApiConstantsInfo |
|
234 }; |
|
235 |
|
236 // Listings |
|
237 const TTag DebugFunctionalityListInfo[] = |
|
238 { |
|
239 {EProcesses,ETagTypeBitField,0,EScopeGlobal}, |
|
240 {EThreads,ETagTypeBitField,0,EScopeGlobal|EScopeProcessSpecific|EScopeThreadSpecific}, |
|
241 {ECodeSegs,ETagTypeBitField,0,EScopeGlobal|EScopeProcessSpecific|EScopeThreadSpecific}, |
|
242 {EXipLibraries,ETagTypeBitField,0,EScopeGlobal}, |
|
243 {EExecutables,ETagTypeBitField,0,EScopeGlobal}, |
|
244 {ELogicalDevices,ETagTypeBitField,0,EScopeNone}, |
|
245 {EMutexes,ETagTypeBitField,0,EScopeNone}, |
|
246 {EServers,ETagTypeBitField,0,EScopeNone}, |
|
247 {ESessions,ETagTypeBitField,0,EScopeNone}, |
|
248 {ESemaphores,ETagTypeBitField,0,EScopeNone}, |
|
249 {EChunks,ETagTypeBitField,0,EScopeNone}, |
|
250 {EBreakpoints,ETagTypeBitField,0,EScopeNone}, |
|
251 {ESetBreak,ETagTypeBitField,0,EScopeNone}, |
|
252 {ERemoveBreak,ETagTypeBitField,0,EScopeNone}, |
|
253 {EModifyBreak,ETagTypeBitField,0,EScopeNone}, |
|
254 }; |
|
255 |
|
256 const TSubBlock DebugFunctionalityList[] = |
|
257 { |
|
258 ETagHeaderList, EListLast, |
|
259 (TTag*)DebugFunctionalityListInfo |
|
260 }; |
|
261 |
|
262 // Security |
|
263 const TTag DebugFunctionalitySecurityInfo[]= |
|
264 { |
|
265 {ESecurityOEMDebugToken,ETagTypeBoolean,0,ETrue} |
|
266 }; |
|
267 |
|
268 const TSubBlock DebugFunctionalitySecurity[] = |
|
269 { |
|
270 ETagHeaderIdSecurity, ESecurityLast, |
|
271 (TTag*)DebugFunctionalitySecurityInfo |
|
272 }; |
|
273 |
|
274 TUint32 TDebugFunctionality::GetDebugFunctionalityBufSize(void) |
|
275 { |
|
276 TUint32 df_size = 0; |
|
277 |
|
278 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityCore); |
|
279 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityMemory); |
|
280 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityRegistersCore); |
|
281 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityRegistersCoPro); |
|
282 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityBreakpoints); |
|
283 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityStepping); |
|
284 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityExecution); |
|
285 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityEvents); |
|
286 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityApiConstants); |
|
287 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityList); |
|
288 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalityKillObjects); |
|
289 df_size += ComputeBlockSize((const TSubBlock&)DebugFunctionalitySecurity); |
|
290 |
|
291 return df_size; |
|
292 } |
|
293 |
|
294 TBool TDebugFunctionality::GetDebugFunctionality(TDes8& aDFBlock) |
|
295 { |
|
296 if (aDFBlock.MaxLength() < GetDebugFunctionalityBufSize() ) |
|
297 { |
|
298 // Insufficient space to contain the debug functionality block |
|
299 return EFalse; |
|
300 } |
|
301 |
|
302 AppendBlock((const TSubBlock&)DebugFunctionalityCore,aDFBlock); |
|
303 AppendBlock((const TSubBlock&)DebugFunctionalityMemory,aDFBlock); |
|
304 AppendBlock((const TSubBlock&)DebugFunctionalityRegistersCore,aDFBlock); |
|
305 AppendBlock((const TSubBlock&)DebugFunctionalityRegistersCoPro,aDFBlock); |
|
306 AppendBlock((const TSubBlock&)DebugFunctionalityBreakpoints,aDFBlock); |
|
307 AppendBlock((const TSubBlock&)DebugFunctionalityStepping,aDFBlock); |
|
308 AppendBlock((const TSubBlock&)DebugFunctionalityExecution,aDFBlock); |
|
309 AppendBlock((const TSubBlock&)DebugFunctionalityEvents,aDFBlock); |
|
310 AppendBlock((const TSubBlock&)DebugFunctionalityApiConstants,aDFBlock); |
|
311 AppendBlock((const TSubBlock&)DebugFunctionalityList,aDFBlock); |
|
312 AppendBlock((const TSubBlock&)DebugFunctionalityKillObjects,aDFBlock); |
|
313 AppendBlock((const TSubBlock&)DebugFunctionalitySecurity,aDFBlock); |
|
314 |
|
315 return ETrue; |
|
316 } |
|
317 |
|
318 /** |
|
319 * Get the register information associated with aRegisterInfo. If aRegisterInfo is |
|
320 * an unsupported register then an entry of the form: |
|
321 * {aRegisterInfo, x, 0, EAccessUnknown} |
|
322 * will be returned where x is an arbitrary value. |
|
323 * |
|
324 * @param aRegisterInfo register id information |
|
325 * @param aTag The functionality information for this register. |
|
326 * @return One of the system wide error codes |
|
327 */ |
|
328 TInt TDebugFunctionality::GetRegister(const TRegisterInfo aRegisterInfo, TTag& aTag) |
|
329 { |
|
330 if(Register::IsCoreReg(aRegisterInfo)) |
|
331 { |
|
332 for(TInt i=0; i<ERegisterLast; i++) |
|
333 { |
|
334 if(Register::GetCoreRegId(DebugFunctionalityRegistersCoreInfo[i].iTagId) == Register::GetCoreRegId(aRegisterInfo)) |
|
335 { |
|
336 aTag = DebugFunctionalityRegistersCoreInfo[i]; |
|
337 return KErrNone; |
|
338 } |
|
339 } |
|
340 } |
|
341 else if(Register::IsCoproReg(aRegisterInfo)) |
|
342 { |
|
343 //get aRegisterInfo's details |
|
344 TUint32 crn = Register::GetCRn(aRegisterInfo); |
|
345 TUint32 crm = Register::GetCRm(aRegisterInfo); |
|
346 TUint32 opcode1 = Register::GetOpcode1(aRegisterInfo); |
|
347 TUint32 opcode2 = Register::GetOpcode2(aRegisterInfo); |
|
348 TUint32 coproNum = Register::GetCoproNum(aRegisterInfo); |
|
349 |
|
350 for(TInt i=0; i<sizeof(DebugFunctionalityRegistersCoProInfo)/sizeof(TTag); i++) |
|
351 { |
|
352 TUint32 tagId = DebugFunctionalityRegistersCoProInfo[i].iTagId; |
|
353 |
|
354 //if this entry is the DACR |
|
355 if((Register::GetCRm(tagId) == 3) && (Register::GetCoproNum(tagId) == 15)) |
|
356 { |
|
357 if((crm == 3) && (coproNum == 15)) |
|
358 { |
|
359 aTag = DebugFunctionalityRegistersCoProInfo[i]; |
|
360 return KErrNone; |
|
361 } |
|
362 } |
|
363 //each coprocessor register that is supported will need logic adding here |
|
364 } |
|
365 } |
|
366 else // in the future there could be other types of register supported |
|
367 { |
|
368 //for now just fall through to unsupported case |
|
369 } |
|
370 |
|
371 //found an unsupported register so just return EAccessUnknown as the access level |
|
372 aTag.iTagId = aRegisterInfo; |
|
373 aTag.iSize = 0; |
|
374 aTag.iValue = EAccessUnknown; |
|
375 |
|
376 return KErrNotSupported; |
|
377 } |
|
378 |
|
379 /** |
|
380 * Returns the maximum memory block size which can be read or written. |
|
381 * @return the maximum memory block size which can be read or written |
|
382 */ |
|
383 TUint32 TDebugFunctionality::GetMemoryOperationMaxBlockSize() |
|
384 { |
|
385 return DebugFunctionalityMemoryInfo[EMemoryMaxBlockSize].iValue; |
|
386 } |
|
387 |
|
388 /** |
|
389 * Helper function to append a DebugFunctionalityXXX SubBlock |
|
390 * into a TDes buffer |
|
391 */ |
|
392 void TDebugFunctionality::AppendBlock(const TSubBlock& aDFSubBlock, TDes8& aDFBlock) |
|
393 { |
|
394 // Copy the aSubDFBlock.header into aDFBlock (Note we don't put in a TSubBlock structure |
|
395 // as the block is just that - a flat block so the pointer is not required) |
|
396 TPtr8 SubDFBlockHdrPtr((TUint8*)&aDFSubBlock.iHeader,sizeof(TTagHeader),sizeof(TTagHeader)); |
|
397 |
|
398 aDFBlock.Append(SubDFBlockHdrPtr); |
|
399 |
|
400 // Append all the Tags |
|
401 for (TUint i=0; i<aDFSubBlock.iHeader.iNumTags; i++) |
|
402 { |
|
403 TPtr8 tmpPtr((TUint8*)&aDFSubBlock.iTagArray[i],sizeof(TTag),sizeof(TTag)); |
|
404 |
|
405 aDFBlock.Append(tmpPtr); |
|
406 } |
|
407 } |
|
408 |
|
409 /** |
|
410 * Computes the size in bytes of aDFBlock |
|
411 * @param aDFSubBlock |
|
412 * @return TUint32 size of sub block |
|
413 */ |
|
414 TUint32 TDebugFunctionality::ComputeBlockSize(const TSubBlock& aDFSubBlock) |
|
415 { |
|
416 TUint32 size = 0; |
|
417 |
|
418 // Header size |
|
419 size += sizeof(TTagHeader); |
|
420 |
|
421 // size of all the tags within the header: |
|
422 size += aDFSubBlock.iHeader.iNumTags * sizeof(TTag); |
|
423 |
|
424 return size; |
|
425 } |
|
426 |
|