|
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.Text; |
|
20 using System.Collections.Generic; |
|
21 using SymbianUtils; |
|
22 using SymbianUtils.Range; |
|
23 using SymbianUtils.Streams; |
|
24 using SymbianStructuresLib.Arm; |
|
25 using SymbianStructuresLib.Arm.Instructions; |
|
26 using SymbianStructuresLib.CodeSegments; |
|
27 using SymbianStructuresLib.Debug.Common.Id; |
|
28 using SymbianStructuresLib.Debug.Common.FileName; |
|
29 using SymbianStructuresLib.Debug.Common.Interfaces; |
|
30 using SymbianStructuresLib.Debug.Code.Interfaces; |
|
31 |
|
32 namespace SymbianStructuresLib.Debug.Code |
|
33 { |
|
34 public sealed class CodeCollection : DisposableObject, IComparable<CodeCollection>, IArmInstructionProvider |
|
35 { |
|
36 #region Static constructors |
|
37 public static CodeCollection New( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice ) |
|
38 { |
|
39 CodeCollection ret = new CodeCollection( aIdAllocator, aFileNameInHost, aFileNameInDevice ); |
|
40 return ret; |
|
41 } |
|
42 |
|
43 public static CodeCollection NewCopy( IPlatformIdAllocator aIdAllocator, CodeCollection aCollection ) |
|
44 { |
|
45 CodeCollection ret = new CodeCollection( aIdAllocator, aCollection ); |
|
46 return ret; |
|
47 } |
|
48 |
|
49 public static CodeCollection NewByHostFileName( IPlatformIdAllocator aIdAllocator, string aFileName ) |
|
50 { |
|
51 CodeCollection ret = new CodeCollection( aIdAllocator, aFileName ); |
|
52 return ret; |
|
53 } |
|
54 #endregion |
|
55 |
|
56 #region Delegates & events |
|
57 public delegate void RelocationStatusChangeHandler( CodeCollection aCollection ); |
|
58 public event RelocationStatusChangeHandler RelocationStatusChanged; |
|
59 #endregion |
|
60 |
|
61 #region Constructors |
|
62 private CodeCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost ) |
|
63 { |
|
64 iId = aIdAllocator.AllocateId(); |
|
65 iFileName = PlatformFileName.NewByHostName( aFileNameInHost ); |
|
66 } |
|
67 |
|
68 private CodeCollection( IPlatformIdAllocator aIdAllocator, string aFileNameInHost, string aFileNameInDevice ) |
|
69 : this( aIdAllocator, aFileNameInHost ) |
|
70 { |
|
71 iFileName.FileNameInDevice = aFileNameInDevice; |
|
72 } |
|
73 |
|
74 private CodeCollection( IPlatformIdAllocator aIdAllocator, CodeCollection aCopy ) |
|
75 { |
|
76 iId = aIdAllocator.AllocateId(); |
|
77 // |
|
78 iCode = aCopy.iCode; |
|
79 iTag = aCopy.iTag; |
|
80 iFlags = aCopy.iFlags; |
|
81 iTagged = aCopy.iTagged; |
|
82 iBaseAddress = aCopy.iBaseAddress; |
|
83 iCodeSegmentResolver = aCopy.iCodeSegmentResolver; |
|
84 iRelocationHandler = aCopy.iRelocationHandler; |
|
85 iFileName = PlatformFileName.New( aCopy.FileName ); |
|
86 iInstructionConverter = aCopy.IfaceInstructionConverter; |
|
87 iCodeSegmentResolver = aCopy.IfaceCodeSegmentResolver; |
|
88 iRelocationHandler = aCopy.IfaceRelocationHandler; |
|
89 } |
|
90 #endregion |
|
91 |
|
92 #region API |
|
93 public bool Contains( uint aAddress ) |
|
94 { |
|
95 bool ret = IsInstructionAddressValid( aAddress ); |
|
96 return ret; |
|
97 } |
|
98 |
|
99 public bool IsMatchingCodeSegment( CodeSegDefinition aCodeSegment ) |
|
100 { |
|
101 bool ret = false; |
|
102 // |
|
103 if ( iCodeSegmentResolver != null ) |
|
104 { |
|
105 ret = iCodeSegmentResolver.IsMatchingCodeSegment( this, aCodeSegment ); |
|
106 } |
|
107 else |
|
108 { |
|
109 PlatformFileName codeSegName = PlatformFileName.NewByDeviceName( aCodeSegment.FileName ); |
|
110 ret = FileName.Equals( codeSegName ); |
|
111 } |
|
112 // |
|
113 return ret; |
|
114 } |
|
115 |
|
116 public void Relocate( uint aTo ) |
|
117 { |
|
118 if ( aTo != iBaseAddress ) |
|
119 { |
|
120 uint old = iBaseAddress; |
|
121 iBaseAddress = aTo; |
|
122 // |
|
123 if ( iRelocationHandler != null ) |
|
124 { |
|
125 iRelocationHandler.PrepareForRelocation( this, old, BaseAddress ); |
|
126 } |
|
127 } |
|
128 } |
|
129 #endregion |
|
130 |
|
131 #region Properties |
|
132 public uint Size |
|
133 { |
|
134 get |
|
135 { |
|
136 uint ret = 0; |
|
137 if ( iCode != null ) |
|
138 { |
|
139 ret = (uint) iCode.Length; |
|
140 } |
|
141 return ret; |
|
142 } |
|
143 } |
|
144 |
|
145 public bool Tagged |
|
146 { |
|
147 get { return iTagged; } |
|
148 set |
|
149 { |
|
150 iTagged = value; |
|
151 } |
|
152 } |
|
153 |
|
154 public bool IsRelocatable |
|
155 { |
|
156 get { return ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable; } |
|
157 set |
|
158 { |
|
159 lock ( iFlagLock ) |
|
160 { |
|
161 bool wasSet = ( iFlags & TFlags.EFlagsIsRelocatable ) == TFlags.EFlagsIsRelocatable; |
|
162 if ( wasSet != value ) |
|
163 { |
|
164 if ( value ) |
|
165 { |
|
166 iFlags |= TFlags.EFlagsIsRelocatable; |
|
167 } |
|
168 else |
|
169 { |
|
170 iFlags &= ~TFlags.EFlagsIsRelocatable; |
|
171 } |
|
172 |
|
173 // Report event if needed |
|
174 if ( RelocationStatusChanged != null ) |
|
175 { |
|
176 RelocationStatusChanged( this ); |
|
177 } |
|
178 } |
|
179 } |
|
180 } |
|
181 } |
|
182 |
|
183 public bool IsFixed |
|
184 { |
|
185 get { return !IsRelocatable; } |
|
186 set { IsRelocatable = !value; } |
|
187 } |
|
188 |
|
189 public object Tag |
|
190 { |
|
191 get { return iTag; } |
|
192 set |
|
193 { |
|
194 iTag = value; |
|
195 } |
|
196 } |
|
197 |
|
198 public uint BaseAddress |
|
199 { |
|
200 get |
|
201 { |
|
202 uint ret = iBaseAddress; |
|
203 return ret; |
|
204 } |
|
205 } |
|
206 |
|
207 public bool IsCodeAvailable |
|
208 { |
|
209 get { return iCode != null; } |
|
210 } |
|
211 |
|
212 public byte[] Code |
|
213 { |
|
214 get { return iCode; } |
|
215 set |
|
216 { |
|
217 iCode = value; |
|
218 } |
|
219 } |
|
220 |
|
221 public PlatformId Id |
|
222 { |
|
223 get { return iId; } |
|
224 } |
|
225 |
|
226 public PlatformFileName FileName |
|
227 { |
|
228 get { return iFileName; } |
|
229 } |
|
230 |
|
231 public CodeCollectionList ParentList |
|
232 { |
|
233 get { return iParentList; } |
|
234 internal set { iParentList = value; } |
|
235 } |
|
236 #endregion |
|
237 |
|
238 #region Properties - interfaces |
|
239 public ICodeCollectionCodeSegmentResolver IfaceCodeSegmentResolver |
|
240 { |
|
241 get { return iCodeSegmentResolver; } |
|
242 set { iCodeSegmentResolver = value; } |
|
243 } |
|
244 |
|
245 public ICodeCollectionRelocationHandler IfaceRelocationHandler |
|
246 { |
|
247 get { return iRelocationHandler; } |
|
248 set { iRelocationHandler = value; } |
|
249 } |
|
250 |
|
251 public ICodeCollectionInstructionConverter IfaceInstructionConverter |
|
252 { |
|
253 get { return iInstructionConverter; } |
|
254 set { iInstructionConverter = value; } |
|
255 } |
|
256 #endregion |
|
257 |
|
258 #region Internal enumerations |
|
259 [Flags] |
|
260 private enum TFlags : byte |
|
261 { |
|
262 EFlagsNone = 0, |
|
263 EFlagsIsRelocatable = 1 |
|
264 }; |
|
265 #endregion |
|
266 |
|
267 #region Internal constants |
|
268 #endregion |
|
269 |
|
270 #region Internal methods |
|
271 #endregion |
|
272 |
|
273 #region From IArmInstructionProvider |
|
274 public bool IsInstructionAddressValid( uint aAddress ) |
|
275 { |
|
276 bool valid = false; |
|
277 // |
|
278 if ( IsCodeAvailable ) |
|
279 { |
|
280 AddressRange range = new AddressRange( this.BaseAddress, 0 ); |
|
281 range.UpdateMax( range.Min + iCode.Length ); |
|
282 // |
|
283 valid = range.Contains( aAddress ); |
|
284 } |
|
285 // |
|
286 return valid; |
|
287 } |
|
288 |
|
289 public uint GetDataUInt32( uint aAddress ) |
|
290 { |
|
291 uint ret = 0; |
|
292 IArmInstruction[] inst = null; |
|
293 // |
|
294 bool available = GetInstructions( aAddress, TArmInstructionSet.EARM, 1, out inst ); |
|
295 if ( available && inst.Length >= 1 ) |
|
296 { |
|
297 ret = inst[ 0 ].AIRawValue; |
|
298 } |
|
299 // |
|
300 return ret; |
|
301 } |
|
302 |
|
303 public ushort GetDataUInt16( uint aAddress ) |
|
304 { |
|
305 ushort ret = 0; |
|
306 IArmInstruction[] inst = null; |
|
307 // |
|
308 bool available = GetInstructions( aAddress, TArmInstructionSet.ETHUMB, 1, out inst ); |
|
309 if ( available && inst.Length >= 1 ) |
|
310 { |
|
311 ret = inst[ 0 ].AIRawValue; |
|
312 } |
|
313 // |
|
314 return ret; |
|
315 } |
|
316 |
|
317 public bool GetInstructions( uint aAddress, TArmInstructionSet aInstructionSet, int aCount, out IArmInstruction[] aInstructions ) |
|
318 { |
|
319 bool valid = false; |
|
320 aInstructions = new IArmInstruction[ 0 ]; |
|
321 |
|
322 // We need the code and the instruction converter |
|
323 if ( IsCodeAvailable && IfaceInstructionConverter != null ) |
|
324 { |
|
325 // Check range is valid |
|
326 AddressRange range = new AddressRange( iBaseAddress, 0 ); |
|
327 range.UpdateMax( range.Min + iCode.Length ); |
|
328 uint extent = aAddress + ( (uint) aCount * (uint) aInstructionSet ); |
|
329 // |
|
330 valid = range.Contains( aAddress ) && range.Contains( extent ); |
|
331 if ( valid ) |
|
332 { |
|
333 List<uint> rawInstructions = new List<uint>(); |
|
334 // |
|
335 using ( SymbianStreamReaderLE reader = SymbianStreamReaderLE.New( new MemoryStream( iCode ) ) ) |
|
336 { |
|
337 uint address = aAddress - iBaseAddress; |
|
338 reader.Seek( address ); |
|
339 // |
|
340 for ( int i = 0; i < aCount; i++ ) |
|
341 { |
|
342 uint value = 0; |
|
343 // |
|
344 switch ( aInstructionSet ) |
|
345 { |
|
346 case TArmInstructionSet.ETHUMB: |
|
347 value = reader.ReadUInt16(); |
|
348 break; |
|
349 case TArmInstructionSet.EARM: |
|
350 value = reader.ReadUInt32(); |
|
351 break; |
|
352 default: |
|
353 case TArmInstructionSet.EJAZELLE: |
|
354 throw new NotSupportedException( "Jazelle is not supported" ); |
|
355 } |
|
356 // |
|
357 rawInstructions.Add( value ); |
|
358 address += (uint) aInstructionSet; |
|
359 } |
|
360 } |
|
361 // |
|
362 aInstructions = iInstructionConverter.ConvertRawValuesToInstructions( aInstructionSet, rawInstructions.ToArray(), aAddress ); |
|
363 } |
|
364 } |
|
365 |
|
366 // Return empty array if not valid |
|
367 return valid; |
|
368 } |
|
369 #endregion |
|
370 |
|
371 #region From IComparable<CodeCollection> |
|
372 public int CompareTo( CodeCollection aCollection ) |
|
373 { |
|
374 int ret = ( aCollection.FileName == this.FileName ) ? 0 : -1; |
|
375 // |
|
376 if ( ret == 0 ) |
|
377 { |
|
378 if ( BaseAddress == aCollection.BaseAddress ) |
|
379 { |
|
380 ret = 0; |
|
381 } |
|
382 else if ( BaseAddress > aCollection.BaseAddress ) |
|
383 { |
|
384 ret = 1; |
|
385 } |
|
386 else |
|
387 { |
|
388 ret = -1; |
|
389 } |
|
390 } |
|
391 // |
|
392 return ret; |
|
393 } |
|
394 #endregion |
|
395 |
|
396 #region From DisposableObject |
|
397 protected override void CleanupManagedResources() |
|
398 { |
|
399 try |
|
400 { |
|
401 base.CleanupManagedResources(); |
|
402 } |
|
403 finally |
|
404 { |
|
405 iTag = null; |
|
406 iParentList = null; |
|
407 iInstructionConverter = null; |
|
408 iCodeSegmentResolver = null; |
|
409 iRelocationHandler = null; |
|
410 } |
|
411 } |
|
412 #endregion |
|
413 |
|
414 #region From System.Object |
|
415 public override string ToString() |
|
416 { |
|
417 return iFileName.ToString(); |
|
418 } |
|
419 |
|
420 public override bool Equals( object aObject ) |
|
421 { |
|
422 if ( aObject != null && aObject is CodeCollection ) |
|
423 { |
|
424 CodeCollection col = (CodeCollection) aObject; |
|
425 bool ret = ( col.FileName == this.FileName ); |
|
426 return ret; |
|
427 } |
|
428 // |
|
429 return base.Equals( aObject ); |
|
430 } |
|
431 |
|
432 public override int GetHashCode() |
|
433 { |
|
434 return iFileName.GetHashCode(); |
|
435 } |
|
436 #endregion |
|
437 |
|
438 #region Data members |
|
439 private readonly PlatformId iId; |
|
440 private readonly PlatformFileName iFileName; |
|
441 private object iTag = null; |
|
442 private object iFlagLock = new object(); |
|
443 private byte[] iCode = null; |
|
444 private uint iBaseAddress = 0; |
|
445 private bool iTagged = false; |
|
446 private TFlags iFlags = TFlags.EFlagsNone; |
|
447 private CodeCollectionList iParentList = null; |
|
448 private ICodeCollectionCodeSegmentResolver iCodeSegmentResolver = null; |
|
449 private ICodeCollectionRelocationHandler iRelocationHandler = null; |
|
450 private ICodeCollectionInstructionConverter iInstructionConverter = null; |
|
451 #endregion |
|
452 } |
|
453 } |