toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,428 @@
     1.4 +// Copyright (c) 2006, Google Inc.
     1.5 +// All rights reserved.
     1.6 +//
     1.7 +// Redistribution and use in source and binary forms, with or without
     1.8 +// modification, are permitted provided that the following conditions are
     1.9 +// met:
    1.10 +//
    1.11 +//     * Redistributions of source code must retain the above copyright
    1.12 +// notice, this list of conditions and the following disclaimer.
    1.13 +//     * Redistributions in binary form must reproduce the above
    1.14 +// copyright notice, this list of conditions and the following disclaimer
    1.15 +// in the documentation and/or other materials provided with the
    1.16 +// distribution.
    1.17 +//     * Neither the name of Google Inc. nor the names of its
    1.18 +// contributors may be used to endorse or promote products derived from
    1.19 +// this software without specific prior written permission.
    1.20 +//
    1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.32 +
    1.33 +// stackwalker_selftest.cc: Tests StackwalkerX86 or StackwalkerPPC using the
    1.34 +// running process' stack as test data, if running on an x86 or ppc and
    1.35 +// compiled with gcc.  This test is not enabled in the "make check" suite
    1.36 +// by default, because certain optimizations interfere with its proper
    1.37 +// operation.  To turn it on, configure with --enable-selftest.
    1.38 +//
    1.39 +// Optimizations that cause problems:
    1.40 +//  - stack frame reuse.  The Recursor function here calls itself with
    1.41 +//    |return Recursor|.  When the caller's frame is reused, it will cause
    1.42 +//    CountCallerFrames to correctly return the same number of frames
    1.43 +//    in both the caller and callee.  This is considered an unexpected
    1.44 +//    condition in the test, which expects a callee to have one more
    1.45 +//    caller frame in the stack than its caller.
    1.46 +//  - frame pointer omission.  Even with a stackwalker that understands
    1.47 +//    this optimization, the code to harness debug information currently
    1.48 +//    only exists to retrieve it from minidumps, not the current process.
    1.49 +//
    1.50 +// This test can also serve as a developmental and debugging aid if
    1.51 +// PRINT_STACKS is defined.
    1.52 +//
    1.53 +// Author: Mark Mentovai
    1.54 +
    1.55 +#include "processor/logging.h"
    1.56 +
    1.57 +#if defined(__i386) && !defined(__i386__)
    1.58 +#define __i386__
    1.59 +#endif
    1.60 +#if defined(__sparc) && !defined(__sparc__)
    1.61 +#define __sparc__
    1.62 +#endif
    1.63 + 
    1.64 +#if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \
    1.65 +    (defined(__i386__) || defined(__ppc__) || defined(__sparc__))
    1.66 +
    1.67 +
    1.68 +#include <stdio.h>
    1.69 +
    1.70 +#include "common/scoped_ptr.h"
    1.71 +#include "google_breakpad/common/breakpad_types.h"
    1.72 +#include "google_breakpad/common/minidump_format.h"
    1.73 +#include "google_breakpad/processor/basic_source_line_resolver.h"
    1.74 +#include "google_breakpad/processor/call_stack.h"
    1.75 +#include "google_breakpad/processor/code_module.h"
    1.76 +#include "google_breakpad/processor/memory_region.h"
    1.77 +#include "google_breakpad/processor/stack_frame.h"
    1.78 +#include "google_breakpad/processor/stack_frame_cpu.h"
    1.79 +
    1.80 +using google_breakpad::BasicSourceLineResolver;
    1.81 +using google_breakpad::CallStack;
    1.82 +using google_breakpad::CodeModule;
    1.83 +using google_breakpad::MemoryRegion;
    1.84 +using google_breakpad::scoped_ptr;
    1.85 +using google_breakpad::StackFrame;
    1.86 +using google_breakpad::StackFramePPC;
    1.87 +using google_breakpad::StackFrameX86;
    1.88 +using google_breakpad::StackFrameSPARC;
    1.89 +
    1.90 +#if defined(__i386__)
    1.91 +#include "processor/stackwalker_x86.h"
    1.92 +using google_breakpad::StackwalkerX86;
    1.93 +#elif defined(__ppc__)
    1.94 +#include "processor/stackwalker_ppc.h"
    1.95 +using google_breakpad::StackwalkerPPC;
    1.96 +#elif defined(__sparc__)
    1.97 +#include "processor/stackwalker_sparc.h"
    1.98 +using google_breakpad::StackwalkerSPARC;
    1.99 +#endif  // __i386__ || __ppc__ || __sparc__
   1.100 +
   1.101 +#define RECURSION_DEPTH 100
   1.102 +
   1.103 +
   1.104 +// A simple MemoryRegion subclass that provides direct access to this
   1.105 +// process' memory space by pointer.
   1.106 +class SelfMemoryRegion : public MemoryRegion {
   1.107 + public:
   1.108 +  virtual uint64_t GetBase() { return 0; }
   1.109 +  virtual uint32_t GetSize() { return 0xffffffff; }
   1.110 +
   1.111 +  bool GetMemoryAtAddress(uint64_t address, uint8_t*  value) {
   1.112 +      return GetMemoryAtAddressInternal(address, value); }
   1.113 +  bool GetMemoryAtAddress(uint64_t address, uint16_t* value) {
   1.114 +      return GetMemoryAtAddressInternal(address, value); }
   1.115 +  bool GetMemoryAtAddress(uint64_t address, uint32_t* value) {
   1.116 +      return GetMemoryAtAddressInternal(address, value); }
   1.117 +  bool GetMemoryAtAddress(uint64_t address, uint64_t* value) {
   1.118 +      return GetMemoryAtAddressInternal(address, value); }
   1.119 +
   1.120 + private:
   1.121 +  template<typename T> bool GetMemoryAtAddressInternal(uint64_t address,
   1.122 +                                                       T*        value) {
   1.123 +    // Without knowing what addresses are actually mapped, just assume that
   1.124 +    // everything low is not mapped.  This helps the stackwalker catch the
   1.125 +    // end of a stack when it tries to dereference a null or low pointer
   1.126 +    // in an attempt to find the caller frame.  Other unmapped accesses will
   1.127 +    // cause the program to crash, but that would properly be a test failure.
   1.128 +    if (address < 0x100)
   1.129 +      return false;
   1.130 +
   1.131 +    uint8_t* memory = 0;
   1.132 +    *value = *reinterpret_cast<const T*>(&memory[address]);
   1.133 +    return true;
   1.134 +  }
   1.135 +};
   1.136 +
   1.137 +
   1.138 +#if defined(__GNUC__)
   1.139 +
   1.140 +
   1.141 +#if defined(__i386__)
   1.142 +
   1.143 +// GetEBP returns the current value of the %ebp register.  Because it's
   1.144 +// implemented as a function, %ebp itself contains GetEBP's frame pointer
   1.145 +// and not the caller's frame pointer.  Dereference %ebp to obtain the
   1.146 +// caller's frame pointer, which the compiler-generated preamble stored
   1.147 +// on the stack (provided frame pointers are not being omitted.)  Because
   1.148 +// this function depends on the compiler-generated preamble, inlining is
   1.149 +// disabled.
   1.150 +static uint32_t GetEBP() __attribute__((noinline));
   1.151 +static uint32_t GetEBP() {
   1.152 +  uint32_t ebp;
   1.153 +  __asm__ __volatile__(
   1.154 +    "movl (%%ebp), %0"
   1.155 +    : "=a" (ebp)
   1.156 +  );
   1.157 +  return ebp;
   1.158 +}
   1.159 +
   1.160 +
   1.161 +// The caller's %esp is 8 higher than the value of %ebp in this function,
   1.162 +// assuming that it's not inlined and that the standard prolog is used.
   1.163 +// The CALL instruction places a 4-byte return address on the stack above
   1.164 +// the caller's %esp, and this function's prolog will save the caller's %ebp
   1.165 +// on the stack as well, for another 4 bytes, before storing %esp in %ebp.
   1.166 +static uint32_t GetESP() __attribute__((noinline));
   1.167 +static uint32_t GetESP() {
   1.168 +  uint32_t ebp;
   1.169 +  __asm__ __volatile__(
   1.170 +    "movl %%ebp, %0"
   1.171 +    : "=a" (ebp)
   1.172 +  );
   1.173 +  return ebp + 8;
   1.174 +}
   1.175 +
   1.176 +
   1.177 +// GetEIP returns the instruction pointer identifying the next instruction
   1.178 +// to execute after GetEIP returns.  It obtains this information from the
   1.179 +// stack, where it was placed by the call instruction that called GetEIP.
   1.180 +// This function depends on frame pointers not being omitted.  It is possible
   1.181 +// to write a pure asm version of this routine that has no compiler-generated
   1.182 +// preamble and uses %esp instead of %ebp; that would function in the
   1.183 +// absence of frame pointers.  However, the simpler approach is used here
   1.184 +// because GetEBP and stackwalking necessarily depends on access to frame
   1.185 +// pointers.  Because this function depends on a call instruction and the
   1.186 +// compiler-generated preamble, inlining is disabled.
   1.187 +static uint32_t GetEIP() __attribute__((noinline));
   1.188 +static uint32_t GetEIP() {
   1.189 +  uint32_t eip;
   1.190 +  __asm__ __volatile__(
   1.191 +    "movl 4(%%ebp), %0"
   1.192 +    : "=a" (eip)
   1.193 +  );
   1.194 +  return eip;
   1.195 +}
   1.196 +
   1.197 +
   1.198 +#elif defined(__ppc__)
   1.199 +
   1.200 +
   1.201 +// GetSP returns the current value of the %r1 register, which by convention,
   1.202 +// is the stack pointer on ppc.  Because it's implemented as a function,
   1.203 +// %r1 itself contains GetSP's own stack pointer and not the caller's stack
   1.204 +// pointer.  Dereference %r1 to obtain the caller's stack pointer, which the
   1.205 +// compiler-generated prolog stored on the stack.  Because this function
   1.206 +// depends on the compiler-generated prolog, inlining is disabled.
   1.207 +static uint32_t GetSP() __attribute__((noinline));
   1.208 +static uint32_t GetSP() {
   1.209 +  uint32_t sp;
   1.210 +  __asm__ __volatile__(
   1.211 +    "lwz %0, 0(r1)"
   1.212 +    : "=r" (sp)
   1.213 +  );
   1.214 +  return sp;
   1.215 +}
   1.216 +
   1.217 +
   1.218 +// GetPC returns the program counter identifying the next instruction to
   1.219 +// execute after GetPC returns.  It obtains this information from the
   1.220 +// link register, where it was placed by the branch instruction that called
   1.221 +// GetPC.  Because this function depends on the caller's use of a branch
   1.222 +// instruction, inlining is disabled.
   1.223 +static uint32_t GetPC() __attribute__((noinline));
   1.224 +static uint32_t GetPC() {
   1.225 +  uint32_t lr;
   1.226 +  __asm__ __volatile__(
   1.227 +    "mflr %0"
   1.228 +    : "=r" (lr)
   1.229 +  );
   1.230 +  return lr;
   1.231 +}
   1.232 +
   1.233 +
   1.234 +#elif defined(__sparc__)
   1.235 +
   1.236 +
   1.237 +// GetSP returns the current value of the %sp/%o6/%g_r[14] register, which 
   1.238 +// by convention, is the stack pointer on sparc.  Because it's implemented
   1.239 +// as a function, %sp itself contains GetSP's own stack pointer and not 
   1.240 +// the caller's stack pointer.  Dereference  to obtain the caller's stack 
   1.241 +// pointer, which the compiler-generated prolog stored on the stack.
   1.242 +// Because this function depends on the compiler-generated prolog, inlining
   1.243 +// is disabled.
   1.244 +static uint32_t GetSP() __attribute__((noinline));
   1.245 +static uint32_t GetSP() {
   1.246 +  uint32_t sp;
   1.247 +  __asm__ __volatile__(
   1.248 +    "mov %%fp, %0"
   1.249 +    : "=r" (sp)
   1.250 +  );
   1.251 +  return sp;
   1.252 +}
   1.253 +
   1.254 +// GetFP returns the current value of the %fp register.  Because it's
   1.255 +// implemented as a function, %fp itself contains GetFP's frame pointer
   1.256 +// and not the caller's frame pointer.  Dereference %fp to obtain the
   1.257 +// caller's frame pointer, which the compiler-generated preamble stored
   1.258 +// on the stack (provided frame pointers are not being omitted.)  Because
   1.259 +// this function depends on the compiler-generated preamble, inlining is
   1.260 +// disabled.
   1.261 +static uint32_t GetFP() __attribute__((noinline));
   1.262 +static uint32_t GetFP() {
   1.263 +  uint32_t fp;
   1.264 +  __asm__ __volatile__(
   1.265 +    "ld [%%fp+56], %0"
   1.266 +    : "=r" (fp)
   1.267 +  );
   1.268 +  return fp;
   1.269 +}
   1.270 +
   1.271 +// GetPC returns the program counter identifying the next instruction to
   1.272 +// execute after GetPC returns.  It obtains this information from the
   1.273 +// link register, where it was placed by the branch instruction that called
   1.274 +// GetPC.  Because this function depends on the caller's use of a branch
   1.275 +// instruction, inlining is disabled.
   1.276 +static uint32_t GetPC() __attribute__((noinline));
   1.277 +static uint32_t GetPC() {
   1.278 +  uint32_t pc;
   1.279 +  __asm__ __volatile__(
   1.280 +    "mov %%i7, %0"
   1.281 +    : "=r" (pc)
   1.282 +  );
   1.283 +  return pc + 8;
   1.284 +}
   1.285 +
   1.286 +#endif  // __i386__ || __ppc__ || __sparc__
   1.287 +
   1.288 +#elif defined(__SUNPRO_CC)
   1.289 +
   1.290 +#if defined(__i386__)
   1.291 +extern "C" {
   1.292 +extern uint32_t GetEIP();
   1.293 +extern uint32_t GetEBP();
   1.294 +extern uint32_t GetESP();
   1.295 +}
   1.296 +#elif defined(__sparc__)
   1.297 +extern "C" {
   1.298 +extern uint32_t GetPC();
   1.299 +extern uint32_t GetFP();
   1.300 +extern uint32_t GetSP();
   1.301 +}
   1.302 +#endif // __i386__ || __sparc__
   1.303 +
   1.304 +#endif // __GNUC__ || __SUNPRO_CC
   1.305 +
   1.306 +// CountCallerFrames returns the number of stack frames beneath the function
   1.307 +// that called CountCallerFrames.  Because this function's return value
   1.308 +// is dependent on the size of the stack beneath it, inlining is disabled,
   1.309 +// and any function that calls this should not be inlined either.
   1.310 +#if defined(__GNUC__)
   1.311 +static unsigned int CountCallerFrames() __attribute__((noinline));
   1.312 +#elif defined(__SUNPRO_CC)
   1.313 +static unsigned int CountCallerFrames();
   1.314 +#endif
   1.315 +static unsigned int CountCallerFrames() {
   1.316 +  SelfMemoryRegion memory;
   1.317 +  BasicSourceLineResolver resolver;
   1.318 +
   1.319 +#if defined(__i386__)
   1.320 +  MDRawContextX86 context = MDRawContextX86();
   1.321 +  context.eip = GetEIP();
   1.322 +  context.ebp = GetEBP();
   1.323 +  context.esp = GetESP();
   1.324 +
   1.325 +  StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL,
   1.326 +                                              NULL, &resolver);
   1.327 +#elif defined(__ppc__)
   1.328 +  MDRawContextPPC context = MDRawContextPPC();
   1.329 +  context.srr0 = GetPC();
   1.330 +  context.gpr[1] = GetSP();
   1.331 +
   1.332 +  StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL,
   1.333 +                                              NULL, &resolver);
   1.334 +#elif defined(__sparc__)
   1.335 +  MDRawContextSPARC context = MDRawContextSPARC();
   1.336 +  context.pc = GetPC();
   1.337 +  context.g_r[14] = GetSP();
   1.338 +  context.g_r[30] = GetFP();
   1.339 +
   1.340 +  StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory,
   1.341 +                                                  NULL, NULL, &resolver);
   1.342 +#endif  // __i386__ || __ppc__ || __sparc__
   1.343 +
   1.344 +  CallStack stack;
   1.345 +  vector<const CodeModule*> modules_without_symbols;
   1.346 +  stackwalker.Walk(&stack, &modules_without_symbols);
   1.347 +
   1.348 +#ifdef PRINT_STACKS
   1.349 +  printf("\n");
   1.350 +  for (unsigned int frame_index = 0;
   1.351 +      frame_index < stack.frames()->size();
   1.352 +      ++frame_index) {
   1.353 +    StackFrame *frame = stack.frames()->at(frame_index);
   1.354 +    printf("frame %-3d  instruction = 0x%08" PRIx64,
   1.355 +           frame_index, frame->instruction);
   1.356 +#if defined(__i386__)
   1.357 +    StackFrameX86 *frame_x86 = reinterpret_cast<StackFrameX86*>(frame);
   1.358 +    printf("  esp = 0x%08x  ebp = 0x%08x\n",
   1.359 +           frame_x86->context.esp, frame_x86->context.ebp);
   1.360 +#elif defined(__ppc__)
   1.361 +    StackFramePPC *frame_ppc = reinterpret_cast<StackFramePPC*>(frame);
   1.362 +    printf("  gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]);
   1.363 +#elif defined(__sparc__)
   1.364 +    StackFrameSPARC *frame_sparc = reinterpret_cast<StackFrameSPARC*>(frame);
   1.365 +    printf("  sp = 0x%08x  fp = 0x%08x\n",
   1.366 +           frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]);
   1.367 +#endif  // __i386__ || __ppc__ || __sparc__
   1.368 +  }
   1.369 +#endif  // PRINT_STACKS
   1.370 +
   1.371 +  // Subtract 1 because the caller wants the number of frames beneath
   1.372 +  // itself.  Because the caller called us, subract two for our frame and its
   1.373 +  // frame, which are included in stack.size().
   1.374 +  return stack.frames()->size() - 2;
   1.375 +}
   1.376 +
   1.377 +
   1.378 +// Recursor verifies that the number stack frames beneath itself is one more
   1.379 +// than the number of stack frames beneath its parent.  When depth frames
   1.380 +// have been reached, Recursor stops checking and returns success.  If the
   1.381 +// frame count check fails at any depth, Recursor will stop and return false.
   1.382 +// Because this calls CountCallerFrames, inlining is disabled.
   1.383 +#if defined(__GNUC__)
   1.384 +static bool Recursor(unsigned int depth, unsigned int parent_callers)
   1.385 +    __attribute__((noinline));
   1.386 +#elif defined(__SUNPRO_CC)
   1.387 +static bool Recursor(unsigned int depth, unsigned int parent_callers);
   1.388 +#endif
   1.389 +static bool Recursor(unsigned int depth, unsigned int parent_callers) {
   1.390 +  unsigned int callers = CountCallerFrames();
   1.391 +  if (callers != parent_callers + 1)
   1.392 +    return false;
   1.393 +
   1.394 +  if (depth)
   1.395 +    return Recursor(depth - 1, callers);
   1.396 +
   1.397 +  // depth == 0
   1.398 +  return true;
   1.399 +}
   1.400 +
   1.401 +
   1.402 +// Because this calls CountCallerFrames, inlining is disabled - but because
   1.403 +// it's main (and nobody calls it other than the entry point), it wouldn't
   1.404 +// be inlined anyway.
   1.405 +#if defined(__GNUC__)
   1.406 +int main(int argc, char** argv) __attribute__((noinline));
   1.407 +#elif defined(__SUNPRO_CC)
   1.408 +int main(int argc, char** argv);
   1.409 +#endif
   1.410 +int main(int argc, char** argv) {
   1.411 +  BPLOG_INIT(&argc, &argv);
   1.412 +
   1.413 +  return Recursor(RECURSION_DEPTH, CountCallerFrames()) ? 0 : 1;
   1.414 +}
   1.415 +
   1.416 +
   1.417 +#else
   1.418 +// Not i386 or ppc or sparc?  We can only test stacks we know how to walk.
   1.419 +
   1.420 +
   1.421 +int main(int argc, char **argv) {
   1.422 +  BPLOG_INIT(&argc, &argv);
   1.423 +
   1.424 +  // "make check" interprets an exit status of 77 to mean that the test is
   1.425 +  // not supported.
   1.426 +  BPLOG(ERROR) << "Selftest not supported here";
   1.427 +  return 77;
   1.428 +}
   1.429 +
   1.430 +
   1.431 +#endif  // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__)

mercurial