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 <assert.h>
53
54#include "processor/logging.h"
55
56#if defined(__i386) && !defined(__i386__)
57#define __i386__
58#endif
59#if defined(__sparc) && !defined(__sparc__)
60#define __sparc__
61#endif
62
63#if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \
64    (defined(__i386__) || defined(__ppc__) || defined(__sparc__))
65
66
67#include <stdio.h>
68
69#include "common/scoped_ptr.h"
70#include "google_breakpad/common/breakpad_types.h"
71#include "google_breakpad/common/minidump_format.h"
72#include "google_breakpad/processor/basic_source_line_resolver.h"
73#include "google_breakpad/processor/call_stack.h"
74#include "google_breakpad/processor/code_module.h"
75#include "google_breakpad/processor/memory_region.h"
76#include "google_breakpad/processor/stack_frame.h"
77#include "google_breakpad/processor/stack_frame_cpu.h"
78
79using google_breakpad::BasicSourceLineResolver;
80using google_breakpad::CallStack;
81using google_breakpad::CodeModule;
82using google_breakpad::MemoryRegion;
83using google_breakpad::scoped_ptr;
84using google_breakpad::StackFrame;
85using google_breakpad::StackFramePPC;
86using google_breakpad::StackFrameX86;
87using google_breakpad::StackFrameSPARC;
88
89#if defined(__i386__)
90#include "processor/stackwalker_x86.h"
91using google_breakpad::StackwalkerX86;
92#elif defined(__ppc__)
93#include "processor/stackwalker_ppc.h"
94using google_breakpad::StackwalkerPPC;
95#elif defined(__sparc__)
96#include "processor/stackwalker_sparc.h"
97using google_breakpad::StackwalkerSPARC;
98#endif  // __i386__ || __ppc__ || __sparc__
99
100#define RECURSION_DEPTH 100
101
102
103// A simple MemoryRegion subclass that provides direct access to this
104// process' memory space by pointer.
105class SelfMemoryRegion : public MemoryRegion {
106 public:
107  virtual uint64_t GetBase() const { return 0; }
108  virtual uint32_t GetSize() const { return 0xffffffff; }
109
110  bool GetMemoryAtAddress(uint64_t address, uint8_t*  value) const {
111      return GetMemoryAtAddressInternal(address, value); }
112  bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const {
113      return GetMemoryAtAddressInternal(address, value); }
114  bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const {
115      return GetMemoryAtAddressInternal(address, value); }
116  bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const {
117      return GetMemoryAtAddressInternal(address, value); }
118  void Print() const {
119    assert(false);
120  }
121
122 private:
123  template<typename T> bool GetMemoryAtAddressInternal(uint64_t address,
124                                                       T*        value) {
125    // Without knowing what addresses are actually mapped, just assume that
126    // everything low is not mapped.  This helps the stackwalker catch the
127    // end of a stack when it tries to dereference a null or low pointer
128    // in an attempt to find the caller frame.  Other unmapped accesses will
129    // cause the program to crash, but that would properly be a test failure.
130    if (address < 0x100)
131      return false;
132
133    uint8_t* memory = 0;
134    *value = *reinterpret_cast<const T*>(&memory[address]);
135    return true;
136  }
137};
138
139
140#if defined(__GNUC__)
141
142
143#if defined(__i386__)
144
145// GetEBP returns the current value of the %ebp register.  Because it's
146// implemented as a function, %ebp itself contains GetEBP's frame pointer
147// and not the caller's frame pointer.  Dereference %ebp to obtain the
148// caller's frame pointer, which the compiler-generated preamble stored
149// on the stack (provided frame pointers are not being omitted.)  Because
150// this function depends on the compiler-generated preamble, inlining is
151// disabled.
152static uint32_t GetEBP() __attribute__((noinline));
153static uint32_t GetEBP() {
154  uint32_t ebp;
155  __asm__ __volatile__(
156    "movl (%%ebp), %0"
157    : "=a" (ebp)
158  );
159  return ebp;
160}
161
162
163// The caller's %esp is 8 higher than the value of %ebp in this function,
164// assuming that it's not inlined and that the standard prolog is used.
165// The CALL instruction places a 4-byte return address on the stack above
166// the caller's %esp, and this function's prolog will save the caller's %ebp
167// on the stack as well, for another 4 bytes, before storing %esp in %ebp.
168static uint32_t GetESP() __attribute__((noinline));
169static uint32_t GetESP() {
170  uint32_t ebp;
171  __asm__ __volatile__(
172    "movl %%ebp, %0"
173    : "=a" (ebp)
174  );
175  return ebp + 8;
176}
177
178
179// GetEIP returns the instruction pointer identifying the next instruction
180// to execute after GetEIP returns.  It obtains this information from the
181// stack, where it was placed by the call instruction that called GetEIP.
182// This function depends on frame pointers not being omitted.  It is possible
183// to write a pure asm version of this routine that has no compiler-generated
184// preamble and uses %esp instead of %ebp; that would function in the
185// absence of frame pointers.  However, the simpler approach is used here
186// because GetEBP and stackwalking necessarily depends on access to frame
187// pointers.  Because this function depends on a call instruction and the
188// compiler-generated preamble, inlining is disabled.
189static uint32_t GetEIP() __attribute__((noinline));
190static uint32_t GetEIP() {
191  uint32_t eip;
192  __asm__ __volatile__(
193    "movl 4(%%ebp), %0"
194    : "=a" (eip)
195  );
196  return eip;
197}
198
199
200#elif defined(__ppc__)
201
202
203// GetSP returns the current value of the %r1 register, which by convention,
204// is the stack pointer on ppc.  Because it's implemented as a function,
205// %r1 itself contains GetSP's own stack pointer and not the caller's stack
206// pointer.  Dereference %r1 to obtain the caller's stack pointer, which the
207// compiler-generated prolog stored on the stack.  Because this function
208// depends on the compiler-generated prolog, inlining is disabled.
209static uint32_t GetSP() __attribute__((noinline));
210static uint32_t GetSP() {
211  uint32_t sp;
212  __asm__ __volatile__(
213    "lwz %0, 0(r1)"
214    : "=r" (sp)
215  );
216  return sp;
217}
218
219
220// GetPC returns the program counter identifying the next instruction to
221// execute after GetPC returns.  It obtains this information from the
222// link register, where it was placed by the branch instruction that called
223// GetPC.  Because this function depends on the caller's use of a branch
224// instruction, inlining is disabled.
225static uint32_t GetPC() __attribute__((noinline));
226static uint32_t GetPC() {
227  uint32_t lr;
228  __asm__ __volatile__(
229    "mflr %0"
230    : "=r" (lr)
231  );
232  return lr;
233}
234
235
236#elif defined(__sparc__)
237
238
239// GetSP returns the current value of the %sp/%o6/%g_r[14] register, which
240// by convention, is the stack pointer on sparc.  Because it's implemented
241// as a function, %sp itself contains GetSP's own stack pointer and not
242// the caller's stack pointer.  Dereference  to obtain the caller's stack
243// pointer, which the compiler-generated prolog stored on the stack.
244// Because this function depends on the compiler-generated prolog, inlining
245// is disabled.
246static uint32_t GetSP() __attribute__((noinline));
247static uint32_t GetSP() {
248  uint32_t sp;
249  __asm__ __volatile__(
250    "mov %%fp, %0"
251    : "=r" (sp)
252  );
253  return sp;
254}
255
256// GetFP returns the current value of the %fp register.  Because it's
257// implemented as a function, %fp itself contains GetFP's frame pointer
258// and not the caller's frame pointer.  Dereference %fp to obtain the
259// caller's frame pointer, which the compiler-generated preamble stored
260// on the stack (provided frame pointers are not being omitted.)  Because
261// this function depends on the compiler-generated preamble, inlining is
262// disabled.
263static uint32_t GetFP() __attribute__((noinline));
264static uint32_t GetFP() {
265  uint32_t fp;
266  __asm__ __volatile__(
267    "ld [%%fp+56], %0"
268    : "=r" (fp)
269  );
270  return fp;
271}
272
273// GetPC returns the program counter identifying the next instruction to
274// execute after GetPC returns.  It obtains this information from the
275// link register, where it was placed by the branch instruction that called
276// GetPC.  Because this function depends on the caller's use of a branch
277// instruction, inlining is disabled.
278static uint32_t GetPC() __attribute__((noinline));
279static uint32_t GetPC() {
280  uint32_t pc;
281  __asm__ __volatile__(
282    "mov %%i7, %0"
283    : "=r" (pc)
284  );
285  return pc + 8;
286}
287
288#endif  // __i386__ || __ppc__ || __sparc__
289
290#elif defined(__SUNPRO_CC)
291
292#if defined(__i386__)
293extern "C" {
294extern uint32_t GetEIP();
295extern uint32_t GetEBP();
296extern uint32_t GetESP();
297}
298#elif defined(__sparc__)
299extern "C" {
300extern uint32_t GetPC();
301extern uint32_t GetFP();
302extern uint32_t GetSP();
303}
304#endif // __i386__ || __sparc__
305
306#endif // __GNUC__ || __SUNPRO_CC
307
308// CountCallerFrames returns the number of stack frames beneath the function
309// that called CountCallerFrames.  Because this function's return value
310// is dependent on the size of the stack beneath it, inlining is disabled,
311// and any function that calls this should not be inlined either.
312#if defined(__GNUC__)
313static unsigned int CountCallerFrames() __attribute__((noinline));
314#elif defined(__SUNPRO_CC)
315static unsigned int CountCallerFrames();
316#endif
317static unsigned int CountCallerFrames() {
318  SelfMemoryRegion memory;
319  BasicSourceLineResolver resolver;
320
321#if defined(__i386__)
322  MDRawContextX86 context = MDRawContextX86();
323  context.eip = GetEIP();
324  context.ebp = GetEBP();
325  context.esp = GetESP();
326
327  StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL,
328                                              NULL, &resolver);
329#elif defined(__ppc__)
330  MDRawContextPPC context = MDRawContextPPC();
331  context.srr0 = GetPC();
332  context.gpr[1] = GetSP();
333
334  StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL,
335                                              NULL, &resolver);
336#elif defined(__sparc__)
337  MDRawContextSPARC context = MDRawContextSPARC();
338  context.pc = GetPC();
339  context.g_r[14] = GetSP();
340  context.g_r[30] = GetFP();
341
342  StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory,
343                                                  NULL, NULL, &resolver);
344#endif  // __i386__ || __ppc__ || __sparc__
345
346  CallStack stack;
347  vector<const CodeModule*> modules_without_symbols;
348  stackwalker.Walk(&stack, &modules_without_symbols);
349
350#ifdef PRINT_STACKS
351  printf("\n");
352  for (unsigned int frame_index = 0;
353      frame_index < stack.frames()->size();
354      ++frame_index) {
355    StackFrame *frame = stack.frames()->at(frame_index);
356    printf("frame %-3d  instruction = 0x%08" PRIx64,
357           frame_index, frame->instruction);
358#if defined(__i386__)
359    StackFrameX86 *frame_x86 = reinterpret_cast<StackFrameX86*>(frame);
360    printf("  esp = 0x%08x  ebp = 0x%08x\n",
361           frame_x86->context.esp, frame_x86->context.ebp);
362#elif defined(__ppc__)
363    StackFramePPC *frame_ppc = reinterpret_cast<StackFramePPC*>(frame);
364    printf("  gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]);
365#elif defined(__sparc__)
366    StackFrameSPARC *frame_sparc = reinterpret_cast<StackFrameSPARC*>(frame);
367    printf("  sp = 0x%08x  fp = 0x%08x\n",
368           frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]);
369#endif  // __i386__ || __ppc__ || __sparc__
370  }
371#endif  // PRINT_STACKS
372
373  // Subtract 1 because the caller wants the number of frames beneath
374  // itself.  Because the caller called us, subract two for our frame and its
375  // frame, which are included in stack.size().
376  return stack.frames()->size() - 2;
377}
378
379
380// Recursor verifies that the number stack frames beneath itself is one more
381// than the number of stack frames beneath its parent.  When depth frames
382// have been reached, Recursor stops checking and returns success.  If the
383// frame count check fails at any depth, Recursor will stop and return false.
384// Because this calls CountCallerFrames, inlining is disabled.
385#if defined(__GNUC__)
386static bool Recursor(unsigned int depth, unsigned int parent_callers)
387    __attribute__((noinline));
388#elif defined(__SUNPRO_CC)
389static bool Recursor(unsigned int depth, unsigned int parent_callers);
390#endif
391static bool Recursor(unsigned int depth, unsigned int parent_callers) {
392  unsigned int callers = CountCallerFrames();
393  if (callers != parent_callers + 1)
394    return false;
395
396  if (depth)
397    return Recursor(depth - 1, callers);
398
399  // depth == 0
400  return true;
401}
402
403
404// Because this calls CountCallerFrames, inlining is disabled - but because
405// it's main (and nobody calls it other than the entry point), it wouldn't
406// be inlined anyway.
407#if defined(__GNUC__)
408int main(int argc, char** argv) __attribute__((noinline));
409#elif defined(__SUNPRO_CC)
410int main(int argc, char** argv);
411#endif
412int main(int argc, char** argv) {
413  BPLOG_INIT(&argc, &argv);
414
415  return Recursor(RECURSION_DEPTH, CountCallerFrames()) ? 0 : 1;
416}
417
418
419#else
420// Not i386 or ppc or sparc?  We can only test stacks we know how to walk.
421
422
423int main(int argc, char **argv) {
424  BPLOG_INIT(&argc, &argv);
425
426  // "make check" interprets an exit status of 77 to mean that the test is
427  // not supported.
428  BPLOG(ERROR) << "Selftest not supported here";
429  return 77;
430}
431
432
433#endif  // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__)
434