|
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 "MemSpyDriverLogChanHeapDataUser.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 "MemSpyDriverDevice.h" |
|
34 #include "MemSpyDriverOSAdaption.h" |
|
35 #include "MemSpyDriverHeapWalker.h" |
|
36 #include "MemSpyDriverUserEventMonitor.h" |
|
37 #include "MemSpyDriverSuspensionManager.h" |
|
38 |
|
39 DMemSpyDriverLogChanHeapDataUser::DMemSpyDriverLogChanHeapDataUser( DMemSpyDriverDevice& aDevice, DThread& aThread ) |
|
40 : DMemSpyDriverLogChanHeapDataBase( aDevice, aThread ) |
|
41 { |
|
42 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::DMemSpyDriverLogChanHeapDataUser() - this: 0x%08x", this )); |
|
43 } |
|
44 |
|
45 TInt DMemSpyDriverLogChanHeapDataUser::Request( TInt aFunction, TAny* a1, TAny* a2 ) |
|
46 { |
|
47 TInt r = DMemSpyDriverLogChanHeapBase::Request( aFunction, a1, a2 ); |
|
48 if ( r == KErrNone ) |
|
49 { |
|
50 if ( aFunction != EMemSpyDriverOpCodeHeapUserDataFetchCellList ) |
|
51 { |
|
52 ReleaseCellList(); |
|
53 } |
|
54 // |
|
55 switch( aFunction ) |
|
56 { |
|
57 case EMemSpyDriverOpCodeHeapUserDataGetInfo: |
|
58 r = GetInfoData( (TMemSpyDriverInternalHeapRequestParameters*) a1 ); |
|
59 break; |
|
60 case EMemSpyDriverOpCodeHeapUserDataFetchCellList: |
|
61 r = FetchCellList( (TDes8*) a1 ); |
|
62 break; |
|
63 case EMemSpyDriverOpCodeHeapUserDataGetFull: |
|
64 r = DMemSpyDriverLogChanHeapDataBase::GetFullData( (TMemSpyDriverInternalHeapDataParams*) a1 ); |
|
65 break; |
|
66 |
|
67 default: |
|
68 r = KErrNotSupported; |
|
69 break; |
|
70 } |
|
71 } |
|
72 // |
|
73 return r; |
|
74 } |
|
75 |
|
76 |
|
77 TBool DMemSpyDriverLogChanHeapDataUser::IsHandler( TInt aFunction ) const |
|
78 { |
|
79 return ( aFunction > EMemSpyDriverOpCodeHeapUserDataBase && aFunction < EMemSpyDriverOpCodeHeapUserDataEnd ); |
|
80 } |
|
81 |
|
82 TInt DMemSpyDriverLogChanHeapDataUser::GetInfoData( TMemSpyDriverInternalHeapRequestParameters* aParams ) |
|
83 { |
|
84 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData() - START" ) ); |
|
85 |
|
86 TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, &iHeapInfoParams, sizeof(TMemSpyDriverInternalHeapRequestParameters) ); |
|
87 if ( r != KErrNone ) |
|
88 { |
|
89 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - params read error: %d", r)); |
|
90 } |
|
91 else |
|
92 { |
|
93 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - thread id: %d, vtable: 0x%08x, debugAllocator: %d", iHeapInfoParams.iTid, iHeapInfoParams.iRHeapVTable, iHeapInfoParams.iDebugAllocator) ); |
|
94 |
|
95 r = OpenTempObject( iHeapInfoParams.iTid, EThread ); |
|
96 if ( r != KErrNone ) |
|
97 { |
|
98 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - thread not found") ); |
|
99 } |
|
100 else |
|
101 { |
|
102 // Check that the process' thread's are suspended |
|
103 DThread* thread = (DThread*) TempObject(); |
|
104 if ( SuspensionManager().IsSuspended( *thread ) ) |
|
105 { |
|
106 // Open client's heap |
|
107 RMemSpyDriverRHeapUser rHeap( OSAdaption() ); |
|
108 r = rHeap.OpenUserHeap(*thread, iHeapInfoParams.iDebugAllocator); |
|
109 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - opening client heap returned: %d", r) ); |
|
110 |
|
111 if ( r == KErrNone ) |
|
112 { |
|
113 // This object holds all of the info we will accumulate for the client. |
|
114 TMemSpyHeapInfo masterHeapInfo; |
|
115 masterHeapInfo.SetType(rHeap.GetTypeFromHelper()); |
|
116 masterHeapInfo.SetTid( iHeapInfoParams.iTid ); |
|
117 masterHeapInfo.SetPid( OSAdaption().DThread().GetOwningProcessId( *thread ) ); |
|
118 |
|
119 // This is the RHeap-specific object that contains all RHeap info |
|
120 TMemSpyHeapInfoRHeap& rHeapInfo = masterHeapInfo.AsRHeap(); |
|
121 |
|
122 |
|
123 // We must walk the client's heap in order to build statistics |
|
124 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - calling heap walker constructor...")); |
|
125 RMemSpyDriverHeapWalker heapWalker(rHeap); |
|
126 if (iHeapInfoParams.iBuildFreeCellList || iHeapInfoParams.iBuildAllocCellList) |
|
127 { |
|
128 heapWalker.SetObserver( this ); |
|
129 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - collecting cells")); |
|
130 } |
|
131 else |
|
132 { |
|
133 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - not collecting cells")); |
|
134 } |
|
135 |
|
136 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - starting traversal ..." )); |
|
137 |
|
138 #if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) ) |
|
139 heapWalker.SetPrintDebug(); |
|
140 #endif |
|
141 if (r == KErrNone) r = heapWalker.Traverse(); |
|
142 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - finished traversal - err: %d", r )); |
|
143 |
|
144 TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); |
|
145 heapWalker.CopyStatsTo( rHeapStats ); |
|
146 |
|
147 // Get remaining meta data that isn't stored elsewhere |
|
148 TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); |
|
149 DChunk& userHeapChunk = rHeap.Chunk(); |
|
150 TFullName chunkName; |
|
151 userHeapChunk.FullName(chunkName); |
|
152 rHeapMetaData.SetChunkName( chunkName ); |
|
153 rHeapMetaData.SetChunkSize( (TUint) OSAdaption().DChunk().GetSize( userHeapChunk ) ); |
|
154 rHeapMetaData.SetChunkHandle( &userHeapChunk ); |
|
155 rHeapMetaData.SetChunkBaseAddress( OSAdaption().DChunk().GetBase( userHeapChunk ) ); |
|
156 rHeapMetaData.SetDebugAllocator(rHeap.Helper()->AllocatorIsUdeb()); |
|
157 rHeapMetaData.SetUserThread( ETrue ); |
|
158 rHeapMetaData.iHeapSize = rHeap.Helper()->CommittedSize(); |
|
159 rHeapMetaData.iAllocatorAddress = (TAny*)rHeap.Helper()->AllocatorAddress(); |
|
160 rHeapMetaData.iMinHeapSize = rHeap.Helper()->MinCommittedSize(); |
|
161 rHeapMetaData.iMaxHeapSize = rHeap.Helper()->MaxCommittedSize(); |
|
162 |
|
163 PrintHeapInfo( masterHeapInfo ); |
|
164 |
|
165 // Write free cells if requested |
|
166 if ( r == KErrNone && (iHeapInfoParams.iBuildFreeCellList || iHeapInfoParams.iBuildAllocCellList)) |
|
167 { |
|
168 r = PrepareCellListTransferBuffer(); |
|
169 } |
|
170 |
|
171 // Update info ready for writing back to the user-side |
|
172 if ( r >= KErrNone ) |
|
173 { |
|
174 // Write results back to user-side |
|
175 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - writing to user-side...")); |
|
176 TMemSpyHeapInfo* userMasterInfo = iHeapInfoParams.iMasterInfo; |
|
177 const TInt error = Kern::ThreadRawWrite( &ClientThread(), userMasterInfo, &masterHeapInfo, sizeof(TMemSpyHeapInfo) ); |
|
178 if ( error < 0 ) |
|
179 { |
|
180 r = error; |
|
181 } |
|
182 } |
|
183 |
|
184 // Release resources |
|
185 rHeap.Close(); |
|
186 } |
|
187 } |
|
188 else |
|
189 { |
|
190 r = KErrAccessDenied; |
|
191 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData - parent process not suspended => KErrAccessDenied")); |
|
192 } |
|
193 |
|
194 CloseTempObject(); |
|
195 } |
|
196 } |
|
197 |
|
198 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetInfoData() - END - ret: %d", r)); |
|
199 return r; |
|
200 } |
|
201 |
|
202 TInt DMemSpyDriverLogChanHeapDataUser::GetFullData( TMemSpyDriverInternalHeapDataParams& aParams ) |
|
203 { |
|
204 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData() - START") ); |
|
205 |
|
206 TInt r = OpenTempObject( aParams.iTid, EThread ); |
|
207 if ( r != KErrNone ) |
|
208 { |
|
209 Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData() - END - thread not found"); |
|
210 return r; |
|
211 } |
|
212 else |
|
213 { |
|
214 const DMemSpyDriverLogChanHeapBase::TDrmMatchType drmMatchType = IsDrmThread( TempObjectAsThread() ); |
|
215 |
|
216 if ( drmMatchType != DMemSpyDriverLogChanHeapBase::EMatchTypeNone ) |
|
217 { |
|
218 // Check whether it's a DRM thread... |
|
219 DThread* thread = (DThread*) TempObject(); |
|
220 Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData() - END - Not allowing dump of DRM heap - matchType: %d, thread: %O", drmMatchType, thread ); |
|
221 CloseTempObject(); |
|
222 return KErrAccessDenied; |
|
223 } |
|
224 } |
|
225 |
|
226 // Check that the process' thread's are suspended |
|
227 DThread* thread = (DThread*) TempObject(); |
|
228 if ( SuspensionManager().IsSuspended( *thread ) ) |
|
229 { |
|
230 // Open the heap |
|
231 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData - thread: %O", thread) ); |
|
232 RMemSpyDriverRHeapUser heap( OSAdaption() ); |
|
233 r = heap.OpenUserHeap(*thread, aParams.iDebugAllocator); |
|
234 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData - opening heap returned: %d", r) ); |
|
235 if (r == KErrNone) |
|
236 { |
|
237 r = DoGetFullData(aParams, thread, heap); |
|
238 } |
|
239 else |
|
240 { |
|
241 Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData - couldnt open heap for thread %O, err=%d", thread, r); |
|
242 r = KErrNotSupported; |
|
243 } |
|
244 heap.Close(); |
|
245 } |
|
246 else |
|
247 { |
|
248 Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData - parent process not suspended => KErrAccessDenied - thread: %O", thread ); |
|
249 r = KErrAccessDenied; |
|
250 } |
|
251 |
|
252 CloseTempObject(); |
|
253 |
|
254 TRACE( Kern::Printf("DMemSpyDriverLogChanHeapDataUser::GetFullData() - END - ret: %d", r) ); |
|
255 return r; |
|
256 } |