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