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