diff options
author | Arun Sharma <asharma@fb.com> | 2011-04-05 21:26:56 -0700 |
---|---|---|
committer | Arun Sharma <asharma@fb.com> | 2011-04-05 22:07:05 -0700 |
commit | e2962af9d31266761700b431da894421c0d757ec (patch) | |
tree | b5a3370f805707375c556e46f02ccd9700e95bb1 | |
parent | 15f182828d88ea51d419d94b3daabb7a69181c78 (diff) | |
download | libunwind-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.h | 1 | ||||
-rw-r--r-- | include/tdep-hppa/libunwind_i.h | 1 | ||||
-rw-r--r-- | include/tdep-ia64/libunwind_i.h | 1 | ||||
-rw-r--r-- | include/tdep-mips/libunwind_i.h | 1 | ||||
-rw-r--r-- | include/tdep-ppc32/libunwind_i.h | 1 | ||||
-rw-r--r-- | include/tdep-ppc64/libunwind_i.h | 1 | ||||
-rw-r--r-- | include/tdep-x86/libunwind_i.h | 1 | ||||
-rw-r--r-- | include/tdep-x86_64/libunwind_i.h | 2 | ||||
-rw-r--r-- | src/mi/backtrace.c | 2 | ||||
-rw-r--r-- | src/x86_64/getcontext.S | 29 |
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 |