summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Sharma <asharma@fb.com>2011-04-05 21:26:56 -0700
committerArun Sharma <asharma@fb.com>2011-04-05 22:07:05 -0700
commite2962af9d31266761700b431da894421c0d757ec (patch)
treeb5a3370f805707375c556e46f02ccd9700e95bb1
parent15f182828d88ea51d419d94b3daabb7a69181c78 (diff)
downloadlibunwind-e2962af9d31266761700b431da894421c0d757ec.tar.gz
Implement a cheaper getcontext()
Since the fast unwinding code path doesn't need the full context, a faster target dependent getcontext is implemented. Signed-off-by: Lassi Tuura <lat@cern.ch>
-rw-r--r--include/tdep-arm/libunwind_i.h1
-rw-r--r--include/tdep-hppa/libunwind_i.h1
-rw-r--r--include/tdep-ia64/libunwind_i.h1
-rw-r--r--include/tdep-mips/libunwind_i.h1
-rw-r--r--include/tdep-ppc32/libunwind_i.h1
-rw-r--r--include/tdep-ppc64/libunwind_i.h1
-rw-r--r--include/tdep-x86/libunwind_i.h1
-rw-r--r--include/tdep-x86_64/libunwind_i.h2
-rw-r--r--src/mi/backtrace.c2
-rw-r--r--src/x86_64/getcontext.S29
10 files changed, 39 insertions, 1 deletions
diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h
index cd18292e..271e1d3c 100644
--- a/include/tdep-arm/libunwind_i.h
+++ b/include/tdep-arm/libunwind_i.h
@@ -215,6 +215,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#endif /* !UNW_LOCAL_ONLY */
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-hppa/libunwind_i.h b/include/tdep-hppa/libunwind_i.h
index d5ba7ab0..ef0bb5aa 100644
--- a/include/tdep-hppa/libunwind_i.h
+++ b/include/tdep-hppa/libunwind_i.h
@@ -221,6 +221,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#endif /* !UNW_LOCAL_ONLY */
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-ia64/libunwind_i.h b/include/tdep-ia64/libunwind_i.h
index ec20338d..619425c1 100644
--- a/include/tdep-ia64/libunwind_i.h
+++ b/include/tdep-ia64/libunwind_i.h
@@ -216,6 +216,7 @@ struct ia64_global_unwind_state
# endif
};
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization unw.needs_initialization
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-mips/libunwind_i.h b/include/tdep-mips/libunwind_i.h
index 17876d54..5713d95d 100644
--- a/include/tdep-mips/libunwind_i.h
+++ b/include/tdep-mips/libunwind_i.h
@@ -276,6 +276,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#endif /* !UNW_LOCAL_ONLY */
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-ppc32/libunwind_i.h b/include/tdep-ppc32/libunwind_i.h
index 23bf2d11..292da621 100644
--- a/include/tdep-ppc32/libunwind_i.h
+++ b/include/tdep-ppc32/libunwind_i.h
@@ -251,6 +251,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
1, c->as_arg);
}
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-ppc64/libunwind_i.h b/include/tdep-ppc64/libunwind_i.h
index 5e96bee2..31c9ccf0 100644
--- a/include/tdep-ppc64/libunwind_i.h
+++ b/include/tdep-ppc64/libunwind_i.h
@@ -251,6 +251,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
1, c->as_arg);
}
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-x86/libunwind_i.h b/include/tdep-x86/libunwind_i.h
index 739320ee..1f2e1449 100644
--- a/include/tdep-x86/libunwind_i.h
+++ b/include/tdep-x86/libunwind_i.h
@@ -237,6 +237,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
#endif /* !UNW_LOCAL_ONLY */
+#define tdep_getcontext_trace unw_getcontext
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init UNW_OBJ(init)
/* Platforms that support UNW_INFO_FORMAT_TABLE need to define
diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h
index a707efe4..22697b13 100644
--- a/include/tdep-x86_64/libunwind_i.h
+++ b/include/tdep-x86_64/libunwind_i.h
@@ -177,6 +177,7 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val)
1, c->as_arg);
}
+#define tdep_getcontext_trace UNW_ARCH_OBJ(getcontext_trace)
#define tdep_needs_initialization UNW_OBJ(needs_initialization)
#define tdep_init_mem_validate UNW_OBJ(init_mem_validate)
#define tdep_init UNW_OBJ(init)
@@ -244,6 +245,7 @@ extern void tdep_stash_frame (struct dwarf_cursor *c,
struct dwarf_reg_state *rs);
#endif
+extern int tdep_getcontext_trace (unw_tdep_context_t *);
extern int tdep_trace (unw_cursor_t *cursor, void **addresses, int *n);
#endif /* X86_64_LIBUNWIND_I_H */
diff --git a/src/mi/backtrace.c b/src/mi/backtrace.c
index 128a77e5..42e1f5d3 100644
--- a/src/mi/backtrace.c
+++ b/src/mi/backtrace.c
@@ -61,7 +61,7 @@ unw_backtrace (void **buffer, int size)
unw_context_t uc;
int n = size;
- unw_getcontext (&uc);
+ tdep_getcontext_trace (&uc);
if (unw_init_local (&cursor, &uc) < 0)
return 0;
diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S
index 15fff283..7a8b5664 100644
--- a/src/x86_64/getcontext.S
+++ b/src/x86_64/getcontext.S
@@ -101,5 +101,34 @@ _Ux86_64_getcontext:
.cfi_endproc
.size _Ux86_64_getcontext, . - _Ux86_64_getcontext
+/* int _Ux86_64_getcontext_trace (ucontext_t *ucp)
+
+ Saves limited machine context in UCP necessary for libunwind.
+ Unlike _Ux86_64_getcontext, saves only the parts needed for
+ fast trace. If fast trace fails, caller will have to get the
+ full context.
+*/
+
+ .global _Ux86_64_getcontext_trace
+ .hidden _Ux86_64_getcontext_trace
+ .type _Ux86_64_getcontext_trace, @function
+_Ux86_64_getcontext_trace:
+ .cfi_startproc
+
+ /* Save only RBP, RBX, RSP, RIP - exclude this call. */
+ movq %rbp, UC_MCONTEXT_GREGS_RBP(%rdi)
+ movq %rbx, UC_MCONTEXT_GREGS_RBX(%rdi)
+
+ leaq 8(%rsp), %rax
+ movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi)
+
+ movq 0(%rsp), %rax
+ movq %rax, UC_MCONTEXT_GREGS_RIP(%rdi)
+
+ xorq %rax, %rax
+ retq
+ .cfi_endproc
+ .size _Ux86_64_getcontext_trace, . - _Ux86_64_getcontext_trace
+
/* We do not need executable stack. */
.section .note.GNU-stack,"",@progbits