|
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 "MemSpyDriverLogChanHeapInfo.h" |
|
19 |
|
20 // System includes |
|
21 #include <u32hal.h> |
|
22 #include <e32rom.h> |
|
23 #include <memspy/driver/memspydriverconstants.h> |
|
24 #include <memspy/driver/memspydriverobjectsshared.h> |
|
25 |
|
26 // Shared includes |
|
27 #include "MemSpyDriverOpCodes.h" |
|
28 #include "MemSpyDriverObjectsInternal.h" |
|
29 |
|
30 // User includes |
|
31 #include "MemSpyDriverHeap.h" |
|
32 #include "MemSpyDriverUtils.h" |
|
33 #include "MemSpyDriverOSAdaption.h" |
|
34 #include "MemSpyDriverHeapWalker.h" |
|
35 #include "MemSpyDriverSuspensionManager.h" |
|
36 |
|
37 |
|
38 |
|
39 DMemSpyDriverLogChanHeapInfo::DMemSpyDriverLogChanHeapInfo( DMemSpyDriverDevice& aDevice, DThread& aThread ) |
|
40 : DMemSpyDriverLogChanHeapBase( aDevice, aThread ) |
|
41 { |
|
42 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::DMemSpyDriverLogChanHeapInfo() - this: 0x%08x", this )); |
|
43 } |
|
44 |
|
45 |
|
46 DMemSpyDriverLogChanHeapInfo::~DMemSpyDriverLogChanHeapInfo() |
|
47 { |
|
48 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::~DMemSpyDriverLogChanHeapInfo() - START - this: 0x%08x", this )); |
|
49 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::~DMemSpyDriverLogChanHeapInfo() - END - this: 0x%08x", this )); |
|
50 } |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 TInt DMemSpyDriverLogChanHeapInfo::Request( TInt aFunction, TAny* a1, TAny* a2 ) |
|
60 { |
|
61 TInt r = DMemSpyDriverLogChanHeapBase::Request( aFunction, a1, a2 ); |
|
62 if ( r == KErrNone ) |
|
63 { |
|
64 if ( aFunction != EMemSpyDriverOpCodeHeapInfoFetchFreeCells ) |
|
65 { |
|
66 ReleaseFreeCells(); |
|
67 } |
|
68 // |
|
69 switch( aFunction ) |
|
70 { |
|
71 case EMemSpyDriverOpCodeHeapInfoGetUser: |
|
72 r = GetHeapInfoUser( (TMemSpyDriverInternalHeapRequestParameters*) a1 ); |
|
73 break; |
|
74 case EMemSpyDriverOpCodeHeapInfoGetKernel: |
|
75 r = GetHeapInfoKernel( (TMemSpyDriverInternalHeapRequestParameters*) a1, (TDes8*) a2 ); |
|
76 break; |
|
77 case EMemSpyDriverOpCodeHeapInfoGetIsDebugKernel: |
|
78 r = GetIsDebugKernel( (TBool*) a1 ); |
|
79 break; |
|
80 case EMemSpyDriverOpCodeHeapInfoFetchFreeCells: |
|
81 r = FetchFreeCells( (TDes8*) a1 ); |
|
82 break; |
|
83 |
|
84 default: |
|
85 r = KErrNotSupported; |
|
86 break; |
|
87 } |
|
88 } |
|
89 // |
|
90 return r; |
|
91 } |
|
92 |
|
93 |
|
94 TBool DMemSpyDriverLogChanHeapInfo::IsHandler( TInt aFunction ) const |
|
95 { |
|
96 return ( aFunction > EMemSpyDriverOpCodeHeapInfoBase && aFunction < EMemSpyDriverOpCodeHeapInfoEnd ); |
|
97 } |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 TInt DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser( TMemSpyDriverInternalHeapRequestParameters* aParams ) |
|
112 { |
|
113 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser() - START" ) ); |
|
114 |
|
115 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &iHeapInfoParams, sizeof(TMemSpyDriverInternalHeapRequestParameters) ); |
|
116 if ( r != KErrNone ) |
|
117 { |
|
118 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - params read error: %d", r)); |
|
119 } |
|
120 else |
|
121 { |
|
122 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - thread id: %d, vtable: 0x%08x, debugAllocator: %d", iHeapInfoParams.iTid, iHeapInfoParams.iRHeapVTable, iHeapInfoParams.iDebugAllocator) ); |
|
123 |
|
124 r = OpenTempObject( iHeapInfoParams.iTid, EThread ); |
|
125 if ( r != KErrNone ) |
|
126 { |
|
127 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - thread not found") ); |
|
128 } |
|
129 else |
|
130 { |
|
131 // Check that the process' thread's are suspended |
|
132 DThread* thread = (DThread*) TempObject(); |
|
133 if ( SuspensionManager().IsSuspended( *thread ) ) |
|
134 { |
|
135 TFullName chunkName; |
|
136 |
|
137 // Open client's heap |
|
138 RMemSpyDriverRHeapUser rHeap( OSAdaption() ); |
|
139 DChunk* userHeapChunk = NULL; |
|
140 r = OpenUserHeap( *thread, iHeapInfoParams.iRHeapVTable, rHeap, userHeapChunk, &chunkName ); |
|
141 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - opening client heap returned: %d", r) ); |
|
142 |
|
143 if ( r == KErrNone ) |
|
144 { |
|
145 // This object holds all of the info we will accumulate for the client. |
|
146 TMemSpyHeapInfo masterHeapInfo; |
|
147 masterHeapInfo.SetType( TMemSpyHeapInfo::ETypeRHeap ); |
|
148 masterHeapInfo.SetTid( iHeapInfoParams.iTid ); |
|
149 masterHeapInfo.SetPid( OSAdaption().DThread().GetOwningProcessId( *thread ) ); |
|
150 |
|
151 // This is the RHeap-specific object that contains all RHeap info |
|
152 TMemSpyHeapInfoRHeap& rHeapInfo = masterHeapInfo.AsRHeap(); |
|
153 |
|
154 // This is the object data for the RHeap instance |
|
155 TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); |
|
156 rHeap.CopyObjectDataTo( rHeapObjectData ); |
|
157 |
|
158 // We must walk the client's heap in order to build statistics |
|
159 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - calling heap walker constructor...")); |
|
160 TMemSpyHeapWalkerNullObserver observer; |
|
161 RMemSpyDriverHeapWalker heapWalker( rHeap, iHeapInfoParams.iDebugAllocator ); |
|
162 if ( iHeapInfoParams.iBuildFreeCellList ) |
|
163 { |
|
164 heapWalker.SetObserver( this ); |
|
165 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - collecting free cells")); |
|
166 } |
|
167 else |
|
168 { |
|
169 heapWalker.SetObserver( &observer ); |
|
170 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - not collecting free cells")); |
|
171 } |
|
172 |
|
173 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - starting traversal..." )); |
|
174 |
|
175 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) ) |
|
176 heapWalker.SetPrintDebug(); |
|
177 #endif |
|
178 r = heapWalker.Traverse(); |
|
179 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - finished traversal - err: %d", r )); |
|
180 |
|
181 TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); |
|
182 heapWalker.CopyStatsTo( rHeapStats ); |
|
183 |
|
184 // Get remaining meta data that isn't stored elsewhere |
|
185 TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); |
|
186 rHeapMetaData.SetChunkName( chunkName ); |
|
187 rHeapMetaData.SetChunkSize( (TUint) OSAdaption().DChunk().GetSize( *userHeapChunk ) ); |
|
188 rHeapMetaData.SetChunkHandle( userHeapChunk ); |
|
189 rHeapMetaData.SetChunkBaseAddress( OSAdaption().DChunk().GetBase( *userHeapChunk ) ); |
|
190 rHeapMetaData.SetDebugAllocator( iHeapInfoParams.iDebugAllocator ); |
|
191 rHeapMetaData.SetHeaderSizeFree( RMemSpyDriverRHeapBase::FreeCellHeaderSize() ); |
|
192 rHeapMetaData.SetHeaderSizeAllocated( RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( iHeapInfoParams.iDebugAllocator ) ); |
|
193 rHeapMetaData.SetUserThread( ETrue ); |
|
194 |
|
195 // Get any heap-specific info |
|
196 rHeap.GetHeapSpecificInfo( masterHeapInfo ); |
|
197 |
|
198 PrintHeapInfo( masterHeapInfo ); |
|
199 |
|
200 // Write free cells if requested |
|
201 if ( r == KErrNone && iHeapInfoParams.iBuildFreeCellList ) |
|
202 { |
|
203 r = PrepareFreeCellTransferBuffer(); |
|
204 } |
|
205 |
|
206 // Update info ready for writing back to the user-side |
|
207 if ( r >= KErrNone ) |
|
208 { |
|
209 // Write results back to user-side |
|
210 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - writing to user-side...")); |
|
211 TMemSpyHeapInfo* userMasterInfo = iHeapInfoParams.iMasterInfo; |
|
212 const TInt error = Kern::ThreadRawWrite( &ClientThread(), userMasterInfo, &masterHeapInfo, sizeof(TMemSpyHeapInfo) ); |
|
213 if ( error < 0 ) |
|
214 { |
|
215 r = error; |
|
216 } |
|
217 } |
|
218 |
|
219 // Release resources |
|
220 rHeap.DisassociateWithKernelChunk(); |
|
221 } |
|
222 } |
|
223 else |
|
224 { |
|
225 r = KErrAccessDenied; |
|
226 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser - parent process not suspended => KErrAccessDenied")); |
|
227 } |
|
228 |
|
229 CloseTempObject(); |
|
230 } |
|
231 } |
|
232 |
|
233 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoUser() - END - ret: %d", r)); |
|
234 return r; |
|
235 } |
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 TInt DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel( TMemSpyDriverInternalHeapRequestParameters* aParams, TDes8* aTransferBuffer ) |
|
244 { |
|
245 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - START - aTransferBuffer: 0x%08x", aTransferBuffer ) ); |
|
246 |
|
247 TMemSpyDriverInternalHeapRequestParameters params; |
|
248 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalHeapRequestParameters) ); |
|
249 if ( r == KErrNone ) |
|
250 { |
|
251 // Open kernel heap |
|
252 TFullName heapChunkName; |
|
253 RMemSpyDriverRHeapKernelInPlace rHeap; |
|
254 r = OpenKernelHeap( rHeap, &heapChunkName ); |
|
255 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - open err: %d", r ) ); |
|
256 |
|
257 if ( r == KErrNone ) |
|
258 { |
|
259 // We must identify if we have a debug kernel allocator |
|
260 const TBool debugAllocator = IsDebugKernel( rHeap ); |
|
261 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - debugAllocator: %d", debugAllocator ) ); |
|
262 |
|
263 r = DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel( rHeap, debugAllocator, heapChunkName, params.iMasterInfo, aTransferBuffer ); |
|
264 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - base class get heap info: %d", r) ); |
|
265 } |
|
266 } |
|
267 else |
|
268 { |
|
269 Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - params read error: %d", r); |
|
270 } |
|
271 |
|
272 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - END - ret: %d", r) ); |
|
273 return r; |
|
274 } |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 TInt DMemSpyDriverLogChanHeapInfo::GetIsDebugKernel( TBool* aIsDebugKernel ) |
|
282 { |
|
283 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetIsDebugKernel() - START") ); |
|
284 |
|
285 TInt r = KErrNone; |
|
286 TBool debugKernel = EFalse; |
|
287 |
|
288 NKern::ThreadEnterCS(); |
|
289 |
|
290 RMemSpyDriverRHeapKernelInPlace rHeap; |
|
291 r = OpenKernelHeap( rHeap ); |
|
292 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetIsDebugKernel() - open kernel heap returned: %d", r) ); |
|
293 |
|
294 if ( r == KErrNone ) |
|
295 { |
|
296 debugKernel = IsDebugKernel( rHeap ); |
|
297 |
|
298 // Tidy up |
|
299 rHeap.DisassociateWithKernelChunk(); |
|
300 } |
|
301 |
|
302 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetIsDebugKernel() - debugKernel: %d", debugKernel) ); |
|
303 |
|
304 // Write back to user-land |
|
305 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetIsDebugKernel() - writing to user-side...") ); |
|
306 r = Kern::ThreadRawWrite( &ClientThread(), aIsDebugKernel, &debugKernel, sizeof(TBool) ); |
|
307 |
|
308 NKern::ThreadLeaveCS(); |
|
309 |
|
310 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetIsDebugKernel() - END - ret: %d", r) ); |
|
311 return r; |
|
312 } |
|
313 |
|
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 |
|
321 |
|
322 |
|
323 |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
|
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 |
|
349 |