|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <memspy/engine/memspyenginehelperheap.h> |
|
19 |
|
20 // System includes |
|
21 #include <s32mem.h> |
|
22 |
|
23 // Driver includes |
|
24 #include <memspy/driver/memspydriverclient.h> |
|
25 |
|
26 // User includes |
|
27 #include <memspy/engine/memspyengine.h> |
|
28 #include <memspy/engine/memspyengineutils.h> |
|
29 #include <memspy/engine/memspyengineoutputsink.h> |
|
30 #include <memspy/engine/memspyengineoutputlist.h> |
|
31 #include <memspy/engine/memspyengineobjectthread.h> |
|
32 #include <memspy/engine/memspyengineobjectprocess.h> |
|
33 #include <memspy/engine/memspyenginehelperrom.h> |
|
34 #include <memspy/engine/memspyengineobjectcontainer.h> |
|
35 #include <memspy/engine/memspyenginehelpercodesegment.h> |
|
36 #include <memspy/driver/memspydriverenumerationsshared.h> |
|
37 |
|
38 // Constants |
|
39 const TBool KMemSpyHeapDumpCreateOwnDataStream = ETrue; |
|
40 |
|
41 // Literal constants |
|
42 _LIT( KCellTypeGoodAllocatedCell, "[Allocated Cell] "); |
|
43 _LIT( KCellTypeGoodFreeCell, "[Free Cell] "); |
|
44 _LIT( KCellTypeBadAllocatedCellSize, "[Bad Allocated Cell Size] "); |
|
45 _LIT( KCellTypeBadAllocatedCellAddress, "[Bad Allocated Cell Address]"); |
|
46 _LIT( KCellTypeBadFreeCellAddress, "[Bad Free Cell Address] "); |
|
47 _LIT( KCellTypeBadFreeCellSize, "[Bad Free Cell Size] "); |
|
48 _LIT( KCellTypeUnknown, "[Unknown!] "); |
|
49 _LIT( KCellListLineFormat, "%S cell: 0x%08x, cellLen: %8d, allocNum: %8d, nestingLev: %8d, cellData: 0x%08x, cellDataAddr: 0x%08x, headerSize: %02d"); |
|
50 _LIT( KMemSpyMarkerHeapData, "<%SMEMSPY_HEAP_DATA_%03d>" ); |
|
51 _LIT( KMemSpyMarkerCSV, "<%SMEMSPY_HEAP_CSV>" ); |
|
52 _LIT( KMemSpyPrefixHeapData, "HeapData - %S - "); |
|
53 _LIT( KMemSpyPrefixCellList, "CellList - %S - "); |
|
54 _LIT( KMemSpyPrefixCSV, "CSV - " ); |
|
55 |
|
56 |
|
57 CMemSpyEngineHelperHeap::CMemSpyEngineHelperHeap( CMemSpyEngine& aEngine ) |
|
58 : iEngine( aEngine ) |
|
59 { |
|
60 } |
|
61 |
|
62 |
|
63 CMemSpyEngineHelperHeap::~CMemSpyEngineHelperHeap() |
|
64 { |
|
65 } |
|
66 |
|
67 |
|
68 void CMemSpyEngineHelperHeap::ConstructL() |
|
69 { |
|
70 } |
|
71 |
|
72 |
|
73 CMemSpyEngineHelperHeap* CMemSpyEngineHelperHeap::NewL( CMemSpyEngine& aEngine ) |
|
74 { |
|
75 CMemSpyEngineHelperHeap* self = new(ELeave) CMemSpyEngineHelperHeap( aEngine ); |
|
76 CleanupStack::PushL( self ); |
|
77 self->ConstructL(); |
|
78 CleanupStack::Pop( self ); |
|
79 return self; |
|
80 } |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 EXPORT_C void CMemSpyEngineHelperHeap::OutputCellListingUserL( const CMemSpyThread& aThread ) |
|
92 { |
|
93 // Suspend the process |
|
94 iEngine.ProcessSuspendLC( aThread.Process().Id() ); |
|
95 |
|
96 // Free cells |
|
97 RArray<TMemSpyDriverFreeCell> freeCells; |
|
98 CleanupClosePushL( freeCells ); |
|
99 |
|
100 // Info section |
|
101 TMemSpyHeapInfo heapInfo; |
|
102 const TInt error = iEngine.Driver().GetHeapInfoUser( heapInfo, aThread.Id(), freeCells ); |
|
103 if ( error == KErrNone ) |
|
104 { |
|
105 UpdateSharedHeapInfoL( aThread.Process().Id(), aThread.Id(), heapInfo ); |
|
106 } |
|
107 if ( error == KErrNone && heapInfo.Type() == TMemSpyHeapInfo::ETypeRHeap ) |
|
108 { |
|
109 // Get thread name for context |
|
110 const TFullName pName( aThread.FullName() ); |
|
111 |
|
112 // Begin a new data stream |
|
113 _LIT( KMemSpyFolder, "Heap\\Cell List" ); |
|
114 _LIT( KMemSpyContext, "Cell List - %S" ); |
|
115 HBufC* context = HBufC::NewLC( KMaxFileName ); |
|
116 TPtr pContext( context->Des() ); |
|
117 pContext.Format( KMemSpyContext, &pName ); |
|
118 iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder ); |
|
119 CleanupStack::PopAndDestroy( context ); |
|
120 |
|
121 // Set prefix for overall listing |
|
122 iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixCellList, &pName ); |
|
123 |
|
124 // Start new section |
|
125 _LIT(KHeader, "CELL LISTING"); |
|
126 iEngine.Sink().OutputSectionHeadingL( KHeader, '=' ); |
|
127 |
|
128 // Prepare temp buffers |
|
129 TBuf<KMaxFullName + 100> printFormat; |
|
130 HBufC* tempBuffer = HBufC::NewLC( 2048 ); |
|
131 TPtr pTempBuffer( tempBuffer->Des() ); |
|
132 |
|
133 // Print initial info |
|
134 OutputHeapInfoL( heapInfo, pName, &freeCells ); |
|
135 |
|
136 // Code segments (needed for map file reading...) |
|
137 _LIT(KCellListCodeSegInfoFormat, "CodeSegs - "); |
|
138 iEngine.HelperCodeSegment().OutputCodeSegmentsL( aThread.Process().Id(), printFormat, KCellListCodeSegInfoFormat, '-', ETrue ); |
|
139 |
|
140 // Now walk the heap! |
|
141 TInt r = iEngine.Driver().WalkHeapInit( aThread.Id() ); |
|
142 if ( r == KErrNone ) |
|
143 { |
|
144 _LIT(KHeader2, "Cells"); |
|
145 iEngine.Sink().OutputSectionHeadingL( KHeader2, '-' ); |
|
146 |
|
147 TMemSpyDriverCellType cellType; |
|
148 TAny* cellAddress; |
|
149 TInt cellLength; |
|
150 TInt cellNestingLevel; |
|
151 TInt cellAllocationNumber; |
|
152 TInt cellHeaderSize; |
|
153 TAny* cellPayloadAddress; |
|
154 TBuf8<4> cellData; |
|
155 // |
|
156 r = iEngine.Driver().WalkHeapNextCell( aThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress ); |
|
157 while( r == KErrNone ) |
|
158 { |
|
159 TUint fourByteCellData = 0; |
|
160 TPtrC pType(KNullDesC); |
|
161 // |
|
162 switch(cellType) |
|
163 { |
|
164 case EMemSpyDriverGoodAllocatedCell: |
|
165 { |
|
166 r = iEngine.Driver().WalkHeapReadCellData( cellAddress, cellData, 4 ); |
|
167 if ( r == KErrNone ) |
|
168 { |
|
169 fourByteCellData = DescriptorAsDWORD( cellData ); |
|
170 } |
|
171 pType.Set(KCellTypeGoodAllocatedCell); |
|
172 break; |
|
173 } |
|
174 case EMemSpyDriverGoodFreeCell: |
|
175 pType.Set(KCellTypeGoodFreeCell); |
|
176 break; |
|
177 case EMemSpyDriverBadAllocatedCellSize: |
|
178 pType.Set(KCellTypeBadAllocatedCellSize); |
|
179 break; |
|
180 case EMemSpyDriverBadAllocatedCellAddress: |
|
181 pType.Set(KCellTypeBadAllocatedCellAddress); |
|
182 break; |
|
183 case EMemSpyDriverBadFreeCellAddress: |
|
184 pType.Set(KCellTypeBadFreeCellAddress); |
|
185 break; |
|
186 case EMemSpyDriverBadFreeCellSize: |
|
187 pType.Set(KCellTypeBadFreeCellSize); |
|
188 break; |
|
189 default: |
|
190 pType.Set(KCellTypeUnknown); |
|
191 break; |
|
192 } |
|
193 |
|
194 if ( r == KErrNone ) |
|
195 { |
|
196 pTempBuffer.Format( KCellListLineFormat, &pType, cellAddress, cellLength, cellAllocationNumber, cellNestingLevel, fourByteCellData, cellPayloadAddress, cellHeaderSize ); |
|
197 iEngine.Sink().OutputLineL( pTempBuffer ); |
|
198 // |
|
199 r = iEngine.Driver().WalkHeapNextCell( aThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress ); |
|
200 } |
|
201 } |
|
202 // |
|
203 iEngine.Driver().WalkHeapClose(); |
|
204 } |
|
205 CleanupStack::PopAndDestroy( tempBuffer ); |
|
206 CleanupStack::PopAndDestroy(); // clear prefix |
|
207 |
|
208 iEngine.Sink().DataStreamEndL(); |
|
209 } |
|
210 |
|
211 CleanupStack::PopAndDestroy( &freeCells ); |
|
212 CleanupStack::PopAndDestroy(); // resume process |
|
213 } |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const CMemSpyThread& aThread ) |
|
234 { |
|
235 OutputHeapDataUserL( aThread, KMemSpyHeapDumpCreateOwnDataStream ); |
|
236 } |
|
237 |
|
238 |
|
239 void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const CMemSpyThread& aThread, TBool aCreateDataStream ) |
|
240 { |
|
241 // Make sure the process is suspended for the entire time we are manipulating it's heap |
|
242 iEngine.ProcessSuspendLC( aThread.Process().Id() ); |
|
243 |
|
244 // Get the heap info, including free cell information |
|
245 RArray<TMemSpyDriverFreeCell> freeCells; |
|
246 CleanupClosePushL( freeCells ); |
|
247 TMemSpyHeapInfo heapInfo; |
|
248 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum1: 0x%08x", heapInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); |
|
249 GetHeapInfoUserL( aThread.Process().Id(), aThread.Id(), heapInfo, &freeCells ); |
|
250 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum2: 0x%08x", heapInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); |
|
251 |
|
252 // Get the heap data |
|
253 const TFullName pName( aThread.FullName() ); |
|
254 OutputHeapDataUserL( aThread.Process().Id(), aThread.Id(), pName, heapInfo, aCreateDataStream, &freeCells ); |
|
255 CleanupStack::PopAndDestroy( &freeCells ); |
|
256 |
|
257 // Resume process |
|
258 CleanupStack::PopAndDestroy(); |
|
259 } |
|
260 |
|
261 |
|
262 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const TProcessId& aPid, const TThreadId& aTid, const TDesC& aThreadName, const TMemSpyHeapInfo& aInfo, const RArray<TMemSpyDriverFreeCell>* aFreeCells ) |
|
263 { |
|
264 OutputHeapDataUserL( aPid, aTid, aThreadName, aInfo, ETrue, aFreeCells ); |
|
265 } |
|
266 |
|
267 |
|
268 void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const TProcessId& aPid, const TThreadId& aTid, const TDesC& aThreadName, const TMemSpyHeapInfo& aInfo, TBool aCreateDataStream, const RArray<TMemSpyDriverFreeCell>* aFreeCells ) |
|
269 { |
|
270 TBuf<KMaxFullName + 100> printFormat; |
|
271 |
|
272 // Begin a new data stream |
|
273 if ( aCreateDataStream ) |
|
274 { |
|
275 _LIT( KMemSpyFolder, "Heap\\Data" ); |
|
276 _LIT( KMemSpyContext, "Heap Data - %S" ); |
|
277 HBufC* context = HBufC::NewLC( KMaxFileName ); |
|
278 TPtr pContext( context->Des() ); |
|
279 pContext.Format( KMemSpyContext, &aThreadName ); |
|
280 iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder ); |
|
281 CleanupStack::PopAndDestroy( context ); |
|
282 } |
|
283 |
|
284 // Get the heap info first of all |
|
285 iEngine.ProcessSuspendLC( aPid ); |
|
286 |
|
287 // Start marker |
|
288 iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KNullDesC, (TUint) aTid ); |
|
289 |
|
290 // Set overall prefix |
|
291 iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixHeapData, &aThreadName ); |
|
292 |
|
293 // Info section |
|
294 OutputHeapInfoL( aInfo, aThreadName, aFreeCells ); |
|
295 |
|
296 // Code segments (needed for map file reading...) |
|
297 _LIT(KCellListCodeSegInfoFormat, "CodeSegs - "); |
|
298 iEngine.HelperCodeSegment().OutputCodeSegmentsL( aPid, printFormat, KCellListCodeSegInfoFormat, '-', ETrue ); |
|
299 |
|
300 // Dump section |
|
301 _LIT(KHeaderDump, "Heap Data"); |
|
302 iEngine.Sink().OutputSectionHeadingL( KHeaderDump, '-' ); |
|
303 |
|
304 HBufC8* data = HBufC8::NewLC( 4096 * 12 ); |
|
305 TPtr8 pData(data->Des()); |
|
306 TUint remaining = 0; |
|
307 TUint readAddress = 0; |
|
308 |
|
309 // When we obtained the heap info, we also obtained a checksum of all the free cells |
|
310 // within the specified heap. We validate that this hasn't changed at the time we |
|
311 // request the heap data for paranoia purposes (There have been "Issues" with MemSpy |
|
312 // not actually suspending a process between fetching heap info & heap data, causing |
|
313 // a mismatch in free cell information). |
|
314 const TUint32 checksum = aInfo.AsRHeap().Statistics().StatsFree().Checksum(); |
|
315 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum: 0x%08x", checksum ) ); |
|
316 |
|
317 TInt r = iEngine.Driver().GetHeapData( aTid, checksum, pData, readAddress, remaining ); |
|
318 if ( r == KErrNone ) |
|
319 { |
|
320 while ( r == KErrNone ) |
|
321 { |
|
322 _LIT(KHeapDumpDataFormat, "%S"); |
|
323 iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, pData.Ptr(), (const TUint8*) readAddress, pData.Length() ); |
|
324 if ( remaining > 0 ) |
|
325 r = iEngine.Driver().GetHeapDataNext( aTid, pData, readAddress, remaining ); |
|
326 else |
|
327 break; |
|
328 } |
|
329 } |
|
330 else |
|
331 { |
|
332 _LIT( KHeapFetchError, "Heap error: %d"); |
|
333 iEngine.Sink().OutputLineFormattedL( KHeapFetchError, r ); |
|
334 } |
|
335 |
|
336 CleanupStack::PopAndDestroy( data ); |
|
337 |
|
338 CleanupStack::PopAndDestroy(); // clear prefix |
|
339 CleanupStack::PopAndDestroy(); // resume process |
|
340 |
|
341 // End marker |
|
342 iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KMemSpySinkTagClose, (TUint) aTid ); |
|
343 |
|
344 if ( aCreateDataStream ) |
|
345 { |
|
346 iEngine.Sink().DataStreamEndL(); |
|
347 } |
|
348 } |
|
349 |
|
350 |
|
351 |
|
352 |
|
353 |
|
354 |
|
355 |
|
356 |
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoL( const TMemSpyHeapInfo& aInfo, const TDesC& aThreadName, const RArray<TMemSpyDriverFreeCell>* aFreeCells ) |
|
371 { |
|
372 CMemSpyEngineOutputList* list = NewHeapSummaryExtendedLC( aInfo, aFreeCells ); |
|
373 |
|
374 // Format the thread name according to upper/lower case request parameters |
|
375 _LIT( KOverallCaption1, "HEAP INFO FOR THREAD '%S'"); |
|
376 list->InsertItemFormatUCL( 0, KOverallCaption1, &aThreadName ); |
|
377 list->InsertUnderlineForItemAtL( 0 ); |
|
378 |
|
379 // Print it |
|
380 list->PrintL(); |
|
381 |
|
382 // Tidy up |
|
383 CleanupStack::PopAndDestroy( list ); |
|
384 } |
|
385 |
|
386 |
|
387 |
|
388 |
|
389 |
|
390 |
|
391 |
|
392 |
|
393 |
|
394 |
|
395 |
|
396 |
|
397 |
|
398 |
|
399 |
|
400 |
|
401 |
|
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 |
|
415 void CMemSpyEngineHelperHeap::OutputCSVEntryL( TInt aIndex, const TMemSpyHeapInfo& aInfo, const TDesC& aThreadName, const TDesC& aProcessName ) |
|
416 { |
|
417 const TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap(); |
|
418 const TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); |
|
419 const TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); |
|
420 const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); |
|
421 |
|
422 // Example: |
|
423 // |
|
424 // <ENTRY_001> |
|
425 // <THREAD_NAME_001>ESock_IP</THREAD_NAME_001> |
|
426 // <PROCESS_NAME_001>c32exe.exe[101f7989]0001</PROCESS_NAME_001> |
|
427 // <CHUNK_NAME_001>Local-c812ba58</CHUNK_NAME_001> |
|
428 // <FIELDS_001>1,0x12400000,0x00c00074,36744,4092,524288,0x00c011a4,0,13,6872,1368,1680,2584,219,40,28996,0</FIELDS_001> |
|
429 // </ENTRY_001> |
|
430 |
|
431 _LIT( KFmtTagOpenAndClose, "<%S_%04d>%S</%S_%04d>" ); |
|
432 |
|
433 _LIT( KFmtEntryId, "<%SENTRY_%04d>"); |
|
434 _LIT( KFmtNameThread, "THREAD_NAME"); |
|
435 _LIT( KFmtNameProcess, "PROCESS_NAME"); |
|
436 _LIT( KFmtNameChunk, "CHUNK_NAME"); |
|
437 _LIT( KFmtFields, "FIELDS"); |
|
438 _LIT( KFmtFieldContent , "<%S_%04d>%06d,0x%08x,0x%08x,%d,%d,%d,0x%08x,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d</%S_%04d>"); |
|
439 |
|
440 // <ENTRY_001> |
|
441 iEngine.Sink().OutputLineFormattedL( KFmtEntryId, &KNullDesC, aIndex ); |
|
442 |
|
443 // <THREAD_NAME_001>ESock_IP</THREAD_NAME_001> |
|
444 iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameThread, aIndex, &aThreadName, &KFmtNameThread, aIndex ); |
|
445 |
|
446 // <PROCESS_NAME_001>c32exe.exe[101f7989]0001</PROCESS_NAME_001> |
|
447 iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameProcess, aIndex, &aProcessName, &KFmtNameProcess, aIndex ); |
|
448 |
|
449 // <CHUNK_NAME_001>Local-c812ba58</CHUNK_NAME_001> |
|
450 const TPtrC pChunkName( rHeapMetaData.ChunkName() ); |
|
451 iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameChunk, aIndex, &pChunkName, &KFmtNameChunk, aIndex ); |
|
452 |
|
453 // Fields |
|
454 iEngine.Sink().OutputLineFormattedL( KFmtFieldContent, |
|
455 &KFmtFields, |
|
456 aIndex, |
|
457 aInfo.Tid(), |
|
458 rHeapMetaData.ChunkHandle(), |
|
459 rHeapObjectData.Base(), |
|
460 rHeapObjectData.Size(), |
|
461 rHeapObjectData.iMinLength, |
|
462 rHeapObjectData.iMaxLength, |
|
463 rHeapObjectData.iFree.next, |
|
464 rHeapObjectData.iFree.len, |
|
465 rHeapStats.StatsFree().TypeCount(), |
|
466 rHeapStats.StatsFree().TypeSize(), |
|
467 rHeapStats.StatsFree().SlackSpaceCellSize(), |
|
468 rHeapStats.StatsFree().LargestCellSize(), |
|
469 rHeapStats.StatsAllocated().LargestCellSize(), |
|
470 rHeapObjectData.iCellCount, |
|
471 rHeapObjectData.iMinCell, |
|
472 rHeapObjectData.iTotalAllocSize, |
|
473 rHeapMetaData.IsSharedHeap(), |
|
474 &KFmtFields, |
|
475 aIndex |
|
476 ); |
|
477 |
|
478 // </ENTRY_001> |
|
479 iEngine.Sink().OutputLineFormattedL( KFmtEntryId, &KMemSpySinkTagClose, aIndex ); |
|
480 } |
|
481 |
|
482 |
|
483 |
|
484 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoForDeviceL( TBool aIncludeKernel ) |
|
485 { |
|
486 // NB: The goal here is to minimise the line length. We already look like we |
|
487 // could exceed the available RDebug::Print length... |
|
488 const TInt count = iEngine.Container().Count(); |
|
489 TInt index = 0; |
|
490 // |
|
491 HBufC* buf = HBufC::NewLC( 1024 ); |
|
492 TPtr pBuf(buf->Des()); |
|
493 // |
|
494 _LIT( KMemSpyFolder, "Heap\\Compact" ); |
|
495 _LIT( KMemSpyContext, "Heap Compact" ); |
|
496 _LIT( KMemSpyExtension, ".log" ); |
|
497 iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder, KMemSpyExtension ); |
|
498 |
|
499 // Start marker |
|
500 iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerCSV, &KNullDesC ); |
|
501 |
|
502 // Set overall prefix |
|
503 iEngine.Sink().OutputPrefixSetLC( KMemSpyPrefixCSV ); |
|
504 |
|
505 // Output version info |
|
506 _LIT( KVersionNumber, "<VERSION>1</VERSION>" ); |
|
507 iEngine.Sink().OutputLineL( KVersionNumber ); |
|
508 |
|
509 // Output time stamp |
|
510 _LIT( KTimeStamp, "<TIMESTAMP>%u</TIMESTAMP>" ); |
|
511 iEngine.Sink().OutputLineFormattedL( KTimeStamp, User::FastCounter() ); |
|
512 |
|
513 // Heap info we'll populate by calling the driver |
|
514 TMemSpyHeapInfo info; |
|
515 TFullName processName; |
|
516 |
|
517 if ( aIncludeKernel ) |
|
518 { |
|
519 // Get kernel heap info |
|
520 GetHeapInfoKernelL( info ); |
|
521 |
|
522 if ( info.Type() == TMemSpyHeapInfo::ETypeRHeap ) |
|
523 { |
|
524 TName threadName; |
|
525 MemSpyEngineUtils::GetKernelHeapThreadAndProcessNames( threadName, processName ); |
|
526 OutputCSVEntryL( index++, info, threadName, processName ); |
|
527 } |
|
528 } |
|
529 |
|
530 for(TInt ii=0; ii<count; ii++) |
|
531 { |
|
532 const CMemSpyProcess& process = iEngine.Container().At( ii ); |
|
533 process.FullName( processName ); |
|
534 // |
|
535 if ( iEngine.ProcessSuspendAndGetErrorLC( process.Id() ) == KErrNone ) |
|
536 { |
|
537 const TInt threadCount = process.Count(); |
|
538 // |
|
539 for(TInt j=0; j<threadCount; j++) |
|
540 { |
|
541 const CMemSpyThread& thread = process.At( j ); |
|
542 const TPtrC threadName( thread.Name() ); |
|
543 // |
|
544 const TInt error = iEngine.Driver().GetHeapInfoUser( info, thread.Id() ); |
|
545 if ( error == KErrNone ) |
|
546 { |
|
547 UpdateSharedHeapInfoL( process.Id(), thread.Id(), info ); |
|
548 } |
|
549 if ( error == KErrNone && info.Type() == TMemSpyHeapInfo::ETypeRHeap ) |
|
550 { |
|
551 OutputCSVEntryL( index++, info, threadName, processName ); |
|
552 } |
|
553 } |
|
554 |
|
555 CleanupStack::PopAndDestroy(); // ProcessSuspendLC |
|
556 } |
|
557 } |
|
558 |
|
559 CleanupStack::PopAndDestroy(); // clear prefix |
|
560 CleanupStack::PopAndDestroy( buf ); |
|
561 |
|
562 // End marker |
|
563 iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerCSV, &KMemSpySinkTagClose ); |
|
564 iEngine.Sink().DataStreamEndL(); |
|
565 } |
|
566 |
|
567 |
|
568 |
|
569 |
|
570 |
|
571 |
|
572 |
|
573 |
|
574 |
|
575 |
|
576 |
|
577 |
|
578 |
|
579 |
|
580 EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoUserL( const TProcessId& aProcess, const TThreadId& aThread, TMemSpyHeapInfo& aInfo, RArray<TMemSpyDriverFreeCell>* aFreeCells ) |
|
581 { |
|
582 iEngine.ProcessSuspendLC( aProcess ); |
|
583 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::GetHeapInfoUserL() - checksum1: 0x%08x", aInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); |
|
584 |
|
585 TInt r = KErrNone; |
|
586 // |
|
587 if ( aFreeCells ) |
|
588 { |
|
589 r = iEngine.Driver().GetHeapInfoUser( aInfo, aThread, *aFreeCells ); |
|
590 } |
|
591 else |
|
592 { |
|
593 r = iEngine.Driver().GetHeapInfoUser( aInfo, aThread ); |
|
594 } |
|
595 if ( !r ) |
|
596 { |
|
597 UpdateSharedHeapInfoL( aProcess, aThread, aInfo ); |
|
598 } |
|
599 |
|
600 // |
|
601 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::GetHeapInfoUserL() - checksum2: 0x%08x", aInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); |
|
602 CleanupStack::PopAndDestroy(); // ProcessSuspendLC |
|
603 User::LeaveIfError( r ); |
|
604 } |
|
605 |
|
606 |
|
607 EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoUserL( const CMemSpyProcess& aProcess, RArray<TMemSpyHeapInfo >& aInfos ) |
|
608 { |
|
609 aInfos.Reset(); |
|
610 iEngine.ProcessSuspendLC( aProcess.Id() ); |
|
611 // |
|
612 TMemSpyHeapInfo info; |
|
613 // |
|
614 const TInt count = aProcess.Count(); |
|
615 for( TInt i=0; i<count; i++ ) |
|
616 { |
|
617 const CMemSpyThread& thread = aProcess.At( i ); |
|
618 // |
|
619 GetHeapInfoUserL( aProcess.Id(), thread.Id(), info ); |
|
620 aInfos.AppendL( info ); |
|
621 } |
|
622 // |
|
623 CleanupStack::PopAndDestroy(); // ProcessSuspendLC |
|
624 } |
|
625 |
|
626 |
|
627 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoUserL( const CMemSpyThread& aThread ) |
|
628 { |
|
629 HBufC* threadName = aThread.FullName().AllocLC(); |
|
630 // |
|
631 RArray<TMemSpyDriverFreeCell> freeCells; |
|
632 CleanupClosePushL( freeCells ); |
|
633 // |
|
634 TMemSpyHeapInfo info; |
|
635 GetHeapInfoUserL( aThread.Process().Id(), aThread.Id(), info, &freeCells ); |
|
636 OutputHeapInfoL( info, *threadName, &freeCells ); |
|
637 // |
|
638 CleanupStack::PopAndDestroy( 2, threadName ); // freecells & thread name |
|
639 } |
|
640 |
|
641 |
|
642 |
|
643 |
|
644 |
|
645 |
|
646 |
|
647 |
|
648 |
|
649 |
|
650 |
|
651 |
|
652 |
|
653 |
|
654 |
|
655 |
|
656 |
|
657 EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoKernelL( TMemSpyHeapInfo& aInfo, RArray<TMemSpyDriverFreeCell>* aFreeCells ) |
|
658 { |
|
659 TInt error = KErrNone; |
|
660 // |
|
661 if ( aFreeCells ) |
|
662 { |
|
663 error = iEngine.Driver().GetHeapInfoKernel( aInfo, *aFreeCells ); |
|
664 } |
|
665 else |
|
666 { |
|
667 error = iEngine.Driver().GetHeapInfoKernel( aInfo ); |
|
668 } |
|
669 // |
|
670 User::LeaveIfError( error ); |
|
671 } |
|
672 |
|
673 |
|
674 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoKernelL() |
|
675 { |
|
676 // Get thread name |
|
677 TFullName threadName; |
|
678 MemSpyEngineUtils::GetKernelHeapThreadName( threadName ); |
|
679 |
|
680 // Free cells |
|
681 RArray<TMemSpyDriverFreeCell> freeCells; |
|
682 CleanupClosePushL( freeCells ); |
|
683 |
|
684 // Get info |
|
685 TMemSpyHeapInfo info; |
|
686 GetHeapInfoKernelL( info, &freeCells ); |
|
687 |
|
688 // Ouput |
|
689 OutputHeapInfoL( info, threadName, &freeCells ); |
|
690 |
|
691 CleanupStack::PopAndDestroy( &freeCells ); |
|
692 } |
|
693 |
|
694 |
|
695 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataKernelL() |
|
696 { |
|
697 OutputHeapDataKernelL( KMemSpyHeapDumpCreateOwnDataStream ); |
|
698 } |
|
699 |
|
700 |
|
701 void CMemSpyEngineHelperHeap::OutputHeapDataKernelL( TBool aCreateDataStream ) |
|
702 { |
|
703 // Get thread name |
|
704 TFullName threadName; |
|
705 MemSpyEngineUtils::GetKernelHeapThreadName( threadName, EFalse ); |
|
706 |
|
707 // Begin a new data stream |
|
708 if ( aCreateDataStream ) |
|
709 { |
|
710 _LIT( KMemSpyFolder, "Heap\\Data" ); |
|
711 _LIT( KMemSpyContext, "Heap Data - %S" ); |
|
712 HBufC* context = HBufC::NewLC( KMaxFileName ); |
|
713 TPtr pContext( context->Des() ); |
|
714 pContext.Format( KMemSpyContext, &threadName ); |
|
715 iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder ); |
|
716 CleanupStack::PopAndDestroy( context ); |
|
717 } |
|
718 |
|
719 RArray<TMemSpyDriverFreeCell> freeCells; |
|
720 CleanupClosePushL( freeCells ); |
|
721 |
|
722 // Get kernel data and heap info before outputting anything... |
|
723 TMemSpyHeapInfo info; |
|
724 HBufC8* data = iEngine.Driver().GetHeapDataKernelLC( info, freeCells ); |
|
725 |
|
726 // Start marker |
|
727 iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KNullDesC, info.Tid() ); |
|
728 |
|
729 // Set overall prefix |
|
730 iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixHeapData, &threadName ); |
|
731 |
|
732 // Info section |
|
733 OutputHeapInfoL( info, threadName, &freeCells ); |
|
734 |
|
735 // Dump section |
|
736 _LIT(KHeaderDump, "Heap Data"); |
|
737 iEngine.Sink().OutputSectionHeadingL( KHeaderDump, '-' ); |
|
738 |
|
739 _LIT(KHeapDumpDataFormat, "%S"); |
|
740 const TUint8* heapBaseAddress = info.AsRHeap().ObjectData().Base(); |
|
741 iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, data->Ptr(), heapBaseAddress, data->Length() ); |
|
742 |
|
743 CleanupStack::PopAndDestroy(); // clear prefix |
|
744 CleanupStack::PopAndDestroy( data ); |
|
745 CleanupStack::PopAndDestroy( &freeCells ); |
|
746 |
|
747 // End marker |
|
748 iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KMemSpySinkTagClose, info.Tid() ); |
|
749 |
|
750 if ( aCreateDataStream ) |
|
751 { |
|
752 iEngine.Sink().DataStreamEndL(); |
|
753 } |
|
754 } |
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 |
|
786 |
|
787 EXPORT_C CMemSpyEngineOutputList* CMemSpyEngineHelperHeap::NewHeapSummaryShortLC( const TMemSpyHeapInfo& aInfo ) |
|
788 { |
|
789 CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() ); |
|
790 |
|
791 // Heap type |
|
792 _LIT( KItem0, "Heap type" ); |
|
793 if ( aInfo.Type() == TMemSpyHeapInfo::ETypeUnknown ) |
|
794 { |
|
795 _LIT( KItem0_Type_Unknown, "Unknown" ); |
|
796 list->AddItemL( KItem0, KItem0_Type_Unknown ); |
|
797 } |
|
798 else if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap ) |
|
799 { |
|
800 const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); |
|
801 const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData(); |
|
802 const TMemSpyHeapObjectDataRHeap& objectData = rHeap.ObjectData(); |
|
803 const TMemSpyHeapStatisticsRHeap& statistics = rHeap.Statistics(); |
|
804 |
|
805 _LIT( KItem0_Type_RHeap, "RHeap" ); |
|
806 list->AddItemL( KItem0, KItem0_Type_RHeap ); |
|
807 |
|
808 // Heap size is the size of the heap minus the size of the embedded (in-place) RHeap. |
|
809 _LIT( KItem1, "Heap size" ); |
|
810 list->AddItemL( KItem1, objectData.Size() ); |
|
811 |
|
812 _LIT( KItem8b, "Heap base address" ); |
|
813 list->AddItemHexL( KItem8b, (TUint) objectData.Base() ); |
|
814 |
|
815 _LIT( KItem1b, "Shared" ); |
|
816 list->AddItemYesNoL( KItem1b, metaData.IsSharedHeap() ); |
|
817 |
|
818 // This is the size (rounded to the page) of memory associated with |
|
819 // the underlying heap chunk |
|
820 _LIT( KItem2, "Chunk size" ); |
|
821 list->AddItemL( KItem2, metaData.ChunkSize() ); |
|
822 |
|
823 _LIT( KItem3, "Alloc. count" ); |
|
824 list->AddItemL( KItem3, statistics.StatsAllocated().TypeCount() ); |
|
825 |
|
826 _LIT( KItem4, "Free. count" ); |
|
827 list->AddItemL( KItem4, statistics.StatsFree().TypeCount() ); |
|
828 |
|
829 _LIT( KItem5, "Biggest alloc." ); |
|
830 list->AddItemL( KItem5, statistics.StatsAllocated().LargestCellSize() ); |
|
831 |
|
832 _LIT( KItem6, "Biggest free" ); |
|
833 list->AddItemL( KItem6, statistics.StatsFree().LargestCellSize() ); |
|
834 |
|
835 _LIT( KItem6a, "Total alloc." ); |
|
836 list->AddItemL( KItem6a, statistics.StatsAllocated().TypeSize() ); |
|
837 |
|
838 _LIT( KItem6b, "Total free" ); |
|
839 list->AddItemL( KItem6b, statistics.StatsFree().TypeSize() ); |
|
840 |
|
841 // Slack is the free space at the end of the heap |
|
842 _LIT( KItem7, "Slack free space" ); |
|
843 list->AddItemL( KItem7, statistics.StatsFree().SlackSpaceCellSize() ); |
|
844 |
|
845 // Fragmentation is a measurement of free space scattered throughout the heap, but ignoring |
|
846 // any slack space at the end (which can often be recovered, to the granularity of one page of ram) |
|
847 _LIT( KItem8a, "Fragmentation" ); |
|
848 list->AddItemPercentageL( KItem8a, objectData.Size(), ( statistics.StatsFree().TypeSize() - statistics.StatsFree().SlackSpaceCellSize() ) ); |
|
849 |
|
850 _LIT( KItem13, "Header size (A)" ); |
|
851 list->AddItemL( KItem13, metaData.HeaderSizeAllocated() ); |
|
852 |
|
853 _LIT( KItem14, "Header size (F)" ); |
|
854 list->AddItemL( KItem14, metaData.HeaderSizeFree() ); |
|
855 |
|
856 _LIT( KItem9a, "Overhead (alloc)" ); |
|
857 const TInt allocOverhead = metaData.HeaderSizeAllocated() * statistics.StatsAllocated().TypeCount(); |
|
858 list->AddItemL( KItem9a, allocOverhead ); |
|
859 |
|
860 _LIT( KItem9b, "Overhead (free)" ); |
|
861 const TInt freeOverhead = metaData.HeaderSizeFree() * statistics.StatsFree().TypeCount(); |
|
862 list->AddItemL( KItem9b, freeOverhead ); |
|
863 |
|
864 _LIT( KItem9c, "Overhead (total)" ); |
|
865 const TInt totalOverhead = freeOverhead + allocOverhead; |
|
866 list->AddItemL( KItem9c, totalOverhead ); |
|
867 |
|
868 _LIT( KItem9d, "Overhead" ); |
|
869 list->AddItemPercentageL( KItem9d, objectData.Size(), totalOverhead ); |
|
870 |
|
871 _LIT( KItem10, "Min. length" ); |
|
872 list->AddItemL( KItem10, objectData.iMinLength ); |
|
873 |
|
874 _LIT( KItem11, "Max. length" ); |
|
875 list->AddItemL( KItem11, objectData.iMaxLength ); |
|
876 |
|
877 _LIT( KItem12, "Debug Allocator Library" ); |
|
878 list->AddItemYesNoL( KItem12, metaData.IsDebugAllocator() ); |
|
879 } |
|
880 |
|
881 return list; |
|
882 } |
|
883 |
|
884 |
|
885 EXPORT_C CMemSpyEngineOutputList* CMemSpyEngineHelperHeap::NewHeapSummaryExtendedLC( const TMemSpyHeapInfo& aInfo, const RArray<TMemSpyDriverFreeCell>* aFreeCells ) |
|
886 { |
|
887 CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() ); |
|
888 // |
|
889 AppendMetaDataL( aInfo, *list ); |
|
890 AppendObjectDataL( aInfo, *list ); |
|
891 AppendStatisticsL( aInfo, *list ); |
|
892 // |
|
893 if ( aFreeCells ) |
|
894 { |
|
895 AppendFreeCellsL( *aFreeCells, *list ); |
|
896 } |
|
897 // |
|
898 return list; |
|
899 } |
|
900 |
|
901 |
|
902 |
|
903 |
|
904 |
|
905 |
|
906 |
|
907 |
|
908 |
|
909 |
|
910 |
|
911 |
|
912 |
|
913 |
|
914 |
|
915 |
|
916 |
|
917 |
|
918 |
|
919 |
|
920 |
|
921 |
|
922 |
|
923 |
|
924 |
|
925 |
|
926 |
|
927 |
|
928 |
|
929 |
|
930 |
|
931 |
|
932 |
|
933 TUint CMemSpyEngineHelperHeap::DescriptorAsDWORD( const TDesC8& aItem) |
|
934 { |
|
935 __ASSERT_ALWAYS( aItem.Length() >= 4, User::Invariant() ); |
|
936 const TUint ret = aItem[0] + |
|
937 (aItem[1] << 8) + |
|
938 (aItem[2] << 16) + |
|
939 (aItem[3] << 24); |
|
940 return ret; |
|
941 } |
|
942 |
|
943 |
|
944 void CMemSpyEngineHelperHeap::AppendMetaDataL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList ) |
|
945 { |
|
946 const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); |
|
947 |
|
948 // Make caption |
|
949 _LIT( KOverallCaption1, "Meta Data" ); |
|
950 aList.AddItemL( KOverallCaption1 ); |
|
951 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
952 |
|
953 // Type |
|
954 _LIT( KMetaData_Type, "Type:" ); |
|
955 if ( aInfo.Type() != TMemSpyHeapInfo::ETypeRHeap ) |
|
956 { |
|
957 _LIT( KMetaData_Type_Unknown, "Unknown" ); |
|
958 aList.AddItemL( KMetaData_Type, KMetaData_Type_Unknown ); |
|
959 } |
|
960 else |
|
961 { |
|
962 const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData(); |
|
963 |
|
964 // Type |
|
965 _LIT( KMetaData_Type_RHeap, "Symbian OS RHeap" ); |
|
966 aList.AddItemL( KMetaData_Type, KMetaData_Type_RHeap ); |
|
967 |
|
968 // VTable |
|
969 _LIT( KMetaData_VTable, "VTable:" ); |
|
970 aList.AddItemHexL( KMetaData_VTable, metaData.VTable() ); |
|
971 |
|
972 // Object size |
|
973 _LIT( KMetaData_ObjectSize, "Object Size:" ); |
|
974 aList.AddItemL( KMetaData_ObjectSize, metaData.ClassSize() ); |
|
975 |
|
976 // Chunk name |
|
977 _LIT( KMetaData_ChunkName, "Chunk Name:" ); |
|
978 TPtrC pChunkName( metaData.ChunkName() ); |
|
979 aList.AddItemL( KMetaData_ChunkName, pChunkName ); |
|
980 |
|
981 // Chunk size |
|
982 _LIT( KMetaData_ChunkSize, "Chunk Size:" ); |
|
983 aList.AddItemL( KMetaData_ChunkSize, metaData.ChunkSize() ); |
|
984 |
|
985 // Chunk base address |
|
986 _LIT( KMetaData_ChunkBaseAddress, "Chunk Base Address:" ); |
|
987 aList.AddItemL( KMetaData_ChunkBaseAddress, metaData.ChunkBaseAddress() ); |
|
988 |
|
989 // Debug allocator |
|
990 _LIT( KMetaData_DebugAllocator, "Debug Allocator:" ); |
|
991 aList.AddItemYesNoL( KMetaData_DebugAllocator, metaData.IsDebugAllocator() ); |
|
992 |
|
993 // Cell header overhead (free cells) |
|
994 _LIT( KMetaData_CellHeaderOverheadFree, "Overhead (Free):" ); |
|
995 aList.AddItemL( KMetaData_CellHeaderOverheadFree, metaData.HeaderSizeFree() ); |
|
996 |
|
997 // Cell header overhead (allocated cells) |
|
998 _LIT( KMetaData_CellHeaderOverheadAlloc, "Overhead (Alloc):" ); |
|
999 aList.AddItemL( KMetaData_CellHeaderOverheadAlloc, metaData.HeaderSizeAllocated() ); |
|
1000 |
|
1001 // Shared Heap |
|
1002 _LIT( KMetaData_Shared, "Shared:" ); |
|
1003 aList.AddItemYesNoL( KMetaData_Shared, metaData.IsSharedHeap() ); |
|
1004 |
|
1005 // Add ROM info |
|
1006 iEngine.HelperROM().AddInfoL( aList ); |
|
1007 } |
|
1008 |
|
1009 aList.AddBlankItemL( 1 ); |
|
1010 } |
|
1011 |
|
1012 |
|
1013 void CMemSpyEngineHelperHeap::AppendObjectDataL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList ) |
|
1014 { |
|
1015 if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap ) |
|
1016 { |
|
1017 const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); |
|
1018 const TMemSpyHeapObjectDataRHeap& objectData = rHeap.ObjectData(); |
|
1019 |
|
1020 // Make caption |
|
1021 _LIT( KOverallCaption1, "RAllocator" ); |
|
1022 aList.AddItemL( KOverallCaption1 ); |
|
1023 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
1024 |
|
1025 // RAllocator |
|
1026 _LIT( KObjectData_RAllocator_iAccessCount, "RAllocator::iAccessCount" ); |
|
1027 aList.AddItemL( KObjectData_RAllocator_iAccessCount, objectData.iAccessCount ); |
|
1028 _LIT( KObjectData_RAllocator_iHandleCount, "RAllocator::iHandleCount" ); |
|
1029 aList.AddItemL( KObjectData_RAllocator_iHandleCount, objectData.iHandleCount ); |
|
1030 _LIT( KObjectData_RAllocator_iHandles, "RAllocator::iHandles" ); |
|
1031 aList.AddItemL( KObjectData_RAllocator_iHandles, objectData.iHandles ); |
|
1032 _LIT( KObjectData_RAllocator_iFlags, "RAllocator::iFlags" ); |
|
1033 aList.AddItemHexL( KObjectData_RAllocator_iFlags, objectData.iFlags ); |
|
1034 _LIT( KObjectData_RAllocator_iCellCount, "RAllocator::iCellCount" ); |
|
1035 aList.AddItemL( KObjectData_RAllocator_iCellCount, objectData.iCellCount ); |
|
1036 _LIT( KObjectData_RAllocator_iTotalAllocSize, "RAllocator::iTotalAllocSize" ); |
|
1037 aList.AddItemL( KObjectData_RAllocator_iTotalAllocSize, objectData.iTotalAllocSize ); |
|
1038 |
|
1039 aList.AddBlankItemL( 1 ); |
|
1040 |
|
1041 // Make caption |
|
1042 _LIT( KOverallCaption2, "RHeap" ); |
|
1043 aList.AddItemL( KOverallCaption2 ); |
|
1044 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
1045 |
|
1046 // RHeap |
|
1047 _LIT( KObjectData_RHeap_iMinLength, "RHeap::iMinLength" ); |
|
1048 aList.AddItemL( KObjectData_RHeap_iMinLength, objectData.iMinLength ); |
|
1049 _LIT( KObjectData_RHeap_iMaxLength, "RHeap::iMaxLength" ); |
|
1050 aList.AddItemL( KObjectData_RHeap_iMaxLength, objectData.iMaxLength ); |
|
1051 _LIT( KObjectData_RHeap_iOffset, "RHeap::iOffset" ); |
|
1052 aList.AddItemL( KObjectData_RHeap_iOffset, objectData.iOffset ); |
|
1053 _LIT( KObjectData_RHeap_iGrowBy, "RHeap::iGrowBy" ); |
|
1054 aList.AddItemL( KObjectData_RHeap_iGrowBy, objectData.iGrowBy ); |
|
1055 _LIT( KObjectData_RHeap_iChunkHandle, "RHeap::iChunkHandle" ); |
|
1056 aList.AddItemHexL( KObjectData_RHeap_iChunkHandle, objectData.iChunkHandle ); |
|
1057 _LIT( KObjectData_RHeap_iBase, "RHeap::iBase" ); |
|
1058 aList.AddItemL( KObjectData_RHeap_iBase, objectData.iBase ); |
|
1059 _LIT( KObjectData_RHeap_iTop, "RHeap::iTop" ); |
|
1060 aList.AddItemL( KObjectData_RHeap_iTop, objectData.iTop ); |
|
1061 _LIT( KObjectData_RHeap_iAlign, "RHeap::iAlign" ); |
|
1062 aList.AddItemL( KObjectData_RHeap_iAlign, objectData.iAlign ); |
|
1063 _LIT( KObjectData_RHeap_iMinCell, "RHeap::iMinCell" ); |
|
1064 aList.AddItemL( KObjectData_RHeap_iMinCell, objectData.iMinCell ); |
|
1065 _LIT( KObjectData_RHeap_iPageSize, "RHeap::iPageSize" ); |
|
1066 aList.AddItemL( KObjectData_RHeap_iPageSize, objectData.iPageSize ); |
|
1067 _LIT( KObjectData_RHeap_iFree_next, "RHeap::iFree.next" ); |
|
1068 aList.AddItemL( KObjectData_RHeap_iFree_next, objectData.iFree.next ); |
|
1069 _LIT( KObjectData_RHeap_iFree_len, "RHeap::iFree.len" ); |
|
1070 aList.AddItemL( KObjectData_RHeap_iFree_len, objectData.iFree.len ); |
|
1071 _LIT( KObjectData_RHeap_iNestingLevel, "RHeap::iNestingLevel" ); |
|
1072 aList.AddItemL( KObjectData_RHeap_iNestingLevel, objectData.iNestingLevel ); |
|
1073 _LIT( KObjectData_RHeap_iAllocCount, "RHeap::iAllocCount" ); |
|
1074 aList.AddItemL( KObjectData_RHeap_iAllocCount, objectData.iAllocCount ); |
|
1075 _LIT( KObjectData_RHeap_iFailType, "RHeap::iFailType" ); |
|
1076 aList.AddItemL( KObjectData_RHeap_iFailType, (TInt) objectData.iFailType ); |
|
1077 _LIT( KObjectData_RHeap_iFailRate, "RHeap::iFailRate" ); |
|
1078 aList.AddItemL( KObjectData_RHeap_iFailRate, objectData.iFailRate ); |
|
1079 _LIT( KObjectData_RHeap_iFailed, "RHeap::iFailed" ); |
|
1080 aList.AddItemTrueFalseL( KObjectData_RHeap_iFailed, objectData.iFailed ); |
|
1081 _LIT( KObjectData_RHeap_iFailAllocCount, "RHeap::iFailAllocCount" ); |
|
1082 aList.AddItemL( KObjectData_RHeap_iFailAllocCount, objectData.iFailAllocCount ); |
|
1083 _LIT( KObjectData_RHeap_iRand, "RHeap::iRand" ); |
|
1084 aList.AddItemL( KObjectData_RHeap_iRand, objectData.iRand ); |
|
1085 _LIT( KObjectData_RHeap_iTestData, "RHeap::iTestData" ); |
|
1086 aList.AddItemL( KObjectData_RHeap_iTestData, objectData.iTestData ); |
|
1087 |
|
1088 aList.AddBlankItemL( 1 ); |
|
1089 } |
|
1090 } |
|
1091 |
|
1092 |
|
1093 void CMemSpyEngineHelperHeap::AppendStatisticsL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList ) |
|
1094 { |
|
1095 if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap ) |
|
1096 { |
|
1097 const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); |
|
1098 const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeap.Statistics(); |
|
1099 |
|
1100 // Shared captions |
|
1101 _LIT( KStatsData_CellCount, "Number of cells:" ); |
|
1102 _LIT( KStatsData_CellSize, "Size of cells:" ); |
|
1103 _LIT( KStatsData_LargestCellAddress, "Largest cell:" ); |
|
1104 _LIT( KStatsData_LargestCellSize, "Largest cell size:" ); |
|
1105 |
|
1106 // Free space |
|
1107 _LIT( KOverallCaption1, "Free Cell Statistics" ); |
|
1108 aList.AddItemL( KOverallCaption1 ); |
|
1109 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
1110 |
|
1111 aList.AddItemL( KStatsData_CellCount, rHeapStats.StatsFree().TypeCount() ); |
|
1112 aList.AddItemL( KStatsData_CellSize, rHeapStats.StatsFree().TypeSize() ); |
|
1113 aList.AddItemL( KStatsData_LargestCellAddress, rHeapStats.StatsFree().LargestCellAddress() ); |
|
1114 aList.AddItemL( KStatsData_LargestCellSize, rHeapStats.StatsFree().LargestCellSize() ); |
|
1115 _LIT( KStatsData_Free_SlackCellAddress, "Slack:" ); |
|
1116 aList.AddItemL( KStatsData_Free_SlackCellAddress, rHeapStats.StatsFree().SlackSpaceCellAddress() ); |
|
1117 _LIT( KStatsData_Free_SlackCellSize, "Slack size:" ); |
|
1118 aList.AddItemL( KStatsData_Free_SlackCellSize, rHeapStats.StatsFree().SlackSpaceCellSize() ); |
|
1119 _LIT( KStatsData_Free_Checksum, "Checksum:" ); |
|
1120 aList.AddItemHexL( KStatsData_Free_Checksum, rHeapStats.StatsFree().Checksum() ); |
|
1121 |
|
1122 aList.AddBlankItemL( 1 ); |
|
1123 |
|
1124 // Allocated space |
|
1125 _LIT( KOverallCaption2, "Allocated Cell Statistics" ); |
|
1126 aList.AddItemL( KOverallCaption2 ); |
|
1127 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
1128 |
|
1129 aList.AddItemL( KStatsData_CellCount, rHeapStats.StatsAllocated().TypeCount() ); |
|
1130 aList.AddItemL( KStatsData_CellSize, rHeapStats.StatsAllocated().TypeSize() ); |
|
1131 aList.AddItemL( KStatsData_LargestCellAddress, rHeapStats.StatsAllocated().LargestCellAddress() ); |
|
1132 aList.AddItemL( KStatsData_LargestCellSize, rHeapStats.StatsAllocated().LargestCellSize() ); |
|
1133 |
|
1134 aList.AddBlankItemL( 1 ); |
|
1135 |
|
1136 // Common |
|
1137 _LIT( KOverallCaption3, "Common Statistics" ); |
|
1138 aList.AddItemL( KOverallCaption3 ); |
|
1139 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
1140 |
|
1141 _LIT( KStatsData_Common_TotalCellCount, "Total cell count:" ); |
|
1142 aList.AddItemL( KStatsData_Common_TotalCellCount, rHeapStats.StatsCommon().TotalCellCount() ); |
|
1143 |
|
1144 _LIT( KStatsData_Common_TotalSize, "Total cell size:" ); |
|
1145 aList.AddItemL( KStatsData_Common_TotalSize, rHeapStats.StatsAllocated().TypeSize() + rHeapStats.StatsFree().TypeSize() ); |
|
1146 |
|
1147 aList.AddBlankItemL( 1 ); |
|
1148 } |
|
1149 } |
|
1150 |
|
1151 |
|
1152 void CMemSpyEngineHelperHeap::AppendFreeCellsL( const RArray<TMemSpyDriverFreeCell>& aFreeCells, CMemSpyEngineOutputList& aList ) |
|
1153 { |
|
1154 // Free space |
|
1155 _LIT( KOverallCaption1, "Free Cell List" ); |
|
1156 aList.AddItemL( KOverallCaption1 ); |
|
1157 aList.AddUnderlineForPreviousItemL( '=', 0 ); |
|
1158 |
|
1159 TBuf<128> caption; |
|
1160 _LIT( KCaptionFormat, "FC %04d" ); |
|
1161 _LIT( KValueFormat, "0x%08x %8d %1d" ); |
|
1162 |
|
1163 const TInt count = aFreeCells.Count(); |
|
1164 for( TInt i=0; i<count; i++ ) |
|
1165 { |
|
1166 const TMemSpyDriverFreeCell& cell = aFreeCells[ i ]; |
|
1167 caption.Format( KCaptionFormat, i + 1 ); |
|
1168 aList.AddItemFormatL( caption, KValueFormat, cell.iAddress, cell.iLength, cell.iType ); |
|
1169 } |
|
1170 } |
|
1171 |
|
1172 |
|
1173 void CMemSpyEngineHelperHeap::UpdateSharedHeapInfoL( const TProcessId& aProcess, const TThreadId& aThread, TMemSpyHeapInfo& aInfo ) |
|
1174 { |
|
1175 RArray<TThreadId> threads; |
|
1176 CleanupClosePushL( threads ); |
|
1177 iEngine.Driver().GetThreadsL( aProcess, threads ); |
|
1178 TMemSpyHeapInfo otherHeap; |
|
1179 TThreadId otherThreadId; |
|
1180 TInt r( KErrNone ); |
|
1181 for ( TInt i = 0; i < threads.Count(); i++ ) |
|
1182 { |
|
1183 otherThreadId = threads[i]; |
|
1184 if ( aThread != otherThreadId ) // skip current thread |
|
1185 { |
|
1186 r = iEngine.Driver().GetHeapInfoUser( otherHeap, otherThreadId ); |
|
1187 if ( !r && otherHeap.AsRHeap().MetaData().ChunkHandle() == aInfo.AsRHeap().MetaData().ChunkHandle() ) |
|
1188 { |
|
1189 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::UpdateSharedHeapInfoL - shared heap detected chunkhandle: 0x%08x", aInfo.AsRHeap().MetaData().ChunkHandle() ) ); |
|
1190 aInfo.AsRHeap().MetaData().SetSharedHeap( ETrue ); |
|
1191 break; |
|
1192 } |
|
1193 } |
|
1194 } |
|
1195 CleanupStack::PopAndDestroy( &threads ); |
|
1196 } |
|
1197 |