|
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 using System; |
|
18 using System.IO; |
|
19 using System.Collections.Generic; |
|
20 using System.Text; |
|
21 using System.Threading; |
|
22 using System.Windows.Forms; |
|
23 using SymbianUtils.Range; |
|
24 using SymbianUtils.Tracer; |
|
25 using SymbianStructuresLib.CodeSegments; |
|
26 using SymbianStructuresLib.Debug.Symbols; |
|
27 using SymbianDebugLib.Engine; |
|
28 using SymbianDebugLib.Entity; |
|
29 using SymbianDebugLib.PluginAPI; |
|
30 using SymbianDebugLib.PluginAPI.Types; |
|
31 using SymbianDebugLib.PluginAPI.Types.Symbols; |
|
32 |
|
33 namespace SymbolTestGUI |
|
34 { |
|
35 public partial class Form1 : Form, ITracer |
|
36 { |
|
37 #region Constructors |
|
38 public Form1() |
|
39 { |
|
40 InitializeComponent(); |
|
41 |
|
42 iDebugEngine = new DbgEngine( this ); |
|
43 iDebugEngine.UiMode = SymbianDebugLib.TDbgUiMode.EUiDisabled; |
|
44 iDebugEngine.EntityPrimingStarted += new DbgEngine.EventHandler( DebugEngine_EntityPrimingStarted ); |
|
45 iDebugEngine.EntityPrimingProgress += new DbgEngine.EventHandler( DebugEngine_EntityPrimingProgress ); |
|
46 iDebugEngine.EntityPrimingComplete += new DbgEngine.EventHandler( DebugEngine_EntityPrimingComplete ); |
|
47 } |
|
48 #endregion |
|
49 |
|
50 #region Event handlers |
|
51 private void DebugEngine_EntityPrimingStarted( DbgEngine aEngine, DbgEntity aEntity, object aContext ) |
|
52 { |
|
53 if ( this.InvokeRequired ) |
|
54 { |
|
55 DbgEngine.EventHandler observer = new DbgEngine.EventHandler( DebugEngine_EntityPrimingStarted ); |
|
56 this.BeginInvoke( observer, new object[] { aEngine, aEntity, aContext } ); |
|
57 } |
|
58 else |
|
59 { |
|
60 label1.Text = "Reading..."; |
|
61 progressBar1.Minimum = 0; |
|
62 progressBar1.Maximum = 100; |
|
63 progressBar1.Value = 0; |
|
64 } |
|
65 } |
|
66 |
|
67 private void DebugEngine_EntityPrimingProgress( DbgEngine aEngine, DbgEntity aEntity, object aContext ) |
|
68 { |
|
69 if ( this.InvokeRequired ) |
|
70 { |
|
71 DbgEngine.EventHandler observer = new DbgEngine.EventHandler( DebugEngine_EntityPrimingProgress ); |
|
72 this.BeginInvoke( observer, new object[] { aEngine, aEntity, aContext } ); |
|
73 } |
|
74 else |
|
75 { |
|
76 if ( aContext != null && aContext is int ) |
|
77 { |
|
78 progressBar1.Value = (int) aContext; |
|
79 } |
|
80 } |
|
81 } |
|
82 |
|
83 private void DebugEngine_EntityPrimingComplete( DbgEngine aEngine, DbgEntity aEntity, object aContext ) |
|
84 { |
|
85 if ( this.InvokeRequired ) |
|
86 { |
|
87 DbgEngine.EventHandler observer = new DbgEngine.EventHandler( DebugEngine_EntityPrimingComplete ); |
|
88 this.BeginInvoke( observer, new object[] { aEngine, aEntity, aContext } ); |
|
89 } |
|
90 else |
|
91 { |
|
92 DateTime endTime = DateTime.Now; |
|
93 TimeSpan span = endTime - iStartTime; |
|
94 label1.Text = "Done - " + span.ToString(); |
|
95 progressBar1.Value = progressBar1.Maximum; |
|
96 |
|
97 if ( AreAllEntitiesPrimed ) |
|
98 { |
|
99 RunTests(); |
|
100 } |
|
101 } |
|
102 } |
|
103 |
|
104 private void button1_Click( object sender, EventArgs e ) |
|
105 { |
|
106 iDebugEngine.Add( @"Z:\epoc32\rom\S60_3_2_200846_RnD_merlin_emulator_hw.rom.symbol" ); |
|
107 //iDebugEngine.Add( @"z:\epoc32\rom\S60_3_2_200846_RnD_merlin_emulator_hw.rofs1.oby" ); |
|
108 //iDebugEngine.Add( @"C:\Tool Demo Files\2. Crash Data\File43\CoreImage\MemSpy.EXE.map" ); |
|
109 iDebugEngine.Add( @"C:\Tool Demo Files\2. Crash Data\File44\Platform_wk49\Symbols\mapfiles.zip" ); |
|
110 //iDebugEngine.Add( @"C:\Tool Demo Files\2. Crash Data\File55\alarmserver.exe.map" ); |
|
111 |
|
112 iStartTime = DateTime.Now; |
|
113 iDebugEngine.Prime( SymbianUtils.TSynchronicity.EAsynchronous ); |
|
114 } |
|
115 #endregion |
|
116 |
|
117 #region Internal methods |
|
118 private bool AreAllEntitiesPrimed |
|
119 { |
|
120 get |
|
121 { |
|
122 bool ret = true; |
|
123 // |
|
124 foreach ( DbgEntity entity in iDebugEngine ) |
|
125 { |
|
126 if ( !entity.IsPrimed ) |
|
127 { |
|
128 ret = false; |
|
129 break; |
|
130 } |
|
131 } |
|
132 // |
|
133 return ret; |
|
134 } |
|
135 } |
|
136 |
|
137 private void RunTests() |
|
138 { |
|
139 //RunObyMapViewTest(); |
|
140 RunZipMapFileTest(); |
|
141 } |
|
142 |
|
143 private void RunObyMapViewTest() |
|
144 { |
|
145 CodeSegDefinitionCollection codeSegs = new CodeSegDefinitionCollection(); |
|
146 // |
|
147 codeSegs.Add( new CodeSegDefinition( @"Z:\sys\bin\WidgetLauncher.exe", 0x7A120000, 0x7A170000 ) ); |
|
148 |
|
149 using ( DbgEngineView view = iDebugEngine.CreateView( "TestView", codeSegs ) ) |
|
150 { |
|
151 } |
|
152 } |
|
153 |
|
154 private void CheckNoOverlaps( SymbolCollection aCollection ) |
|
155 { |
|
156 int count = aCollection.Count; |
|
157 for ( int i = 0; i < count - 1; i++ ) |
|
158 { |
|
159 Symbol s1 = aCollection[ i + 0 ]; |
|
160 Symbol s2 = aCollection[ i + 1 ]; |
|
161 // |
|
162 System.Diagnostics.Debug.WriteLine( "Comparing: " + s1 + " vs " + s2 ); |
|
163 // |
|
164 System.Diagnostics.Debug.Assert( s1.AddressRange.Min <= s1.AddressRange.Max ); |
|
165 System.Diagnostics.Debug.Assert( s1.AddressRange.Min < s2.AddressRange.Min ); |
|
166 System.Diagnostics.Debug.Assert( s1.AddressRange.Max < s2.AddressRange.Min ); |
|
167 } |
|
168 } |
|
169 |
|
170 private Symbol FindByName( string aName, SymbolCollection aCollection ) |
|
171 { |
|
172 Symbol ret = null; |
|
173 // |
|
174 foreach ( Symbol sym in aCollection ) |
|
175 { |
|
176 if ( sym.Name == aName ) |
|
177 { |
|
178 ret = sym; |
|
179 break; |
|
180 } |
|
181 } |
|
182 // |
|
183 return ret; |
|
184 } |
|
185 |
|
186 private void RunZipMapFileTest() |
|
187 { |
|
188 // So we can spot it in the profiler... |
|
189 //Thread.Sleep( 2000 ); |
|
190 |
|
191 using ( DbgEngineView view = iDebugEngine.CreateView( "TestView" ) ) |
|
192 { |
|
193 DbgViewSymbols symView = view.Symbols; |
|
194 |
|
195 // Should be possible to activate a file within a zip |
|
196 SymbolCollection activatedCol = symView.ActivateAndGetCollection( new CodeSegDefinition( @"Z:\sys\bin\AcCmOnItOr.dll", 0x70000000, 0x7A000000 ) ); |
|
197 System.Diagnostics.Debug.Assert( activatedCol != null ); |
|
198 |
|
199 // Verify that the symbols were really read. |
|
200 SymbolCollection col = view.Symbols.CollectionByAddress( 0x70000000 ); |
|
201 //System.Diagnostics.Debug.Assert( col.Count == 0xaa ); |
|
202 System.Diagnostics.Debug.WriteLine( col.ToString( "full", null ) ); |
|
203 |
|
204 // Verify that the collections are the same |
|
205 System.Diagnostics.Debug.Assert( activatedCol.Count == col.Count ); |
|
206 System.Diagnostics.Debug.Assert( activatedCol.FileName == col.FileName ); |
|
207 System.Diagnostics.Debug.Assert( activatedCol == col ); |
|
208 |
|
209 // Cannot activate the same dll twice |
|
210 bool activated = symView.Activate( new CodeSegDefinition( @"Z:\sys\bin\AcCmOnItOr.dll", 0x80000000, 0x8A000000 ) ); |
|
211 System.Diagnostics.Debug.Assert( activated == false ); |
|
212 |
|
213 // Cannot activate an overlapping area. |
|
214 activated = symView.Activate( new CodeSegDefinition( @"Z:\sys\bin\AIFW.dll", 0x70000000, 0x70040000 ) ); |
|
215 System.Diagnostics.Debug.Assert( activated == false ); |
|
216 |
|
217 // Cannot deactivate a non-activated dll |
|
218 bool deactivated = symView.Deactivate( new CodeSegDefinition( @"Z:\sys\bin\AIUTILS.DLL" ) ); |
|
219 System.Diagnostics.Debug.Assert( deactivated == false ); |
|
220 |
|
221 // Cannot deactivate a missing dll |
|
222 deactivated = symView.Deactivate( new CodeSegDefinition( @"Z:\sys\bin\THIS_DOES_NOT_EXIST.EXE" ) ); |
|
223 System.Diagnostics.Debug.Assert( deactivated == false ); |
|
224 |
|
225 // Look up first symbol |
|
226 Symbol sym = null; |
|
227 Symbol sym2 = null; |
|
228 sym = symView.Lookup( 0x70000000, out col ); |
|
229 System.Diagnostics.Debug.Assert( sym != null && col == activatedCol && sym.Name == "_E32Dll" ); |
|
230 sym = symView.Lookup( 0x70000027, out col ); |
|
231 System.Diagnostics.Debug.Assert( sym != null && col == activatedCol && sym.Name == "_E32Dll" ); |
|
232 |
|
233 // For the following sequence, ensure that we discard the CAccMonitor::~CAccMonitor__sub_object() |
|
234 // line and keep the CAccMonitor::~CAccMonitor() line instead. Ensure that the size of the |
|
235 // CAccMonitor::~CAccMonitor() entry has been calculated using the data from the sub_object entry which |
|
236 // we threw away. |
|
237 // |
|
238 // CAccMonitor::~CAccMonitor__deallocating() 0x00009195 Thumb Code 16 accmonitor.in(i._ZN11CAccMonitorD0Ev) |
|
239 // CAccMonitor::~CAccMonitor() 0x000091a5 Thumb Code 0 accmonitor.in(i._ZN11CAccMonitorD2Ev) |
|
240 // CAccMonitor::~CAccMonitor__sub_object() 0x000091a5 Thumb Code 8 accmonitor.in(i._ZN11CAccMonitorD2Ev) |
|
241 // CAccMonitorInfo::Reset() 0x000091ad Thumb Code 28 accmonitor.in(i._ZN15CAccMonitorInfo5ResetEv) |
|
242 // |
|
243 sym = FindByName( "CAccMonitor::~CAccMonitor__sub_object()", col ); |
|
244 System.Diagnostics.Debug.Assert( sym == null ); |
|
245 sym = FindByName( "CAccMonitor::~CAccMonitor()", col ); |
|
246 System.Diagnostics.Debug.Assert( sym != null && sym.Size == 8 ); |
|
247 |
|
248 // For the following sequence, ensure that we discard the sub object and keep the destructor. |
|
249 // |
|
250 // RArray<unsigned long>::RArray() 0x00009289 Thumb Code 10 accmonitor.in(t._ZN6RArrayImEC1Ev) |
|
251 // RArray<unsigned long>::RArray__sub_object() 0x00009289 Thumb Code 0 accmonitor.in(t._ZN6RArrayImEC1Ev) |
|
252 sym = FindByName( "RArray<unsigned long>::RArray__sub_object()", col ); |
|
253 System.Diagnostics.Debug.Assert( sym == null ); |
|
254 sym = FindByName( "RArray<unsigned long>::RArray()", col ); |
|
255 System.Diagnostics.Debug.Assert( sym != null && sym.Size == 10 ); |
|
256 |
|
257 // For the following sequence, ensure that the end of the first entry doesn't overlap with the start of the second. |
|
258 // |
|
259 // typeinfo name for CAccMonitorCapMapper 0x000094a8 Data 23 accmonitor.in(.constdata__ZTS20CAccMonitorCapMapper) |
|
260 // typeinfo name for CAccMonitorContainer 0x000094bf Data 23 accmonitor.in(.constdata__ZTS20CAccMonitorContainer) |
|
261 // |
|
262 sym = FindByName( "typeinfo name for CAccMonitorCapMapper", col ); |
|
263 System.Diagnostics.Debug.Assert( sym != null ); |
|
264 sym2 = FindByName( "typeinfo name for CAccMonitorContainer", col ); |
|
265 System.Diagnostics.Debug.Assert( sym2 != null ); |
|
266 System.Diagnostics.Debug.Assert( sym.AddressRange.Max + 1 == sym2.Address ); |
|
267 |
|
268 // Check no overlap |
|
269 CheckNoOverlaps( col ); |
|
270 |
|
271 // Second symbol |
|
272 sym = symView.Lookup( 0x70000028, out col ); |
|
273 System.Diagnostics.Debug.Assert( sym != null && col == activatedCol && sym.Name == "__cpp_initialize__aeabi_" ); |
|
274 |
|
275 // Multithreaded symbol lookup times |
|
276 ThreadPool.QueueUserWorkItem( new WaitCallback( MultiThreadedLookup ), new AsyncData( symView, iWaiter1, col, 10000 ) ); |
|
277 ThreadPool.QueueUserWorkItem( new WaitCallback( MultiThreadedLookup ), new AsyncData( symView, iWaiter2, col, 5000 ) ); |
|
278 ThreadPool.QueueUserWorkItem( new WaitCallback( MultiThreadedLookup ), new AsyncData( symView, iWaiter3, col, 8000 ) ); |
|
279 ThreadPool.QueueUserWorkItem( new WaitCallback( MultiThreadedLookup ), new AsyncData( symView, iWaiter4, col, 20000 ) ); |
|
280 |
|
281 // Wait |
|
282 using( iWaiter4 ) |
|
283 { |
|
284 iWaiter4.WaitOne(); |
|
285 } |
|
286 using ( iWaiter3 ) |
|
287 { |
|
288 iWaiter3.WaitOne(); |
|
289 } |
|
290 using ( iWaiter2 ) |
|
291 { |
|
292 iWaiter2.WaitOne(); |
|
293 } |
|
294 using ( iWaiter1 ) |
|
295 { |
|
296 iWaiter1.WaitOne(); |
|
297 } |
|
298 |
|
299 // Deactivate an activated dll |
|
300 deactivated = symView.Deactivate( new CodeSegDefinition( @"Z:\sys\bin\ACCMONITOR.DLL" ) ); |
|
301 System.Diagnostics.Debug.Assert( deactivated == true ); |
|
302 |
|
303 // symbol shouldn't be available anymore |
|
304 sym = symView.Lookup( 0x70000000, out col ); |
|
305 System.Diagnostics.Debug.Assert( sym == null && col == null ); |
|
306 } |
|
307 } |
|
308 |
|
309 #region Internal classes |
|
310 private class AsyncData |
|
311 { |
|
312 public AsyncData( DbgViewSymbols aView, AutoResetEvent aWaiter, SymbolCollection aCollection, int aIterations ) |
|
313 { |
|
314 iView = aView; |
|
315 iWaiter = aWaiter; |
|
316 iCollection = aCollection; |
|
317 iIterations = aIterations; |
|
318 } |
|
319 |
|
320 public readonly DbgViewSymbols iView; |
|
321 public readonly AutoResetEvent iWaiter; |
|
322 public readonly SymbolCollection iCollection; |
|
323 public readonly int iIterations; |
|
324 } |
|
325 #endregion |
|
326 |
|
327 private void MultiThreadedLookup( object aState ) |
|
328 { |
|
329 AsyncData data = (AsyncData) aState; |
|
330 Random rand = new Random( 666 ); |
|
331 AddressRange colRange = data.iCollection.SubsumedPrimaryRange; |
|
332 // |
|
333 for ( int i = 0; i < data.iIterations; i++ ) |
|
334 { |
|
335 uint offset = (uint) rand.Next( (int) colRange.Size ); |
|
336 uint address = colRange.Min + offset; |
|
337 // |
|
338 SymbolCollection col = null; |
|
339 Symbol sym = data.iView.Lookup( address, out col ); |
|
340 } |
|
341 |
|
342 data.iWaiter.Set(); |
|
343 } |
|
344 #endregion |
|
345 |
|
346 #region ITracer Members |
|
347 public void Trace( string aMessage ) |
|
348 { |
|
349 System.Diagnostics.Debug.WriteLine( aMessage ); |
|
350 } |
|
351 |
|
352 public void Trace( string aFormat, params object[] aParams ) |
|
353 { |
|
354 string t = string.Format( aFormat, aParams ); |
|
355 Trace( t ); |
|
356 } |
|
357 #endregion |
|
358 |
|
359 #region Data members |
|
360 private DateTime iStartTime = new DateTime(); |
|
361 private readonly DbgEngine iDebugEngine; |
|
362 private AutoResetEvent iWaiter1 = new AutoResetEvent( false ); |
|
363 private AutoResetEvent iWaiter2 = new AutoResetEvent( false ); |
|
364 private AutoResetEvent iWaiter3 = new AutoResetEvent( false ); |
|
365 private AutoResetEvent iWaiter4 = new AutoResetEvent( false ); |
|
366 #endregion |
|
367 } |
|
368 } |