|
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_HandleLookupLock(); |
|
168 const TInt processHandleCount = processHandles->Count(); |
|
169 MemSpyObjectIx_HandleLookupUnlock(); |
|
170 |
|
171 for( TInt processHandleIndex = 0; processHandleIndex<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ ) |
|
172 { |
|
173 // Get a handle from the process container... |
|
174 MemSpyObjectIx_HandleLookupLock(); |
|
175 if (processHandleIndex >= processHandles->Count()) break; // Count may have changed in the meantime |
|
176 DObject* object = (*processHandles)[ processHandleIndex ]; |
|
177 if (object && object->Open() != KErrNone) object = NULL; |
|
178 MemSpyObjectIx_HandleLookupUnlock(); |
|
179 |
|
180 if ( object ) |
|
181 { |
|
182 const TObjectType objectType = processAdaption.GetObjectType( *object ); |
|
183 if ( objectType == EChunk ) |
|
184 { |
|
185 DChunk* chunk = (DChunk*) object; |
|
186 TAny* handle = (TAny*) chunk; |
|
187 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) ); |
|
188 if ( r == KErrNone ) |
|
189 { |
|
190 ++currentWriteIndex; |
|
191 } |
|
192 } |
|
193 object->Close(NULL); |
|
194 } |
|
195 } |
|
196 |
|
197 // If we were asked for process-related chunks, also check the chunk container |
|
198 // for entries which we don't have handles to, but do refer to our process |
|
199 // Need a listing of all chunks in the system. Let client filter duplicates. |
|
200 DObjectCon* container = Kern::Containers()[ EChunk ]; |
|
201 container->Wait(); |
|
202 // |
|
203 const TInt count = container->Count(); |
|
204 for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ ) |
|
205 { |
|
206 DChunk* chunk= (DChunk*) (*container)[ i ]; |
|
207 // |
|
208 const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() ); |
|
209 if ( isRelated ) |
|
210 { |
|
211 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) ); |
|
212 if ( r == KErrNone ) |
|
213 { |
|
214 ++currentWriteIndex; |
|
215 } |
|
216 } |
|
217 } |
|
218 // |
|
219 container->Signal(); |
|
220 NKern::ThreadLeaveCS(); |
|
221 |
|
222 CloseTempObject(); |
|
223 } |
|
224 else |
|
225 { |
|
226 // Need a listing of all chunks in the system. Let client filter duplicates. |
|
227 DObjectCon* container = Kern::Containers()[ EChunk ]; |
|
228 NKern::ThreadEnterCS(); |
|
229 container->Wait(); |
|
230 // |
|
231 const TInt count = container->Count(); |
|
232 for( TInt i=0; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ ) |
|
233 { |
|
234 DChunk* chunk= (DChunk*) (*container)[ i ]; |
|
235 // |
|
236 r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) ); |
|
237 if (r == KErrNone) |
|
238 { |
|
239 ++currentWriteIndex; |
|
240 } |
|
241 } |
|
242 // |
|
243 container->Signal(); |
|
244 NKern::ThreadLeaveCS(); |
|
245 } |
|
246 |
|
247 if ( r == KErrBadDescriptor ) |
|
248 { |
|
249 MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); |
|
250 } |
|
251 else |
|
252 { |
|
253 const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, ¤tWriteIndex, sizeof(TInt) ); |
|
254 if ( r == KErrNone ) |
|
255 { |
|
256 r = finalWrite; |
|
257 } |
|
258 } |
|
259 |
|
260 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r)); |
|
261 return r; |
|
262 } |
|
263 |
|
264 |
|
265 TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams ) |
|
266 { |
|
267 TMemSpyDriverInternalChunkInfoParams params; |
|
268 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); |
|
269 if ( r != KErrNone ) |
|
270 { |
|
271 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r)); |
|
272 return r; |
|
273 } |
|
274 |
|
275 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle)); |
|
276 |
|
277 DObjectCon* container = Kern::Containers()[EChunk]; |
|
278 NKern::ThreadEnterCS(); |
|
279 |
|
280 container->Wait(); |
|
281 const TInt count = container->Count(); |
|
282 |
|
283 DChunk* foundChunk = NULL; |
|
284 |
|
285 for(TInt i=0; i<count; i++) |
|
286 { |
|
287 DChunk* chunk = (DChunk*) (*container)[i]; |
|
288 if ( chunk == params.iHandle ) |
|
289 { |
|
290 foundChunk = chunk; |
|
291 TRACE( PrintChunkInfo( *chunk ) ); |
|
292 r = foundChunk->Open(); |
|
293 break; |
|
294 } |
|
295 } |
|
296 |
|
297 container->Signal(); |
|
298 |
|
299 if ( foundChunk == NULL ) |
|
300 { |
|
301 Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk"); |
|
302 NKern::ThreadLeaveCS(); |
|
303 return KErrNotFound; |
|
304 } |
|
305 if (r) |
|
306 { |
|
307 Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - %d - Failed to open chunk", r); |
|
308 NKern::ThreadLeaveCS(); |
|
309 return r; |
|
310 } |
|
311 |
|
312 // Prepare return data |
|
313 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
314 // |
|
315 params.iBaseAddress = chunkAdaption.GetBase( *foundChunk ); |
|
316 params.iSize = chunkAdaption.GetSize( *foundChunk ); |
|
317 params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk ); |
|
318 foundChunk->FullName( params.iName ); |
|
319 |
|
320 // Mirror the process memory tracker |
|
321 DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk ); |
|
322 if ( owner ) |
|
323 { |
|
324 params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); |
|
325 } |
|
326 else |
|
327 { |
|
328 owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) ); |
|
329 if ( owner ) |
|
330 { |
|
331 params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); |
|
332 } |
|
333 else |
|
334 { |
|
335 params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk ); |
|
336 } |
|
337 } |
|
338 |
|
339 // Get type & attribs |
|
340 params.iType = IdentifyChunkType( *foundChunk ); |
|
341 params.iAttributes = chunkAdaption.GetAttributes( *foundChunk ); |
|
342 |
|
343 // Finished with foundChunk |
|
344 foundChunk->Close(NULL); |
|
345 NKern::ThreadLeaveCS(); |
|
346 |
|
347 // Write back to client |
|
348 r = Kern::ThreadRawWrite( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); |
|
349 if ( r == KErrBadDescriptor ) |
|
350 { |
|
351 MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); |
|
352 } |
|
353 |
|
354 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r )); |
|
355 return r; |
|
356 } |
|
357 |
|
358 |
|
359 void DMemSpyDriverLogChanChunks::PrintChunkInfo( DChunk& aChunk ) |
|
360 { |
|
361 MemSpyDriverUtils::PrintChunkInfo( aChunk, OSAdaption() ); |
|
362 } |
|
363 |
|
364 |
|
365 TMemSpyDriverChunkType DMemSpyDriverLogChanChunks::IdentifyChunkType( DChunk& aChunk ) |
|
366 { |
|
367 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - START" ) ); |
|
368 |
|
369 TMemSpyDriverChunkType ret = EMemSpyDriverChunkTypeUnknown; |
|
370 |
|
371 TName name; |
|
372 aChunk.Name( name ); |
|
373 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - name: %S", &name ) ); |
|
374 |
|
375 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
376 const TChunkType type = chunkAdaption.GetType( aChunk ); |
|
377 |
|
378 if ( name == KMemSpyLitDllDollarData ) |
|
379 { |
|
380 // This chunk contains Dll Global Data for the process |
|
381 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobalData" ) ); |
|
382 ret = EMemSpyDriverChunkTypeGlobalData; |
|
383 } |
|
384 else if ( type == ERamDrive ) |
|
385 { |
|
386 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeRamDrive" ) ); |
|
387 ret = EMemSpyDriverChunkTypeRamDrive; |
|
388 } |
|
389 else if ( type == EKernelStack ) |
|
390 { |
|
391 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackKernel" ) ); |
|
392 ret = EMemSpyDriverChunkTypeStackKernel; |
|
393 } |
|
394 else if ( name == KMemSpyLitDollarDat ) |
|
395 { |
|
396 // This chunk contains process global data as well as user-side stacks for |
|
397 // the process. |
|
398 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackAndProcessGlobalData" ) ); |
|
399 ret = EMemSpyDriverChunkTypeStackAndProcessGlobalData; |
|
400 } |
|
401 else if ( name == KMemSpyLitDollarGlobalCode && type == EDll ) |
|
402 { |
|
403 // GLOBAL$CODE is used for RAM loaded code which is globally visible. This |
|
404 // basically means locale DLLs - these must be visible to every process, even |
|
405 // those which haven't loaded them. |
|
406 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeGlobal" ) ); |
|
407 ret = EMemSpyDriverChunkTypeCodeGlobal; |
|
408 } |
|
409 else if ( name == KMemSpyLitDollarCode || type == EKernelCode || type == EDll || type == EUserCode ) |
|
410 { |
|
411 // RAM-loaded code, which on the multiple memory model at least means that the code chunk is eseentially just a mapping |
|
412 // artifact. The RAM itself is owned by the code segment, therefore counting the size of these CODE elements may result |
|
413 // in inaccurate results if the code is shared amongst multiple processes. |
|
414 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCode" ) ); |
|
415 ret = EMemSpyDriverChunkTypeCode; |
|
416 } |
|
417 else if ( type == EUserSelfModCode ) |
|
418 { |
|
419 // Dynamically create code chunk |
|
420 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeSelfModifiable" ) ); |
|
421 ret = EMemSpyDriverChunkTypeCodeSelfModifiable; |
|
422 } |
|
423 else if ( IsHeapChunk( aChunk, name ) ) |
|
424 { |
|
425 // Catch kernel heap too |
|
426 if ( type == EKernelData ) |
|
427 { |
|
428 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeapKernel" ) ); |
|
429 ret = EMemSpyDriverChunkTypeHeapKernel; |
|
430 } |
|
431 else |
|
432 { |
|
433 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeap" ) ); |
|
434 ret = EMemSpyDriverChunkTypeHeap; |
|
435 } |
|
436 } |
|
437 else if ( type == EUserData && chunkAdaption.GetOwningProcess( aChunk ) == NULL ) |
|
438 { |
|
439 // Global shared chunks match this pattern. Of course, we could check the memory model mapping attributes |
|
440 // as that would give us the info in a heartbeat, but it's too specific. |
|
441 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobal" ) ); |
|
442 ret = EMemSpyDriverChunkTypeGlobal; |
|
443 } |
|
444 else if ( type == EUserData && chunkAdaption.GetOwner( aChunk ) != NULL && name.Length() > KMemSpyLitLocalObject().Length() && name.Left( KMemSpyLitLocalObject().Length() ) == KMemSpyLitLocalObject ) |
|
445 { |
|
446 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeLocal" ) ); |
|
447 ret = EMemSpyDriverChunkTypeLocal; |
|
448 } |
|
449 else |
|
450 { |
|
451 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeUnknown" ) ); |
|
452 TRACE( PrintChunkInfo( aChunk ) ); |
|
453 ret = EMemSpyDriverChunkTypeUnknown; |
|
454 } |
|
455 |
|
456 return ret; |
|
457 } |
|
458 |
|
459 |
|
460 TBool DMemSpyDriverLogChanChunks::IsHeapChunk( DChunk& aChunk, const TName& aName ) |
|
461 { |
|
462 (void) aName; // UREL warning |
|
463 const TUint rHeapVTable = MemSpyDevice().RHeapVTable(); |
|
464 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, aName: %S, [%O]", this, &aChunk, rHeapVTable, &aName, &aChunk ) ); |
|
465 |
|
466 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
467 DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); |
|
468 |
|
469 // The first 4 bytes of every chunk correspond to the allocator VTable (For heap chunks). |
|
470 // If it matches RHeap's vtable, we'll treat it as a heap. |
|
471 TBool isHeap = EFalse; |
|
472 |
|
473 // There must be an owning process or else it's definitely not a heap chunk. |
|
474 DProcess* process = chunkAdaption.GetOwningProcess( aChunk ); |
|
475 TUint8* base = chunkAdaption.GetBase( aChunk ); |
|
476 const TInt size = chunkAdaption.GetSize( aChunk ); |
|
477 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - base: 0x%08x, size: %d, process: 0x%08x (%O)", base, size, process, process ) ); |
|
478 |
|
479 if ( process && size >= 4 ) |
|
480 { |
|
481 NKern::ThreadEnterCS(); |
|
482 // Chunks are mapped into entire process so any thread within the process is enough... |
|
483 DThread* firstThread = processAdaption.OpenFirstThread( *process ); |
|
484 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) ); |
|
485 if ( firstThread != NULL ) |
|
486 { |
|
487 TBuf8<4> allocatorVTableBuffer; |
|
488 TInt err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() ); |
|
489 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - read result of vtable data from requested thread is: %d", err )); |
|
490 // |
|
491 if ( err == KErrNone ) |
|
492 { |
|
493 TRACE( MemSpyDriverUtils::DataDump("possible chunk vtable data - %lS", allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength(), allocatorVTableBuffer.MaxLength() ) ); |
|
494 allocatorVTableBuffer.SetLength( allocatorVTableBuffer.MaxLength() ); |
|
495 |
|
496 const TUint32 vtable = allocatorVTableBuffer[0] + |
|
497 (allocatorVTableBuffer[1] << 8) + |
|
498 (allocatorVTableBuffer[2] << 16) + |
|
499 (allocatorVTableBuffer[3] << 24); |
|
500 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - [possible] vTable within chunk is: 0x%08x", vtable) ); |
|
501 |
|
502 // Check the v-table to work out if it really is an RHeap |
|
503 isHeap = ( vtable == rHeapVTable ); |
|
504 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - isHeap: %d", isHeap ) ); |
|
505 } |
|
506 |
|
507 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - closing first thread..." ) ); |
|
508 Kern::SafeClose( (DObject*&) firstThread, NULL ); |
|
509 } |
|
510 NKern::ThreadLeaveCS(); |
|
511 } |
|
512 |
|
513 /* We only want RHeap's at the moment |
|
514 if ( !isHeap && aName == KMemSpyLitDollarHeap ) |
|
515 { |
|
516 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - its called $HEAP, but its not an RHeap... we\'ll let it through though..." ) ); |
|
517 isHeap = ETrue; |
|
518 } |
|
519 */ |
|
520 |
|
521 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) ); |
|
522 return isHeap; |
|
523 } |
|
524 |
|
525 |
|
526 TBool DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess( DChunk& aChunk, DProcess& aProcess ) |
|
527 { |
|
528 TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - START - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O)", this, &aChunk, &aChunk, &aProcess, &aProcess ) ); |
|
529 TBool ret = EFalse; |
|
530 // |
|
531 DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); |
|
532 DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); |
|
533 // |
|
534 const TUint pid = processAdaption.GetId( aProcess ); |
|
535 DProcess* process = chunkAdaption.GetOwningProcess( aChunk ); |
|
536 if ( process ) |
|
537 { |
|
538 ret = ( pid == processAdaption.GetId( *process ) ); |
|
539 } |
|
540 else |
|
541 { |
|
542 DObject* owner = chunkAdaption.GetOwner( aChunk, EProcess ); |
|
543 if ( owner ) |
|
544 { |
|
545 process = (DProcess*) owner; |
|
546 ret = ( pid == processAdaption.GetId( *process ) ); |
|
547 } |
|
548 else |
|
549 { |
|
550 ret = ( pid == chunkAdaption.GetControllingOwnerId( aChunk ) ); |
|
551 } |
|
552 } |
|
553 // |
|
554 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 ) ); |
|
555 return ret; |
|
556 } |
|
557 |