|
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.Text; |
|
19 using System.Collections.Generic; |
|
20 using CrashItemLib.Crash; |
|
21 using CrashItemLib.Crash.Base; |
|
22 using CrashItemLib.Crash.Processes; |
|
23 using CrashItemLib.Crash.Registers; |
|
24 using CrashItemLib.Crash.Stacks; |
|
25 using CrashItemLib.Crash.CodeSegs; |
|
26 using CrashItemLib.Crash.Threads; |
|
27 using CrashItemLib.Crash.Messages; |
|
28 using SymbianStructuresLib.Arm.Registers; |
|
29 |
|
30 namespace CrashItemLib.Crash.Summarisable |
|
31 { |
|
32 public class CISummarisableEntity : CIElement |
|
33 { |
|
34 #region Enumerations |
|
35 public enum TContext |
|
36 { |
|
37 /// <summary> |
|
38 /// A thread-specific entity, the normal case when the crash occurs within a Symbian |
|
39 /// OS kernel or user side thread context. |
|
40 /// </summary> |
|
41 EContextTypeThread = 0, |
|
42 |
|
43 /// <summary> |
|
44 /// An exception mode entity. For example, an object that represents the associated |
|
45 /// stack et al for an IRQ handler or FIQ handler crash. |
|
46 /// </summary> |
|
47 EContextTypeException |
|
48 } |
|
49 |
|
50 public enum TElement |
|
51 { |
|
52 EElementThread = 0, |
|
53 EElementProcess, |
|
54 EElementCodeSegments, |
|
55 EElementStack, |
|
56 EElementRegisters |
|
57 } |
|
58 #endregion |
|
59 |
|
60 #region Constructors |
|
61 /// <summary> |
|
62 /// Preferred constructor that is called by CISummarisableEntityList during finalization. |
|
63 /// This constructor is used to create a summary wrapper for any stack-level objects that |
|
64 /// were created during container preparation. Those stack objects may be stand-alone exception |
|
65 /// mode stacks (IRQ, FIQ, ABT, UND et al) or then they may be associated with a specific |
|
66 /// Symbian OS thread (user or supervisor). |
|
67 /// </summary> |
|
68 /// <param name="aStack"></param> |
|
69 internal CISummarisableEntity( CIStack aStack ) |
|
70 : base( aStack.Container ) |
|
71 { |
|
72 // NB: If the stack has an associated register list, |
|
73 // and the register list's owner is a thread, then we |
|
74 // automatically know we're dealing with a thread-based stack. |
|
75 AddChild( aStack ); |
|
76 } |
|
77 |
|
78 /// <summary> |
|
79 /// Fall back constructor which is called when the thread in question has no associated |
|
80 /// stack. This means that stack data is unavailable and therefore stack reconstruction is |
|
81 /// obviously impossible. However, the thread (and by implication the process) may well still |
|
82 /// contain useful information. |
|
83 /// </summary> |
|
84 /// <param name="aThread"></param> |
|
85 internal CISummarisableEntity( CIThread aThread ) |
|
86 : base( aThread.Container ) |
|
87 { |
|
88 AddChild( aThread ); |
|
89 } |
|
90 #endregion |
|
91 |
|
92 #region API |
|
93 public bool IsAvailable( TElement aElement ) |
|
94 { |
|
95 bool ret = false; |
|
96 // |
|
97 switch ( aElement ) |
|
98 { |
|
99 case TElement.EElementThread: |
|
100 ret = ( Thread != null ); |
|
101 break; |
|
102 case TElement.EElementProcess: |
|
103 ret = ( Process != null ); |
|
104 break; |
|
105 case TElement.EElementCodeSegments: |
|
106 ret = ( CodeSegments != null ); |
|
107 break; |
|
108 case TElement.EElementStack: |
|
109 ret = ( Stack != null ); |
|
110 break; |
|
111 case TElement.EElementRegisters: |
|
112 ret = ( Registers != null ); |
|
113 break; |
|
114 } |
|
115 // |
|
116 return ret; |
|
117 } |
|
118 |
|
119 public CIMessageDictionary GetMessages() |
|
120 { |
|
121 CIElementList<CIMessage> list = base.ChildrenByType<CIMessage>( TChildSearchType.EEntireHierarchy ); |
|
122 CIMessageDictionary ret = new CIMessageDictionary( list ); |
|
123 return ret; |
|
124 } |
|
125 #endregion |
|
126 |
|
127 #region Properties |
|
128 public TContext Context |
|
129 { |
|
130 get |
|
131 { |
|
132 TContext ret = TContext.EContextTypeException; |
|
133 // |
|
134 if ( IsAvailable( TElement.EElementThread ) ) |
|
135 { |
|
136 ret = TContext.EContextTypeThread; |
|
137 } |
|
138 // |
|
139 return ret; |
|
140 } |
|
141 } |
|
142 |
|
143 public bool IsAbnormalTermination |
|
144 { |
|
145 get |
|
146 { |
|
147 // A crash can be an exception stack (i.e. without a thread) |
|
148 // or then a thread that has panics/crashed in some way. |
|
149 bool ret = false; |
|
150 // |
|
151 if ( IsAvailable( TElement.EElementThread ) ) |
|
152 { |
|
153 ret = Thread.IsAbnormalTermination; |
|
154 } |
|
155 else if ( IsAvailable( TElement.EElementStack ) ) |
|
156 { |
|
157 // All stand-alone stacks are treated as crashes. |
|
158 ret = true; |
|
159 } |
|
160 // |
|
161 return ret; |
|
162 } |
|
163 } |
|
164 |
|
165 public CIThread Thread |
|
166 { |
|
167 get |
|
168 { |
|
169 CIThread ret = null; |
|
170 |
|
171 // Use the stack object to find associated thread. |
|
172 CIStack stack = this.Stack; |
|
173 if ( stack != null ) |
|
174 { |
|
175 ret = stack.OwningThread; |
|
176 } |
|
177 |
|
178 // Did we find a thread? If not, fall back to trying our children. |
|
179 if ( ret == null ) |
|
180 { |
|
181 // Register set unavailable - check child nodes for |
|
182 // presence of thread object. Implies no stack data for |
|
183 // this summary wrapper object. |
|
184 ret = base.ChildByType( typeof( CIThread ) ) as CIThread; |
|
185 } |
|
186 // |
|
187 return ret; |
|
188 } |
|
189 } |
|
190 |
|
191 public CIProcess Process |
|
192 { |
|
193 get |
|
194 { |
|
195 CIProcess ret = null; |
|
196 // |
|
197 if ( Thread != null ) |
|
198 { |
|
199 ret = Thread.OwningProcess; |
|
200 } |
|
201 // |
|
202 return ret; |
|
203 } |
|
204 } |
|
205 |
|
206 public CICodeSegList CodeSegments |
|
207 { |
|
208 get |
|
209 { |
|
210 CICodeSegList ret = null; |
|
211 // |
|
212 CIProcess process = this.Process; |
|
213 if ( process != null ) |
|
214 { |
|
215 ret = process.CodeSegments; |
|
216 } |
|
217 // |
|
218 return ret; |
|
219 } |
|
220 } |
|
221 |
|
222 public CIRegisterList Registers |
|
223 { |
|
224 get |
|
225 { |
|
226 CIRegisterList ret = null; |
|
227 // |
|
228 CIStack stack = this.Stack; |
|
229 if ( stack != null ) |
|
230 { |
|
231 // Use registers associated with stack |
|
232 ret = stack.Registers; |
|
233 } |
|
234 else |
|
235 { |
|
236 // No stack, if we have a thread then try to |
|
237 // find the thread register list that is current. |
|
238 CIThread thread = this.Thread; |
|
239 if ( thread != null ) |
|
240 { |
|
241 ret = thread.CurrentProcessorModeRegisters; |
|
242 } |
|
243 } |
|
244 // |
|
245 return ret; |
|
246 } |
|
247 } |
|
248 |
|
249 public CIStack Stack |
|
250 { |
|
251 get |
|
252 { |
|
253 // Might return null |
|
254 CIStack ret = base.ChildByType( typeof( CIStack ) ) as CIStack; |
|
255 return ret; |
|
256 } |
|
257 } |
|
258 |
|
259 public TArmRegisterBank Bank |
|
260 { |
|
261 get |
|
262 { |
|
263 TArmRegisterBank ret = TArmRegisterBank.ETypeUnknown; |
|
264 // |
|
265 if ( IsAvailable( TElement.EElementStack ) ) |
|
266 { |
|
267 ret = Stack.Type; |
|
268 } |
|
269 // |
|
270 return ret; |
|
271 } |
|
272 } |
|
273 |
|
274 public override string Name |
|
275 { |
|
276 get |
|
277 { |
|
278 StringBuilder ret = new StringBuilder(); |
|
279 // |
|
280 if ( IsAvailable( TElement.EElementThread ) ) |
|
281 { |
|
282 // Just use thread name |
|
283 ret.Append( Thread.FullName ); |
|
284 } |
|
285 else if ( IsAvailable( TElement.EElementStack ) ) |
|
286 { |
|
287 // Get associated bank type |
|
288 TArmRegisterBank bank = Stack.Registers.Bank; |
|
289 string type = ArmRegisterBankUtils.BankAsStringLong( bank ); |
|
290 ret.AppendFormat( "{0} mode", type ); |
|
291 } |
|
292 // |
|
293 return ret.ToString(); |
|
294 } |
|
295 set |
|
296 { |
|
297 } |
|
298 } |
|
299 #endregion |
|
300 |
|
301 #region Internal methods |
|
302 #endregion |
|
303 |
|
304 #region Data members |
|
305 #endregion |
|
306 } |
|
307 } |