1 | // -*- mode: c++ -*- |
2 | |
3 | // Copyright (c) 2010 Google Inc. |
4 | // All rights reserved. |
5 | // |
6 | // Redistribution and use in source and binary forms, with or without |
7 | // modification, are permitted provided that the following conditions are |
8 | // met: |
9 | // |
10 | // * Redistributions of source code must retain the above copyright |
11 | // notice, this list of conditions and the following disclaimer. |
12 | // * Redistributions in binary form must reproduce the above |
13 | // copyright notice, this list of conditions and the following disclaimer |
14 | // in the documentation and/or other materials provided with the |
15 | // distribution. |
16 | // * Neither the name of Google Inc. nor the names of its |
17 | // contributors may be used to endorse or promote products derived from |
18 | // this software without specific prior written permission. |
19 | // |
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | |
32 | // stack_frame_cpu.h: CPU-specific StackFrame extensions. |
33 | // |
34 | // These types extend the StackFrame structure to carry CPU-specific register |
35 | // state. They are defined in this header instead of stack_frame.h to |
36 | // avoid the need to include minidump_format.h when only the generic |
37 | // StackFrame type is needed. |
38 | // |
39 | // Author: Mark Mentovai |
40 | |
41 | #ifndef GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ |
42 | #define GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ |
43 | |
44 | #include "google_breakpad/common/minidump_format.h" |
45 | #include "google_breakpad/processor/stack_frame.h" |
46 | |
47 | namespace google_breakpad { |
48 | |
49 | struct WindowsFrameInfo; |
50 | class CFIFrameInfo; |
51 | |
52 | struct StackFrameX86 : public StackFrame { |
53 | // ContextValidity has one entry for each relevant hardware pointer |
54 | // register (%eip and %esp) and one entry for each general-purpose |
55 | // register. It's worthwhile having validity flags for caller-saves |
56 | // registers: they are valid in the youngest frame, and such a frame |
57 | // might save a callee-saves register in a caller-saves register, but |
58 | // SimpleCFIWalker won't touch registers unless they're marked as valid. |
59 | enum ContextValidity { |
60 | CONTEXT_VALID_NONE = 0, |
61 | CONTEXT_VALID_EIP = 1 << 0, |
62 | CONTEXT_VALID_ESP = 1 << 1, |
63 | CONTEXT_VALID_EBP = 1 << 2, |
64 | CONTEXT_VALID_EAX = 1 << 3, |
65 | CONTEXT_VALID_EBX = 1 << 4, |
66 | CONTEXT_VALID_ECX = 1 << 5, |
67 | CONTEXT_VALID_EDX = 1 << 6, |
68 | CONTEXT_VALID_ESI = 1 << 7, |
69 | CONTEXT_VALID_EDI = 1 << 8, |
70 | CONTEXT_VALID_ALL = -1 |
71 | }; |
72 | |
73 | StackFrameX86() |
74 | : context(), |
75 | context_validity(CONTEXT_VALID_NONE), |
76 | windows_frame_info(NULL), |
77 | cfi_frame_info(NULL) {} |
78 | ~StackFrameX86(); |
79 | |
80 | // Overriden to return the return address as saved on the stack. |
81 | virtual uint64_t ReturnAddress() const; |
82 | |
83 | // Register state. This is only fully valid for the topmost frame in a |
84 | // stack. In other frames, the values of nonvolatile registers may be |
85 | // present, given sufficient debugging information. Refer to |
86 | // context_validity. |
87 | MDRawContextX86 context; |
88 | |
89 | // context_validity is actually ContextValidity, but int is used because |
90 | // the OR operator doesn't work well with enumerated types. This indicates |
91 | // which fields in context are valid. |
92 | int context_validity; |
93 | |
94 | // Any stack walking information we found describing this.instruction. |
95 | // These may be NULL if there is no such information for that address. |
96 | WindowsFrameInfo *windows_frame_info; |
97 | CFIFrameInfo *cfi_frame_info; |
98 | }; |
99 | |
100 | struct StackFramePPC : public StackFrame { |
101 | // ContextValidity should eventually contain entries for the validity of |
102 | // other nonvolatile (callee-save) registers as in |
103 | // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently |
104 | // locate registers other than the ones listed here. |
105 | enum ContextValidity { |
106 | CONTEXT_VALID_NONE = 0, |
107 | CONTEXT_VALID_SRR0 = 1 << 0, |
108 | CONTEXT_VALID_GPR1 = 1 << 1, |
109 | CONTEXT_VALID_ALL = -1 |
110 | }; |
111 | |
112 | StackFramePPC() : context(), context_validity(CONTEXT_VALID_NONE) {} |
113 | |
114 | // Register state. This is only fully valid for the topmost frame in a |
115 | // stack. In other frames, the values of nonvolatile registers may be |
116 | // present, given sufficient debugging information. Refer to |
117 | // context_validity. |
118 | MDRawContextPPC context; |
119 | |
120 | // context_validity is actually ContextValidity, but int is used because |
121 | // the OR operator doesn't work well with enumerated types. This indicates |
122 | // which fields in context are valid. |
123 | int context_validity; |
124 | }; |
125 | |
126 | struct StackFramePPC64 : public StackFrame { |
127 | // ContextValidity should eventually contain entries for the validity of |
128 | // other nonvolatile (callee-save) registers as in |
129 | // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently |
130 | // locate registers other than the ones listed here. |
131 | enum ContextValidity { |
132 | CONTEXT_VALID_NONE = 0, |
133 | CONTEXT_VALID_SRR0 = 1 << 0, |
134 | CONTEXT_VALID_GPR1 = 1 << 1, |
135 | CONTEXT_VALID_ALL = -1 |
136 | }; |
137 | |
138 | StackFramePPC64() : context(), context_validity(CONTEXT_VALID_NONE) {} |
139 | |
140 | // Register state. This is only fully valid for the topmost frame in a |
141 | // stack. In other frames, the values of nonvolatile registers may be |
142 | // present, given sufficient debugging information. Refer to |
143 | // context_validity. |
144 | MDRawContextPPC64 context; |
145 | |
146 | // context_validity is actually ContextValidity, but int is used because |
147 | // the OR operator doesn't work well with enumerated types. This indicates |
148 | // which fields in context are valid. |
149 | int context_validity; |
150 | }; |
151 | |
152 | struct StackFrameAMD64 : public StackFrame { |
153 | // ContextValidity has one entry for each register that we might be able |
154 | // to recover. |
155 | enum ContextValidity { |
156 | CONTEXT_VALID_NONE = 0, |
157 | CONTEXT_VALID_RAX = 1 << 0, |
158 | CONTEXT_VALID_RDX = 1 << 1, |
159 | CONTEXT_VALID_RCX = 1 << 2, |
160 | CONTEXT_VALID_RBX = 1 << 3, |
161 | CONTEXT_VALID_RSI = 1 << 4, |
162 | CONTEXT_VALID_RDI = 1 << 5, |
163 | CONTEXT_VALID_RBP = 1 << 6, |
164 | CONTEXT_VALID_RSP = 1 << 7, |
165 | CONTEXT_VALID_R8 = 1 << 8, |
166 | CONTEXT_VALID_R9 = 1 << 9, |
167 | CONTEXT_VALID_R10 = 1 << 10, |
168 | CONTEXT_VALID_R11 = 1 << 11, |
169 | CONTEXT_VALID_R12 = 1 << 12, |
170 | CONTEXT_VALID_R13 = 1 << 13, |
171 | CONTEXT_VALID_R14 = 1 << 14, |
172 | CONTEXT_VALID_R15 = 1 << 15, |
173 | CONTEXT_VALID_RIP = 1 << 16, |
174 | CONTEXT_VALID_ALL = -1 |
175 | }; |
176 | |
177 | StackFrameAMD64() : context(), context_validity(CONTEXT_VALID_NONE) {} |
178 | |
179 | // Overriden to return the return address as saved on the stack. |
180 | virtual uint64_t ReturnAddress() const; |
181 | |
182 | // Register state. This is only fully valid for the topmost frame in a |
183 | // stack. In other frames, which registers are present depends on what |
184 | // debugging information we had available. Refer to context_validity. |
185 | MDRawContextAMD64 context; |
186 | |
187 | // For each register in context whose value has been recovered, we set |
188 | // the corresponding CONTEXT_VALID_ bit in context_validity. |
189 | // |
190 | // context_validity's type should actually be ContextValidity, but |
191 | // we use int instead because the bitwise inclusive or operator |
192 | // yields an int when applied to enum values, and C++ doesn't |
193 | // silently convert from ints to enums. |
194 | int context_validity; |
195 | }; |
196 | |
197 | struct StackFrameSPARC : public StackFrame { |
198 | // to be confirmed |
199 | enum ContextValidity { |
200 | CONTEXT_VALID_NONE = 0, |
201 | CONTEXT_VALID_PC = 1 << 0, |
202 | CONTEXT_VALID_SP = 1 << 1, |
203 | CONTEXT_VALID_FP = 1 << 2, |
204 | CONTEXT_VALID_ALL = -1 |
205 | }; |
206 | |
207 | StackFrameSPARC() : context(), context_validity(CONTEXT_VALID_NONE) {} |
208 | |
209 | // Register state. This is only fully valid for the topmost frame in a |
210 | // stack. In other frames, the values of nonvolatile registers may be |
211 | // present, given sufficient debugging information. Refer to |
212 | // context_validity. |
213 | MDRawContextSPARC context; |
214 | |
215 | // context_validity is actually ContextValidity, but int is used because |
216 | // the OR operator doesn't work well with enumerated types. This indicates |
217 | // which fields in context are valid. |
218 | int context_validity; |
219 | }; |
220 | |
221 | struct StackFrameARM : public StackFrame { |
222 | // A flag for each register we might know. |
223 | enum ContextValidity { |
224 | CONTEXT_VALID_NONE = 0, |
225 | CONTEXT_VALID_R0 = 1 << 0, |
226 | CONTEXT_VALID_R1 = 1 << 1, |
227 | CONTEXT_VALID_R2 = 1 << 2, |
228 | CONTEXT_VALID_R3 = 1 << 3, |
229 | CONTEXT_VALID_R4 = 1 << 4, |
230 | CONTEXT_VALID_R5 = 1 << 5, |
231 | CONTEXT_VALID_R6 = 1 << 6, |
232 | CONTEXT_VALID_R7 = 1 << 7, |
233 | CONTEXT_VALID_R8 = 1 << 8, |
234 | CONTEXT_VALID_R9 = 1 << 9, |
235 | CONTEXT_VALID_R10 = 1 << 10, |
236 | CONTEXT_VALID_R11 = 1 << 11, |
237 | CONTEXT_VALID_R12 = 1 << 12, |
238 | CONTEXT_VALID_R13 = 1 << 13, |
239 | CONTEXT_VALID_R14 = 1 << 14, |
240 | CONTEXT_VALID_R15 = 1 << 15, |
241 | CONTEXT_VALID_ALL = ~CONTEXT_VALID_NONE, |
242 | |
243 | // Aliases for registers with dedicated or conventional roles. |
244 | CONTEXT_VALID_FP = CONTEXT_VALID_R11, |
245 | CONTEXT_VALID_SP = CONTEXT_VALID_R13, |
246 | CONTEXT_VALID_LR = CONTEXT_VALID_R14, |
247 | CONTEXT_VALID_PC = CONTEXT_VALID_R15 |
248 | }; |
249 | |
250 | StackFrameARM() : context(), context_validity(CONTEXT_VALID_NONE) {} |
251 | |
252 | // Return the ContextValidity flag for register rN. |
253 | static ContextValidity RegisterValidFlag(int n) { |
254 | if (0 <= n && n <= 15) { |
255 | return ContextValidity(1 << n); |
256 | } |
257 | return CONTEXT_VALID_NONE; |
258 | } |
259 | |
260 | // Register state. This is only fully valid for the topmost frame in a |
261 | // stack. In other frames, the values of nonvolatile registers may be |
262 | // present, given sufficient debugging information. Refer to |
263 | // context_validity. |
264 | MDRawContextARM context; |
265 | |
266 | // For each register in context whose value has been recovered, we set |
267 | // the corresponding CONTEXT_VALID_ bit in context_validity. |
268 | // |
269 | // context_validity's type should actually be ContextValidity, but |
270 | // we use int instead because the bitwise inclusive or operator |
271 | // yields an int when applied to enum values, and C++ doesn't |
272 | // silently convert from ints to enums. |
273 | int context_validity; |
274 | }; |
275 | |
276 | struct StackFrameARM64 : public StackFrame { |
277 | // A flag for each register we might know. Note that we can't use an enum |
278 | // here as there are 33 values to represent. |
279 | static const uint64_t CONTEXT_VALID_NONE = 0; |
280 | static const uint64_t CONTEXT_VALID_X0 = 1ULL << 0; |
281 | static const uint64_t CONTEXT_VALID_X1 = 1ULL << 1; |
282 | static const uint64_t CONTEXT_VALID_X2 = 1ULL << 2; |
283 | static const uint64_t CONTEXT_VALID_X3 = 1ULL << 3; |
284 | static const uint64_t CONTEXT_VALID_X4 = 1ULL << 4; |
285 | static const uint64_t CONTEXT_VALID_X5 = 1ULL << 5; |
286 | static const uint64_t CONTEXT_VALID_X6 = 1ULL << 6; |
287 | static const uint64_t CONTEXT_VALID_X7 = 1ULL << 7; |
288 | static const uint64_t CONTEXT_VALID_X8 = 1ULL << 8; |
289 | static const uint64_t CONTEXT_VALID_X9 = 1ULL << 9; |
290 | static const uint64_t CONTEXT_VALID_X10 = 1ULL << 10; |
291 | static const uint64_t CONTEXT_VALID_X11 = 1ULL << 11; |
292 | static const uint64_t CONTEXT_VALID_X12 = 1ULL << 12; |
293 | static const uint64_t CONTEXT_VALID_X13 = 1ULL << 13; |
294 | static const uint64_t CONTEXT_VALID_X14 = 1ULL << 14; |
295 | static const uint64_t CONTEXT_VALID_X15 = 1ULL << 15; |
296 | static const uint64_t CONTEXT_VALID_X16 = 1ULL << 16; |
297 | static const uint64_t CONTEXT_VALID_X17 = 1ULL << 17; |
298 | static const uint64_t CONTEXT_VALID_X18 = 1ULL << 18; |
299 | static const uint64_t CONTEXT_VALID_X19 = 1ULL << 19; |
300 | static const uint64_t CONTEXT_VALID_X20 = 1ULL << 20; |
301 | static const uint64_t CONTEXT_VALID_X21 = 1ULL << 21; |
302 | static const uint64_t CONTEXT_VALID_X22 = 1ULL << 22; |
303 | static const uint64_t CONTEXT_VALID_X23 = 1ULL << 23; |
304 | static const uint64_t CONTEXT_VALID_X24 = 1ULL << 24; |
305 | static const uint64_t CONTEXT_VALID_X25 = 1ULL << 25; |
306 | static const uint64_t CONTEXT_VALID_X26 = 1ULL << 26; |
307 | static const uint64_t CONTEXT_VALID_X27 = 1ULL << 27; |
308 | static const uint64_t CONTEXT_VALID_X28 = 1ULL << 28; |
309 | static const uint64_t CONTEXT_VALID_X29 = 1ULL << 29; |
310 | static const uint64_t CONTEXT_VALID_X30 = 1ULL << 30; |
311 | static const uint64_t CONTEXT_VALID_X31 = 1ULL << 31; |
312 | static const uint64_t CONTEXT_VALID_X32 = 1ULL << 32; |
313 | static const uint64_t CONTEXT_VALID_ALL = ~CONTEXT_VALID_NONE; |
314 | |
315 | // Aliases for registers with dedicated or conventional roles. |
316 | static const uint64_t CONTEXT_VALID_FP = CONTEXT_VALID_X29; |
317 | static const uint64_t CONTEXT_VALID_LR = CONTEXT_VALID_X30; |
318 | static const uint64_t CONTEXT_VALID_SP = CONTEXT_VALID_X31; |
319 | static const uint64_t CONTEXT_VALID_PC = CONTEXT_VALID_X32; |
320 | |
321 | StackFrameARM64() : context(), |
322 | context_validity(CONTEXT_VALID_NONE) {} |
323 | |
324 | // Return the validity flag for register xN. |
325 | static uint64_t RegisterValidFlag(int n) { |
326 | return 1ULL << n; |
327 | } |
328 | |
329 | // Register state. This is only fully valid for the topmost frame in a |
330 | // stack. In other frames, the values of nonvolatile registers may be |
331 | // present, given sufficient debugging information. Refer to |
332 | // context_validity. |
333 | MDRawContextARM64 context; |
334 | |
335 | // For each register in context whose value has been recovered, we set |
336 | // the corresponding CONTEXT_VALID_ bit in context_validity. |
337 | uint64_t context_validity; |
338 | }; |
339 | |
340 | struct StackFrameMIPS : public StackFrame { |
341 | // MIPS callee save registers for o32 ABI (32bit registers) are: |
342 | // 1. $s0-$s7, |
343 | // 2. $sp, $fp |
344 | // 3. $f20-$f31 |
345 | // |
346 | // The register structure is available at |
347 | // http://en.wikipedia.org/wiki/MIPS_architecture#Compiler_register_usage |
348 | |
349 | #define INDEX_MIPS_REG_S0 MD_CONTEXT_MIPS_REG_S0 // 16 |
350 | #define INDEX_MIPS_REG_S7 MD_CONTEXT_MIPS_REG_S7 // 23 |
351 | #define INDEX_MIPS_REG_GP MD_CONTEXT_MIPS_REG_GP // 28 |
352 | #define INDEX_MIPS_REG_RA MD_CONTEXT_MIPS_REG_RA // 31 |
353 | #define INDEX_MIPS_REG_PC 34 |
354 | #define SHIFT_MIPS_REG_S0 0 |
355 | #define SHIFT_MIPS_REG_GP 8 |
356 | #define SHIFT_MIPS_REG_PC 12 |
357 | |
358 | enum ContextValidity { |
359 | CONTEXT_VALID_NONE = 0, |
360 | CONTEXT_VALID_S0 = 1 << 0, // $16 |
361 | CONTEXT_VALID_S1 = 1 << 1, // $17 |
362 | CONTEXT_VALID_S2 = 1 << 2, // $18 |
363 | CONTEXT_VALID_S3 = 1 << 3, // $19 |
364 | CONTEXT_VALID_S4 = 1 << 4, // $20 |
365 | CONTEXT_VALID_S5 = 1 << 5, // $21 |
366 | CONTEXT_VALID_S6 = 1 << 6, // $22 |
367 | CONTEXT_VALID_S7 = 1 << 7, // $23 |
368 | // GP is not calee-save for o32 abi. |
369 | CONTEXT_VALID_GP = 1 << 8, // $28 |
370 | CONTEXT_VALID_SP = 1 << 9, // $29 |
371 | CONTEXT_VALID_FP = 1 << 10, // $30 |
372 | CONTEXT_VALID_RA = 1 << 11, // $31 |
373 | CONTEXT_VALID_PC = 1 << 12, // $34 |
374 | CONTEXT_VALID_ALL = ~CONTEXT_VALID_NONE |
375 | }; |
376 | |
377 | // Return the ContextValidity flag for register rN. |
378 | static ContextValidity RegisterValidFlag(int n) { |
379 | if (n >= INDEX_MIPS_REG_S0 && n <= INDEX_MIPS_REG_S7) |
380 | return ContextValidity(1 << (n - INDEX_MIPS_REG_S0 + SHIFT_MIPS_REG_S0)); |
381 | else if (n >= INDEX_MIPS_REG_GP && n <= INDEX_MIPS_REG_RA) |
382 | return ContextValidity(1 << (n - INDEX_MIPS_REG_GP + SHIFT_MIPS_REG_GP)); |
383 | else if (n == INDEX_MIPS_REG_PC) |
384 | return ContextValidity(1 << SHIFT_MIPS_REG_PC); |
385 | |
386 | return CONTEXT_VALID_NONE; |
387 | } |
388 | |
389 | StackFrameMIPS() : context(), context_validity(CONTEXT_VALID_NONE) {} |
390 | |
391 | // Register state. This is only fully valid for the topmost frame in a |
392 | // stack. In other frames, which registers are present depends on what |
393 | // debugging information were available. Refer to 'context_validity' below. |
394 | MDRawContextMIPS context; |
395 | |
396 | // For each register in context whose value has been recovered, |
397 | // the corresponding CONTEXT_VALID_ bit in 'context_validity' is set. |
398 | // |
399 | // context_validity's type should actually be ContextValidity, but |
400 | // type int is used instead because the bitwise inclusive or operator |
401 | // yields an int when applied to enum values, and C++ doesn't |
402 | // silently convert from ints to enums. |
403 | int context_validity; |
404 | }; |
405 | |
406 | } // namespace google_breakpad |
407 | |
408 | #endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ |
409 | |