|
1 // Copyright (c) 2006, Google Inc. |
|
2 // All rights reserved. |
|
3 // |
|
4 // Redistribution and use in source and binary forms, with or without |
|
5 // modification, are permitted provided that the following conditions are |
|
6 // met: |
|
7 // |
|
8 // * Redistributions of source code must retain the above copyright |
|
9 // notice, this list of conditions and the following disclaimer. |
|
10 // * Redistributions in binary form must reproduce the above |
|
11 // copyright notice, this list of conditions and the following disclaimer |
|
12 // in the documentation and/or other materials provided with the |
|
13 // distribution. |
|
14 // * Neither the name of Google Inc. nor the names of its |
|
15 // contributors may be used to endorse or promote products derived from |
|
16 // this software without specific prior written permission. |
|
17 // |
|
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
29 |
|
30 // stackwalker_selftest.cc: Tests StackwalkerX86 or StackwalkerPPC using the |
|
31 // running process' stack as test data, if running on an x86 or ppc and |
|
32 // compiled with gcc. This test is not enabled in the "make check" suite |
|
33 // by default, because certain optimizations interfere with its proper |
|
34 // operation. To turn it on, configure with --enable-selftest. |
|
35 // |
|
36 // Optimizations that cause problems: |
|
37 // - stack frame reuse. The Recursor function here calls itself with |
|
38 // |return Recursor|. When the caller's frame is reused, it will cause |
|
39 // CountCallerFrames to correctly return the same number of frames |
|
40 // in both the caller and callee. This is considered an unexpected |
|
41 // condition in the test, which expects a callee to have one more |
|
42 // caller frame in the stack than its caller. |
|
43 // - frame pointer omission. Even with a stackwalker that understands |
|
44 // this optimization, the code to harness debug information currently |
|
45 // only exists to retrieve it from minidumps, not the current process. |
|
46 // |
|
47 // This test can also serve as a developmental and debugging aid if |
|
48 // PRINT_STACKS is defined. |
|
49 // |
|
50 // Author: Mark Mentovai |
|
51 |
|
52 #include "processor/logging.h" |
|
53 |
|
54 #if defined(__i386) && !defined(__i386__) |
|
55 #define __i386__ |
|
56 #endif |
|
57 #if defined(__sparc) && !defined(__sparc__) |
|
58 #define __sparc__ |
|
59 #endif |
|
60 |
|
61 #if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \ |
|
62 (defined(__i386__) || defined(__ppc__) || defined(__sparc__)) |
|
63 |
|
64 |
|
65 #include <stdio.h> |
|
66 |
|
67 #include "common/scoped_ptr.h" |
|
68 #include "google_breakpad/common/breakpad_types.h" |
|
69 #include "google_breakpad/common/minidump_format.h" |
|
70 #include "google_breakpad/processor/basic_source_line_resolver.h" |
|
71 #include "google_breakpad/processor/call_stack.h" |
|
72 #include "google_breakpad/processor/code_module.h" |
|
73 #include "google_breakpad/processor/memory_region.h" |
|
74 #include "google_breakpad/processor/stack_frame.h" |
|
75 #include "google_breakpad/processor/stack_frame_cpu.h" |
|
76 |
|
77 using google_breakpad::BasicSourceLineResolver; |
|
78 using google_breakpad::CallStack; |
|
79 using google_breakpad::CodeModule; |
|
80 using google_breakpad::MemoryRegion; |
|
81 using google_breakpad::scoped_ptr; |
|
82 using google_breakpad::StackFrame; |
|
83 using google_breakpad::StackFramePPC; |
|
84 using google_breakpad::StackFrameX86; |
|
85 using google_breakpad::StackFrameSPARC; |
|
86 |
|
87 #if defined(__i386__) |
|
88 #include "processor/stackwalker_x86.h" |
|
89 using google_breakpad::StackwalkerX86; |
|
90 #elif defined(__ppc__) |
|
91 #include "processor/stackwalker_ppc.h" |
|
92 using google_breakpad::StackwalkerPPC; |
|
93 #elif defined(__sparc__) |
|
94 #include "processor/stackwalker_sparc.h" |
|
95 using google_breakpad::StackwalkerSPARC; |
|
96 #endif // __i386__ || __ppc__ || __sparc__ |
|
97 |
|
98 #define RECURSION_DEPTH 100 |
|
99 |
|
100 |
|
101 // A simple MemoryRegion subclass that provides direct access to this |
|
102 // process' memory space by pointer. |
|
103 class SelfMemoryRegion : public MemoryRegion { |
|
104 public: |
|
105 virtual uint64_t GetBase() { return 0; } |
|
106 virtual uint32_t GetSize() { return 0xffffffff; } |
|
107 |
|
108 bool GetMemoryAtAddress(uint64_t address, uint8_t* value) { |
|
109 return GetMemoryAtAddressInternal(address, value); } |
|
110 bool GetMemoryAtAddress(uint64_t address, uint16_t* value) { |
|
111 return GetMemoryAtAddressInternal(address, value); } |
|
112 bool GetMemoryAtAddress(uint64_t address, uint32_t* value) { |
|
113 return GetMemoryAtAddressInternal(address, value); } |
|
114 bool GetMemoryAtAddress(uint64_t address, uint64_t* value) { |
|
115 return GetMemoryAtAddressInternal(address, value); } |
|
116 |
|
117 private: |
|
118 template<typename T> bool GetMemoryAtAddressInternal(uint64_t address, |
|
119 T* value) { |
|
120 // Without knowing what addresses are actually mapped, just assume that |
|
121 // everything low is not mapped. This helps the stackwalker catch the |
|
122 // end of a stack when it tries to dereference a null or low pointer |
|
123 // in an attempt to find the caller frame. Other unmapped accesses will |
|
124 // cause the program to crash, but that would properly be a test failure. |
|
125 if (address < 0x100) |
|
126 return false; |
|
127 |
|
128 uint8_t* memory = 0; |
|
129 *value = *reinterpret_cast<const T*>(&memory[address]); |
|
130 return true; |
|
131 } |
|
132 }; |
|
133 |
|
134 |
|
135 #if defined(__GNUC__) |
|
136 |
|
137 |
|
138 #if defined(__i386__) |
|
139 |
|
140 // GetEBP returns the current value of the %ebp register. Because it's |
|
141 // implemented as a function, %ebp itself contains GetEBP's frame pointer |
|
142 // and not the caller's frame pointer. Dereference %ebp to obtain the |
|
143 // caller's frame pointer, which the compiler-generated preamble stored |
|
144 // on the stack (provided frame pointers are not being omitted.) Because |
|
145 // this function depends on the compiler-generated preamble, inlining is |
|
146 // disabled. |
|
147 static uint32_t GetEBP() __attribute__((noinline)); |
|
148 static uint32_t GetEBP() { |
|
149 uint32_t ebp; |
|
150 __asm__ __volatile__( |
|
151 "movl (%%ebp), %0" |
|
152 : "=a" (ebp) |
|
153 ); |
|
154 return ebp; |
|
155 } |
|
156 |
|
157 |
|
158 // The caller's %esp is 8 higher than the value of %ebp in this function, |
|
159 // assuming that it's not inlined and that the standard prolog is used. |
|
160 // The CALL instruction places a 4-byte return address on the stack above |
|
161 // the caller's %esp, and this function's prolog will save the caller's %ebp |
|
162 // on the stack as well, for another 4 bytes, before storing %esp in %ebp. |
|
163 static uint32_t GetESP() __attribute__((noinline)); |
|
164 static uint32_t GetESP() { |
|
165 uint32_t ebp; |
|
166 __asm__ __volatile__( |
|
167 "movl %%ebp, %0" |
|
168 : "=a" (ebp) |
|
169 ); |
|
170 return ebp + 8; |
|
171 } |
|
172 |
|
173 |
|
174 // GetEIP returns the instruction pointer identifying the next instruction |
|
175 // to execute after GetEIP returns. It obtains this information from the |
|
176 // stack, where it was placed by the call instruction that called GetEIP. |
|
177 // This function depends on frame pointers not being omitted. It is possible |
|
178 // to write a pure asm version of this routine that has no compiler-generated |
|
179 // preamble and uses %esp instead of %ebp; that would function in the |
|
180 // absence of frame pointers. However, the simpler approach is used here |
|
181 // because GetEBP and stackwalking necessarily depends on access to frame |
|
182 // pointers. Because this function depends on a call instruction and the |
|
183 // compiler-generated preamble, inlining is disabled. |
|
184 static uint32_t GetEIP() __attribute__((noinline)); |
|
185 static uint32_t GetEIP() { |
|
186 uint32_t eip; |
|
187 __asm__ __volatile__( |
|
188 "movl 4(%%ebp), %0" |
|
189 : "=a" (eip) |
|
190 ); |
|
191 return eip; |
|
192 } |
|
193 |
|
194 |
|
195 #elif defined(__ppc__) |
|
196 |
|
197 |
|
198 // GetSP returns the current value of the %r1 register, which by convention, |
|
199 // is the stack pointer on ppc. Because it's implemented as a function, |
|
200 // %r1 itself contains GetSP's own stack pointer and not the caller's stack |
|
201 // pointer. Dereference %r1 to obtain the caller's stack pointer, which the |
|
202 // compiler-generated prolog stored on the stack. Because this function |
|
203 // depends on the compiler-generated prolog, inlining is disabled. |
|
204 static uint32_t GetSP() __attribute__((noinline)); |
|
205 static uint32_t GetSP() { |
|
206 uint32_t sp; |
|
207 __asm__ __volatile__( |
|
208 "lwz %0, 0(r1)" |
|
209 : "=r" (sp) |
|
210 ); |
|
211 return sp; |
|
212 } |
|
213 |
|
214 |
|
215 // GetPC returns the program counter identifying the next instruction to |
|
216 // execute after GetPC returns. It obtains this information from the |
|
217 // link register, where it was placed by the branch instruction that called |
|
218 // GetPC. Because this function depends on the caller's use of a branch |
|
219 // instruction, inlining is disabled. |
|
220 static uint32_t GetPC() __attribute__((noinline)); |
|
221 static uint32_t GetPC() { |
|
222 uint32_t lr; |
|
223 __asm__ __volatile__( |
|
224 "mflr %0" |
|
225 : "=r" (lr) |
|
226 ); |
|
227 return lr; |
|
228 } |
|
229 |
|
230 |
|
231 #elif defined(__sparc__) |
|
232 |
|
233 |
|
234 // GetSP returns the current value of the %sp/%o6/%g_r[14] register, which |
|
235 // by convention, is the stack pointer on sparc. Because it's implemented |
|
236 // as a function, %sp itself contains GetSP's own stack pointer and not |
|
237 // the caller's stack pointer. Dereference to obtain the caller's stack |
|
238 // pointer, which the compiler-generated prolog stored on the stack. |
|
239 // Because this function depends on the compiler-generated prolog, inlining |
|
240 // is disabled. |
|
241 static uint32_t GetSP() __attribute__((noinline)); |
|
242 static uint32_t GetSP() { |
|
243 uint32_t sp; |
|
244 __asm__ __volatile__( |
|
245 "mov %%fp, %0" |
|
246 : "=r" (sp) |
|
247 ); |
|
248 return sp; |
|
249 } |
|
250 |
|
251 // GetFP returns the current value of the %fp register. Because it's |
|
252 // implemented as a function, %fp itself contains GetFP's frame pointer |
|
253 // and not the caller's frame pointer. Dereference %fp to obtain the |
|
254 // caller's frame pointer, which the compiler-generated preamble stored |
|
255 // on the stack (provided frame pointers are not being omitted.) Because |
|
256 // this function depends on the compiler-generated preamble, inlining is |
|
257 // disabled. |
|
258 static uint32_t GetFP() __attribute__((noinline)); |
|
259 static uint32_t GetFP() { |
|
260 uint32_t fp; |
|
261 __asm__ __volatile__( |
|
262 "ld [%%fp+56], %0" |
|
263 : "=r" (fp) |
|
264 ); |
|
265 return fp; |
|
266 } |
|
267 |
|
268 // GetPC returns the program counter identifying the next instruction to |
|
269 // execute after GetPC returns. It obtains this information from the |
|
270 // link register, where it was placed by the branch instruction that called |
|
271 // GetPC. Because this function depends on the caller's use of a branch |
|
272 // instruction, inlining is disabled. |
|
273 static uint32_t GetPC() __attribute__((noinline)); |
|
274 static uint32_t GetPC() { |
|
275 uint32_t pc; |
|
276 __asm__ __volatile__( |
|
277 "mov %%i7, %0" |
|
278 : "=r" (pc) |
|
279 ); |
|
280 return pc + 8; |
|
281 } |
|
282 |
|
283 #endif // __i386__ || __ppc__ || __sparc__ |
|
284 |
|
285 #elif defined(__SUNPRO_CC) |
|
286 |
|
287 #if defined(__i386__) |
|
288 extern "C" { |
|
289 extern uint32_t GetEIP(); |
|
290 extern uint32_t GetEBP(); |
|
291 extern uint32_t GetESP(); |
|
292 } |
|
293 #elif defined(__sparc__) |
|
294 extern "C" { |
|
295 extern uint32_t GetPC(); |
|
296 extern uint32_t GetFP(); |
|
297 extern uint32_t GetSP(); |
|
298 } |
|
299 #endif // __i386__ || __sparc__ |
|
300 |
|
301 #endif // __GNUC__ || __SUNPRO_CC |
|
302 |
|
303 // CountCallerFrames returns the number of stack frames beneath the function |
|
304 // that called CountCallerFrames. Because this function's return value |
|
305 // is dependent on the size of the stack beneath it, inlining is disabled, |
|
306 // and any function that calls this should not be inlined either. |
|
307 #if defined(__GNUC__) |
|
308 static unsigned int CountCallerFrames() __attribute__((noinline)); |
|
309 #elif defined(__SUNPRO_CC) |
|
310 static unsigned int CountCallerFrames(); |
|
311 #endif |
|
312 static unsigned int CountCallerFrames() { |
|
313 SelfMemoryRegion memory; |
|
314 BasicSourceLineResolver resolver; |
|
315 |
|
316 #if defined(__i386__) |
|
317 MDRawContextX86 context = MDRawContextX86(); |
|
318 context.eip = GetEIP(); |
|
319 context.ebp = GetEBP(); |
|
320 context.esp = GetESP(); |
|
321 |
|
322 StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL, |
|
323 NULL, &resolver); |
|
324 #elif defined(__ppc__) |
|
325 MDRawContextPPC context = MDRawContextPPC(); |
|
326 context.srr0 = GetPC(); |
|
327 context.gpr[1] = GetSP(); |
|
328 |
|
329 StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL, |
|
330 NULL, &resolver); |
|
331 #elif defined(__sparc__) |
|
332 MDRawContextSPARC context = MDRawContextSPARC(); |
|
333 context.pc = GetPC(); |
|
334 context.g_r[14] = GetSP(); |
|
335 context.g_r[30] = GetFP(); |
|
336 |
|
337 StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory, |
|
338 NULL, NULL, &resolver); |
|
339 #endif // __i386__ || __ppc__ || __sparc__ |
|
340 |
|
341 CallStack stack; |
|
342 vector<const CodeModule*> modules_without_symbols; |
|
343 stackwalker.Walk(&stack, &modules_without_symbols); |
|
344 |
|
345 #ifdef PRINT_STACKS |
|
346 printf("\n"); |
|
347 for (unsigned int frame_index = 0; |
|
348 frame_index < stack.frames()->size(); |
|
349 ++frame_index) { |
|
350 StackFrame *frame = stack.frames()->at(frame_index); |
|
351 printf("frame %-3d instruction = 0x%08" PRIx64, |
|
352 frame_index, frame->instruction); |
|
353 #if defined(__i386__) |
|
354 StackFrameX86 *frame_x86 = reinterpret_cast<StackFrameX86*>(frame); |
|
355 printf(" esp = 0x%08x ebp = 0x%08x\n", |
|
356 frame_x86->context.esp, frame_x86->context.ebp); |
|
357 #elif defined(__ppc__) |
|
358 StackFramePPC *frame_ppc = reinterpret_cast<StackFramePPC*>(frame); |
|
359 printf(" gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]); |
|
360 #elif defined(__sparc__) |
|
361 StackFrameSPARC *frame_sparc = reinterpret_cast<StackFrameSPARC*>(frame); |
|
362 printf(" sp = 0x%08x fp = 0x%08x\n", |
|
363 frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]); |
|
364 #endif // __i386__ || __ppc__ || __sparc__ |
|
365 } |
|
366 #endif // PRINT_STACKS |
|
367 |
|
368 // Subtract 1 because the caller wants the number of frames beneath |
|
369 // itself. Because the caller called us, subract two for our frame and its |
|
370 // frame, which are included in stack.size(). |
|
371 return stack.frames()->size() - 2; |
|
372 } |
|
373 |
|
374 |
|
375 // Recursor verifies that the number stack frames beneath itself is one more |
|
376 // than the number of stack frames beneath its parent. When depth frames |
|
377 // have been reached, Recursor stops checking and returns success. If the |
|
378 // frame count check fails at any depth, Recursor will stop and return false. |
|
379 // Because this calls CountCallerFrames, inlining is disabled. |
|
380 #if defined(__GNUC__) |
|
381 static bool Recursor(unsigned int depth, unsigned int parent_callers) |
|
382 __attribute__((noinline)); |
|
383 #elif defined(__SUNPRO_CC) |
|
384 static bool Recursor(unsigned int depth, unsigned int parent_callers); |
|
385 #endif |
|
386 static bool Recursor(unsigned int depth, unsigned int parent_callers) { |
|
387 unsigned int callers = CountCallerFrames(); |
|
388 if (callers != parent_callers + 1) |
|
389 return false; |
|
390 |
|
391 if (depth) |
|
392 return Recursor(depth - 1, callers); |
|
393 |
|
394 // depth == 0 |
|
395 return true; |
|
396 } |
|
397 |
|
398 |
|
399 // Because this calls CountCallerFrames, inlining is disabled - but because |
|
400 // it's main (and nobody calls it other than the entry point), it wouldn't |
|
401 // be inlined anyway. |
|
402 #if defined(__GNUC__) |
|
403 int main(int argc, char** argv) __attribute__((noinline)); |
|
404 #elif defined(__SUNPRO_CC) |
|
405 int main(int argc, char** argv); |
|
406 #endif |
|
407 int main(int argc, char** argv) { |
|
408 BPLOG_INIT(&argc, &argv); |
|
409 |
|
410 return Recursor(RECURSION_DEPTH, CountCallerFrames()) ? 0 : 1; |
|
411 } |
|
412 |
|
413 |
|
414 #else |
|
415 // Not i386 or ppc or sparc? We can only test stacks we know how to walk. |
|
416 |
|
417 |
|
418 int main(int argc, char **argv) { |
|
419 BPLOG_INIT(&argc, &argv); |
|
420 |
|
421 // "make check" interprets an exit status of 77 to mean that the test is |
|
422 // not supported. |
|
423 BPLOG(ERROR) << "Selftest not supported here"; |
|
424 return 77; |
|
425 } |
|
426 |
|
427 |
|
428 #endif // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__) |