diff options
author | csilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2007-03-22 03:28:56 +0000 |
---|---|---|
committer | csilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2007-03-22 03:28:56 +0000 |
commit | 91fad389784766782263133c5510976a8f76d89e (patch) | |
tree | 4058058dc6bd6eb12bf72efc06c1d1ac11cd170b /src/stacktrace.cc | |
parent | 51b4875f8ade3e0930eed2dc2a842ec607a94a2c (diff) | |
download | gperftools-91fad389784766782263133c5510976a8f76d89e.tar.gz |
Tue May 31 08:14:38 2005 Google Inc. <opensource@google.com>
* google-perftools: version 0.2 release
* Use mmap2() instead of mmap(), to map more memory (menage)
* Do correct pthread-local checking in heap-checker! (maxim)
* Avoid overflow on 64-bit machines in pprof (sanjay)
* Add a few more GetPC() functions, including for AMD (csilvers)
* Better method for overriding pthread functions (menage)
* (Hacky) fix to avoid overwriting profile files after fork() (csilvers)
* Crashing bugfix involving dumping heaps on small-stack threads (tudor)
* Allow library versions with letters at the end (csilvers)
* Config fixes for systems that don't define PATH_MAX (csilvers)
* Confix fixes so we no longer need config.h after install (csilvers)
* Fix to pprof to correctly read very big cpu profiles (csilvers)
* Fix to pprof to deal with new commandline flags in modern gv's
* Better error reporting when we can't access /proc/maps (etune)
* Get rid of the libc-preallocate code (which could crash on some
systems); no longer needed with local-threads fix (csilvers)
git-svn-id: http://gperftools.googlecode.com/svn/trunk@11 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
Diffstat (limited to 'src/stacktrace.cc')
-rw-r--r-- | src/stacktrace.cc | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/src/stacktrace.cc b/src/stacktrace.cc index 66a47a5..07fd321 100644 --- a/src/stacktrace.cc +++ b/src/stacktrace.cc @@ -32,7 +32,8 @@ // // Produce stack trace -#include "google/perftools/config.h" +#include "config.h" +#include <stdlib.h> #include "google/stacktrace.h" #undef IMPLEMENTED_STACK_TRACE @@ -43,6 +44,10 @@ defined(__linux) && !defined(NO_FRAME_POINTER) && !defined(_LP64) #define IMPLEMENTED_STACK_TRACE +#include <stdint.h> // for uintptr_t + +// Note: the code for GetStackExtent below is pretty similar to this one; +// change both if chaning one. int GetStackTrace(void** result, int max_depth, int skip_count) { void **sp; #ifdef __i386__ @@ -71,13 +76,56 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { void** new_sp = (void**) *sp; // A little bit of sanity checking to avoid crashes - if (new_sp < sp || new_sp > sp + 100000) { + if (new_sp < sp || + (uintptr_t)new_sp - (uintptr_t)sp > 100000) { break; } sp = new_sp; } return n; } + +// Note: the code is pretty similar to GetStackTrace above; +// change both if chaning one. +bool GetStackExtent(void* sp, void** stack_top, void** stack_bottom) { + void** cur_sp; + + if (sp != NULL) { + cur_sp = (void**)sp; + *stack_top = sp; + } else { +#ifdef __i386__ + // Stack frame format: + // sp[0] pointer to previous frame + // sp[1] caller address + // sp[2] first argument + // ... + cur_sp = (void**)&sp - 2; +#endif + +#ifdef __x86_64__ + // Arguments are passed in registers on x86-64, so we can't just + // offset from &result + cur_sp = (void**)__builtin_frame_address(0); +#endif + *stack_top = NULL; + } + + while (cur_sp) { + void** new_sp = (void**)*cur_sp; + // A little bit of sanity checking to avoid crashes + if (new_sp < cur_sp || + (uintptr_t)new_sp - (uintptr_t)cur_sp > 100000) { + *stack_bottom = (void*)cur_sp; + return true; + } + cur_sp = new_sp; + if (*stack_top == NULL) *stack_top = (void*)cur_sp; + // get out of the stack frame for this call + } + return false; +} + #endif // Portable implementation - just use glibc @@ -89,7 +137,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { static const int kStackLength = 64; void * stack[kStackLength]; int size; - + size = backtrace(stack, kStackLength); skip_count++; // we want to skip the current frame as well int result_count = size - skip_count; @@ -103,6 +151,11 @@ int GetStackTrace(void** result, int max_depth, int skip_count) { return result_count; } + +bool GetStackExtent(void* sp, void** stack_bottom, void** stack_top) { + return false; // can't climb up +} + #endif #if !defined(IMPLEMENTED_STACK_TRACE) && !defined(HAVE_EXECINFO_H) |