+ unsigned start_frame,
+ unsigned nr_frames)
+{
+ unw_cursor_t cursor;
+ unw_context_t context;
+ unw_proc_info_t pip;
+ unsigned i = 0;
+
+ pip.unwind_info = NULL;
+
+ unw_getcontext(&context);
+ unw_init_local(&cursor, &context);
+
+ while ((start_frame > 0) && (unw_step(&cursor) > 0))
+ start_frame--;
+
+ while ((i < nr_frames) && (unw_step(&cursor) > 0)) {
+ unw_word_t ip;
+
+ unw_get_reg(&cursor, UNW_REG_IP, &ip);
+ unw_get_proc_info(&cursor, &pip);
+
+ backtrace[i].start_ip = pip.start_ip;
+ backtrace[i].off = ip - pip.start_ip;
+ backtrace[i].procname = symbol_name_cached(&cursor, &pip);
+
+ i++;
+ }
+
+ while (i < nr_frames) {
+ backtrace[i].start_ip = 0;
+ i++;
+ }
+}
+
+static const void *
+frame_ip(const struct debug_stack_frame *frame)
+{
+ return (void *)(uintptr_t)(frame->start_ip + frame->off);
+}
+
+static const char *
+frame_info(const struct debug_stack_frame *frame, unsigned *offset)
+{
+ Dl_info dlinfo;
+ const void *addr = frame_ip(frame);
+
+
+ if (dladdr(addr, &dlinfo) && dlinfo.dli_fname &&
+ *dlinfo.dli_fname) {
+ *offset = (unsigned)((uintptr_t)addr - (uintptr_t)dlinfo.dli_fbase);
+ return dlinfo.dli_fname;
+ }
+
+ *offset = 0;
+ return "?";
+}
+
+void
+debug_backtrace_dump(const struct debug_stack_frame *backtrace,
+ unsigned nr_frames)
+{
+ unsigned i, offset;
+ const char *filename;
+
+ for (i = 0; i < nr_frames; ++i) {
+ if (!backtrace[i].start_ip)
+ break;
+ filename = frame_info(&backtrace[i], &offset);
+ debug_printf("\t%s(+0x%x) (%s+0x%x) [%p]\n", filename, offset,
+ backtrace[i].procname, backtrace[i].off,
+ frame_ip(&backtrace[i]));
+ }
+}
+
+void
+debug_backtrace_print(FILE *f,
+ const struct debug_stack_frame *backtrace,
+ unsigned nr_frames)
+{
+ unsigned i, offset;
+ const char *filename;
+
+ for (i = 0; i < nr_frames; ++i) {
+ if (!backtrace[i].start_ip)
+ break;
+ filename = frame_info(&backtrace[i], &offset);
+ fprintf(f, "\t%s(+0x%x) (%s+0x%x) [%p]\n", filename, offset,
+ backtrace[i].procname, backtrace[i].off,
+ frame_ip(&backtrace[i]));
+ }
+}
+#elif defined(ANDROID)
+ /* Not implemented here; see u_debug_stack_android.cpp */
+#else /* ! HAVE_LIBUNWIND */
+
+#if defined(PIPE_OS_WINDOWS)
+#include <windows.h>
+#endif
+
+
+/**
+ * Capture stack backtrace.
+ *
+ * NOTE: The implementation of this function is quite big, but it is important
+ * not to break it down in smaller functions to avoid adding new frames to the
+ * calling stack.
+ */
+void
+debug_backtrace_capture(struct debug_stack_frame *backtrace,
+ unsigned start_frame,