Add SPARC/Solaris support to client handler and processor (#201, 200).

Patch by Michael shang <satisfy123>.  r=me, r=Alfred Peng.

2fba07577f


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@215 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
mmentovai 2007-09-26 18:28:05 +00:00
parent 278946c3b5
commit ea2bba9706
17 changed files with 1044 additions and 40 deletions

View file

@ -49,7 +49,17 @@
//
// Author: Mark Mentovai
#if defined(__GNUC__) && (defined(__i386__) || defined(__ppc__))
#include "processor/logging.h"
#if defined(__i386) && !defined(__i386__)
#define __i386__
#endif
#if defined(__sparc) && !defined(__sparc__)
#define __sparc__
#endif
#if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \
(defined(__i386__) || defined(__ppc__) || defined(__sparc__))
#include <cstdio>
@ -61,7 +71,6 @@
#include "google_breakpad/processor/memory_region.h"
#include "google_breakpad/processor/stack_frame.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/logging.h"
#include "processor/scoped_ptr.h"
using google_breakpad::BasicSourceLineResolver;
@ -71,6 +80,7 @@ using google_breakpad::scoped_ptr;
using google_breakpad::StackFrame;
using google_breakpad::StackFramePPC;
using google_breakpad::StackFrameX86;
using google_breakpad::StackFrameSPARC;
#if defined(__i386__)
#include "processor/stackwalker_x86.h"
@ -78,7 +88,10 @@ using google_breakpad::StackwalkerX86;
#elif defined(__ppc__)
#include "processor/stackwalker_ppc.h"
using google_breakpad::StackwalkerPPC;
#endif // __i386__ || __ppc__
#elif defined(__sparc__)
#include "processor/stackwalker_sparc.h"
using google_breakpad::StackwalkerSPARC;
#endif // __i386__ || __ppc__ || __sparc__
#define RECURSION_DEPTH 100
@ -117,6 +130,9 @@ class SelfMemoryRegion : public MemoryRegion {
};
#if defined(__GNUC__)
#if defined(__i386__)
// GetEBP returns the current value of the %ebp register. Because it's
@ -210,14 +226,87 @@ static u_int32_t GetPC() {
}
#endif // __i386__ || __ppc__
#elif defined(__sparc__)
// GetSP returns the current value of the %sp/%o6/%g_r[14] register, which
// by convention, is the stack pointer on sparc. Because it's implemented
// as a function, %sp itself contains GetSP's own stack pointer and not
// the caller's stack pointer. Dereference to obtain the caller's stack
// pointer, which the compiler-generated prolog stored on the stack.
// Because this function depends on the compiler-generated prolog, inlining
// is disabled.
static u_int32_t GetSP() __attribute__((noinline));
static u_int32_t GetSP() {
u_int32_t sp;
__asm__ __volatile__(
"mov %%fp, %0"
: "=r" (sp)
);
return sp;
}
// GetFP returns the current value of the %fp register. Because it's
// implemented as a function, %fp itself contains GetFP's frame pointer
// and not the caller's frame pointer. Dereference %fp to obtain the
// caller's frame pointer, which the compiler-generated preamble stored
// on the stack (provided frame pointers are not being omitted.) Because
// this function depends on the compiler-generated preamble, inlining is
// disabled.
static u_int32_t GetFP() __attribute__((noinline));
static u_int32_t GetFP() {
u_int32_t fp;
__asm__ __volatile__(
"ld [%%fp+56], %0"
: "=r" (fp)
);
return fp;
}
// GetPC returns the program counter identifying the next instruction to
// execute after GetPC returns. It obtains this information from the
// link register, where it was placed by the branch instruction that called
// GetPC. Because this function depends on the caller's use of a branch
// instruction, inlining is disabled.
static u_int32_t GetPC() __attribute__((noinline));
static u_int32_t GetPC() {
u_int32_t pc;
__asm__ __volatile__(
"mov %%i7, %0"
: "=r" (pc)
);
return pc + 8;
}
#endif // __i386__ || __ppc__ || __sparc__
#elif defined(__SUNPRO_CC)
#if defined(__i386__)
extern "C" {
extern u_int32_t GetEIP();
extern u_int32_t GetEBP();
extern u_int32_t GetESP();
}
#elif defined(__sparc__)
extern "C" {
extern u_int32_t GetPC();
extern u_int32_t GetFP();
extern u_int32_t GetSP();
}
#endif // __i386__ || __sparc__
#endif // __GNUC__ || __SUNPRO_CC
// CountCallerFrames returns the number of stack frames beneath the function
// that called CountCallerFrames. Because this function's return value
// is dependent on the size of the stack beneath it, inlining is disabled,
// and any function that calls this should not be inlined either.
#if defined(__GNUC__)
static unsigned int CountCallerFrames() __attribute__((noinline));
#elif defined(__SUNPRO_CC)
static unsigned int CountCallerFrames();
#endif
static unsigned int CountCallerFrames() {
SelfMemoryRegion memory;
BasicSourceLineResolver resolver;
@ -237,7 +326,15 @@ static unsigned int CountCallerFrames() {
StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL,
NULL, &resolver);
#endif // __i386__ || __ppc__
#elif defined(__sparc__)
MDRawContextSPARC context = MDRawContextSPARC();
context.pc = GetPC();
context.g_r[14] = GetSP();
context.g_r[30] = GetFP();
StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory,
NULL, NULL, &resolver);
#endif // __i386__ || __ppc__ || __sparc__
CallStack stack;
stackwalker.Walk(&stack);
@ -257,7 +354,11 @@ static unsigned int CountCallerFrames() {
#elif defined(__ppc__)
StackFramePPC *frame_ppc = reinterpret_cast<StackFramePPC*>(frame);
printf(" gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]);
#endif // __i386__ || __ppc__
#elif defined(__sparc__)
StackFrameSPARC *frame_sparc = reinterpret_cast<StackFrameSPARC*>(frame);
printf(" sp = 0x%08x fp = 0x%08x\n",
frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]);
#endif // __i386__ || __ppc__ || __sparc__
}
#endif // PRINT_STACKS
@ -273,8 +374,12 @@ static unsigned int CountCallerFrames() {
// have been reached, Recursor stops checking and returns success. If the
// frame count check fails at any depth, Recursor will stop and return false.
// Because this calls CountCallerFrames, inlining is disabled.
#if defined(__GNUC__)
static bool Recursor(unsigned int depth, unsigned int parent_callers)
__attribute__((noinline));
#elif defined(__SUNPRO_CC)
static bool Recursor(unsigned int depth, unsigned int parent_callers);
#endif
static bool Recursor(unsigned int depth, unsigned int parent_callers) {
unsigned int callers = CountCallerFrames();
if (callers != parent_callers + 1)
@ -291,7 +396,11 @@ static bool Recursor(unsigned int depth, unsigned int parent_callers) {
// Because this calls CountCallerFrames, inlining is disabled - but because
// it's main (and nobody calls it other than the entry point), it wouldn't
// be inlined anyway.
#if defined(__GNUC__)
int main(int argc, char** argv) __attribute__((noinline));
#elif defined(__SUNPRO_CC)
int main(int argc, char** argv);
#endif
int main(int argc, char** argv) {
BPLOG_INIT(&argc, &argv);
@ -299,9 +408,8 @@ int main(int argc, char** argv) {
}
#else // __GNUC__ && (__i386__ || __ppc__)
// Not gcc? We use gcc's __asm__.
// Not i386 or ppc? We can only test stacks we know how to walk.
#else
// Not i386 or ppc or sparc? We can only test stacks we know how to walk.
int main(int argc, char **argv) {
@ -314,4 +422,4 @@ int main(int argc, char **argv) {
}
#endif // __GNUC__ && (__i386__ || __ppc__)
#endif // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__)