mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-22 07:37:38 +01:00
Drop a call frame in tdep_trace and avoid a call to unw_step.
Dropping the extra frame for unw_backtrace itself using unw_step is approximately 15% slower than skipping the frame in tdep_trace. So drop the frame in the latter, and make the function a private implementation detail for libunwind, not an exported interface. Also moves unw_getcontext call back into unw_backtrace to avoid an extra call frame in case slow_backtrace does not get inlined into unw_backtrace.
This commit is contained in:
parent
50bc12afba
commit
5f38f35d5d
20 changed files with 135 additions and 142 deletions
|
@ -286,19 +286,11 @@ typedef struct
|
|||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no arm-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -103,12 +103,6 @@ unw_tdep_save_loc_t;
|
|||
/* On PA-RISC, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no hppa-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_HPPA_FR) < 32)
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
@ -124,8 +118,6 @@ unw_tdep_proc_info_t;
|
|||
#define unw_tdep_getcontext UNW_ARCH_OBJ (getcontext)
|
||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -150,12 +150,6 @@ unw_tdep_save_loc_t;
|
|||
/* On IA-64, we can directly use ucontext_t as the unwind context. */
|
||||
typedef ucontext_t unw_tdep_context_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ia64-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#define unw_tdep_is_fpreg(r) ((unsigned) ((r) - UNW_IA64_FR) < 128)
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
|
@ -193,8 +187,6 @@ extern unw_word_t _Uia64_find_dyn_list (unw_addr_space_t, unw_dyn_info_t *,
|
|||
signal-safe. */
|
||||
extern int _Uia64_get_kernel_table (unw_dyn_info_t *);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -137,12 +137,6 @@ typedef struct
|
|||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no mips-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
/* There is no getcontext() on MIPS. Use a stub version which only saves GP
|
||||
|
@ -154,8 +148,6 @@ extern int unw_tdep_getcontext (ucontext_t *uc);
|
|||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -195,19 +195,11 @@ typedef struct
|
|||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc32-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -252,19 +252,11 @@ typedef struct
|
|||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc64-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -172,12 +172,6 @@ typedef struct
|
|||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no x86-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||
|
@ -186,8 +180,6 @@ extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
|||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
#define unw_tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -104,39 +104,15 @@ typedef struct
|
|||
}
|
||||
unw_tdep_proc_info_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_X86_64_FRAME_STANDARD = -2, /* regular rbp, rsp +/- offset */
|
||||
UNW_X86_64_FRAME_SIGRETURN = -1, /* special sigreturn frame */
|
||||
UNW_X86_64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
|
||||
UNW_X86_64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
|
||||
}
|
||||
unw_tdep_frame_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t virtual_address;
|
||||
int64_t frame_type : 2; /* unw_tdep_frame_type_t classification */
|
||||
int64_t last_frame : 1; /* non-zero if last frame in chain */
|
||||
int64_t cfa_reg_rsp : 1; /* cfa dwarf base register is rsp vs. rbp */
|
||||
int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
|
||||
int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */
|
||||
int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
#include "libunwind-dynamic.h"
|
||||
#include "libunwind-common.h"
|
||||
|
||||
#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext)
|
||||
#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg)
|
||||
#define unw_tdep_trace UNW_OBJ(trace)
|
||||
|
||||
extern int unw_tdep_getcontext (unw_tdep_context_t *);
|
||||
extern int unw_tdep_is_fpreg (int);
|
||||
|
||||
extern int unw_tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "dwarf.h"
|
||||
#include "ex_tables.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no arm-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -222,6 +228,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
|
|
|
@ -35,6 +35,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "elf32.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no hppa-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -228,6 +234,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
|
|
|
@ -32,6 +32,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "elf64.h"
|
||||
#include "mempool.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ia64-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
enum ia64_pregnum
|
||||
{
|
||||
/* primary unat: */
|
||||
|
@ -224,6 +230,7 @@ struct ia64_global_unwind_state
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
#define tdep_get_as(c) ((c)->as)
|
||||
#define tdep_get_as_arg(c) ((c)->as_arg)
|
||||
#define tdep_get_ip(c) ((c)->ip)
|
||||
|
|
|
@ -39,6 +39,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no mips-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -283,6 +289,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
|
|
|
@ -42,6 +42,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc32-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -258,6 +264,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
|
|
@ -42,6 +42,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no ppc64-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -258,6 +264,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
#define tdep_get_func_addr UNW_OBJ(get_func_addr)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
|
|
|
@ -36,6 +36,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* no x86-specific fast trace */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -244,6 +250,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
#define tdep_cache_frame(c,rs) do {} while(0)
|
||||
#define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#define tdep_stash_frame(c,rs) do {} while(0)
|
||||
#define tdep_trace(cur,addr,n) (-UNW_ENOINFO)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
|
|
|
@ -38,6 +38,27 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
#include "mempool.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNW_X86_64_FRAME_STANDARD = -2, /* regular rbp, rsp +/- offset */
|
||||
UNW_X86_64_FRAME_SIGRETURN = -1, /* special sigreturn frame */
|
||||
UNW_X86_64_FRAME_OTHER = 0, /* not cacheable (special or unrecognised) */
|
||||
UNW_X86_64_FRAME_GUESSED = 1 /* guessed it was regular, but not known */
|
||||
}
|
||||
unw_tdep_frame_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t virtual_address;
|
||||
int64_t frame_type : 2; /* unw_tdep_frame_type_t classification */
|
||||
int64_t last_frame : 1; /* non-zero if last frame in chain */
|
||||
int64_t cfa_reg_rsp : 1; /* cfa dwarf base register is rsp vs. rbp */
|
||||
int64_t cfa_reg_offset : 30; /* cfa is at this offset from base register value */
|
||||
int64_t rbp_cfa_offset : 15; /* rbp saved at this offset from cfa (-1 = not saved) */
|
||||
int64_t rsp_cfa_offset : 15; /* rsp saved at this offset from cfa (-1 = not saved) */
|
||||
}
|
||||
unw_tdep_frame_t;
|
||||
|
||||
struct unw_addr_space
|
||||
{
|
||||
struct unw_accessors acc;
|
||||
|
@ -176,6 +197,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
|
|||
# define tdep_reuse_frame(c,rs) do {} while(0)
|
||||
#endif
|
||||
#define tdep_stash_frame UNW_OBJ(stash_frame)
|
||||
#define tdep_trace UNW_OBJ(tdep_trace)
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
# define tdep_find_proc_info(c,ip,n) \
|
||||
|
@ -222,4 +244,6 @@ extern void tdep_stash_frame (struct dwarf_cursor *c,
|
|||
struct dwarf_reg_state *rs);
|
||||
#endif
|
||||
|
||||
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
|
||||
|
||||
#endif /* X86_64_LIBUNWIND_I_H */
|
||||
|
|
|
@ -33,15 +33,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||
/* See glibc manual for a description of this function. */
|
||||
|
||||
static ALWAYS_INLINE int
|
||||
slow_backtrace (void **buffer, int size)
|
||||
slow_backtrace (void **buffer, int size, unw_context_t *uc)
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
unw_word_t ip;
|
||||
int n = 0;
|
||||
|
||||
unw_getcontext (&uc);
|
||||
if (unw_init_local (&cursor, &uc) < 0)
|
||||
if (unw_init_local (&cursor, uc) < 0)
|
||||
return 0;
|
||||
|
||||
while (unw_step (&cursor) > 0)
|
||||
|
@ -62,21 +60,16 @@ unw_backtrace (void **buffer, int size)
|
|||
unw_cursor_t cursor;
|
||||
unw_context_t uc;
|
||||
int n = size;
|
||||
int ret;
|
||||
|
||||
unw_getcontext (&uc);
|
||||
|
||||
if (unw_init_local (&cursor, &uc) < 0)
|
||||
return 0;
|
||||
|
||||
/* We don't need backtrace() to show up in buffer */
|
||||
ret = unw_step (&cursor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (unw_tdep_trace (&cursor, buffer, &n) < 0)
|
||||
if (tdep_trace (&cursor, buffer, &n) < 0)
|
||||
{
|
||||
return slow_backtrace(buffer, size);
|
||||
unw_getcontext (&uc);
|
||||
return slow_backtrace (buffer, size, &uc);
|
||||
}
|
||||
|
||||
return n;
|
||||
|
|
|
@ -328,13 +328,13 @@ trace_lookup (unw_cursor_t *cursor,
|
|||
|
||||
/* Fast stack backtrace for x86-64.
|
||||
|
||||
Intended for use when the application makes frequent queries to the
|
||||
current call stack without any desire to unwind. Somewhat like the
|
||||
GLIBC backtrace() function: fills BUFFER with the call tree from
|
||||
CURSOR upwards, and SIZE with the number of stack levels so found.
|
||||
When called, SIZE should tell the maximum number of entries that
|
||||
can be stored in BUFFER. An internal thread-specific cache is used
|
||||
to accelerate the stack queries.
|
||||
This is used by backtrace() implementation to accelerate frequent
|
||||
queries for current stack, without any desire to unwind. It fills
|
||||
BUFFER with the call tree from CURSOR upwards for at most SIZE
|
||||
stack levels. The first frame, backtrace itself, is omitted. When
|
||||
called, SIZE should give the maximum number of entries that can be
|
||||
stored into BUFFER. Uses an internal thread-specific cache to
|
||||
accelerate queries.
|
||||
|
||||
The caller should fall back to a unw_step() loop if this function
|
||||
fails by returning -UNW_ESTOPUNWIND, meaning the routine hit a
|
||||
|
@ -351,7 +351,7 @@ trace_lookup (unw_cursor_t *cursor,
|
|||
they are at the outermost (final) frame or can conservatively be
|
||||
assumed to be frame-pointer based.
|
||||
|
||||
Any other stack layout will cause the routine to give up. There
|
||||
Any other stack layout will cause the routine to give up. There
|
||||
are only a handful of relatively rarely used functions which do
|
||||
not have a stack in the standard form: vfork, longjmp, setcontext
|
||||
and _dl_runtime_profile on common linux systems for example.
|
||||
|
@ -369,31 +369,28 @@ trace_lookup (unw_cursor_t *cursor,
|
|||
Callers of this function would normally look like this:
|
||||
|
||||
unw_cursor_t cur;
|
||||
unw_context_t ctx, saved;
|
||||
unw_context_t ctx;
|
||||
void addrs[128];
|
||||
int depth = 128;
|
||||
int ret;
|
||||
|
||||
unw_getcontext(&ctx);
|
||||
memcpy(&saved, &ctx, sizeof(ctx));
|
||||
|
||||
unw_init_local(&cur, &ctx);
|
||||
if ((ret = unw_tdep_trace(&cur, addrs, &depth)) < 0)
|
||||
{
|
||||
depth = 0;
|
||||
unw_init_local(&cur, &saved);
|
||||
while (depth < 128)
|
||||
unw_getcontext(&ctx);
|
||||
unw_init_local(&cur, &ctx);
|
||||
while ((ret = unw_step(&cur)) > 0 && depth < 128)
|
||||
{
|
||||
unw_word_t ip;
|
||||
unw_get_reg(&cur, UNW_REG_IP, &ip);
|
||||
addresses[depth++] = (void *) ip;
|
||||
if ((ret = unw_step(&cur)) <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
int
|
||||
unw_tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||
HIDDEN int
|
||||
tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
||||
{
|
||||
struct cursor *c = (struct cursor *) cursor;
|
||||
struct dwarf_cursor *d = &c->dwarf;
|
||||
|
@ -449,9 +446,6 @@ unw_tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
|||
for common failures. */
|
||||
unw_tdep_frame_t *f = trace_lookup (cursor, cache, cfa, rip, rbp, rsp);
|
||||
|
||||
/* Record this address in stack trace. */
|
||||
buffer[depth++] = (void *) rip;
|
||||
|
||||
/* If we don't have information for this frame, give up. */
|
||||
if (! f)
|
||||
{
|
||||
|
@ -530,6 +524,9 @@ unw_tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
|
|||
/* If we failed on ended up somewhere bogus, stop. */
|
||||
if (ret < 0 || rip < 0x4000)
|
||||
break;
|
||||
|
||||
/* Record this address in stack trace. We skipped the first address. */
|
||||
buffer[depth++] = (void *) (rip - d->use_prev_instr);
|
||||
}
|
||||
|
||||
#if UNW_DEBUG
|
||||
|
|
|
@ -50,7 +50,7 @@ int num_errors;
|
|||
/* These variables are global because they
|
||||
* cause the signal stack to overflow */
|
||||
char buf[512], name[256];
|
||||
void *addresses[2][128];
|
||||
void *addresses[3][128];
|
||||
unw_cursor_t cursor;
|
||||
ucontext_t uc;
|
||||
|
||||
|
@ -59,42 +59,28 @@ do_backtrace (void)
|
|||
{
|
||||
unw_word_t ip;
|
||||
int ret = -UNW_ENOINFO;
|
||||
int depth = 128;
|
||||
int i, n;
|
||||
int depth = 0;
|
||||
int i, n, m;
|
||||
|
||||
if (verbose)
|
||||
printf ("\tfast backtrace:\n");
|
||||
printf ("\tnormal trace:\n");
|
||||
|
||||
unw_getcontext (&uc);
|
||||
if (unw_init_local (&cursor, &uc) < 0)
|
||||
panic ("unw_init_local failed!\n");
|
||||
|
||||
#if UNW_TARGET_X86_64
|
||||
if ((ret = unw_tdep_trace (&cursor, addresses[0], &depth)) < 0)
|
||||
do
|
||||
{
|
||||
unw_get_reg (&cursor, UNW_REG_IP, &ip);
|
||||
printf ("FAILURE: unw_tdep_trace() returned %d for ip=%lx\n", ret, (long) ip);
|
||||
++num_errors;
|
||||
addresses[0][depth] = (void *) ip;
|
||||
}
|
||||
#endif
|
||||
while ((ret = unw_step (&cursor)) > 0 && ++depth < 128);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
unw_get_reg (&cursor, UNW_REG_IP, &ip);
|
||||
addresses[0][i] = (void *) ip;
|
||||
}
|
||||
while ((ret = unw_step (&cursor)) > 0 && ++i < 128);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
unw_get_reg (&cursor, UNW_REG_IP, &ip);
|
||||
printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip);
|
||||
++num_errors;
|
||||
}
|
||||
depth = i;
|
||||
unw_get_reg (&cursor, UNW_REG_IP, &ip);
|
||||
printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip);
|
||||
++num_errors;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
|
@ -110,17 +96,43 @@ do_backtrace (void)
|
|||
for (i = 0; i < n; ++i)
|
||||
printf ("\t #%-3d ip=%p\n", i, addresses[1][i]);
|
||||
|
||||
if (n != depth)
|
||||
if (verbose)
|
||||
printf ("\n\tvia unw_backtrace():\n");
|
||||
|
||||
m = unw_backtrace (addresses[2], 128);
|
||||
|
||||
if (verbose)
|
||||
for (i = 0; i < m; ++i)
|
||||
printf ("\t #%-3d ip=%p\n", i, addresses[2][i]);
|
||||
|
||||
if (m != depth+1)
|
||||
{
|
||||
printf ("FAILURE: unw_tdep_trace() and backtrace() depths differ: %d vs. %d\n", depth, n);
|
||||
printf ("FAILURE: unw_step() loop and unw_backtrace() depths differ: %d vs. %d\n", depth, m);
|
||||
++num_errors;
|
||||
}
|
||||
else
|
||||
|
||||
if (n != depth+1)
|
||||
{
|
||||
printf ("FAILURE: unw_step() loop and backtrace() depths differ: %d vs. %d\n", depth, n);
|
||||
++num_errors;
|
||||
}
|
||||
|
||||
if (n == m)
|
||||
for (i = 1; i < n; ++i)
|
||||
/* Allow one in difference in comparison, trace returns adjusted addresses. */
|
||||
if (labs((unw_word_t) addresses[1][i] - (unw_word_t) addresses[2][i]) > 1)
|
||||
{
|
||||
printf ("FAILURE: backtrace() and unw_backtrace() addresses differ at %d: %p vs. %p\n",
|
||||
i, addresses[1][n], addresses[2][n]);
|
||||
++num_errors;
|
||||
}
|
||||
|
||||
if (n == depth+1)
|
||||
for (i = 1; i < depth; ++i)
|
||||
/* Allow one in difference in comparison, trace returns adjusted addresses. */
|
||||
if (labs((unw_word_t) addresses[0][i] - (unw_word_t) addresses[1][i]) > 1)
|
||||
{
|
||||
printf ("FAILURE: unw_tdep_trace() and backtrace() addresses differ at %d: %p vs. %p\n",
|
||||
printf ("FAILURE: unw_step() loop and backtrace() addresses differ at %d: %p vs. %p\n",
|
||||
i, addresses[0][n], addresses[1][n]);
|
||||
++num_errors;
|
||||
}
|
||||
|
|
|
@ -124,7 +124,6 @@ check_local_unw_abi () {
|
|||
match _U${plat}_is_fpreg
|
||||
match _UL${plat}_dwarf_search_unwind_table
|
||||
match _U${plat}_setcontext
|
||||
match _UL${plat}_trace
|
||||
;;
|
||||
*)
|
||||
match _U${plat}_is_fpreg
|
||||
|
@ -188,7 +187,6 @@ check_generic_unw_abi () {
|
|||
match _U${plat}_get_elf_image
|
||||
match _U${plat}_is_fpreg
|
||||
match _U${plat}_dwarf_search_unwind_table
|
||||
match _U${plat}_trace
|
||||
;;
|
||||
*)
|
||||
match _U${plat}_is_fpreg
|
||||
|
|
Loading…
Reference in a new issue