aboutsummaryrefslogtreecommitdiff
path: root/debug/backtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'debug/backtrace.c')
-rw-r--r--debug/backtrace.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/debug/backtrace.c b/debug/backtrace.c
index 05cdc84..d563a04 100644
--- a/debug/backtrace.c
+++ b/debug/backtrace.c
@@ -20,6 +20,9 @@
#include <stdlib.h>
#include <unwind.h>
#include <unwind-link.h>
+#if ENABLE_SFRAME
+#include <sframe.h>
+#endif
struct trace_arg
{
@@ -30,6 +33,42 @@ struct trace_arg
int size;
};
+#if ENABLE_SFRAME
+/* Initialize the SFrame backtrace routine and attempt to backtrace
+ the current stack using SFrame information. For the SFrame
+ backtrace to be considered valid, the tracer must return more than
+ one frame. If it doesn't, this could indicate a mixed
+ environment for example, glibc may have been compiled with SFrame
+ support, while the application was not. An even more complex
+ scenario arises when the application uses shared objects compiled
+ with differing configurations.
+
+ Additionally, glibc includes certain callback paths that must be
+ considered. For example: an application calls shared object A,
+ which calls shared object B, which in turn calls qsort() in
+ glibc. qsort() then invokes a helper in shared object C, which
+ raises a SIGFPE signal, handled by object D, which requests a
+ backtrace. Any of these components may or may not include SFrame
+ encoding.
+
+ In cases where a stack frame lacks SFrame information, the SFrame
+ backtracer can fall back to using the DWARF unwinder.
+
+ This function must be always inline. Otherwise the
+ __builtin_frame_address and the __getXX helper functions will not
+ return the right addresses. */
+
+static inline int __attribute__ ((always_inline))
+do_sframe_backtrace (void **array, int size)
+{
+ frame frame;
+ frame.pc = __getPC ();
+ frame.sp = __getSP ();
+ frame.fp = (_Unwind_Ptr) __builtin_frame_address (0);
+ return __stacktrace_sframe (array, size, &frame);
+}
+#endif
+
static _Unwind_Reason_Code
backtrace_helper (struct _Unwind_Context *ctx, void *a)
{
@@ -72,7 +111,18 @@ __backtrace (void **array, int size)
.cnt = -1
};
- if (size <= 0 || arg.unwind_link == NULL)
+ if (size <= 0)
+ return 0;
+
+#if ENABLE_SFRAME
+ /* Try first the SFrame backtracer. */
+ int cnt = do_sframe_backtrace (array, size);
+ if (cnt > 1)
+ return cnt;
+#endif
+
+ /* Try the dwarf unwinder. */
+ if (arg.unwind_link == NULL)
return 0;
UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)