|
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 "MemSpyDriverLogChanChunks.h" |
|
19 |
|
20 // System includes |
|
21 #include <memspy/driver/memspydriverobjectsshared.h> |
|
22 |
|
23 // Shared includes |
|
24 #include "MemSpyDriverOpCodes.h" |
|
25 #include "MemSpyDriverObjectsInternal.h" |
|
26 |
|
27 // User includes |
|
28 #include "MemSpyDriverUtils.h" |
|
29 #include "MemSpyDriverDevice.h" |
|
30 #include "MemSpyDriverOSAdaption.h" |
|
31 |
|
32 // Constants |
|
33 _LIT8( KMemSpyLitDllDollarData, "DLL$DATA" ); |
|
34 _LIT8( KMemSpyLitDollarDat, "$DAT" ); |
|
35 _LIT8( KMemSpyLitDollarCode, "$CODE" ); |
|
36 _LIT8( KMemSpyLitDollarGlobalCode, "GLOBAL$CODE" ); |
|
37 _LIT8( KMemSpyLitLocalObject, "Local-" ); |
|
38 |
|
39 |
|
40 DMemSpyDriverLogChanChunks::DMemSpyDriverLogChanChunks( DMemSpyDriverDevice& aDevice, DThread& aThread ) |
|
41 : DMemSpyDriverLogChanBase( aDevice, aThread ) |
|
42 { |
|
43 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DMemSpyDriverLogChanChunks() - this: 0x%08x", this )); |
|
44 } |
|
45 |
|
46 |
|
47 DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() |
|
48 { |
|
49 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - START - this: 0x%08x", this )); |
|
50 |
|
51 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - END - this: 0x%08x", this )); |
|
52 } |
|
53 |
|
54 |
|
55 |
|
56 TInt DMemSpyDriverLogChanChunks::Request( TInt aFunction, TAny* a1, TAny* a2 ) |
|
57 { |
|
58 TInt r = DMemSpyDriverLogChanBase::Request( aFunction, a1, a2 ); |
|
59 if ( r == KErrNone ) |
|
60 { |
|
61 switch( aFunction ) |
|
62 { |
|
63 case EMemSpyDriverOpCodeChunkGetHandles: |
|
64 r = GetChunkHandles( (TMemSpyDriverInternalChunkHandleParams*) a1 ); |
|
65 break; |
|
66 case EMemSpyDriverOpCodeChunkGetInfo: |
|
67 r = GetChunkInfo( (TMemSpyDriverInternalChunkInfoParams*) a1 ); |
|
68 break; |
|
69 |
|
70 default: |
|
71 r = KErrNotSupported; |
|
72 break; |
|
73 } |
|
74 } |
|
75 // |
|
76 return r; |
|
77 } |
|
78 |
|
79 |
|
80 TBool DMemSpyDriverLogChanChunks::IsHandler( TInt aFunction ) const |
|
81 { |
|
82 return ( aFunction > EMemSpyDriverOpCodeChunkBase && aFunction < EMemSpyDriverOpCodeChunkEnd ); |
|
83 } |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 TInt DMemSpyDriverLogChanChunks::GetChunkHandles( TMemSpyDriverInternalChunkHandleParams* aParams ) |
|
105 { |
|
106 TMemSpyDriverInternalChunkHandleParams params; |
|
107 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkHandleParams) ); |
|
108 if ( r != KErrNone ) |
|
109 { |
|
110 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - params read error: %d", r)); |
|
111 return r; |
|
112 } |
|
113 |
|
114 const TInt maxCount = params.iMaxCount; |
|
115 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - START - id: %d, maxCount: %d, type: %d", params.iId, maxCount, params.iType)); |
|
116 |
|
117 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
118 DMemSpyDriverOSAdaptionDThread& threadAdaption = OSAdaption().DThread(); |
|
119 DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); |
|
120 |
|
121 |
|
122 // This variable holds the number of handles that we have already |
|
123 // written to the client-side. |
|
124 TInt currentWriteIndex = 0; |
|
125 |
|
126 if ( params.iType == EMemSpyDriverPrivateObjectTypeProcess || params.iType == EMemSpyDriverPrivateObjectTypeThread ) |
|
127 { |
|
128 if ( params.iType == EMemSpyDriverPrivateObjectTypeThread ) |
|
129 { |
|
130 r = OpenTempObject( params.iId, EThread ); |
|
131 if ( r == KErrNone ) |
|
132 { |
|
133 // Open the owning process instead, so that we can see which chunks are mapped |
|
134 // into the thread. |
|
135 DThread* thread = (DThread*) TempObject(); |
|
136 DProcess* process = threadAdaption.GetOwningProcess( *thread ); |
|
137 if ( process ) |
|
138 { |
|
139 const TUint parentProcessId = processAdaption.GetId( *process ); |
|
140 CloseTempObject(); |
|
141 r = OpenTempObject( parentProcessId, EProcess ); |
|
142 } |
|
143 else |
|
144 { |
|
145 CloseTempObject(); |
|
146 r = KErrNotFound; |
|
147 } |
|
148 } |
|
149 } |
|
150 else |
|
151 { |
|
152 r = OpenTempObject( params.iId, EProcess ); |
|
153 } |
|
154 |
|
155 // Handle error opening correct process |
|
156 if (r != KErrNone) |
|
157 { |
|
158 Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - parent process not found"); |
|
159 return r; |
|
160 } |
|
161 |
|
162 DProcess* process = (DProcess*) TempObject(); |
|
163 NKern::ThreadEnterCS(); |
|
164 |
|
165 // Iterate through each handle in the process |
|
166 MemSpyObjectIx* processHandles = processAdaption.GetHandles( *process ); |
|
167 MemSpyObjectIx_Wait( processHandles ); |
|
168 |
|
169 const TInt processHandleCount = processHandles->Count(); |
|
170 for( TInt processHandleIndex = 0; processHandleIndex<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ ) |
|
171 { |
|
172 // Get a handle from the process container... |
|
173 NKern::LockSystem(); |
|
174 DObject* object = (*processHandles)[ processHandleIndex ]; |
|
175 NKern::UnlockSystem(); |
|
176 |
|
177 if ( object ) |
|
178 { |
|
179 const TObjectType objectType = processAdaption.GetObjectType( *object ); |
|
180 if ( objectType == EChunk ) |
|
181 { |
|
182 DChunk* chunk = (DChunk*) object; |
|
183 TAny* handle = (TAny*) chunk; |
|
184 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) ); |
|
185 if ( r == KErrNone ) |
|
186 { |
|
187 ++currentWriteIndex; |
|
188 } |
|
189 } |
|
190 } |
|
191 } |
|
192 |
|
193 MemSpyObjectIx_Signal( processHandles ); |
|
194 |
|
195 // If we were asked for process-related chunks, also check the chunk container |
|
196 // for entries which we don't have handles to, but do refer to our process |
|
197 // Need a listing of all chunks in the system. Let client filter duplicates. |
|
198 DObjectCon* container = Kern::Containers()[ EChunk ]; |
|
199 container->Wait(); |
|
200 // |
|
201 const TInt count = container->Count(); |
|
202 for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ ) |
|
203 { |
|
204 DChunk* chunk= (DChunk*) (*container)[ i ]; |
|
205 // |
|
206 const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() ); |
|
207 if ( isRelated ) |
|
208 { |
|
209 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) ); |
|
210 if ( r == KErrNone ) |
|
211 { |
|
212 ++currentWriteIndex; |
|
213 } |
|
214 } |
|
215 } |
|
216 // |
|
217 container->Signal(); |
|
218 NKern::ThreadLeaveCS(); |
|
219 |
|
220 CloseTempObject(); |
|
221 } |
|
222 else |
|
223 { |
|
224 // Need a listing of all chunks in the system. Let client filter duplicates. |
|
225 DObjectCon* container = Kern::Containers()[ EChunk ]; |
|
226 NKern::ThreadEnterCS(); |
|
227 container->Wait(); |
|
228 // |
|
229 const TInt count = container->Count(); |
|
230 for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ ) |
|
231 { |
|
232 DChunk* chunk= (DChunk*) (*container)[ i ]; |
|
233 // |
|
234 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) ); |
|
235 if (r == KErrNone) |
|
236 { |
|
237 ++currentWriteIndex; |
|
238 } |
|
239 } |
|
240 // |
|
241 container->Signal(); |
|
242 NKern::ThreadLeaveCS(); |
|
243 } |
|
244 |
|
245 if ( r == KErrBadDescriptor ) |
|
246 { |
|
247 MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); |
|
248 } |
|
249 else |
|
250 { |
|
251 const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, ¤tWriteIndex, sizeof(TInt) ); |
|
252 if ( r == KErrNone ) |
|
253 { |
|
254 r = finalWrite; |
|
255 } |
|
256 } |
|
257 |
|
258 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r)); |
|
259 return r; |
|
260 } |
|
261 |
|
262 |
|
263 TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams ) |
|
264 { |
|
265 TMemSpyDriverInternalChunkInfoParams params; |
|
266 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); |
|
267 if ( r != KErrNone ) |
|
268 { |
|
269 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r)); |
|
270 return r; |
|
271 } |
|
272 |
|
273 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle)); |
|
274 |
|
275 DObjectCon* container = Kern::Containers()[EChunk]; |
|
276 NKern::ThreadEnterCS(); |
|
277 |
|
278 container->Wait(); |
|
279 NKern::LockSystem(); |
|
280 const TInt count = container->Count(); |
|
281 NKern::UnlockSystem(); |
|
282 |
|
283 DChunk* foundChunk = NULL; |
|
284 |
|
285 for(TInt i=0; i<count; i++) |
|
286 { |
|
287 NKern::LockSystem(); |
|
288 DChunk* chunk = (DChunk*) (*container)[i]; |
|
289 NKern::UnlockSystem(); |
|
290 // |
|
291 if ( chunk == params.iHandle ) |
|
292 { |
|
293 foundChunk = chunk; |
|
294 TRACE( PrintChunkInfo( *chunk ) ); |
|
295 break; |
|
296 } |
|
297 } |
|
298 |
|
299 container->Signal(); |
|
300 NKern::ThreadLeaveCS(); |
|
301 |
|
302 if ( foundChunk == NULL ) |
|
303 { |
|
304 Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk"); |
|
305 return KErrNotFound; |
|
306 } |
|
307 |
|
308 // Prepare return data |
|
309 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
310 // |
|
311 params.iBaseAddress = chunkAdaption.GetBase( *foundChunk ); |
|
312 params.iSize = chunkAdaption.GetSize( *foundChunk ); |
|
313 params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk ); |
|
314 foundChunk->FullName( params.iName ); |
|
315 |
|
316 // Mirror the process memory tracker |
|
317 DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk ); |
|
318 if ( owner ) |
|
319 { |
|
320 params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); |
|
321 } |
|
322 else |
|
323 { |
|
324 owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) ); |
|
325 if ( owner ) |
|
326 { |
|
327 params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); |
|
328 } |
|
329 else |
|
330 { |
|
331 params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk ); |
|
332 } |
|
333 } |
|
334 |
|
335 // Get type & attribs |
|
336 params.iType = IdentifyChunkType( *foundChunk ); |
|
337 params.iAttributes = chunkAdaption.GetAttributes( *foundChunk ); |
|
338 |
|
339 // Write back to client |
|
340 r = Kern::ThreadRawWrite( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); |
|
341 if ( r == KErrBadDescriptor ) |
|
342 { |
|
343 MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); |
|
344 } |
|
345 |
|
346 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r )); |
|
347 return r; |
|
348 } |
|
349 |
|
350 |
|
351 void DMemSpyDriverLogChanChunks::PrintChunkInfo( DChunk& aChunk ) |
|
352 { |
|
353 MemSpyDriverUtils::PrintChunkInfo( aChunk, OSAdaption() ); |
|
354 } |
|
355 |
|
356 |
|
357 TMemSpyDriverChunkType DMemSpyDriverLogChanChunks::IdentifyChunkType( DChunk& aChunk ) |
|
358 { |
|
359 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - START" ) ); |
|
360 |
|
361 TMemSpyDriverChunkType ret = EMemSpyDriverChunkTypeUnknown; |
|
362 |
|
363 TName name; |
|
364 aChunk.Name( name ); |
|
365 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - name: %S", &name ) ); |
|
366 |
|
367 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
368 const TChunkType type = chunkAdaption.GetType( aChunk ); |
|
369 |
|
370 if ( name == KMemSpyLitDllDollarData ) |
|
371 { |
|
372 // This chunk contains Dll Global Data for the process |
|
373 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobalData" ) ); |
|
374 ret = EMemSpyDriverChunkTypeGlobalData; |
|
375 } |
|
376 else if ( type == ERamDrive ) |
|
377 { |
|
378 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeRamDrive" ) ); |
|
379 ret = EMemSpyDriverChunkTypeRamDrive; |
|
380 } |
|
381 else if ( type == EKernelStack ) |
|
382 { |
|
383 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackKernel" ) ); |
|
384 ret = EMemSpyDriverChunkTypeStackKernel; |
|
385 } |
|
386 else if ( name == KMemSpyLitDollarDat ) |
|
387 { |
|
388 // This chunk contains process global data as well as user-side stacks for |
|
389 // the process. |
|
390 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackAndProcessGlobalData" ) ); |
|
391 ret = EMemSpyDriverChunkTypeStackAndProcessGlobalData; |
|
392 } |
|
393 else if ( name == KMemSpyLitDollarGlobalCode && type == EDll ) |
|
394 { |
|
395 // GLOBAL$CODE is used for RAM loaded code which is globally visible. This |
|
396 // basically means locale DLLs - these must be visible to every process, even |
|
397 // those which haven't loaded them. |
|
398 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeGlobal" ) ); |
|
399 ret = EMemSpyDriverChunkTypeCodeGlobal; |
|
400 } |
|
401 else if ( name == KMemSpyLitDollarCode || type == EKernelCode || type == EDll || type == EUserCode ) |
|
402 { |
|
403 // RAM-loaded code, which on the multiple memory model at least means that the code chunk is eseentially just a mapping |
|
404 // artifact. The RAM itself is owned by the code segment, therefore counting the size of these CODE elements may result |
|
405 // in inaccurate results if the code is shared amongst multiple processes. |
|
406 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCode" ) ); |
|
407 ret = EMemSpyDriverChunkTypeCode; |
|
408 } |
|
409 else if ( type == EUserSelfModCode ) |
|
410 { |
|
411 // Dynamically create code chunk |
|
412 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeSelfModifiable" ) ); |
|
413 ret = EMemSpyDriverChunkTypeCodeSelfModifiable; |
|
414 } |
|
415 else if ( IsHeapChunk( aChunk, name ) ) |
|
416 { |
|
417 // Catch kernel heap too |
|
418 if ( type == EKernelData ) |
|
419 { |
|
420 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeapKernel" ) ); |
|
421 ret = EMemSpyDriverChunkTypeHeapKernel; |
|
422 } |
|
423 else |
|
424 { |
|
425 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeap" ) ); |
|
426 ret = EMemSpyDriverChunkTypeHeap; |
|
427 } |
|
428 } |
|
429 else if ( type == EUserData && chunkAdaption.GetOwningProcess( aChunk ) == NULL ) |
|
430 { |
|
431 // Global shared chunks match this pattern. Of course, we could check the memory model mapping attributes |
|
432 // as that would give us the info in a heartbeat, but it's too specific. |
|
433 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobal" ) ); |
|
434 ret = EMemSpyDriverChunkTypeGlobal; |
|
435 } |
|
436 else if ( type == EUserData && chunkAdaption.GetOwner( aChunk ) != NULL && name.Length() > KMemSpyLitLocalObject().Length() && name.Left( KMemSpyLitLocalObject().Length() ) == KMemSpyLitLocalObject ) |
|
437 { |
|
438 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeLocal" ) ); |
|
439 ret = EMemSpyDriverChunkTypeLocal; |
|
440 } |
|
441 else |
|
442 { |
|
443 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeUnknown" ) ); |
|
444 TRACE( PrintChunkInfo( aChunk ) ); |
|
445 ret = EMemSpyDriverChunkTypeUnknown; |
|
446 } |
|
447 |
|
448 return ret; |
|
449 } |
|
450 |
|
451 |
|
452 TBool DMemSpyDriverLogChanChunks::IsHeapChunk( DChunk& aChunk, const TName& aName ) |
|
453 { |
|
454 (void) aName; // UREL warning |
|
455 const TUint rHeapVTable = MemSpyDevice().RHeapVTable(); |
|
456 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, aName: %S, [%O]", this, &aChunk, rHeapVTable, &aName, &aChunk ) ); |
|
457 |
|
458 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
459 DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); |
|
460 |
|
461 // The first 4 bytes of every chunk correspond to the allocator VTable (For heap chunks). |
|
462 // If it matches RHeap's vtable, we'll treat it as a heap. |
|
463 TBool isHeap = EFalse; |
|
464 |
|
465 // There must be an owning process or else it's definitely not a heap chunk. |
|
466 DProcess* process = chunkAdaption.GetOwningProcess( aChunk ); |
|
467 TUint8* base = chunkAdaption.GetBase( aChunk ); |
|
468 const TInt size = chunkAdaption.GetSize( aChunk ); |
|
469 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - base: 0x%08x, size: %d, process: 0x%08x (%O)", base, size, process, process ) ); |
|
470 |
|
471 if ( process && size >= 4 ) |
|
472 { |
|
473 // Chunks are mapped into entire process so any thread within the process is enough... |
|
474 DThread* firstThread = processAdaption.GetFirstThread( *process ); |
|
475 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) ); |
|
476 if ( firstThread != NULL ) |
|
477 { |
|
478 TInt err = firstThread->Open(); |
|
479 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread open result: %d", err ) ); |
|
480 |
|
481 if ( err == KErrNone ) |
|
482 { |
|
483 TBuf8<4> allocatorVTableBuffer; |
|
484 err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() ); |
|
485 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - read result of vtable data from requested thread is: %d", err )); |
|
486 // |
|
487 if ( err == KErrNone ) |
|
488 { |
|
489 TRACE( MemSpyDriverUtils::DataDump("possible chunk vtable data - %lS", allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength(), allocatorVTableBuffer.MaxLength() ) ); |
|
490 allocatorVTableBuffer.SetLength( allocatorVTableBuffer.MaxLength() ); |
|
491 |
|
492 const TUint32 vtable = allocatorVTableBuffer[0] + |
|
493 (allocatorVTableBuffer[1] << 8) + |
|
494 (allocatorVTableBuffer[2] << 16) + |
|
495 (allocatorVTableBuffer[3] << 24); |
|
496 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - [possible] vTable within chunk is: 0x%08x", vtable) ); |
|
497 |
|
498 // Check the v-table to work out if it really is an RHeap |
|
499 isHeap = ( vtable == rHeapVTable ); |
|
500 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - isHeap: %d", isHeap ) ); |
|
501 } |
|
502 |
|
503 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - closing first thread..." ) ); |
|
504 Kern::SafeClose( (DObject*&) firstThread, NULL ); |
|
505 } |
|
506 } |
|
507 } |
|
508 |
|
509 /* We only want RHeap's at the moment |
|
510 if ( !isHeap && aName == KMemSpyLitDollarHeap ) |
|
511 { |
|
512 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - its called $HEAP, but its not an RHeap... we\'ll let it through though..." ) ); |
|
513 isHeap = ETrue; |
|
514 } |
|
515 */ |
|
516 |
|
517 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) ); |
|
518 return isHeap; |
|
519 } |
|
520 |
|
521 |
|
522 TBool DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess( DChunk& aChunk, DProcess& aProcess ) |
|
523 { |
|
524 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - START - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O)", this, &aChunk, &aChunk, &aProcess, &aProcess ) ); |
|
525 TBool ret = EFalse; |
|
526 // |
|
527 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
528 DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); |
|
529 // |
|
530 const TUint pid = processAdaption.GetId( aProcess ); |
|
531 DProcess* process = chunkAdaption.GetOwningProcess( aChunk ); |
|
532 if ( process ) |
|
533 { |
|
534 ret = ( pid == processAdaption.GetId( *process ) ); |
|
535 } |
|
536 else |
|
537 { |
|
538 DObject* owner = chunkAdaption.GetOwner( aChunk, EProcess ); |
|
539 if ( owner ) |
|
540 { |
|
541 process = (DProcess*) owner; |
|
542 ret = ( pid == processAdaption.GetId( *process ) ); |
|
543 } |
|
544 else |
|
545 { |
|
546 ret = ( pid == chunkAdaption.GetControllingOwnerId( aChunk ) ); |
|
547 } |
|
548 } |
|
549 // |
|
550 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - END - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O), ret: %d", this, &aChunk, &aChunk, &aProcess, &aProcess, ret ) ); |
|
551 return ret; |
|
552 } |
|
553 |