From 35e6a1a108f39a8ab5c3825f85e41b7b08021322 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 27 Aug 2009 17:01:17 -0700 Subject: [PATCH 001/162] This avoids a C++ syntax error with a (non-gcc?) compiler. Signed-off-by: Lassi Tuura --- include/libunwind-dynamic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libunwind-dynamic.h b/include/libunwind-dynamic.h index 8f6041f1..6c94f05a 100644 --- a/include/libunwind-dynamic.h +++ b/include/libunwind-dynamic.h @@ -75,7 +75,7 @@ typedef enum { UNW_INFO_FORMAT_DYNAMIC, /* unw_dyn_proc_info_t */ UNW_INFO_FORMAT_TABLE, /* unw_dyn_table_t */ - UNW_INFO_FORMAT_REMOTE_TABLE, /* unw_dyn_remote_table_t */ + UNW_INFO_FORMAT_REMOTE_TABLE /* unw_dyn_remote_table_t */ } unw_dyn_info_format_t; From 84d4150668d83a98420cc91e00026159c3d74a81 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Mon, 21 Sep 2009 12:02:07 -0700 Subject: [PATCH 002/162] Allow caller to block signals. Greetings, We use libunwind just for stack traces (I suspect many others do as well). The use pattern is: GetStackTrace(void** result, int max_depth) { ... unw_getcontext(&uc); unw_init_local(&cursor, &uc); while (n < max_depth) { if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) { break; } result[n++] = ip; if (unw_step(&cursor) <= 0) { break; } } Given this usage, it is quite convenient for us to block signals (or prevent signal handlers from re-entering libunwind by other means) at the "top level", which makes most of the sigprocmask calls performed by libunwind itself unneccessary. The second patch in this series adds a configure option which removes most of the sigprocmask calls. Attached patch is a preliminary for it -- consolidating all of the "sigprocmask; mutex_lock;" sequences into lock_acquire and "mutex_unlock; sigprocmask;" sequences into lock_release. Thanks, -- Paul Pluzhnikov commit 402d15b123d54a7669db7cf17a76dd315094e472 Author: Paul Pluzhnikov Date: Mon Sep 21 10:18:28 2009 -0700 Replace "sigprocmask + mutext_lock" with a single lock_acquire. Likewise, replace "mutext_unlock + sigprocmask" with lock_release. --- src/arm/Gglobal.c | 6 ++---- src/dwarf/Gparser.c | 6 ++---- src/hppa/Gglobal.c | 6 ++---- src/ia64/Gglobal.c | 6 ++---- src/ia64/Gscript.c | 6 ++---- src/mips/Gglobal.c | 6 ++---- src/ppc32/Gglobal.c | 6 ++---- src/ppc64/Gglobal.c | 6 ++---- src/x86/Gglobal.c | 6 ++---- src/x86_64/Gglobal.c | 6 ++---- 10 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/arm/Gglobal.c b/src/arm/Gglobal.c index 40374327..a93c4ddb 100644 --- a/src/arm/Gglobal.c +++ b/src/arm/Gglobal.c @@ -44,8 +44,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&arm_lock); + lock_acquire (&arm_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -61,6 +60,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&arm_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&arm_lock, saved_mask); } diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 01a37437..3969cb3a 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -489,11 +489,10 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if (AO_test_and_set (&cache->busy) == AO_TS_SET) return NULL; # else - sigprocmask (SIG_SETMASK, &unwi_full_mask, saved_maskp); if (likely (caching == UNW_CACHE_GLOBAL)) { Debug (16, "%s: acquiring lock\n", __FUNCTION__); - mutex_lock (&cache->lock); + lock_acquire (&cache->lock, *saved_maskp); } # endif #endif @@ -521,8 +520,7 @@ put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, AO_CLEAR (&cache->busy); # else if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) - mutex_unlock (&cache->lock); - sigprocmask (SIG_SETMASK, saved_maskp, NULL); + lock_release (&cache->lock, *saved_maskp); # endif #endif } diff --git a/src/hppa/Gglobal.c b/src/hppa/Gglobal.c index a56426da..f453a43b 100644 --- a/src/hppa/Gglobal.c +++ b/src/hppa/Gglobal.c @@ -35,8 +35,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&hppa_lock); + lock_acquire (&hppa_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -52,6 +51,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&hppa_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&hppa_lock, saved_mask); } diff --git a/src/ia64/Gglobal.c b/src/ia64/Gglobal.c index 9525f8c2..b04a5783 100644 --- a/src/ia64/Gglobal.c +++ b/src/ia64/Gglobal.c @@ -71,8 +71,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&unw.lock); + lock_acquire (&unw.lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -120,6 +119,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&unw.lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&unw.lock, saved_mask); } diff --git a/src/ia64/Gscript.c b/src/ia64/Gscript.c index edeee1de..b3e8ef6e 100644 --- a/src/ia64/Gscript.c +++ b/src/ia64/Gscript.c @@ -113,11 +113,10 @@ get_script_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if (AO_test_and_set (&cache->busy) == AO_TS_SET) return NULL; # else - sigprocmask (SIG_SETMASK, &unwi_full_mask, saved_maskp); if (likely (caching == UNW_CACHE_GLOBAL)) { Debug (16, "%s: acquiring lock\n", __FUNCTION__); - mutex_lock (&cache->lock); + lock_acquire (&cache->lock, *saved_maskp); } # endif #endif @@ -144,8 +143,7 @@ put_script_cache (unw_addr_space_t as, struct ia64_script_cache *cache, AO_CLEAR (&cache->busy); # else if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) - mutex_unlock (&cache->lock); - sigprocmask (SIG_SETMASK, saved_maskp, NULL); + lock_release (&cache->lock, *saved_maskp); # endif #endif } diff --git a/src/mips/Gglobal.c b/src/mips/Gglobal.c index 1874a5bc..1aa77eac 100644 --- a/src/mips/Gglobal.c +++ b/src/mips/Gglobal.c @@ -44,8 +44,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&mips_lock); + lock_acquire (&mips_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -61,6 +60,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&mips_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&mips_lock, saved_mask); } diff --git a/src/ppc32/Gglobal.c b/src/ppc32/Gglobal.c index c2d4604d..b7cebff5 100644 --- a/src/ppc32/Gglobal.c +++ b/src/ppc32/Gglobal.c @@ -115,8 +115,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&ppc32_lock); + lock_acquire (&ppc32_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -132,6 +131,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&ppc32_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&ppc32_lock, saved_mask); } diff --git a/src/ppc64/Gglobal.c b/src/ppc64/Gglobal.c index 1506b002..64813571 100644 --- a/src/ppc64/Gglobal.c +++ b/src/ppc64/Gglobal.c @@ -162,8 +162,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&ppc64_lock); + lock_acquire (&ppc64_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -179,6 +178,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&ppc64_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&ppc64_lock, saved_mask); } diff --git a/src/x86/Gglobal.c b/src/x86/Gglobal.c index e55644c9..3c97853c 100644 --- a/src/x86/Gglobal.c +++ b/src/x86/Gglobal.c @@ -47,8 +47,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&x86_lock); + lock_acquire (&x86_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -64,6 +63,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&x86_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&x86_lock, saved_mask); } diff --git a/src/x86_64/Gglobal.c b/src/x86_64/Gglobal.c index ec14efe1..b24d779c 100644 --- a/src/x86_64/Gglobal.c +++ b/src/x86_64/Gglobal.c @@ -61,8 +61,7 @@ tdep_init (void) sigfillset (&unwi_full_mask); - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); - mutex_lock (&x86_64_lock); + lock_acquire (&x86_64_lock, saved_mask); { if (!tdep_needs_initialization) /* another thread else beat us to it... */ @@ -78,6 +77,5 @@ tdep_init (void) tdep_needs_initialization = 0; /* signal that we're initialized... */ } out: - mutex_unlock (&x86_64_lock); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + lock_release (&x86_64_lock, saved_mask); } From 9aa0d6d6805b3b4a852f7e478364301bb31230ae Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Mon, 21 Sep 2009 13:04:33 -0700 Subject: [PATCH 003/162] Allow caller to block signals. Greetings, Here is the second part, actually implementing the configure option. Thanks, -- Paul Pluzhnikov commit cf823ed0d4d2447aa91af0e3cb5fbb6a6cba5068 Author: Paul Pluzhnikov Date: Mon Sep 21 11:37:38 2009 -0700 New configure option to allow caller to block signals. --- configure.in | 8 ++++++++ include/libunwind_i.h | 11 +++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 1271a560..6e55563c 100644 --- a/configure.in +++ b/configure.in @@ -139,6 +139,14 @@ if test x$enable_debug_frame = xyes; then AC_DEFINE([CONFIG_DEBUG_FRAME], [], [Enable Debug Frame]) fi +AC_ARG_ENABLE(block_signals, +[ --enable-block-signals Block signals before performing mutex operations], +[enable_block_signals=$enableval], [enable_block_signals=yes]) +if test x$enable_block_signals = xyes; then + AC_DEFINE([CONFIG_BLOCK_SIGNALS], [], [Block signals before mutex operations]) +fi + + LIBUNWIND___THREAD save_LDFLAGS="$LDFLAGS" diff --git a/include/libunwind_i.h b/include/libunwind_i.h index 333ee378..a8186015 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -178,18 +178,25 @@ typedef sigset_t intrmask_t; extern intrmask_t unwi_full_mask; +#if defined(CONFIG_BLOCK_SIGNALS) +# define SIGPROCMASK(how, old_mask, new_mask) \ + sigprocmask((how), (old_mask), (new_mask)) +#else +# define SIGPROCMASK(how, old_mask, new_mask) /**/ +#endif + #define define_lock(name) \ pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER #define lock_init(l) mutex_init (l) #define lock_acquire(l,m) \ do { \ - sigprocmask (SIG_SETMASK, &unwi_full_mask, &(m)); \ + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \ mutex_lock (l); \ } while (0) #define lock_release(l,m) \ do { \ mutex_unlock (l); \ - sigprocmask (SIG_SETMASK, &(m), NULL); \ + SIGPROCMASK (SIG_SETMASK, &(m), NULL); \ } while (0) #define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */ From 839db77b7b8c74a9a1c844e82bc30b9a8022908f Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Fri, 25 Sep 2009 09:38:55 -0700 Subject: [PATCH 004/162] Wait if there is contention on the cache The behavior on wait vs abort unwind depends on the locking primitive chosen by the user. This makes the API consistent and independent of the locking primitive. --- include/dwarf.h | 4 ---- src/dwarf/Gparser.c | 18 ------------------ 2 files changed, 22 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index c7c757ed..37b5ec1c 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -312,11 +312,7 @@ typedef unsigned char unw_hash_index_t; struct dwarf_rs_cache { -#ifdef HAVE_ATOMIC_OPS_H - AO_TS_t busy; /* is the rs-cache busy? */ -#else pthread_mutex_t lock; -#endif unsigned short lru_head; /* index of lead-recently used rs */ unsigned short lru_tail; /* index of most-recently used rs */ diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 3969cb3a..1e37b5ba 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -481,21 +481,11 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp) if (caching == UNW_CACHE_NONE) return NULL; -#ifdef HAVE_ATOMIC_H - if (!spin_trylock_irqsave (&cache->busy, *saved_maskp)) - return NULL; -#else -# ifdef HAVE_ATOMIC_OPS_H - if (AO_test_and_set (&cache->busy) == AO_TS_SET) - return NULL; -# else if (likely (caching == UNW_CACHE_GLOBAL)) { Debug (16, "%s: acquiring lock\n", __FUNCTION__); lock_acquire (&cache->lock, *saved_maskp); } -# endif -#endif if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation)) { @@ -513,16 +503,8 @@ put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache, assert (as->caching_policy != UNW_CACHE_NONE); Debug (16, "unmasking signals/interrupts and releasing lock\n"); -#ifdef HAVE_ATOMIC_H - spin_unlock_irqrestore (&cache->busy, *saved_maskp); -#else -# ifdef HAVE_ATOMIC_OPS_H - AO_CLEAR (&cache->busy); -# else if (likely (as->caching_policy == UNW_CACHE_GLOBAL)) lock_release (&cache->lock, *saved_maskp); -# endif -#endif } static inline unw_hash_index_t From b7e3444fea7f19f05e1fe033b96efad394ab9b4a Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Fri, 25 Sep 2009 14:17:35 -0700 Subject: [PATCH 005/162] When libunwind is configured with --enable-block-signals=no, we must block recursion via sighandlers by "external" means. --- tests/test-async-sig.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test-async-sig.c b/tests/test-async-sig.c index 9309076c..eaa9ce90 100644 --- a/tests/test-async-sig.c +++ b/tests/test-async-sig.c @@ -32,6 +32,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UNW_LOCAL_ONLY #include +#include "config.h" static const int nerrors_max = 100; @@ -45,6 +46,14 @@ int verbose; int nerrors; int sigcount; +#ifndef CONFIG_BLOCK_SIGNALS +/* When libunwind is configured with --enable-block-signals=no, the caller + is responsible for preventing recursion via signal handlers. + We use a simple global here. In a multithreaded program, one would use + a thread-local variable. */ +int recurcount; +#endif + #define panic(args...) \ { ++nerrors; fprintf (stderr, args); return; } @@ -58,6 +67,12 @@ do_backtrace (int may_print, int get_proc_name) int ret; int depth = 0; +#ifndef CONFIG_BLOCK_SIGNALS + if (recurcount > 0) + return; + recurcount += 1; +#endif + unw_getcontext (&uc); if (unw_init_local (&cursor, &uc) < 0) panic ("unw_init_local failed!\n"); @@ -102,6 +117,10 @@ do_backtrace (int may_print, int get_proc_name) } } while (ret > 0); + +#ifndef CONFIG_BLOCK_SIGNALS + recurcount -= 1; +#endif } void From fc2934aadeff468b751113d56093429fd6bc4832 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Tue, 29 Sep 2009 23:14:50 -0700 Subject: [PATCH 006/162] Make the remaining sigprocmask calls conditional on --enable-block-signals --- src/dwarf/Gfind_proc_info-lsb.c | 4 ++-- src/ia64/Gtables.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index e3ec9ad1..01d91f69 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -728,9 +728,9 @@ dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, cb_data.di.format = -1; cb_data.di_debug.format = -1; - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); ret = dl_iterate_phdr (callback, &cb_data); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); if (ret <= 0) { diff --git a/src/ia64/Gtables.c b/src/ia64/Gtables.c index 63725e80..1a16a2e7 100644 --- a/src/ia64/Gtables.c +++ b/src/ia64/Gtables.c @@ -622,9 +622,9 @@ validate_cache (unw_addr_space_t as) intrmask_t saved_mask; int ret; - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); ret = dl_iterate_phdr (check_callback, as); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); return ret; } @@ -653,9 +653,9 @@ tdep_find_proc_info (unw_addr_space_t as, unw_word_t ip, di.u.ti.segbase = ip; /* this is cheap... */ - sigprocmask (SIG_SETMASK, &unwi_full_mask, &saved_mask); + SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &saved_mask); ret = dl_iterate_phdr (callback, &di); - sigprocmask (SIG_SETMASK, &saved_mask, NULL); + SIGPROCMASK (SIG_SETMASK, &saved_mask, NULL); if (ret <= 0) { From b56375e76a0e23b6e464d994bc6a790e086b91db Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Wed, 7 Oct 2009 12:51:03 -0700 Subject: [PATCH 007/162] Reduce stack use and apply CONFIG_DEBUG_FRAME to more code. Currently, libunwind allocates several PATH_MAX entries on stack, while trying to find a binary via /proc/.../maps. However stack space may be at premium (especially when sigaltstack is used), and PATH_MAX on Linux is 4096, while SIGSTKSZ is only 8192 on x86. Attached patch eliminates multiple PATH_MAX stack allocations, and simplifies code in maps_next, at the cost of being unable to do anything if we can't mmap one page. It appears to me that under such low-memory conditions, libunwind will fail shortly elsewhere anyway. This patch also disables more of debug_frame-handling code when CONFIG_DEBUG_FRAME is undefined. Tested on Linux/x86_64 with and without CONFIG_DEBUG_FRAME, no regressions. --- src/dwarf/Gfind_proc_info-lsb.c | 23 +++--- src/os-linux.c | 19 +++-- src/os-linux.h | 136 +++++++++++++------------------- tests/Gtest-bt.c | 10 +-- 4 files changed, 82 insertions(+), 106 deletions(-) diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 01d91f69..9484289f 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -221,14 +221,6 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) return 0; } -#else -static int -load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) -{ - return 1; -} -#endif /* CONFIG_DEBUG_FRAME */ - /* Locate the binary which originated the contents of address ADDR. Return the name of the binary in *name (space is allocated by the caller) @@ -244,10 +236,16 @@ find_binary_for_address (unw_word_t ip, char *name, size_t name_size) unsigned long segbase, mapoff, hi; maps_init (&mi, pid); - while (maps_next (&mi, &segbase, &hi, &mapoff, name, name_size)) + while (maps_next (&mi, &segbase, &hi, &mapoff)) if (ip >= segbase && ip < hi) { - found = 1; + size_t len = strlen (mi.path); + + if (len + 1 <= name_size) + { + memcpy (name, mi.path, len + 1); + found = 1; + } break; } maps_close (&mi); @@ -400,6 +398,8 @@ debug_frame_tab_compare (const void *a, const void *b) return 0; } +#endif /* CONFIG_DEBUG_FRAME */ + /* ptr is a pointer to a callback_data structure and, on entry, member ip contains the instruction-pointer we're looking for. */ @@ -575,6 +575,8 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) } } +#ifdef CONFIG_DEBUG_FRAME + Debug (15, "Trying to find .debug_frame\n"); di = &cb_data->di_debug; fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name); @@ -707,6 +709,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) (long) di->u.ti.segbase, (long) di->u.ti.table_len, (long) di->gp, (long) di->u.ti.table_data); } +#endif /* CONFIG_DEBUG_FRAME */ return found; } diff --git a/src/os-linux.c b/src/os-linux.c index ae37d8f8..210edd05 100644 --- a/src/os-linux.c +++ b/src/os-linux.c @@ -36,23 +36,28 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, unsigned long *segbase, unsigned long *mapoff) { struct map_iterator mi; - char path[PATH_MAX]; - int found = 0; + int found = 0, rc; unsigned long hi; - maps_init (&mi, pid); - while (maps_next (&mi, segbase, &hi, mapoff, path, sizeof (path))) + if (maps_init (&mi, pid) < 0) + return -1; + + while (maps_next (&mi, segbase, &hi, mapoff)) if (ip >= *segbase && ip < hi) { found = 1; break; } - maps_close (&mi); if (!found) - return -1; + { + maps_close (&mi); + return -1; + } - return elf_map_image (ei, path); + rc = elf_map_image (ei, mi.path); + maps_close (&mi); + return rc; } #endif /* UNW_REMOTE_ONLY */ diff --git a/src/os-linux.h b/src/os-linux.h index b2c9a8be..19f83af7 100644 --- a/src/os-linux.h +++ b/src/os-linux.h @@ -34,6 +34,7 @@ struct map_iterator size_t buf_size; char *buf; char *buf_end; + char *path; }; static inline char * @@ -61,33 +62,33 @@ ltoa (char *buf, long val) return buf + len; } -static inline void +static inline int maps_init (struct map_iterator *mi, pid_t pid) { - char path[PATH_MAX], *cp; + char path[sizeof ("/proc/0123456789/maps")], *cp; memcpy (path, "/proc/", 6); cp = ltoa (path + 6, pid); + assert (cp + 6 < path + sizeof (path)); memcpy (cp, "/maps", 6); mi->fd = open (path, O_RDONLY); - mi->offset = 0; - mi->buf_size = 0; - - cp = NULL; if (mi->fd >= 0) { - /* Try to allocate a page-sized buffer. If that fails, we'll - fall back on reading one line at a time. */ + /* Try to allocate a page-sized buffer. */ mi->buf_size = getpagesize (); cp = mmap (0, mi->buf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (cp == MAP_FAILED) - cp = NULL; + return -1; else - cp += mi->buf_size; + { + mi->offset = 0; + mi->buf = mi->buf_end = cp + mi->buf_size; + return 0; + } } - mi->buf = mi->buf_end = cp; + return -1; } static inline char * @@ -184,7 +185,7 @@ scan_string (char *cp, char *valp, size_t buf_size) while (*cp != ' ' && *cp != '\t' && *cp != '\0') { - if (i < buf_size - 1) + if ((valp != NULL) && (i < buf_size - 1)) valp[i++] = *cp; ++cp; } @@ -196,12 +197,10 @@ scan_string (char *cp, char *valp, size_t buf_size) static inline int maps_next (struct map_iterator *mi, - unsigned long *low, unsigned long *high, unsigned long *offset, - char *path, size_t path_size) + unsigned long *low, unsigned long *high, unsigned long *offset) { - char line[256 + PATH_MAX], perm[16], dash, colon, *cp; + char perm[16], dash, colon, *cp; unsigned long major, minor, inum; - size_t to_read = 256; /* most lines fit in 256 characters easy */ ssize_t i, nread; if (mi->fd < 0) @@ -209,80 +208,52 @@ maps_next (struct map_iterator *mi, while (1) { - if (mi->buf) + ssize_t bytes_left = mi->buf_end - mi->buf; + char *eol = NULL; + + for (i = 0; i < bytes_left; ++i) { - ssize_t bytes_left = mi->buf_end - mi->buf; - char *eol = NULL; - - for (i = 0; i < bytes_left; ++i) + if (mi->buf[i] == '\n') { - if (mi->buf[i] == '\n') - { - eol = mi->buf + i; - break; - } - else if (mi->buf[i] == '\0') - break; + eol = mi->buf + i; + break; } - if (!eol) - { - /* copy down the remaining bytes, if any */ - if (bytes_left > 0) - memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left); - - mi->buf = mi->buf_end - mi->buf_size; - nread = read (mi->fd, mi->buf + bytes_left, - mi->buf_size - bytes_left); - if (nread <= 0) - return 0; - else if ((size_t) (nread + bytes_left) < mi->buf_size) - { - /* Move contents to the end of the buffer so we - maintain the invariant that all bytes between - mi->buf and mi->buf_end are valid. */ - memmove (mi->buf_end - nread - bytes_left, mi->buf, - nread + bytes_left); - mi->buf = mi->buf_end - nread - bytes_left; - } - - eol = mi->buf + bytes_left + nread - 1; - - for (i = bytes_left; i < bytes_left + nread; ++i) - if (mi->buf[i] == '\n') - { - eol = mi->buf + i; - break; - } - } - cp = mi->buf; - mi->buf = eol + 1; - *eol = '\0'; + else if (mi->buf[i] == '\0') + break; } - else + if (!eol) { - /* maps_init() wasn't able to allocate a buffer; do it the - slow way. */ - lseek (mi->fd, mi->offset, SEEK_SET); + /* copy down the remaining bytes, if any */ + if (bytes_left > 0) + memmove (mi->buf_end - mi->buf_size, mi->buf, bytes_left); - if ((nread = read (mi->fd, line, to_read)) <= 0) + mi->buf = mi->buf_end - mi->buf_size; + nread = read (mi->fd, mi->buf + bytes_left, + mi->buf_size - bytes_left); + if (nread <= 0) return 0; - for (i = 0; i < nread && line[i] != '\n'; ++i) - /* skip */; - if (i < nread) + else if ((size_t) (nread + bytes_left) < mi->buf_size) { - line[i] = '\0'; - mi->offset += i + 1; + /* Move contents to the end of the buffer so we + maintain the invariant that all bytes between + mi->buf and mi->buf_end are valid. */ + memmove (mi->buf_end - nread - bytes_left, mi->buf, + nread + bytes_left); + mi->buf = mi->buf_end - nread - bytes_left; } - else - { - if (to_read < sizeof (line)) - to_read = sizeof (line) - 1; - else - mi->offset += nread; /* not supposed to happen... */ - continue; /* duh, no newline found */ - } - cp = line; + + eol = mi->buf + bytes_left + nread - 1; + + for (i = bytes_left; i < bytes_left + nread; ++i) + if (mi->buf[i] == '\n') + { + eol = mi->buf + i; + break; + } } + cp = mi->buf; + mi->buf = eol + 1; + *eol = '\0'; /* scan: "LOW-HIGH PERM OFFSET MAJOR:MINOR INUM PATH" */ cp = scan_hex (cp, low); @@ -294,7 +265,10 @@ maps_next (struct map_iterator *mi, cp = scan_char (cp, &colon); cp = scan_hex (cp, &minor); cp = scan_dec (cp, &inum); - cp = scan_string (cp, path, path_size); + cp = mi->path = skip_whitespace (cp); + if (!cp) + continue; + cp = scan_string (cp, NULL, 0); if (!cp || dash != '-' || colon != ':') continue; /* skip line with unknown or bad format */ return 1; diff --git a/tests/Gtest-bt.c b/tests/Gtest-bt.c index 8211f732..9b07ec47 100644 --- a/tests/Gtest-bt.c +++ b/tests/Gtest-bt.c @@ -38,12 +38,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include -#if UNW_TARGET_X86 || UNW_TARGET_X86_64 || UNW_TARGET_ARM -# define STACK_SIZE (128*1024) /* On x86/-64 and ARM, SIGSTKSZ is too small */ -#else -# define STACK_SIZE SIGSTKSZ -#endif - #define panic(args...) \ { fprintf (stderr, args); exit (-1); } @@ -219,10 +213,10 @@ main (int argc, char **argv) if (verbose) printf ("\nBacktrace across signal handler on alternate stack:\n"); - stk.ss_sp = malloc (STACK_SIZE); + stk.ss_sp = malloc (SIGSTKSZ); if (!stk.ss_sp) panic ("failed to allocate SIGSTKSZ (%u) bytes\n", SIGSTKSZ); - stk.ss_size = STACK_SIZE; + stk.ss_size = SIGSTKSZ; stk.ss_flags = 0; if (sigaltstack (&stk, NULL) < 0) panic ("sigaltstack: %s\n", strerror (errno)); From af9daf66afde3c92b2c7c4f171bf3414c623892c Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 15 Oct 2009 19:29:49 -0700 Subject: [PATCH 008/162] Fix the naming of the sigprocmask parameters. --- include/libunwind_i.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/libunwind_i.h b/include/libunwind_i.h index a8186015..f20fcbc8 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -179,10 +179,10 @@ typedef sigset_t intrmask_t; extern intrmask_t unwi_full_mask; #if defined(CONFIG_BLOCK_SIGNALS) -# define SIGPROCMASK(how, old_mask, new_mask) \ - sigprocmask((how), (old_mask), (new_mask)) +# define SIGPROCMASK(how, new_mask, old_mask) \ + sigprocmask((how), (new_mask), (old_mask)) #else -# define SIGPROCMASK(how, old_mask, new_mask) /**/ +# define SIGPROCMASK(how, new_mask, old_mask) /**/ #endif #define define_lock(name) \ From 491d576529a3b01208accb37627a075d7ce07093 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Fri, 16 Oct 2009 14:01:50 -0700 Subject: [PATCH 009/162] Fix compiler warnings on x86_64 --- include/libunwind_i.h | 11 +- src/dwarf/Gfind_proc_info-lsb.c | 229 ++++++++++++++++---------------- src/dwarf/Gstep.c | 1 - src/x86_64/Gresume.c | 2 +- src/x86_64/unwind_i.h | 3 + 5 files changed, 128 insertions(+), 118 deletions(-) diff --git a/include/libunwind_i.h b/include/libunwind_i.h index f20fcbc8..3e553e2c 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -178,6 +178,11 @@ typedef sigset_t intrmask_t; extern intrmask_t unwi_full_mask; +/* Silence compiler warnings about variables which are used only if libunwind + is configured in a certain way */ +static inline void mark_as_used(void *v) { +} + #if defined(CONFIG_BLOCK_SIGNALS) # define SIGPROCMASK(how, new_mask, old_mask) \ sigprocmask((how), (new_mask), (old_mask)) @@ -191,11 +196,13 @@ extern intrmask_t unwi_full_mask; #define lock_acquire(l,m) \ do { \ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \ + mark_as_used(&(m)); \ mutex_lock (l); \ } while (0) #define lock_release(l,m) \ do { \ mutex_unlock (l); \ + mark_as_used(&(m)); \ SIGPROCMASK (SIG_SETMASK, &(m), NULL); \ } while (0) @@ -272,10 +279,10 @@ do { \ # define Dprintf(format...) #endif -static ALWAYS_INLINE void +static ALWAYS_INLINE int print_error (const char *string) { - write (2, string, strlen (string)); + return write (2, string, strlen (string)); } #define mi_init UNWI_ARCH_OBJ(mi_init) diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 9484289f..d7405301 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -416,7 +416,6 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) struct dwarf_eh_frame_hdr *hdr; unw_accessors_t *a; long n; - struct unw_debug_frame_list *fdesc = 0; int found = 0; ip = cb_data->ip; @@ -576,139 +575,141 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) } #ifdef CONFIG_DEBUG_FRAME + { + struct unw_debug_frame_list *fdesc = 0; + Debug (15, "Trying to find .debug_frame\n"); + di = &cb_data->di_debug; + fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name); - Debug (15, "Trying to find .debug_frame\n"); - di = &cb_data->di_debug; - fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name); + if (!fdesc) + { + Debug (15, "couldn't load .debug_frame\n"); + return found; + } + else + { + char *buf; + size_t bufsize; + unw_word_t item_start, item_end = 0; + uint32_t u32val = 0; + uint64_t cie_id = 0; + struct debug_frame_tab *tab; - if (!fdesc) - { - Debug (15, "couldn't load .debug_frame\n"); - return found; - } - else - { - char *buf; - size_t bufsize; - unw_word_t item_start, item_end = 0; - uint32_t u32val = 0; - uint64_t cie_id = 0; - struct debug_frame_tab *tab; + Debug (15, "loaded .debug_frame\n"); - Debug (15, "loaded .debug_frame\n"); + buf = fdesc->debug_frame; + bufsize = fdesc->debug_frame_size; - buf = fdesc->debug_frame; - bufsize = fdesc->debug_frame_size; + if (bufsize == 0) + { + Debug (15, "zero-length .debug_frame\n"); + return found; + } - if (bufsize == 0) - { - Debug (15, "zero-length .debug_frame\n"); - return found; - } + /* Now create a binary-search table, if it does not already exist. */ + if (!fdesc->index) + { + addr = (unw_word_t) (uintptr_t) buf; - /* Now create a binary-search table, if it does not already exist. */ - if (!fdesc->index) - { - addr = (unw_word_t) (uintptr_t) buf; + a = unw_get_accessors (unw_local_addr_space); - a = unw_get_accessors (unw_local_addr_space); + /* Find all FDE entries in debug_frame, and make into a sorted + index. */ - /* Find all FDE entries in debug_frame, and make into a sorted - index. */ + tab = debug_frame_tab_new (16); - tab = debug_frame_tab_new (16); + while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) + { + uint64_t id_for_cie; + item_start = addr; - while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) - { - uint64_t id_for_cie; - item_start = addr; + dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); - dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); + if (u32val == 0) + break; + else if (u32val != 0xffffffff) + { + uint32_t cie_id32 = 0; + item_end = addr + u32val; + dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, + NULL); + cie_id = cie_id32; + id_for_cie = 0xffffffff; + } + else + { + uint64_t u64val = 0; + /* Extended length. */ + dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); + item_end = addr + u64val; - if (u32val == 0) - break; - else if (u32val != 0xffffffff) - { - uint32_t cie_id32 = 0; - item_end = addr + u32val; - dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, - NULL); - cie_id = cie_id32; - id_for_cie = 0xffffffff; - } - else - { - uint64_t u64val = 0; - /* Extended length. */ - dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); - item_end = addr + u64val; + dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); + id_for_cie = 0xffffffffffffffffull; + } - dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); - id_for_cie = 0xffffffffffffffffull; - } + /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ - /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ + if (cie_id == id_for_cie) + ; + /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ + else + { + unw_word_t fde_addr = item_start; + unw_proc_info_t this_pi; + int err; - if (cie_id == id_for_cie) - ; - /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ - else - { - unw_word_t fde_addr = item_start; - unw_proc_info_t this_pi; - int err; + /*Debug (1, "Found FDE at %.8x\n", item_start);*/ - /*Debug (1, "Found FDE at %.8x\n", item_start);*/ + err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, + a, &fde_addr, + &this_pi, 0, + (uintptr_t) buf, + NULL); + if (err == 0) + { + Debug (15, "start_ip = %x, end_ip = %x\n", + (int) this_pi.start_ip, (int) this_pi.end_ip); + debug_frame_tab_append (tab, + item_start - (unw_word_t) (uintptr_t) buf, + this_pi.start_ip); + } + /*else + Debug (1, "FDE parse failed\n");*/ + } - err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, - a, &fde_addr, - &this_pi, 0, - (uintptr_t) buf, - NULL); - if (err == 0) - { - Debug (15, "start_ip = %x, end_ip = %x\n", - (int) this_pi.start_ip, (int) this_pi.end_ip); - debug_frame_tab_append (tab, - item_start - (unw_word_t) (uintptr_t) buf, - this_pi.start_ip); - } - /*else - Debug (1, "FDE parse failed\n");*/ - } + addr = item_end; + } - addr = item_end; - } + debug_frame_tab_shrink (tab); + qsort (tab->tab, tab->length, sizeof (struct table_entry), + debug_frame_tab_compare); + /* for (i = 0; i < tab->length; i++) + { + fprintf (stderr, "ip %x, fde offset %x\n", + (int) tab->tab[i].start_ip_offset, + (int) tab->tab[i].fde_offset); + }*/ + fdesc->index = tab->tab; + fdesc->index_size = tab->length; + free (tab); + } - debug_frame_tab_shrink (tab); - qsort (tab->tab, tab->length, sizeof (struct table_entry), - debug_frame_tab_compare); - /* for (i = 0; i < tab->length; i++) - { - fprintf (stderr, "ip %x, fde offset %x\n", - (int) tab->tab[i].start_ip_offset, - (int) tab->tab[i].fde_offset); - }*/ - fdesc->index = tab->tab; - fdesc->index_size = tab->length; - free (tab); - } + di->format = UNW_INFO_FORMAT_TABLE; + di->start_ip = fdesc->start; + di->end_ip = fdesc->end; + di->u.ti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; + di->u.ti.table_data = (unw_word_t *) fdesc; + di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); + di->u.ti.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr; - di->format = UNW_INFO_FORMAT_TABLE; - di->start_ip = fdesc->start; - di->end_ip = fdesc->end; - di->u.ti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; - di->u.ti.table_data = (unw_word_t *) fdesc; - di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); - di->u.ti.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr; - - found = 1; - Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " - "gp=0x%lx, table_data=0x%lx\n", - (char *) (uintptr_t) di->u.ti.name_ptr, - (long) di->u.ti.segbase, (long) di->u.ti.table_len, - (long) di->gp, (long) di->u.ti.table_data); - } + found = 1; + Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " + "gp=0x%lx, table_data=0x%lx\n", + (char *) (uintptr_t) di->u.ti.name_ptr, + (long) di->u.ti.segbase, (long) di->u.ti.table_len, + (long) di->gp, (long) di->u.ti.table_data); + } + } #endif /* CONFIG_DEBUG_FRAME */ return found; diff --git a/src/dwarf/Gstep.c b/src/dwarf/Gstep.c index a9b789c6..59138e6f 100644 --- a/src/dwarf/Gstep.c +++ b/src/dwarf/Gstep.c @@ -29,7 +29,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ HIDDEN int dwarf_step (struct dwarf_cursor *c) { - unw_word_t prev_cfa = c->cfa; int ret; if ((ret = dwarf_find_save_locs (c)) >= 0) { diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c index 0a734417..54215c32 100644 --- a/src/x86_64/Gresume.c +++ b/src/x86_64/Gresume.c @@ -71,7 +71,7 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) { Debug (8, "resuming at ip=%llx via setcontext()\n", (unsigned long long) c->dwarf.ip); - _Ux86_64_setcontext (uc); + setcontext (uc); } #else # warning Implement me! diff --git a/src/x86_64/unwind_i.h b/src/x86_64/unwind_i.h index af779bb2..bc828006 100644 --- a/src/x86_64/unwind_i.h +++ b/src/x86_64/unwind_i.h @@ -58,6 +58,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define x86_64_lock UNW_OBJ(lock) #define x86_64_local_resume UNW_OBJ(local_resume) #define x86_64_local_addr_space_init UNW_OBJ(local_addr_space_init) +#define setcontext UNW_ARCH_OBJ (setcontext) #if 0 #define x86_64_scratch_loc UNW_OBJ(scratch_loc) #endif @@ -65,6 +66,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ extern void x86_64_local_addr_space_init (void); extern int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg); +extern int setcontext (const ucontext_t *ucp); + #if 0 extern dwarf_loc_t x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg); #endif From 570c09a2afe255ce30b64e3298218ffbcff73e80 Mon Sep 17 00:00:00 2001 From: Belisko Marek Date: Fri, 16 Oct 2009 14:26:55 -0700 Subject: [PATCH 010/162] Fix another compiler warning. --- tests/Gtest-dyn1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Gtest-dyn1.c b/tests/Gtest-dyn1.c index 039c086d..de9854dd 100644 --- a/tests/Gtest-dyn1.c +++ b/tests/Gtest-dyn1.c @@ -120,7 +120,7 @@ sighandler (int signal) name[0] = '\0'; off[0] = '\0'; if (unw_get_proc_name (&cursor, name, sizeof (name), &offset) == 0 - && off > 0) + && offset > 0) snprintf (off, sizeof (off), "+0x%lx", (long) offset); if (verbose) printf ("ip = %lx <%s%s>\n", (long) ip, name, off); From 4ab26bcdaafce0e7f34dfaafd14c7837d8bb5435 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Fri, 16 Oct 2009 15:52:44 -0700 Subject: [PATCH 011/162] Fix compiler warnings seen with --disable_block_signals --- include/libunwind_i.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libunwind_i.h b/include/libunwind_i.h index 3e553e2c..a749ee17 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -187,7 +187,7 @@ static inline void mark_as_used(void *v) { # define SIGPROCMASK(how, new_mask, old_mask) \ sigprocmask((how), (new_mask), (old_mask)) #else -# define SIGPROCMASK(how, new_mask, old_mask) /**/ +# define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask) #endif #define define_lock(name) \ From 3067acf17287d7357925213d5f11b79a48bbdf9d Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 17 Oct 2009 22:45:30 -0700 Subject: [PATCH 012/162] Remove duplicate calls to mark_as_used --- include/libunwind_i.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/libunwind_i.h b/include/libunwind_i.h index a749ee17..27bfd8db 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -196,13 +196,11 @@ static inline void mark_as_used(void *v) { #define lock_acquire(l,m) \ do { \ SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \ - mark_as_used(&(m)); \ mutex_lock (l); \ } while (0) #define lock_release(l,m) \ do { \ mutex_unlock (l); \ - mark_as_used(&(m)); \ SIGPROCMASK (SIG_SETMASK, &(m), NULL); \ } while (0) From d7089547e2d13c2ae5f9ad896dc4bc5dc796fb0b Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Fri, 23 Oct 2009 22:38:11 -0700 Subject: [PATCH 013/162] Fix a warning message on i386 Without this, we may be accessing data beyond the array bounds. --- src/dwarf/Gparser.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 1e37b5ba..6fa56ee6 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -691,6 +691,7 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) stack-pointer wasn't saved, popping the CFA implicitly pops the stack-pointer as well. */ if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP) + && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg)) && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME)) cfa = c->cfa; else From f88e949d16a3ce5f9c4ad1c2ee9b5b0e298b8f59 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 11 Nov 2009 21:58:15 -0800 Subject: [PATCH 014/162] Set UNW_TDEP_SP on x86 to ESP This is similar to what has been done on other archs and resolves an out of bounds array access elsewhere. --- include/libunwind-x86.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/libunwind-x86.h b/include/libunwind-x86.h index 1e321db1..84da6e92 100644 --- a/include/libunwind-x86.h +++ b/include/libunwind-x86.h @@ -147,7 +147,7 @@ typedef enum UNW_TDEP_LAST_REG = UNW_X86_XMM7, UNW_TDEP_IP = UNW_X86_EIP, - UNW_TDEP_SP = UNW_X86_CFA, + UNW_TDEP_SP = UNW_X86_ESP, UNW_TDEP_EH = UNW_X86_EAX } x86_regnum_t; From f958b9dc4f19c94281b2679b3a6bbb39828beb90 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Wed, 18 Nov 2009 17:16:47 -0800 Subject: [PATCH 015/162] Get rid of some bogus checks. Greetings, Attached patch is rather on the obvious side: - rs1 can't be NULL since it's assigned on previous line - rs_new never returns NULL, and if it ever did, we'd crash on memcpy that preceeds the NULL check. Tested on Linux/x86_64 with no regressions. Thanks, -- Paul Pluzhnikov --- src/dwarf/Gparser.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 6fa56ee6..abef447f 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -784,7 +784,7 @@ HIDDEN int dwarf_find_save_locs (struct dwarf_cursor *c) { dwarf_state_record_t sr; - dwarf_reg_state_t *rs, *rs1; + dwarf_reg_state_t *rs; struct dwarf_rs_cache *cache; int ret = 0; intrmask_t saved_mask; @@ -809,18 +809,8 @@ dwarf_find_save_locs (struct dwarf_cursor *c) if ((ret = create_state_record_for (c, &sr, c->ip)) < 0) goto out; - rs1 = &sr.rs_current; - if (rs1) - { - rs = rs_new (cache, c); - memcpy(rs, rs1, offsetof(struct dwarf_reg_state, ip)); - if (!rs) - { - Dprintf ("%s: failed to create unwind rs\n", __FUNCTION__); - ret = -UNW_EUNSPEC; - goto out; - } - } + rs = rs_new (cache, c); + memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip)); cache->buckets[c->prev_rs].hint = rs - cache->buckets; c->hint = rs->hint; From 2648a77f0499b2aeb3d624a1b44d2f1d2dd01835 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Wed, 18 Nov 2009 17:55:01 -0800 Subject: [PATCH 016/162] Simplify control flow Greetings, Attached patch gets rid of additional unnecessary branch (rs_get_cache can not return NULL unless caching_policy is UNW_CACHE_NONE), gets rid of goto's, and makes apply_reg_state (major CPU consumer) execute with cache lock not held (before the patch, apply_reg_state was called with lock held for newly-inserted entries, but not for found-in-cache entries). Tested on Linux/x86_64 with no regressions. Thanks, -- Paul Pluzhnikov --- src/dwarf/Gparser.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index abef447f..b77bde24 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -793,37 +793,29 @@ dwarf_find_save_locs (struct dwarf_cursor *c) return uncached_dwarf_find_save_locs (c); cache = get_rs_cache(c->as, &saved_mask); - if (!cache) - return -UNW_ENOINFO; /* cache is busy */ rs = rs_lookup(cache, c); if (rs) - { c->ret_addr_column = rs->ret_addr_column; - goto apply; + else + { + if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 || + (ret = create_state_record_for (c, &sr, c->ip)) < 0) + { + put_rs_cache (c->as, cache, &saved_mask); + return ret; + } + + rs = rs_new (cache, c); + memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip)); + cache->buckets[c->prev_rs].hint = rs - cache->buckets; + + c->hint = rs->hint; + c->prev_rs = rs - cache->buckets; + + put_unwind_info (c, &c->pi); } - if ((ret = fetch_proc_info (c, c->ip, 1)) < 0) - goto out; - - if ((ret = create_state_record_for (c, &sr, c->ip)) < 0) - goto out; - - rs = rs_new (cache, c); - memcpy(rs, &sr.rs_current, offsetof(struct dwarf_reg_state, ip)); - cache->buckets[c->prev_rs].hint = rs - cache->buckets; - - c->hint = rs->hint; - c->prev_rs = rs - cache->buckets; - - put_unwind_info (c, &c->pi); - ret = apply_reg_state (c, rs); - -out: - put_rs_cache (c->as, cache, &saved_mask); - return ret; - -apply: put_rs_cache (c->as, cache, &saved_mask); if ((ret = apply_reg_state (c, rs)) < 0) return ret; From 890a630d76ca4af8cb9758e3c74d00897dbcb544 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Fri, 20 Nov 2009 13:23:46 -0800 Subject: [PATCH 017/162] Fix tests/Gtest-concurrent.c to test all caching policies Greetings, Attached patch is rather on the obvious side: setting caching policy and than doing nothing is pointless; we'd better acutally test that it works! Tested on Linux/x86_64. Thanks, -- Paul Pluzhnikov --- tests/Gtest-concurrent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Gtest-concurrent.c b/tests/Gtest-concurrent.c index 8166fc59..126acedd 100644 --- a/tests/Gtest-concurrent.c +++ b/tests/Gtest-concurrent.c @@ -115,10 +115,12 @@ main (int argc, char **argv) if (verbose) printf ("Caching: global\n"); unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + doit (); if (verbose) printf ("Caching: per-thread\n"); unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + doit (); if (nerrors) { From 9626d66019599de925b9ad1f216388d1c890d193 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Tue, 24 Nov 2009 15:18:48 -0800 Subject: [PATCH 018/162] Fix a race condition in dwarf unwinding. Original code was accessing rs_cache memory without holding a lock in some cases. If there was sufficient cache pressure, entry being accessed may be overwritten by another thread, resulting in a data race. We now make a thread local copy of the data, before releasing the lock. If we end up supporting UNW_CACHE_PER_THREAD properly in the future, this memcpy should be unnecessary. --- src/dwarf/Gparser.c | 7 +- tests/Makefile.am | 3 +- tests/rs-race.c | 1506 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1512 insertions(+), 4 deletions(-) create mode 100644 tests/rs-race.c diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index b77bde24..9dcf1a68 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -784,7 +784,7 @@ HIDDEN int dwarf_find_save_locs (struct dwarf_cursor *c) { dwarf_state_record_t sr; - dwarf_reg_state_t *rs; + dwarf_reg_state_t *rs, rs_copy; struct dwarf_rs_cache *cache; int ret = 0; intrmask_t saved_mask; @@ -796,7 +796,7 @@ dwarf_find_save_locs (struct dwarf_cursor *c) rs = rs_lookup(cache, c); if (rs) - c->ret_addr_column = rs->ret_addr_column; + c->ret_addr_column = rs->ret_addr_column; else { if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 || @@ -816,8 +816,9 @@ dwarf_find_save_locs (struct dwarf_cursor *c) put_unwind_info (c, &c->pi); } + memcpy (&rs_copy, rs, sizeof (rs_copy)); put_rs_cache (c->as, cache, &saved_mask); - if ((ret = apply_reg_state (c, rs)) < 0) + if ((ret = apply_reg_state (c, &rs_copy)) < 0) return ret; return 0; diff --git a/tests/Makefile.am b/tests/Makefile.am index f43dc609..401a6ec9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -41,7 +41,7 @@ endif #ARCH_IA64 Gtest-dyn1 Ltest-dyn1 \ test-async-sig test-flush-cache test-init-remote \ test-mem test-setjmp test-ptrace \ - Ltest-nomalloc + Ltest-nomalloc rs-race noinst_PROGRAMS_cdep = forker mapper test-ptrace-misc test-varargs \ Gperf-simple Lperf-simple @@ -99,6 +99,7 @@ test_ptrace_LDADD = ../src/libunwind-ptrace.a $(LIBUNWIND) Ltest_concurrent_LDADD = $(LIBUNWIND) -lpthread Gtest_concurrent_LDADD = $(LIBUNWIND) -lpthread test_async_sig_LDADD = $(LIBUNWIND) -lpthread +rs_race_LDADD = $(LIBUNWIND) -lpthread LDADD += -ldl Ltest_nomalloc_SOURCES = Ltest-nomalloc.c diff --git a/tests/rs-race.c b/tests/rs-race.c new file mode 100644 index 00000000..8f7be676 --- /dev/null +++ b/tests/rs-race.c @@ -0,0 +1,1506 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2003-2005 Hewlett-Packard Co + Contributed by Paul Pluzhnikov + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Verify that register state caches work under all caching policies + in a multi-threaded environment with a large number IPs */ +#include +#include +#include +#include +#include + +int verbose; + +void +foo_0 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_1 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_2 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_3 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_4 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_5 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_6 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_7 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_8 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_9 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_10 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_11 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_12 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_13 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_14 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_15 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_16 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_17 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_18 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_19 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_20 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_21 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_22 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_23 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_24 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_25 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_26 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_27 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_28 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_29 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_30 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_31 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_32 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_33 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_34 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_35 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_36 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_37 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_38 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_39 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_40 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_41 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_42 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_43 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_44 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_45 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_46 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_47 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_48 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_49 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_50 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_51 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_52 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_53 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_54 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_55 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_56 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_57 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_58 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_59 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_60 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_61 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_62 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_63 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_64 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_65 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_66 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_67 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_68 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_69 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_70 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_71 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_72 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_73 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_74 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_75 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_76 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_77 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_78 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_79 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_80 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_81 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_82 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_83 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_84 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_85 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_86 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_87 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_88 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_89 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_90 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_91 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_92 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_93 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_94 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_95 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_96 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_97 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_98 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_99 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_100 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_101 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_102 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_103 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_104 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_105 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_106 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_107 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_108 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_109 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_110 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_111 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_112 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_113 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_114 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_115 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_116 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_117 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_118 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_119 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_120 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_121 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_122 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_123 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_124 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_125 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_126 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_127 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void +foo_128 (void) +{ + void *buf[20]; + int n; + + if ((n = backtrace (buf, 20)) < 3) + abort (); +} + +void * +bar(void *p) +{ + int i; + for (i = 0; i < 1000; ++i) { + foo_0 (); + foo_1 (); + foo_2 (); + foo_3 (); + foo_4 (); + foo_5 (); + foo_6 (); + foo_7 (); + foo_8 (); + foo_9 (); + foo_10 (); + foo_11 (); + foo_12 (); + foo_13 (); + foo_14 (); + foo_15 (); + foo_16 (); + foo_17 (); + foo_18 (); + foo_19 (); + foo_20 (); + foo_21 (); + foo_22 (); + foo_23 (); + foo_24 (); + foo_25 (); + foo_26 (); + foo_27 (); + foo_28 (); + foo_29 (); + foo_30 (); + foo_31 (); + foo_32 (); + foo_33 (); + foo_34 (); + foo_35 (); + foo_36 (); + foo_37 (); + foo_38 (); + foo_39 (); + foo_40 (); + foo_41 (); + foo_42 (); + foo_43 (); + foo_44 (); + foo_45 (); + foo_46 (); + foo_47 (); + foo_48 (); + foo_49 (); + foo_50 (); + foo_51 (); + foo_52 (); + foo_53 (); + foo_54 (); + foo_55 (); + foo_56 (); + foo_57 (); + foo_58 (); + foo_59 (); + foo_60 (); + foo_61 (); + foo_62 (); + foo_63 (); + foo_64 (); + foo_65 (); + foo_66 (); + foo_67 (); + foo_68 (); + foo_69 (); + foo_70 (); + foo_71 (); + foo_72 (); + foo_73 (); + foo_74 (); + foo_75 (); + foo_76 (); + foo_77 (); + foo_78 (); + foo_79 (); + foo_80 (); + foo_81 (); + foo_82 (); + foo_83 (); + foo_84 (); + foo_85 (); + foo_86 (); + foo_87 (); + foo_88 (); + foo_89 (); + foo_90 (); + foo_91 (); + foo_92 (); + foo_93 (); + foo_94 (); + foo_95 (); + foo_96 (); + foo_97 (); + foo_98 (); + foo_99 (); + foo_100 (); + foo_101 (); + foo_102 (); + foo_103 (); + foo_104 (); + foo_105 (); + foo_106 (); + foo_107 (); + foo_108 (); + foo_109 (); + foo_110 (); + foo_111 (); + foo_112 (); + foo_113 (); + foo_114 (); + foo_115 (); + foo_116 (); + foo_117 (); + foo_118 (); + foo_119 (); + foo_120 (); + foo_121 (); + foo_122 (); + foo_123 (); + foo_124 (); + foo_125 (); + foo_126 (); + foo_127 (); + foo_128 (); + } + return NULL; +} + +#ifndef NTHREAD +#define NTHREAD 10 +#endif + +int doit () +{ + pthread_t tid[NTHREAD]; + int i; + + for (i = 0; i < NTHREAD; ++i) + if (pthread_create (&tid[i], NULL, bar, NULL)) + return 1; + + for (i = 0; i < NTHREAD; ++i) + if (pthread_join (tid[i], NULL)) + return 1; + + return 0; +} + +int +main (int argc, char **argv) +{ + if (argc > 1) + verbose = 1; + + if (verbose) + printf ("Caching: none\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_NONE); + doit (); + + if (verbose) + printf ("Caching: global\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_GLOBAL); + doit (); + + if (verbose) + printf ("Caching: per-thread\n"); + unw_set_caching_policy (unw_local_addr_space, UNW_CACHE_PER_THREAD); + doit (); + + if (verbose) + printf ("SUCCESS\n"); + return 0; +} From 0cf76ed0b54f4b64d3a0575a1c85ef8617d4278d Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Tue, 1 Dec 2009 13:59:45 -0800 Subject: [PATCH 019/162] Check for NULL when validating addresses This is rather on the obvious side. While doing strace on an executable using libunwind, I noticed a lot of: msync(0, 1, MS_SYNC) = -1 ENOMEM (Cannot allocate memory) Since we know that the first page isn't mapped (or at least doesn't contain the data we are looking for), we can eliminate all such msync calls. Tested on Linux/x86_64 with no regressions. --- src/x86/Ginit.c | 3 +++ src/x86_64/Ginit.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index e1b1dcfc..2df94f05 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -117,6 +117,9 @@ validate_mem (unw_word_t addr) addr = PAGE_START(addr); + if (addr == 0) + return -1; + for (i = 0; i < NLGA; i++) { if (last_good_addr[i] && (addr == last_good_addr[i])) diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index 031deaa2..51d77c27 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -120,6 +120,9 @@ validate_mem (unw_word_t addr) addr = PAGE_START(addr); + if (addr == 0) + return -1; + for (i = 0; i < NLGA; i++) { if (last_good_addr[i] && (addr == last_good_addr[i])) From 54752e0df0ce7ad535f724e16874ebb00b5f94f6 Mon Sep 17 00:00:00 2001 From: Paul Pluzhnikov Date: Tue, 22 Dec 2009 18:58:17 -0800 Subject: [PATCH 020/162] Implement getcontext for x86 Greetings, Attached patch implements getcontext for x86. Motivation is the same as: http://lists.nongnu.org/archive/html/libunwind-devel/2008-06/msg00009.html This also fixes check-name-space on x86. Tested on Linux/86 with no new failures. Thanks, -- Paul Pluzhnikov --- include/libunwind-x86.h | 9 ++--- src/Makefile.am | 2 +- src/x86/getcontext.S | 73 +++++++++++++++++++++++++++++++++++++++++ src/x86/offsets.h | 1 + 4 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 src/x86/getcontext.S diff --git a/include/libunwind-x86.h b/include/libunwind-x86.h index 84da6e92..65d42baf 100644 --- a/include/libunwind-x86.h +++ b/include/libunwind-x86.h @@ -163,12 +163,6 @@ unw_tdep_save_loc_t; /* On x86, we can directly use ucontext_t as the unwind context. */ typedef ucontext_t unw_tdep_context_t; -/* XXX this is not ideal: an application should not be prevented from - using the "getcontext" name just because it's using libunwind. We - can't just use __getcontext() either, because that isn't exported - by glibc... */ -#define unw_tdep_getcontext(uc) (getcontext (uc), 0) - #include "libunwind-dynamic.h" typedef struct @@ -179,6 +173,9 @@ unw_tdep_proc_info_t; #include "libunwind-common.h" +#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) +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); diff --git a/src/Makefile.am b/src/Makefile.am index e6e3b330..c110e768 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -227,7 +227,7 @@ libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ x86/Lis_signal_frame.c x86/Lget_proc_info.c x86/Lregs.c \ - x86/Lresume.c x86/Lstep.c + x86/Lresume.c x86/Lstep.c x86/getcontext.S # The list of files that go into libunwind-x86: libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S new file mode 100644 index 00000000..a2999bef --- /dev/null +++ b/src/x86/getcontext.S @@ -0,0 +1,73 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2009 Google, Inc + Contributed by Paul Pluzhnikov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" + +/* int _Ux86_getcontext (ucontext_t *ucp) + + Saves the machine context in UCP necessary for libunwind. + Unlike the libc implementation, we don't save the signal mask + and hence avoid the cost of a system call per unwind. + +*/ + + .global _Ux86_getcontext + .type _Ux86_getcontext, @function +_Ux86_getcontext: + mov 4(%esp),%eax /* ucontext_t* */ + + /* EAX is not preserved. */ + movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) + + movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax) + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax) + movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax) + movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax) + movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax) + movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax) + + movl (%esp), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax) + + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax) + + /* glibc getcontext saves FS, but not GS */ + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax) + + leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) + fnstenv (%ecx) + fldenv (%ecx) + + xor %eax, %eax + ret + +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 96f06d1f..94307c12 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -9,6 +9,7 @@ #define LINUX_UC_STACK_OFF 0x08 #define LINUX_UC_MCONTEXT_OFF 0x14 #define LINUX_UC_SIGMASK_OFF 0x6c +#define LINUX_UC_FPREGS_MEM_OFF 0xec /* The struct sigcontext is located at an offset of 4 from the stack pointer in the signal frame. */ From 5a1d3c6fd765e45b97f478c9db3a2d4cdaa75c69 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 21 Feb 2010 22:35:26 -0800 Subject: [PATCH 021/162] Remove bogus check on scan_string which is guaranteed to fail every time. --- src/os-linux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os-linux.h b/src/os-linux.h index 19f83af7..af301ce0 100644 --- a/src/os-linux.h +++ b/src/os-linux.h @@ -269,7 +269,7 @@ maps_next (struct map_iterator *mi, if (!cp) continue; cp = scan_string (cp, NULL, 0); - if (!cp || dash != '-' || colon != ':') + if (dash != '-' || colon != ':') continue; /* skip line with unknown or bad format */ return 1; } From 752076789fdeec16827ddd846485182d4c3cd11f Mon Sep 17 00:00:00 2001 From: Stefan Demharter Date: Sun, 21 Feb 2010 22:45:08 -0800 Subject: [PATCH 022/162] Be gcc compatible for C++ exceptions on 32 bit platforms. --- include/unwind.h | 14 ++++++++------ src/unwind/RaiseException.c | 2 +- src/unwind/unwind-internal.h | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/unwind.h b/include/unwind.h index d9a767dc..f8d43d0d 100644 --- a/include/unwind.h +++ b/include/unwind.h @@ -26,6 +26,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _UNWIND_H #define _UNWIND_H +/* For uint64_t */ +#include + #ifdef __cplusplus extern "C" { #endif @@ -62,23 +65,22 @@ typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, struct _Unwind_Exception *); typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int, _Unwind_Action, - unsigned long, + uint64_t, struct _Unwind_Exception *, struct _Unwind_Context *, void *); /* The C++ ABI requires exception_class, private_1, and private_2 to be of type uint64 and the entire structure to be - double-word-aligned, but that seems a bit overly IA-64-specific. - Using "unsigned long" instead should give us the desired effect on - IA-64, while being more general. */ + double-word-aligned. Please note that exception_class stays 64-bit + even on 32-bit machines for gcc compatibility. */ struct _Unwind_Exception { - unsigned long exception_class; + uint64_t exception_class; _Unwind_Exception_Cleanup_Fn exception_cleanup; unsigned long private_1; unsigned long private_2; - }; + } __attribute__((__aligned__)); extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, diff --git a/src/unwind/RaiseException.c b/src/unwind/RaiseException.c index 55338766..66a681db 100644 --- a/src/unwind/RaiseException.c +++ b/src/unwind/RaiseException.c @@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ PROTECTED _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *exception_object) { - unsigned long exception_class = exception_object->exception_class; + uint64_t exception_class = exception_object->exception_class; _Unwind_Personality_Fn personality; struct _Unwind_Context context; _Unwind_Reason_Code reason; diff --git a/src/unwind/unwind-internal.h b/src/unwind/unwind-internal.h index 169bad57..130cb81a 100644 --- a/src/unwind/unwind-internal.h +++ b/src/unwind/unwind-internal.h @@ -38,7 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define _U_VERSION 1 typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) - (int, _Unwind_Action, unsigned long, struct _Unwind_Exception *, + (int, _Unwind_Action, uint64_t, struct _Unwind_Exception *, struct _Unwind_Context *); struct _Unwind_Context { @@ -59,7 +59,7 @@ _Unwind_Phase2 (struct _Unwind_Exception *exception_object, struct _Unwind_Context *context) { _Unwind_Stop_Fn stop = (_Unwind_Stop_Fn) exception_object->private_1; - unsigned long exception_class = exception_object->exception_class; + uint64_t exception_class = exception_object->exception_class; void *stop_parameter = (void *) exception_object->private_2; _Unwind_Personality_Fn personality; _Unwind_Reason_Code reason; From 3468a6b33d96549d1b01ef0c0fa42eb93fd3645d Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Tue, 23 Feb 2010 10:35:47 -0800 Subject: [PATCH 023/162] Change MS_SYNC to MS_ASYNC Hopefully this makes the address validation a bit cheaper. --- src/x86/Ginit.c | 2 +- src/x86_64/Ginit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 2df94f05..9205fb43 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -126,7 +126,7 @@ validate_mem (unw_word_t addr) return 0; } - if (msync ((void *) addr, 1, MS_SYNC) == -1) + if (msync ((void *) addr, 1, MS_ASYNC) == -1) return -1; victim = lga_victim; diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index 51d77c27..f8469067 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -129,7 +129,7 @@ validate_mem (unw_word_t addr) return 0; } - if (msync ((void *) addr, 1, MS_SYNC) == -1) + if (msync ((void *) addr, 1, MS_ASYNC) == -1) return -1; victim = lga_victim; From 46ea10680d689fed15e2bbeed534c0c52059e0ec Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Tue, 2 Mar 2010 21:18:57 -0800 Subject: [PATCH 024/162] Update documentation on building from git --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 180edd27..7d599897 100644 --- a/README +++ b/README @@ -16,6 +16,7 @@ several architecture/operating-system combinations: In general, this library can be built and installed with the following commands: + $ autoreconf -i # Needed only for building from git. Depends on libtool. $ ./configure $ make $ make install prefix=PREFIX From 905034ce728e84b2a1652ac4b44a2d8a5147a0d1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 00:41:37 +0200 Subject: [PATCH 025/162] Initial attempt at the build infrastructure for FreeBSD. --- configure.in | 6 ++++-- include/libunwind_i.h | 4 +++- include/tdep/dwarf-config.h | 2 +- src/Makefile.am | 5 +++++ src/ptrace/_UPT_internal.h | 8 ++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/configure.in b/configure.in index 6e55563c..72c6f88a 100644 --- a/configure.in +++ b/configure.in @@ -27,8 +27,8 @@ CHECK_ATOMIC_OPS dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h execinfo.h ia64intrin.h \ - sys/uc_access.h unistd.h signal.h) +AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h sys/endian.h execinfo.h \ + ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -80,6 +80,7 @@ get_arch() { hppa*) echo hppa;; mips*) echo mips;; powerpc*) is_gcc_m64;; + amd64) echo x86_64;; *) echo $1;; esac } @@ -99,6 +100,7 @@ AM_CONDITIONAL(ARCH_PPC32, test x$target_arch = xppc32) AM_CONDITIONAL(ARCH_PPC64, test x$target_arch = xppc64) AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null) AM_CONDITIONAL(OS_HPUX, expr x$target_os : xhpux >/dev/null) +AM_CONDITIONAL(OS_FREEBSD, expr x$target_os : xfreebsd >/dev/null) if test x$target_arch = xppc64; then libdir='${exec_prefix}/lib64' diff --git a/include/libunwind_i.h b/include/libunwind_i.h index 27bfd8db..c7bd2231 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -54,8 +54,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include -#ifdef HAVE_ENDIAN_H +#if defined(HAVE_ENDIAN_H) # include +#elif defined(HAVE_SYS_ENDIAN_H) +# include #else # define __LITTLE_ENDIAN 1234 # define __BIG_ENDIAN 4321 diff --git a/include/tdep/dwarf-config.h b/include/tdep/dwarf-config.h index ab36637b..ff5715f6 100644 --- a/include/tdep/dwarf-config.h +++ b/include/tdep/dwarf-config.h @@ -15,7 +15,7 @@ # include "tdep-ppc64/dwarf-config.h" #elif defined __i386__ # include "tdep-x86/dwarf-config.h" -#elif defined __x86_64__ +#elif defined __x86_64__ || defined __amd64__ # include "tdep-x86_64/dwarf-config.h" #else # error "Unsupported arch" diff --git a/src/Makefile.am b/src/Makefile.am index c110e768..4ba1b027 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -351,6 +351,11 @@ if OS_HPUX libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_hpux_local) endif +if OS_FREEBSD + libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd) + libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local) +endif + if ARCH_ARM lib_LTLIBRARIES_arch = libunwind-arm.la libunwind_la_SOURCES = $(libunwind_la_SOURCES_arm) diff --git a/src/ptrace/_UPT_internal.h b/src/ptrace/_UPT_internal.h index 0577097a..534a4ae4 100644 --- a/src/ptrace/_UPT_internal.h +++ b/src/ptrace/_UPT_internal.h @@ -26,6 +26,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _UPT_internal_h #define _UPT_internal_h +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + #include #include #include From d11456ffbf6dd6f556eb3bc64e8a368e7e3381c5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 14:55:11 +0200 Subject: [PATCH 026/162] Code to read/write fpregs on FreeBSD --- configure.in | 18 +++++++++++++++- src/ptrace/_UPT_access_fpreg.c | 39 ++++++++++++++++++++++++++++++++++ src/ptrace/_UPT_internal.h | 6 ++++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 72c6f88a..cbf581ce 100644 --- a/configure.in +++ b/configure.in @@ -28,7 +28,8 @@ CHECK_ATOMIC_OPS dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h sys/endian.h execinfo.h \ - ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h) + ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \ + sys/procfs.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -51,6 +52,21 @@ AC_CHECK_TYPES([sighandler_t], [], [], #endif ]) +AC_CHECK_DECLS(PTRACE_POKEUSER, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PT_GETFPREGS, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) + dnl Checks for library functions. AC_FUNC_MEMCMP AC_TYPE_SIGNAL diff --git a/src/ptrace/_UPT_access_fpreg.c b/src/ptrace/_UPT_access_fpreg.c index 28e08922..7992eb1d 100644 --- a/src/ptrace/_UPT_access_fpreg.c +++ b/src/ptrace/_UPT_access_fpreg.c @@ -25,6 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UPT_internal.h" +#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE int _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, int write, void *arg) @@ -64,3 +65,41 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, } return 0; } +#elif HAVE_DECL_PT_GETFPREGS +int +_UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + unw_word_t *wp = (unw_word_t *) val; + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + fpregset_t fpreg; + + if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0])) + return -UNW_EBADREG; + + if (ptrace(PT_GETFPREGS, pid, &fpreg, 0) == -1) + return -UNW_EBADREG; + if (write) { +#if defined(__amd64__) + memcpy(&fpreg.fpr_xacc[reg], val, sizeof(unw_fpreg_t)); +#elif defined(__i386__) + memcpy(&fpreg.fpr_acc[reg], val, sizeof(unw_fpreg_t)); +#else +#error Fix me +#endif + if (ptrace(PT_SETFPREGS, pid, &fpreg, 0) == -1) + return -UNW_EBADREG; + } else +#if defined(__amd64__) + memcpy(val, &fpreg.fpr_xacc[reg], sizeof(unw_fpreg_t)); +#elif defined(__i386__) + memcpy(val, &fpreg.fpr_acc[reg], sizeof(unw_fpreg_t)); +#else +#error Fix me +#endif + return 0; +} +#else +#error Fix me +#endif diff --git a/src/ptrace/_UPT_internal.h b/src/ptrace/_UPT_internal.h index 534a4ae4..bc7bf9c1 100644 --- a/src/ptrace/_UPT_internal.h +++ b/src/ptrace/_UPT_internal.h @@ -33,6 +33,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_SYS_TYPES_H #include #endif +#include +#ifdef HAVE_SYS_PROCFS_H +#include +#endif #include #include @@ -40,8 +44,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include -#include - #include "libunwind_i.h" struct UPT_info From cf6ae3548f96fa90da32b96529897cb6257355c1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 15:04:56 +0200 Subject: [PATCH 027/162] Code to read/write user memory on FreeBSD --- configure.in | 14 ++++++++++++++ src/ptrace/_UPT_access_mem.c | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/configure.in b/configure.in index cbf581ce..e5d4ac28 100644 --- a/configure.in +++ b/configure.in @@ -59,6 +59,20 @@ AC_CHECK_DECLS(PTRACE_POKEUSER, [], [], #endif #include ]) +AC_CHECK_DECLS(PTRACE_POKEDATA, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PT_IO, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) AC_CHECK_DECLS(PT_GETFPREGS, [], [], [$ac_includes_default #if HAVE_SYS_TYPES_H diff --git a/src/ptrace/_UPT_access_mem.c b/src/ptrace/_UPT_access_mem.c index 6900c19d..8c36387b 100644 --- a/src/ptrace/_UPT_access_mem.c +++ b/src/ptrace/_UPT_access_mem.c @@ -25,6 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UPT_internal.h" +#if HAVE_DECL_PTRACE_POKEDATA || HAVE_TTRACE int _UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, void *arg) @@ -57,3 +58,27 @@ _UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, } return 0; } +#elif HAVE_DECL_PT_IO +int +_UPT_access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + struct ptrace_io_desc iod; + + iod.piod_offs = (void *)addr; + iod.piod_addr = val; + iod.piod_len = sizeof(*val); + iod.piod_op = write ? PIOD_WRITE_D : PIOD_READ_D; + if (write) + Debug (16, "mem[%lx] <- %lx\n", (long) addr, (long) *val); + if (ptrace(PT_IO, pid, (caddr_t)&iod, 0) == -1) + return -UNW_EINVAL; + if (!write) + Debug (16, "mem[%lx] -> %lx\n", (long) addr, (long) *val); + return 0; +} +#else +#error Fix me +#endif From d4a4ddd23d5a059c0b1a637fee5de78b6158eecd Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:17:21 +0200 Subject: [PATCH 028/162] Provide access to the general regs on FreeBSD. --- configure.in | 7 +++++++ src/ptrace/_UPT_access_reg.c | 38 ++++++++++++++++++++++++++++++++++++ src/ptrace/_UPT_reg_offset.c | 28 ++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/configure.in b/configure.in index e5d4ac28..dec0fea3 100644 --- a/configure.in +++ b/configure.in @@ -73,6 +73,13 @@ AC_CHECK_DECLS(PT_IO, [], [], #endif #include ]) +AC_CHECK_DECLS(PT_GETREGS, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) AC_CHECK_DECLS(PT_GETFPREGS, [], [], [$ac_includes_default #if HAVE_SYS_TYPES_H diff --git a/src/ptrace/_UPT_access_reg.c b/src/ptrace/_UPT_access_reg.c index 60e006b9..a85b900f 100644 --- a/src/ptrace/_UPT_access_reg.c +++ b/src/ptrace/_UPT_access_reg.c @@ -33,6 +33,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # include "tdep-ia64/rse.h" #endif +#if HAVE_DECL_PTRACE_POKEUSER || HAVE_TTRACE int _UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, void *arg) @@ -252,3 +253,40 @@ _UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, Debug (1, "bad register number %u (error: %s)\n", reg, strerror (errno)); return -UNW_EBADREG; } +#elif HAVE_DECL_PT_GETREGS +int +_UPT_access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, + int write, void *arg) +{ + struct UPT_info *ui = arg; + pid_t pid = ui->pid; + gregset_t regs; + char *r; + +#if UNW_DEBUG + if (write) + Debug (16, "%s <- %lx\n", unw_regname (reg), (long) *val); +#endif + if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0])) + { + errno = EINVAL; + goto badreg; + } + r = (char *)®s + _UPT_reg_offset[reg]; + if (ptrace(PT_GETREGS, pid, (caddr_t)®s, 0) == -1) + goto badreg; + if (write) { + memcpy(r, val, sizeof(unw_word_t)); + if (ptrace(PT_SETREGS, pid, (caddr_t)®s, 0) == -1) + goto badreg; + } else + memcpy(val, r, sizeof(unw_word_t)); + return 0; + + badreg: + Debug (1, "bad register number %u (error: %s)\n", reg, strerror (errno)); + return -UNW_EBADREG; +} +#else +#error Port me +#endif diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c index f586fb72..83dbcc31 100644 --- a/src/ptrace/_UPT_reg_offset.c +++ b/src/ptrace/_UPT_reg_offset.c @@ -25,6 +25,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UPT_internal.h" +#include + #ifdef HAVE_ASM_PTRACE_OFFSETS_H # include #endif @@ -265,6 +267,31 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = /* EFLAGS = 0x38, */ /* SS = 0x40 */ #elif defined(UNW_TARGET_X86_64) +#if defined(__FreeBSD__) +#define UNW_R_OFF(R, r) \ + [UNW_X86_64_##R] = offsetof(gregset_t, r_##r), + UNW_R_OFF(RAX, rax) + UNW_R_OFF(RDX, rdx) + UNW_R_OFF(RCX, rcx) + UNW_R_OFF(RBX, rbx) + UNW_R_OFF(RSI, rsi) + UNW_R_OFF(RDI, rdi) + UNW_R_OFF(RBP, rbp) + UNW_R_OFF(RSP, rsp) + UNW_R_OFF(R8, r8) + UNW_R_OFF(R9, r9) + UNW_R_OFF(R10, r10) + UNW_R_OFF(R11, r11) + UNW_R_OFF(R12, r12) + UNW_R_OFF(R13, r13) + UNW_R_OFF(R14, r14) + UNW_R_OFF(R15, r15) + UNW_R_OFF(RIP, rip) +// UNW_R_OFF(CS, cs) +// UNW_R_OFF(EFLAGS, rflags) +// UNW_R_OFF(SS, ss) +#undef UNW_R_OFF +#else [UNW_X86_64_RAX] = 0x50, [UNW_X86_64_RDX] = 0x60, [UNW_X86_64_RCX] = 0x58, @@ -286,6 +313,7 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = // [UNW_X86_64_EFLAGS] = 0x90, // [UNW_X86_64_RSP] = 0x98, // [UNW_X86_64_SS] = 0xa0 +#endif #elif defined(UNW_TARGET_PPC32) #elif defined(UNW_TARGET_PPC64) #elif defined(UNW_TARGET_ARM) From 78cb28b4a6a01dabb4ff50bcc2edb8772627e5d4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:20:47 +0200 Subject: [PATCH 029/162] PT_CONTINUE. --- configure.in | 14 ++++++++++++++ src/ptrace/_UPT_resume.c | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index dec0fea3..74439433 100644 --- a/configure.in +++ b/configure.in @@ -66,6 +66,13 @@ AC_CHECK_DECLS(PTRACE_POKEDATA, [], [], #endif #include ]) +AC_CHECK_DECLS(PTRACE_CONT, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) AC_CHECK_DECLS(PT_IO, [], [], [$ac_includes_default #if HAVE_SYS_TYPES_H @@ -87,6 +94,13 @@ AC_CHECK_DECLS(PT_GETFPREGS, [], [], #endif #include ]) +AC_CHECK_DECLS(PT_CONTINUE, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) dnl Checks for library functions. AC_FUNC_MEMCMP diff --git a/src/ptrace/_UPT_resume.c b/src/ptrace/_UPT_resume.c index 11242e8d..f419fed3 100644 --- a/src/ptrace/_UPT_resume.c +++ b/src/ptrace/_UPT_resume.c @@ -32,7 +32,9 @@ _UPT_resume (unw_addr_space_t as, unw_cursor_t *c, void *arg) #ifdef HAVE_TTRACE # warning No support for ttrace() yet. -#else +#elif HAVE_DECL_PTRACE_CONT return ptrace (PTRACE_CONT, ui->pid, 0, 0); +#elif HAVE_DECL_PT_CONTINUE + return ptrace(PT_CONTINUE, ui->pid, (caddr_t)1, 0); #endif } From 8ccebc9307edda6c2315cc81f0381192b2db9df1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:23:24 +0200 Subject: [PATCH 030/162] MAP_ANONYMOUS --- include/libunwind_i.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/libunwind_i.h b/include/libunwind_i.h index c7bd2231..9b9d21bc 100644 --- a/include/libunwind_i.h +++ b/include/libunwind_i.h @@ -208,6 +208,9 @@ do { \ #define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */ +#ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +#endif #define GET_MEMORY(mem, size_in_bytes) \ do { \ /* Hopefully, mmap() goes straight through to a system call stub... */ \ From c7ffca11ae3b77343a9158ff5037cdf2e84136ae Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:35:32 +0200 Subject: [PATCH 031/162] FreeBSD way to name registers. --- src/x86_64/Ginit.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index f8469067..b6501009 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -50,6 +50,25 @@ uc_addr (ucontext_t *uc, int reg) switch (reg) { +#ifdef __FreeBSD__ + case UNW_X86_64_R8: addr = &uc->uc_mcontext.mc_r8; break; + case UNW_X86_64_R9: addr = &uc->uc_mcontext.mc_r9; break; + case UNW_X86_64_R10: addr = &uc->uc_mcontext.mc_r10; break; + case UNW_X86_64_R11: addr = &uc->uc_mcontext.mc_r11; break; + case UNW_X86_64_R12: addr = &uc->uc_mcontext.mc_r12; break; + case UNW_X86_64_R13: addr = &uc->uc_mcontext.mc_r13; break; + case UNW_X86_64_R14: addr = &uc->uc_mcontext.mc_r14; break; + case UNW_X86_64_R15: addr = &uc->uc_mcontext.mc_r15; break; + case UNW_X86_64_RDI: addr = &uc->uc_mcontext.mc_rdi; break; + case UNW_X86_64_RSI: addr = &uc->uc_mcontext.mc_rsi; break; + case UNW_X86_64_RBP: addr = &uc->uc_mcontext.mc_rbp; break; + case UNW_X86_64_RBX: addr = &uc->uc_mcontext.mc_rbx; break; + case UNW_X86_64_RDX: addr = &uc->uc_mcontext.mc_rdx; break; + case UNW_X86_64_RAX: addr = &uc->uc_mcontext.mc_rax; break; + case UNW_X86_64_RCX: addr = &uc->uc_mcontext.mc_rcx; break; + case UNW_X86_64_RSP: addr = &uc->uc_mcontext.mc_rsp; break; + case UNW_X86_64_RIP: addr = &uc->uc_mcontext.mc_rip; break; +#else case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break; case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break; case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break; @@ -67,6 +86,7 @@ uc_addr (ucontext_t *uc, int reg) case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break; case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break; case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break; +#endif default: addr = NULL; From 29c110265f50c14b8611a3f14be3941b23952125 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:43:18 +0200 Subject: [PATCH 032/162] _NSIG. --- src/setjmp/siglongjmp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/setjmp/siglongjmp.c b/src/setjmp/siglongjmp.c index 9a091fae..49d6d9c6 100644 --- a/src/setjmp/siglongjmp.c +++ b/src/setjmp/siglongjmp.c @@ -31,6 +31,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "jmpbuf.h" #include "setjmp_i.h" +#if !defined(_NSIG) && defined(_SIG_MAXSIG) +# define _NSIG (_SIG_MAXSIG - 1) +#endif + void siglongjmp (sigjmp_buf env, int val) { From 3eabce18b1e70c3b26975024e450977dfb4b84b9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:43:39 +0200 Subject: [PATCH 033/162] Include sys/types.h when needed. --- include/dwarf.h | 4 ++++ src/dwarf/Lexpr.c | 8 ++++++++ src/dwarf/Lfde.c | 8 ++++++++ src/dwarf/Lfind_proc_info-lsb.c | 8 ++++++++ src/dwarf/Lparser.c | 8 ++++++++ src/dwarf/Lpe.c | 8 ++++++++ src/dwarf/Lstep.c | 8 ++++++++ src/mi/Ldestroy_addr_space.c | 8 ++++++++ src/mi/Ldyn-extract.c | 8 ++++++++ src/mi/Lfind_dynamic_proc_info.c | 8 ++++++++ src/mi/Lget_accessors.c | 8 ++++++++ src/mi/Lget_fpreg.c | 8 ++++++++ src/mi/Lget_proc_info_by_ip.c | 8 ++++++++ src/mi/Lget_proc_name.c | 8 ++++++++ src/mi/Lget_reg.c | 8 ++++++++ src/mi/Lput_dynamic_unwind_info.c | 8 ++++++++ src/mi/Lset_caching_policy.c | 8 ++++++++ src/mi/Lset_fpreg.c | 8 ++++++++ src/mi/Lset_reg.c | 8 ++++++++ src/mi/backtrace.c | 10 +++++++++- src/setjmp/longjmp.c | 8 ++++++++ src/x86_64/Gcreate_addr_space.c | 4 ++++ src/x86_64/Gis_signal_frame.c | 10 ++++++++++ src/x86_64/Gresume.c | 4 ++++ src/x86_64/Lcreate_addr_space.c | 8 ++++++++ src/x86_64/Lget_proc_info.c | 8 ++++++++ src/x86_64/Lget_save_loc.c | 8 ++++++++ src/x86_64/Lglobal.c | 8 ++++++++ src/x86_64/Linit.c | 8 ++++++++ src/x86_64/Linit_local.c | 8 ++++++++ src/x86_64/Linit_remote.c | 8 ++++++++ src/x86_64/Lis_signal_frame.c | 8 ++++++++ src/x86_64/Lregs.c | 8 ++++++++ src/x86_64/Lresume.c | 8 ++++++++ src/x86_64/Lstep.c | 8 ++++++++ 35 files changed, 271 insertions(+), 1 deletion(-) diff --git a/include/dwarf.h b/include/dwarf.h index 37b5ec1c..c6b95b71 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -34,6 +34,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # include #endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #include struct dwarf_cursor; /* forward-declaration */ diff --git a/src/dwarf/Lexpr.c b/src/dwarf/Lexpr.c index 245970c9..b72fce08 100644 --- a/src/dwarf/Lexpr.c +++ b/src/dwarf/Lexpr.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lfde.c b/src/dwarf/Lfde.c index e779e8f1..9c22b618 100644 --- a/src/dwarf/Lfde.c +++ b/src/dwarf/Lfde.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lfind_proc_info-lsb.c b/src/dwarf/Lfind_proc_info-lsb.c index 27a5eeac..c9865634 100644 --- a/src/dwarf/Lfind_proc_info-lsb.c +++ b/src/dwarf/Lfind_proc_info-lsb.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lparser.c b/src/dwarf/Lparser.c index f23aaf48..0c379003 100644 --- a/src/dwarf/Lparser.c +++ b/src/dwarf/Lparser.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lpe.c b/src/dwarf/Lpe.c index a672358f..f302638d 100644 --- a/src/dwarf/Lpe.c +++ b/src/dwarf/Lpe.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lstep.c b/src/dwarf/Lstep.c index c1ac3c75..2b70fa48 100644 --- a/src/dwarf/Lstep.c +++ b/src/dwarf/Lstep.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Ldestroy_addr_space.c b/src/mi/Ldestroy_addr_space.c index 5bf9364b..a1330987 100644 --- a/src/mi/Ldestroy_addr_space.c +++ b/src/mi/Ldestroy_addr_space.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Ldyn-extract.c b/src/mi/Ldyn-extract.c index 1802f865..e348f831 100644 --- a/src/mi/Ldyn-extract.c +++ b/src/mi/Ldyn-extract.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lfind_dynamic_proc_info.c b/src/mi/Lfind_dynamic_proc_info.c index bc88e1c5..081065f7 100644 --- a/src/mi/Lfind_dynamic_proc_info.c +++ b/src/mi/Lfind_dynamic_proc_info.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_accessors.c b/src/mi/Lget_accessors.c index 555e37f3..72c22b5d 100644 --- a/src/mi/Lget_accessors.c +++ b/src/mi/Lget_accessors.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_fpreg.c b/src/mi/Lget_fpreg.c index e3be4414..6492a5a2 100644 --- a/src/mi/Lget_fpreg.c +++ b/src/mi/Lget_fpreg.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_proc_info_by_ip.c b/src/mi/Lget_proc_info_by_ip.c index 96910d83..e5d63c15 100644 --- a/src/mi/Lget_proc_info_by_ip.c +++ b/src/mi/Lget_proc_info_by_ip.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_proc_name.c b/src/mi/Lget_proc_name.c index 378097b5..0f8c753f 100644 --- a/src/mi/Lget_proc_name.c +++ b/src/mi/Lget_proc_name.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_reg.c b/src/mi/Lget_reg.c index effe8a80..6ca62007 100644 --- a/src/mi/Lget_reg.c +++ b/src/mi/Lget_reg.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lput_dynamic_unwind_info.c b/src/mi/Lput_dynamic_unwind_info.c index 99597cd5..573e8ecc 100644 --- a/src/mi/Lput_dynamic_unwind_info.c +++ b/src/mi/Lput_dynamic_unwind_info.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lset_caching_policy.c b/src/mi/Lset_caching_policy.c index cc18816b..0be4cbf1 100644 --- a/src/mi/Lset_caching_policy.c +++ b/src/mi/Lset_caching_policy.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lset_fpreg.c b/src/mi/Lset_fpreg.c index 2497d404..a903f239 100644 --- a/src/mi/Lset_fpreg.c +++ b/src/mi/Lset_fpreg.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lset_reg.c b/src/mi/Lset_reg.c index c7a872b0..c84d4669 100644 --- a/src/mi/Lset_reg.c +++ b/src/mi/Lset_reg.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/backtrace.c b/src/mi/backtrace.c index 46d6c97f..640675ce 100644 --- a/src/mi/backtrace.c +++ b/src/mi/backtrace.c @@ -24,8 +24,16 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UNW_REMOTE_ONLY - #define UNW_LOCAL_ONLY + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #include /* See glibc manual for a description of this function. */ diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c index ca5f1e42..09662edc 100644 --- a/src/setjmp/longjmp.c +++ b/src/setjmp/longjmp.c @@ -23,6 +23,14 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include diff --git a/src/x86_64/Gcreate_addr_space.c b/src/x86_64/Gcreate_addr_space.c index 975387a6..02b93ebb 100644 --- a/src/x86_64/Gcreate_addr_space.c +++ b/src/x86_64/Gcreate_addr_space.c @@ -29,6 +29,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" +#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#endif + PROTECTED unw_addr_space_t unw_create_addr_space (unw_accessors_t *a, int byte_order) { diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index 72edf46e..db04d750 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -25,6 +25,16 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#include + #include "unwind_i.h" #ifdef __linux__ diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c index 54215c32..90207e11 100644 --- a/src/x86_64/Gresume.c +++ b/src/x86_64/Gresume.c @@ -33,6 +33,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#if defined(__linux) /* sigreturn() is a no-op on x86_64 glibc. */ static NORETURN inline long @@ -45,6 +46,7 @@ my_rt_sigreturn (void *new_sp) : "memory"); abort (); } +#endif HIDDEN inline int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) @@ -73,6 +75,8 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) (unsigned long long) c->dwarf.ip); setcontext (uc); } +#elif defined(__FreeBSD__) + /* XXXKIB */ #else # warning Implement me! #endif diff --git a/src/x86_64/Lcreate_addr_space.c b/src/x86_64/Lcreate_addr_space.c index 0f2dc6be..7cde3622 100644 --- a/src/x86_64/Lcreate_addr_space.c +++ b/src/x86_64/Lcreate_addr_space.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lget_proc_info.c b/src/x86_64/Lget_proc_info.c index 69028b01..83086c32 100644 --- a/src/x86_64/Lget_proc_info.c +++ b/src/x86_64/Lget_proc_info.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lget_save_loc.c b/src/x86_64/Lget_save_loc.c index 9ea048a9..1f6aeb5c 100644 --- a/src/x86_64/Lget_save_loc.c +++ b/src/x86_64/Lget_save_loc.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lglobal.c b/src/x86_64/Lglobal.c index 6d7b489e..85c5d336 100644 --- a/src/x86_64/Lglobal.c +++ b/src/x86_64/Lglobal.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Linit.c b/src/x86_64/Linit.c index e9abfdd4..36f0ad49 100644 --- a/src/x86_64/Linit.c +++ b/src/x86_64/Linit.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Linit_local.c b/src/x86_64/Linit_local.c index 68a1687e..eee77a37 100644 --- a/src/x86_64/Linit_local.c +++ b/src/x86_64/Linit_local.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Linit_remote.c b/src/x86_64/Linit_remote.c index 58cb04ab..11e68b47 100644 --- a/src/x86_64/Linit_remote.c +++ b/src/x86_64/Linit_remote.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lis_signal_frame.c b/src/x86_64/Lis_signal_frame.c index b9a7c4f5..4820751e 100644 --- a/src/x86_64/Lis_signal_frame.c +++ b/src/x86_64/Lis_signal_frame.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lregs.c b/src/x86_64/Lregs.c index 2c9c75cd..f120896f 100644 --- a/src/x86_64/Lregs.c +++ b/src/x86_64/Lregs.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lresume.c b/src/x86_64/Lresume.c index 41a8cf00..3b9591a4 100644 --- a/src/x86_64/Lresume.c +++ b/src/x86_64/Lresume.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lstep.c b/src/x86_64/Lstep.c index c1ac3c75..2b70fa48 100644 --- a/src/x86_64/Lstep.c +++ b/src/x86_64/Lstep.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) From d7f51410753f67c0ae1caa5fbdb428f7718b99ec Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 16:46:52 +0200 Subject: [PATCH 034/162] MAP_ANONYMOUS --- tests/mapper.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/mapper.c b/tests/mapper.c index 1006a8c4..6edce711 100644 --- a/tests/mapper.c +++ b/tests/mapper.c @@ -36,6 +36,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +#endif + int main (int argc, char **argv) { From 5976f1a5b33ba1af3e7dbc663ffbebca3b944024 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 17:47:26 +0200 Subject: [PATCH 035/162] sys/types.h --- tests/Lperf-simple.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/Lperf-simple.c b/tests/Lperf-simple.c index cdf38c20..88c55b64 100644 --- a/tests/Lperf-simple.c +++ b/tests/Lperf-simple.c @@ -1,3 +1,11 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + #define UNW_LOCAL_ONLY #include #if !defined(UNW_REMOTE_ONLY) From 2646e0fde8a5721ec7356dce38e5341b3080ca62 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 17:47:52 +0200 Subject: [PATCH 036/162] Add freebsd stub --- src/Makefile.am | 2 ++ src/os-freebsd.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/os-freebsd.c diff --git a/src/Makefile.am b/src/Makefile.am index 4ba1b027..7cf0d662 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -97,6 +97,8 @@ libunwind_la_SOURCES_os_linux = os-linux.h os-linux.c libunwind_la_SOURCES_os_hpux = os-hpux.c +libunwind_la_SOURCES_os_freebsd = os-freebsd.c + dwarf_SOURCES_common = \ dwarf/global.c diff --git a/src/os-freebsd.c b/src/os-freebsd.c new file mode 100644 index 00000000..15ce3d48 --- /dev/null +++ b/src/os-freebsd.c @@ -0,0 +1,41 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 Konstantin Belousov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef UNW_REMOTE_ONLY + +#include +#include + +#include "libunwind_i.h" + +HIDDEN int +tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff) +{ + + /* XXXKIB */ + return (0); +} + +#endif /* UNW_REMOTE_ONLY */ From 1ba7599250d8bb2be1a4a21c1181d6a87db5e597 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 17:54:51 +0200 Subject: [PATCH 037/162] Add FreeBSD stub. --- src/x86_64/Gis_signal_frame.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index db04d750..e51fc672 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -67,6 +67,15 @@ unw_is_signal_frame (unw_cursor_t *cursor) return (w0 == 0x0f0000000fc0c748 && w1 == 0x05); } +#elif defined(__FreeBSD__) +PROTECTED int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + /* XXXKIB */ + printf ("%s: implement me\n", __FUNCTION__); + return -UNW_ENOINFO; +} + #else /* __linux__ */ PROTECTED int From 81f2de00830e7d68add0c12b68a3c67778acaf6d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 18:08:44 +0200 Subject: [PATCH 038/162] Add implementation of unw_is_signal_frame for freebsd. --- src/x86_64/Gis_signal_frame.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index e51fc672..3bee93a8 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -72,8 +72,35 @@ PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) { /* XXXKIB */ - printf ("%s: implement me\n", __FUNCTION__); - return -UNW_ENOINFO; + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, w2, w3, w4, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors (as); + arg = c->dwarf.as_arg; + + /* Check if RIP points at sigreturn sequence. +48 8d 7c 24 10 lea SIGF_UC(%rsp),%rdi +6a 00 pushq $0 +48 c7 c0 a1 01 00 00 movq $SYS_sigreturn,%rax +0f 05 syscall +f4 0: hlt +eb fd jmp 0b + */ + + ip = c->dwarf.ip; + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) + return 0; + w2 &= 0xffffff; + return (w0 == 0x48006a10247c8d48 && + w1 == 0x050f000001a1c0c7 && + w2 == 0x0000000000fdebf4); } #else /* __linux__ */ From 4de09a9c1569e17132973b801f77bcab8d927480 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 18:53:27 +0200 Subject: [PATCH 039/162] Implement freebsd-specific vm walker. --- src/os-freebsd.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index 15ce3d48..77fb2678 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -24,8 +24,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UNW_REMOTE_ONLY +#include +#include #include #include +#include #include "libunwind_i.h" @@ -33,9 +36,27 @@ HIDDEN int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, unsigned long *segbase, unsigned long *mapoff) { + struct kinfo_vmentry *freep, *kve; + int cnt, rc, i; - /* XXXKIB */ - return (0); + freep = kinfo_getvmmap(pid, &cnt); + if (freep == NULL) + return (-1); + for (i = 0; i < cnt; i++) { + kve = &freep[i]; + if (ip < kve->kve_start || ip >= kve->kve_end) + continue; + if (kve->kve_type != KVME_TYPE_VNODE) { + free(freep); + return (-1); + } + segbase = kve->kve_start; + mapoff = kve->kve_offset; + rc = elf_map_image(ei, kve->kve_path); + free(freep); + return (rc); + } + return (-1); } #endif /* UNW_REMOTE_ONLY */ From 63ae8ca8947c67aaa402abbe46a12d118366e1df Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 22:32:11 +0200 Subject: [PATCH 040/162] Correct assignments, remove unneeded includes. --- src/os-freebsd.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index 77fb2678..143175d2 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -26,9 +26,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include -#include -#include #include +#include #include "libunwind_i.h" @@ -50,8 +49,8 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, free(freep); return (-1); } - segbase = kve->kve_start; - mapoff = kve->kve_offset; + *segbase = kve->kve_start; + *mapoff = kve->kve_offset; rc = elf_map_image(ei, kve->kve_path); free(freep); return (rc); From 62218e10eb372154cfdea16ad8d3c8cb15cd39cb Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 22:33:11 +0200 Subject: [PATCH 041/162] Provide proper offsets for gregs in freebsd ucontext. Note that fp regs are not handled. --- src/x86_64/ucontext_i.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h index 459c56a2..2724bc0b 100644 --- a/src/x86_64/ucontext_i.h +++ b/src/x86_64/ucontext_i.h @@ -22,6 +22,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined __linux__ #define UC_MCONTEXT_GREGS_R8 0x28 #define UC_MCONTEXT_GREGS_R9 0x30 #define UC_MCONTEXT_GREGS_R10 0x38 @@ -42,3 +43,25 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UC_MCONTEXT_FPREGS_PTR 0x1a8 #define UC_MCONTEXT_FPREGS_MEM 0xe0 #define FPREGS_OFFSET_MXCSR 0x18 +#elif defined __FreeBSD__ +#define UC_MCONTEXT_GREGS_R8 0x38 +#define UC_MCONTEXT_GREGS_R9 0x40 +#define UC_MCONTEXT_GREGS_R10 0x60 +#define UC_MCONTEXT_GREGS_R11 0x68 +#define UC_MCONTEXT_GREGS_R12 0x70 +#define UC_MCONTEXT_GREGS_R13 0x78 +#define UC_MCONTEXT_GREGS_R14 0x80 +#define UC_MCONTEXT_GREGS_R15 0x88 +#define UC_MCONTEXT_GREGS_RDI 0x18 +#define UC_MCONTEXT_GREGS_RSI 0x20 +#define UC_MCONTEXT_GREGS_RBP 0x58 +#define UC_MCONTEXT_GREGS_RBX 0x50 +#define UC_MCONTEXT_GREGS_RDX 0x28 +#define UC_MCONTEXT_GREGS_RAX 0x48 +#define UC_MCONTEXT_GREGS_RCX 0x30 +#define UC_MCONTEXT_GREGS_RSP 0xa0 +#define UC_MCONTEXT_GREGS_RIP 0xb0 +#define UC_MCONTEXT_FPREGS_PTR 0x1a8 /* XXXKIB */ +#define UC_MCONTEXT_FPREGS_MEM 0xe0 /* XXXKIB */ +#define FPREGS_OFFSET_MXCSR 0x18 /* XXXKIB */ +#endif From 200147d0f2cdc5479375bb4fdeac8b717f67c3d6 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 6 Mar 2010 23:22:46 +0200 Subject: [PATCH 042/162] Handle fpu state --- src/x86_64/getcontext.S | 10 ++++++++-- src/x86_64/setcontext.S | 11 +++++++++++ src/x86_64/ucontext_i.h | 9 ++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S index 48a52d05..0488bad8 100644 --- a/src/x86_64/getcontext.S +++ b/src/x86_64/getcontext.S @@ -55,12 +55,20 @@ _Ux86_64_getcontext: movq %rax, UC_MCONTEXT_GREGS_RAX(%rdi) movq %rcx, UC_MCONTEXT_GREGS_RCX(%rdi) +#if defined __linux__ /* Save fp state (not needed, except for setcontext not restoring garbage). */ leaq UC_MCONTEXT_FPREGS_MEM(%rdi),%r8 movq %r8, UC_MCONTEXT_FPREGS_PTR(%rdi) fnstenv (%r8) stmxcsr FPREGS_OFFSET_MXCSR(%r8) +#elif defined __FreeBSD__ + fxsave UC_MCONTEXT_FPSTATE(%rdi) + movq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) + movq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) +#else +#error Port me +#endif leaq 8(%rsp), %rax /* exclude this call. */ movq %rax, UC_MCONTEXT_GREGS_RSP(%rdi) @@ -71,7 +79,5 @@ _Ux86_64_getcontext: xorq %rax, %rax retq -#ifdef __linux__ /* We do not need executable stack. */ .section .note.GNU-stack,"",@progbits -#endif diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S index 6b06a7bb..adbcf228 100644 --- a/src/x86_64/setcontext.S +++ b/src/x86_64/setcontext.S @@ -37,9 +37,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ _Ux86_64_setcontext: /* restore fp state */ +#if defined __linux__ mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8 fldenv (%r8) ldmxcsr FPREGS_OFFSET_MXCSR(%r8) +#elif defined __FreeBSD__ + cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) + jne 1f + cmpq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) + jne 1f + fxrstor UC_MCONTEXT_FPSTATE(%rdi) +1: +#else +#error Port me +#endif /* restore the rest of the state */ mov UC_MCONTEXT_GREGS_R8(%rdi),%r8 diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h index 2724bc0b..c942080b 100644 --- a/src/x86_64/ucontext_i.h +++ b/src/x86_64/ucontext_i.h @@ -61,7 +61,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UC_MCONTEXT_GREGS_RCX 0x30 #define UC_MCONTEXT_GREGS_RSP 0xa0 #define UC_MCONTEXT_GREGS_RIP 0xb0 -#define UC_MCONTEXT_FPREGS_PTR 0x1a8 /* XXXKIB */ -#define UC_MCONTEXT_FPREGS_MEM 0xe0 /* XXXKIB */ -#define FPREGS_OFFSET_MXCSR 0x18 /* XXXKIB */ +#define UC_MCONTEXT_FPSTATE 0xf0 +#define UC_MCONTEXT_OWNEDFP 0xe8 +#define UC_MCONTEXT_FPFORMAT 0xe0 +#define UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define UC_MCONTEXT_FPFMT_XMM 0x10002 + #endif From d7eea914485d5d5d3c7b29a74a68541240b6a090 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 12:27:03 +0200 Subject: [PATCH 043/162] Cast caddr_t argument for ptrace --- src/ptrace/_UPT_access_fpreg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ptrace/_UPT_access_fpreg.c b/src/ptrace/_UPT_access_fpreg.c index 7992eb1d..23c34bfc 100644 --- a/src/ptrace/_UPT_access_fpreg.c +++ b/src/ptrace/_UPT_access_fpreg.c @@ -78,7 +78,7 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, if ((unsigned) reg >= sizeof (_UPT_reg_offset) / sizeof (_UPT_reg_offset[0])) return -UNW_EBADREG; - if (ptrace(PT_GETFPREGS, pid, &fpreg, 0) == -1) + if (ptrace(PT_GETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) return -UNW_EBADREG; if (write) { #if defined(__amd64__) @@ -88,7 +88,7 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, #else #error Fix me #endif - if (ptrace(PT_SETFPREGS, pid, &fpreg, 0) == -1) + if (ptrace(PT_SETFPREGS, pid, (caddr_t)&fpreg, 0) == -1) return -UNW_EBADREG; } else #if defined(__amd64__) From 59d38aaccd53c13d962f07dbcb44b3ec5513c5ca Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 12:46:05 +0200 Subject: [PATCH 044/162] Properly handle -ldl and -lutil --- configure.in | 10 ++++++++++ tests/Makefile.am | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 74439433..7272a651 100644 --- a/configure.in +++ b/configure.in @@ -23,6 +23,15 @@ AM_PROG_CC_C_O dnl Checks for libraries. AC_CHECK_LIB(uca, __uc_get_grs) +AC_CHECK_LIB(util, kinfo_getvmmap) +OLD_LIBS=${LIBS} +AC_SEARCH_LIBS(dl, dlopen) +LIBS=${OLD_LIBS} +case "$ac_cv_search_dlopen" in + -l*) DLLIB=$ac_cv_search_dlopen;; + *) DLLIB="";; +esac + CHECK_ATOMIC_OPS dnl Checks for header files. @@ -241,6 +250,7 @@ AC_SUBST(PKG_MINOR) AC_SUBST(PKG_EXTRA) AC_SUBST(PKG_MAINTAINER) AC_SUBST(enable_cxx_exceptions) +AC_SUBST(DLLIB) AC_CONFIG_FILES(Makefile src/Makefile tests/Makefile tests/check-namespace.sh doc/Makefile doc/common.tex include/libunwind-common.h) diff --git a/tests/Makefile.am b/tests/Makefile.am index 401a6ec9..1dd331c1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -101,6 +101,6 @@ Gtest_concurrent_LDADD = $(LIBUNWIND) -lpthread test_async_sig_LDADD = $(LIBUNWIND) -lpthread rs_race_LDADD = $(LIBUNWIND) -lpthread -LDADD += -ldl +LDADD += @DLLIB@ Ltest_nomalloc_SOURCES = Ltest-nomalloc.c From efd0655ff49cd32a24e3f85ff4a6e2565aab62ca Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 17:27:41 +0200 Subject: [PATCH 045/162] Silence warning about symbol redefinition. --- src/elf32.h | 2 ++ src/elf64.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/elf32.h b/src/elf32.h index d27646cc..63fef836 100644 --- a/src/elf32.h +++ b/src/elf32.h @@ -1,7 +1,9 @@ #ifndef elf32_h #define elf32_h +#ifndef ELF_CLASS #define ELF_CLASS ELFCLASS32 +#endif #include "elfxx.h" #endif /* elf32_h */ diff --git a/src/elf64.h b/src/elf64.h index 8f22384a..fd10ed82 100644 --- a/src/elf64.h +++ b/src/elf64.h @@ -1,7 +1,9 @@ #ifndef elf64_h #define elf64_h +#ifndef ELF_CLASS #define ELF_CLASS ELFCLASS64 +#endif #include "elfxx.h" #endif /* elf64_h */ From d0d5f9979b3b870c882587ce6c4c4c01cbfcfe31 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 21:20:43 +0200 Subject: [PATCH 046/162] Correct rsp offset --- src/x86_64/Gis_signal_frame.c | 4 ++++ src/x86_64/ucontext_i.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index 3bee93a8..263ad87a 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -97,6 +97,10 @@ eb fd jmp 0b || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0 || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) return 0; +#if 0 + fprintf(stderr, "is_signal_frame: ip %lx w0 %lx w1 %lx w2 %lx\n", + ip, w0, w1, w2); +#endif w2 &= 0xffffff; return (w0 == 0x48006a10247c8d48 && w1 == 0x050f000001a1c0c7 && diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h index c942080b..82114dd2 100644 --- a/src/x86_64/ucontext_i.h +++ b/src/x86_64/ucontext_i.h @@ -59,7 +59,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UC_MCONTEXT_GREGS_RDX 0x28 #define UC_MCONTEXT_GREGS_RAX 0x48 #define UC_MCONTEXT_GREGS_RCX 0x30 -#define UC_MCONTEXT_GREGS_RSP 0xa0 +#define UC_MCONTEXT_GREGS_RSP 0xc8 #define UC_MCONTEXT_GREGS_RIP 0xb0 #define UC_MCONTEXT_FPSTATE 0xf0 #define UC_MCONTEXT_OWNEDFP 0xe8 From c64723835c0c855fde5bec3d7528db64fe539015 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 21:53:01 +0200 Subject: [PATCH 047/162] Support walk over freebsd sigframes --- include/tdep-x86_64/libunwind_i.h | 3 ++- src/x86/offsets.h | 3 +++ src/x86_64/Gis_signal_frame.c | 13 +++++-------- src/x86_64/Gregs.c | 4 ++++ src/x86_64/Gstep.c | 14 +++++++++++++- 5 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index a949a4cb..974d610e 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -62,7 +62,8 @@ struct cursor enum { X86_64_SCF_NONE, /* no signal frame encountered */ - X86_64_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ + X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */ + X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD ucontext_t */ } sigcontext_format; unw_word_t sigcontext_addr; diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 94307c12..63a28729 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -82,3 +82,6 @@ #define LINUX_FPSTATE_XMM5_OFF 0x160 #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 + +/* FreeBSD specific definitions */ +#define FREEBSD_UC_MCONTEXT_OFF 0x10 diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index 263ad87a..ce81699f 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -97,17 +97,14 @@ eb fd jmp 0b || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0 || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) return 0; -#if 0 - fprintf(stderr, "is_signal_frame: ip %lx w0 %lx w1 %lx w2 %lx\n", - ip, w0, w1, w2); -#endif w2 &= 0xffffff; - return (w0 == 0x48006a10247c8d48 && + ret = w0 == 0x48006a10247c8d48 && w1 == 0x050f000001a1c0c7 && - w2 == 0x0000000000fdebf4); + w2 == 0x0000000000fdebf4; + return ret; } -#else /* __linux__ */ +#else /* !__linux__ && !__FreeBSD__ */ PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) @@ -115,4 +112,4 @@ unw_is_signal_frame (unw_cursor_t *cursor) printf ("%s: implement me\n", __FUNCTION__); return -UNW_ENOINFO; } -#endif /* __linux__ */ +#endif diff --git a/src/x86_64/Gregs.c b/src/x86_64/Gregs.c index ddf7b7e3..5dd7b0b6 100644 --- a/src/x86_64/Gregs.c +++ b/src/x86_64/Gregs.c @@ -41,6 +41,10 @@ linux_scratch_loc (struct cursor *c, unw_regnum_t reg) case X86_64_SCF_LINUX_RT_SIGFRAME: addr += LINUX_UC_MCONTEXT_OFF; break; + + case X86_64_SCF_FREEBSD_SIGFRAME: + addr += FREEBSD_UC_MCONTEXT_OFF; + break; } return DWARF_REG_LOC (&c->dwarf, reg); diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 2da1c25d..5a1654e1 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -28,6 +28,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include "ucontext_i.h" #include +#include + +#if defined __FreeBSD__ +#include +#include +#endif PROTECTED int unw_step (unw_cursor_t *cursor) @@ -79,11 +85,17 @@ unw_step (unw_cursor_t *cursor) if (unw_is_signal_frame (cursor)) { - unw_word_t ucontext = c->dwarf.cfa; + unw_word_t ucontext; Debug(1, "signal frame, skip over trampoline\n"); +#if defined __linux__ + ucontext = c->dwarf.cfa; c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; +#elif defined __FreeBSD__ + ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME; +#endif c->sigcontext_addr = c->dwarf.cfa; rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); From 53095e6b3e4a6738e814c8f40cf546dca96a061f Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 7 Mar 2010 23:43:07 +0200 Subject: [PATCH 048/162] Code for resume --- src/Makefile.am | 2 +- src/x86/offsets.h | 3 --- src/x86_64/Gresume.c | 15 ++++++++------- src/x86_64/offsets.h | 3 +++ 4 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 src/x86_64/offsets.h diff --git a/src/Makefile.am b/src/Makefile.am index 7cf0d662..0aff658d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -244,7 +244,7 @@ libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ # The list of files that go both into libunwind and libunwind-x86_64: libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \ $(dwarf_SOURCES_common) \ - elf64.c elf64.h \ + elf64.c elf64.h x86_64/offsets.h \ x86_64/init.h x86_64/unwind_i.h x86_64/ucontext_i.h \ x86_64/is_fpreg.c x86_64/regname.c diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 63a28729..94307c12 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -82,6 +82,3 @@ #define LINUX_FPSTATE_XMM5_OFF 0x160 #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 - -/* FreeBSD specific definitions */ -#define FREEBSD_UC_MCONTEXT_OFF 0x10 diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c index 90207e11..a7822344 100644 --- a/src/x86_64/Gresume.c +++ b/src/x86_64/Gresume.c @@ -27,13 +27,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#include "offsets.h" #include "unwind_i.h" #ifndef UNW_REMOTE_ONLY #include -#if defined(__linux) +#if defined __linux /* sigreturn() is a no-op on x86_64 glibc. */ static NORETURN inline long @@ -51,7 +52,6 @@ my_rt_sigreturn (void *new_sp) HIDDEN inline int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) { -#if defined(__linux) struct cursor *c = (struct cursor *) cursor; ucontext_t *uc = c->uc; @@ -67,7 +67,13 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", (unsigned long long) c->dwarf.ip, sc); +#if defined __linux__ my_rt_sigreturn (sc); +#elif defined __FreeBSD__ + sigreturn((char *)(c->uc) - FREEBSD_UC_MCONTEXT_OFF); +#else +#error Port me +#endif } else { @@ -75,11 +81,6 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) (unsigned long long) c->dwarf.ip); setcontext (uc); } -#elif defined(__FreeBSD__) - /* XXXKIB */ -#else -# warning Implement me! -#endif return -UNW_EINVAL; } diff --git a/src/x86_64/offsets.h b/src/x86_64/offsets.h new file mode 100644 index 00000000..80cfe361 --- /dev/null +++ b/src/x86_64/offsets.h @@ -0,0 +1,3 @@ +/* FreeBSD specific definitions */ + +#define FREEBSD_UC_MCONTEXT_OFF 0x10 From da357e3c2e34c4d9d51e22d778a6dcea6eccef56 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 00:20:23 +0200 Subject: [PATCH 049/162] Revert "sys/types.h" This reverts commit 5976f1a5b33ba1af3e7dbc663ffbebca3b944024. --- tests/Lperf-simple.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/Lperf-simple.c b/tests/Lperf-simple.c index 88c55b64..cdf38c20 100644 --- a/tests/Lperf-simple.c +++ b/tests/Lperf-simple.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if !defined(UNW_REMOTE_ONLY) From 64b5391b7b77c52ea33b9a46196ce2c3845ec2a7 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 00:24:32 +0200 Subject: [PATCH 050/162] Include sys/types.h once --- include/libunwind-x86_64.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/libunwind-x86_64.h b/include/libunwind-x86_64.h index e3373516..53789cc3 100644 --- a/include/libunwind-x86_64.h +++ b/include/libunwind-x86_64.h @@ -32,6 +32,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ extern "C" { #endif +#include #include #include From 093855f12a00d4eacf548db6095235f970f88305 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 00:25:22 +0200 Subject: [PATCH 051/162] Remove unneeded includes of sys/types.h --- include/dwarf.h | 4 ---- src/dwarf/Lexpr.c | 8 -------- src/dwarf/Lfde.c | 8 -------- src/dwarf/Lfind_proc_info-lsb.c | 8 -------- src/dwarf/Lparser.c | 8 -------- src/dwarf/Lpe.c | 8 -------- src/dwarf/Lstep.c | 8 -------- src/mi/Ldestroy_addr_space.c | 8 -------- src/mi/Ldyn-extract.c | 8 -------- src/mi/Lfind_dynamic_proc_info.c | 8 -------- src/mi/Lget_accessors.c | 8 -------- src/mi/Lget_fpreg.c | 8 -------- src/mi/Lget_proc_info_by_ip.c | 8 -------- src/mi/Lget_proc_name.c | 8 -------- src/mi/Lget_reg.c | 8 -------- src/mi/Lput_dynamic_unwind_info.c | 8 -------- src/mi/Lset_caching_policy.c | 8 -------- src/mi/Lset_fpreg.c | 8 -------- src/mi/Lset_reg.c | 8 -------- src/mi/backtrace.c | 10 +--------- src/setjmp/longjmp.c | 8 -------- src/x86_64/Gis_signal_frame.c | 10 ---------- src/x86_64/Lcreate_addr_space.c | 8 -------- src/x86_64/Lget_proc_info.c | 8 -------- src/x86_64/Lget_save_loc.c | 8 -------- src/x86_64/Lglobal.c | 8 -------- src/x86_64/Linit.c | 8 -------- src/x86_64/Linit_local.c | 8 -------- src/x86_64/Linit_remote.c | 8 -------- src/x86_64/Lis_signal_frame.c | 8 -------- src/x86_64/Lregs.c | 8 -------- src/x86_64/Lresume.c | 8 -------- src/x86_64/Lstep.c | 8 -------- 33 files changed, 1 insertion(+), 263 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index c6b95b71..37b5ec1c 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -34,10 +34,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ # include #endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #include struct dwarf_cursor; /* forward-declaration */ diff --git a/src/dwarf/Lexpr.c b/src/dwarf/Lexpr.c index b72fce08..245970c9 100644 --- a/src/dwarf/Lexpr.c +++ b/src/dwarf/Lexpr.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lfde.c b/src/dwarf/Lfde.c index 9c22b618..e779e8f1 100644 --- a/src/dwarf/Lfde.c +++ b/src/dwarf/Lfde.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lfind_proc_info-lsb.c b/src/dwarf/Lfind_proc_info-lsb.c index c9865634..27a5eeac 100644 --- a/src/dwarf/Lfind_proc_info-lsb.c +++ b/src/dwarf/Lfind_proc_info-lsb.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lparser.c b/src/dwarf/Lparser.c index 0c379003..f23aaf48 100644 --- a/src/dwarf/Lparser.c +++ b/src/dwarf/Lparser.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lpe.c b/src/dwarf/Lpe.c index f302638d..a672358f 100644 --- a/src/dwarf/Lpe.c +++ b/src/dwarf/Lpe.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/dwarf/Lstep.c b/src/dwarf/Lstep.c index 2b70fa48..c1ac3c75 100644 --- a/src/dwarf/Lstep.c +++ b/src/dwarf/Lstep.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Ldestroy_addr_space.c b/src/mi/Ldestroy_addr_space.c index a1330987..5bf9364b 100644 --- a/src/mi/Ldestroy_addr_space.c +++ b/src/mi/Ldestroy_addr_space.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Ldyn-extract.c b/src/mi/Ldyn-extract.c index e348f831..1802f865 100644 --- a/src/mi/Ldyn-extract.c +++ b/src/mi/Ldyn-extract.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lfind_dynamic_proc_info.c b/src/mi/Lfind_dynamic_proc_info.c index 081065f7..bc88e1c5 100644 --- a/src/mi/Lfind_dynamic_proc_info.c +++ b/src/mi/Lfind_dynamic_proc_info.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_accessors.c b/src/mi/Lget_accessors.c index 72c22b5d..555e37f3 100644 --- a/src/mi/Lget_accessors.c +++ b/src/mi/Lget_accessors.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_fpreg.c b/src/mi/Lget_fpreg.c index 6492a5a2..e3be4414 100644 --- a/src/mi/Lget_fpreg.c +++ b/src/mi/Lget_fpreg.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_proc_info_by_ip.c b/src/mi/Lget_proc_info_by_ip.c index e5d63c15..96910d83 100644 --- a/src/mi/Lget_proc_info_by_ip.c +++ b/src/mi/Lget_proc_info_by_ip.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_proc_name.c b/src/mi/Lget_proc_name.c index 0f8c753f..378097b5 100644 --- a/src/mi/Lget_proc_name.c +++ b/src/mi/Lget_proc_name.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lget_reg.c b/src/mi/Lget_reg.c index 6ca62007..effe8a80 100644 --- a/src/mi/Lget_reg.c +++ b/src/mi/Lget_reg.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lput_dynamic_unwind_info.c b/src/mi/Lput_dynamic_unwind_info.c index 573e8ecc..99597cd5 100644 --- a/src/mi/Lput_dynamic_unwind_info.c +++ b/src/mi/Lput_dynamic_unwind_info.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lset_caching_policy.c b/src/mi/Lset_caching_policy.c index 0be4cbf1..cc18816b 100644 --- a/src/mi/Lset_caching_policy.c +++ b/src/mi/Lset_caching_policy.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lset_fpreg.c b/src/mi/Lset_fpreg.c index a903f239..2497d404 100644 --- a/src/mi/Lset_fpreg.c +++ b/src/mi/Lset_fpreg.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/Lset_reg.c b/src/mi/Lset_reg.c index c84d4669..c7a872b0 100644 --- a/src/mi/Lset_reg.c +++ b/src/mi/Lset_reg.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/mi/backtrace.c b/src/mi/backtrace.c index 640675ce..46d6c97f 100644 --- a/src/mi/backtrace.c +++ b/src/mi/backtrace.c @@ -24,16 +24,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UNW_REMOTE_ONLY + #define UNW_LOCAL_ONLY - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #include /* See glibc manual for a description of this function. */ diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c index 09662edc..ca5f1e42 100644 --- a/src/setjmp/longjmp.c +++ b/src/setjmp/longjmp.c @@ -23,14 +23,6 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index ce81699f..fd6599c1 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -25,16 +25,6 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - -#include - #include "unwind_i.h" #ifdef __linux__ diff --git a/src/x86_64/Lcreate_addr_space.c b/src/x86_64/Lcreate_addr_space.c index 7cde3622..0f2dc6be 100644 --- a/src/x86_64/Lcreate_addr_space.c +++ b/src/x86_64/Lcreate_addr_space.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lget_proc_info.c b/src/x86_64/Lget_proc_info.c index 83086c32..69028b01 100644 --- a/src/x86_64/Lget_proc_info.c +++ b/src/x86_64/Lget_proc_info.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lget_save_loc.c b/src/x86_64/Lget_save_loc.c index 1f6aeb5c..9ea048a9 100644 --- a/src/x86_64/Lget_save_loc.c +++ b/src/x86_64/Lget_save_loc.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lglobal.c b/src/x86_64/Lglobal.c index 85c5d336..6d7b489e 100644 --- a/src/x86_64/Lglobal.c +++ b/src/x86_64/Lglobal.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Linit.c b/src/x86_64/Linit.c index 36f0ad49..e9abfdd4 100644 --- a/src/x86_64/Linit.c +++ b/src/x86_64/Linit.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Linit_local.c b/src/x86_64/Linit_local.c index eee77a37..68a1687e 100644 --- a/src/x86_64/Linit_local.c +++ b/src/x86_64/Linit_local.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Linit_remote.c b/src/x86_64/Linit_remote.c index 11e68b47..58cb04ab 100644 --- a/src/x86_64/Linit_remote.c +++ b/src/x86_64/Linit_remote.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lis_signal_frame.c b/src/x86_64/Lis_signal_frame.c index 4820751e..b9a7c4f5 100644 --- a/src/x86_64/Lis_signal_frame.c +++ b/src/x86_64/Lis_signal_frame.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lregs.c b/src/x86_64/Lregs.c index f120896f..2c9c75cd 100644 --- a/src/x86_64/Lregs.c +++ b/src/x86_64/Lregs.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lresume.c b/src/x86_64/Lresume.c index 3b9591a4..41a8cf00 100644 --- a/src/x86_64/Lresume.c +++ b/src/x86_64/Lresume.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) diff --git a/src/x86_64/Lstep.c b/src/x86_64/Lstep.c index 2b70fa48..c1ac3c75 100644 --- a/src/x86_64/Lstep.c +++ b/src/x86_64/Lstep.c @@ -1,11 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) From ad932154a687d381482b66b01b4aaf11fe690969 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 00:50:50 +0200 Subject: [PATCH 052/162] Port test-ptrace --- configure.in | 56 +++++++++++++++++++++++++++++++++++++++++++++ tests/test-ptrace.c | 35 +++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 7272a651..979816e5 100644 --- a/configure.in +++ b/configure.in @@ -82,6 +82,34 @@ AC_CHECK_DECLS(PTRACE_CONT, [], [], #endif #include ]) +AC_CHECK_DECLS(PTRACE_TRACEME, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PTRACE_CONT, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PTRACE_SINGLESTEP, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PTRACE_SYSCALL, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) AC_CHECK_DECLS(PT_IO, [], [], [$ac_includes_default #if HAVE_SYS_TYPES_H @@ -110,6 +138,34 @@ AC_CHECK_DECLS(PT_CONTINUE, [], [], #endif #include ]) +AC_CHECK_DECLS(PT_TRACE_ME, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PT_CONTINUE, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PT_STEP, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) +AC_CHECK_DECLS(PT_SYSCALL, [], [], +[$ac_includes_default +#if HAVE_SYS_TYPES_H +#include +#endif +#include +]) dnl Checks for library functions. AC_FUNC_MEMCMP diff --git a/tests/test-ptrace.c b/tests/test-ptrace.c index 1f46f7d8..cbbf4896 100644 --- a/tests/test-ptrace.c +++ b/tests/test-ptrace.c @@ -39,6 +39,7 @@ main (int argc, char **argv) #include #include #include +#include #include #include #include @@ -47,6 +48,8 @@ main (int argc, char **argv) #include #include +extern char **environ; + static const int nerrors_max = 100; int nerrors; @@ -209,7 +212,13 @@ main (int argc, char **argv) if (!verbose) dup2 (open ("/dev/null", O_WRONLY), 1); +#if HAVE_DECL_PTRACE_TRACEME ptrace (PTRACE_TRACEME, 0, 0, 0); +#elif HAVE_DECL_PT_TRACE_ME + ptrace (PT_TRACE_ME, 0, 0, 0); +#else +#error Trace me +#endif execve (argv[optind], argv + optind, environ); _exit (-1); } @@ -274,11 +283,23 @@ main (int argc, char **argv) { case TRIGGER: if (state) +#if HAVE_DECL_PTRACE_CONT ptrace (PTRACE_CONT, target_pid, 0, 0); +#elif HAVE_DECL_PT_CONTINUE + ptrace (PT_CONTINUE, target_pid, (caddr_t)1, 0); +#else +#error Port me +#endif else { do_backtrace (target_pid); +#if HAVE_DECL_PTRACE_SINGLESTEP ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig); +#elif HAVE_DECL_PT_STEP + ptrace (PT_STEP, target_pid, (caddr_t)1, pending_sig); +#else +#error Singlestep me +#endif } break; @@ -286,12 +307,24 @@ main (int argc, char **argv) if (!state) do_backtrace (target_pid); state ^= 1; +#if HAVE_DECL_PTRACE_SYSCALL ptrace (PTRACE_SYSCALL, target_pid, 0, pending_sig); +#elif HAVE_DECL_PT_SYSCALL + ptrace (PT_SYSCALL, target_pid, 0, pending_sig); +#else +#error Syscall me +#endif break; case INSTRUCTION: do_backtrace (target_pid); - ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig); +#if HAVE_DECL_PTRACE_SINGLESTEP + ptrace (PTRACE_SINGLESTEP, target_pid, 0, pending_sig); +#elif HAVE_DECL_PT_STEP + ptrace (PT_STEP, target_pid, (caddr_t)1, pending_sig); +#else +#error Singlestep me +#endif break; } if (killed) From 5f5b1a5daa9f746b40e85103961734110dacc07c Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 00:52:26 +0200 Subject: [PATCH 053/162] tdep_get_elf_image should be public --- src/os-freebsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index 143175d2..d2dd60a8 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -31,7 +31,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libunwind_i.h" -HIDDEN int +int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, unsigned long *segbase, unsigned long *mapoff) { From 43ed5b3e56279999382b10acf9f3dfaab3257aef Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 00:57:50 +0200 Subject: [PATCH 054/162] Add required assembler magic. --- src/x86_64/getcontext.S | 1 + src/x86_64/longjmp.S | 2 -- src/x86_64/setcontext.S | 7 ++++--- src/x86_64/siglongjmp.S | 5 ++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S index 0488bad8..b6aedbb2 100644 --- a/src/x86_64/getcontext.S +++ b/src/x86_64/getcontext.S @@ -78,6 +78,7 @@ _Ux86_64_getcontext: xorq %rax, %rax retq + .size _Ux86_64_getcontext, . - _Ux86_64_getcontext /* We do not need executable stack. */ .section .note.GNU-stack,"",@progbits diff --git a/src/x86_64/longjmp.S b/src/x86_64/longjmp.S index bda9d066..0c4029e8 100644 --- a/src/x86_64/longjmp.S +++ b/src/x86_64/longjmp.S @@ -31,7 +31,5 @@ _UI_longjmp_cont: mov %rdx, %rax /* set up return-value */ retq .size _UI_longjmp_cont, .-_UI_longjmp_cont -#ifdef __linux__ /* We do not need executable stack. */ .section .note.GNU-stack,"",@progbits -#endif diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S index adbcf228..8720b9a5 100644 --- a/src/x86_64/setcontext.S +++ b/src/x86_64/setcontext.S @@ -33,7 +33,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ */ .global _Ux86_64_setcontext - + .type _Ux86_64_setcontext, @function + _Ux86_64_setcontext: /* restore fp state */ @@ -75,7 +76,7 @@ _Ux86_64_setcontext: mov UC_MCONTEXT_GREGS_RDI(%rdi),%rdi retq -#ifdef __linux__ + .size _Ux86_64_setcontext, . - _Ux86_64_setcontext + /* We do not need executable stack. */ .section .note.GNU-stack,"",@progbits -#endif diff --git a/src/x86_64/siglongjmp.S b/src/x86_64/siglongjmp.S index 8ca7968d..43c4b3e0 100644 --- a/src/x86_64/siglongjmp.S +++ b/src/x86_64/siglongjmp.S @@ -24,10 +24,9 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .globl _UI_siglongjmp_cont - + .type _ui_siglongjmp_cont, @function _UI_siglongjmp_cont: retq -#ifdef __linux__ + .size _UI_siglongjmp_cont, . - _UI_siglongjmp_cont /* We do not need executable stack. */ .section .note.GNU-stack,"",@progbits -#endif From 0f1c0f5f664004f0e812e7c2d939bc21fc5e89df Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 15:51:39 +0200 Subject: [PATCH 055/162] Fix resume. --- src/x86_64/Gresume.c | 8 +++++--- src/x86_64/getcontext.S | 16 ++++++++++++++++ src/x86_64/ucontext_i.h | 10 ++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c index a7822344..13c8059a 100644 --- a/src/x86_64/Gresume.c +++ b/src/x86_64/Gresume.c @@ -45,7 +45,6 @@ my_rt_sigreturn (void *new_sp) "syscall" :: "r"(new_sp), "i"(SYS_rt_sigreturn) : "memory"); - abort (); } #endif @@ -63,17 +62,20 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) if (unlikely (c->sigcontext_format != X86_64_SCF_NONE)) { +#if defined __linux__ struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", (unsigned long long) c->dwarf.ip, sc); -#if defined __linux__ my_rt_sigreturn (sc); #elif defined __FreeBSD__ - sigreturn((char *)(c->uc) - FREEBSD_UC_MCONTEXT_OFF); + Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", + (unsigned long long) c->dwarf.ip, uc); + sigreturn(uc); #else #error Port me #endif + abort(); } else { diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S index b6aedbb2..ce7cbcc1 100644 --- a/src/x86_64/getcontext.S +++ b/src/x86_64/getcontext.S @@ -66,6 +66,22 @@ _Ux86_64_getcontext: fxsave UC_MCONTEXT_FPSTATE(%rdi) movq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi) movq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) + /* Save rflags and segment registers, so that sigreturn(2) + does not complain. */ + pushfq + popq UC_MCONTEXT_RFLAGS(%rdi) + movl $0, UC_MCONTEXT_FLAGS(%rdi) + movw %cs, UC_MCONTEXT_CS(%rdi) + movw %ss, UC_MCONTEXT_SS(%rdi) +#if 0 + /* Setting the flags to 0 above disables restore of segment + registers from the context */ + movw %ds, UC_MCONTEXT_DS(%rdi) + movw %es, UC_MCONTEXT_ES(%rdi) + movw %fs, UC_MCONTEXT_FS(%rdi) + movw %gs, UC_MCONTEXT_GS(%rdi) +#endif + movq $UC_MCONTEXT_MC_LEN_VAL, UC_MCONTEXT_MC_LEN(%rdi) #else #error Port me #endif diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h index 82114dd2..9ce8f273 100644 --- a/src/x86_64/ucontext_i.h +++ b/src/x86_64/ucontext_i.h @@ -61,10 +61,20 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UC_MCONTEXT_GREGS_RCX 0x30 #define UC_MCONTEXT_GREGS_RSP 0xc8 #define UC_MCONTEXT_GREGS_RIP 0xb0 +#define UC_MCONTEXT_RFLAGS 0xc0 +#define UC_MCONTEXT_FLAGS 0xa0 +#define UC_MCONTEXT_CS 0xb8 +#define UC_MCONTEXT_SS 0xd0 +#define UC_MCONTEXT_DS 0xa6 +#define UC_MCONTEXT_ES 0xa4 +#define UC_MCONTEXT_FS 0x94 +#define UC_MCONTEXT_GS 0x96 +#define UC_MCONTEXT_MC_LEN 0xd8 #define UC_MCONTEXT_FPSTATE 0xf0 #define UC_MCONTEXT_OWNEDFP 0xe8 #define UC_MCONTEXT_FPFORMAT 0xe0 #define UC_MCONTEXT_FPOWNED_FPU 0x20001 #define UC_MCONTEXT_FPFMT_XMM 0x10002 +#define UC_MCONTEXT_MC_LEN_VAL 0x320 #endif From 89e1df2d328e96f15539af223f808ebc9dce82b0 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 15:55:29 +0200 Subject: [PATCH 056/162] Fix _UI_siglongjmp_cont name --- src/x86_64/longjmp.S | 1 - src/x86_64/siglongjmp.S | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/x86_64/longjmp.S b/src/x86_64/longjmp.S index 0c4029e8..274778fd 100644 --- a/src/x86_64/longjmp.S +++ b/src/x86_64/longjmp.S @@ -24,7 +24,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .globl _UI_longjmp_cont - .type _UI_longjmp_cont, @function _UI_longjmp_cont: push %rax /* push target IP as return address */ diff --git a/src/x86_64/siglongjmp.S b/src/x86_64/siglongjmp.S index 43c4b3e0..32489e53 100644 --- a/src/x86_64/siglongjmp.S +++ b/src/x86_64/siglongjmp.S @@ -24,7 +24,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .globl _UI_siglongjmp_cont - .type _ui_siglongjmp_cont, @function + .type _UI_siglongjmp_cont, @function _UI_siglongjmp_cont: retq .size _UI_siglongjmp_cont, . - _UI_siglongjmp_cont From 4b3ca293bf941ee2122afc9e7ccef92de55899a0 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 17:01:31 +0200 Subject: [PATCH 057/162] Fix PT_SYSCALL ignoring of ip --- tests/test-ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-ptrace.c b/tests/test-ptrace.c index cbbf4896..b7de6827 100644 --- a/tests/test-ptrace.c +++ b/tests/test-ptrace.c @@ -310,7 +310,7 @@ main (int argc, char **argv) #if HAVE_DECL_PTRACE_SYSCALL ptrace (PTRACE_SYSCALL, target_pid, 0, pending_sig); #elif HAVE_DECL_PT_SYSCALL - ptrace (PT_SYSCALL, target_pid, 0, pending_sig); + ptrace (PT_SYSCALL, target_pid, (caddr_t)1, pending_sig); #else #error Syscall me #endif From c1b1c10cfceccec0cc707b0100e053892bb203f7 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 18:48:27 +0200 Subject: [PATCH 058/162] Fix memory leak on error --- src/os-freebsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index d2dd60a8..f5ad3643 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -55,6 +55,7 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, free(freep); return (rc); } + free(freep); return (-1); } From 752ce15c4fbe0e08c2d19df18caa86887732b3c8 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 19:45:54 +0200 Subject: [PATCH 059/162] Preliminary version of freebsd syscall unwinder --- include/tdep-x86_64/libunwind_i.h | 3 ++- src/ptrace/_UPT_find_proc_info.c | 3 ++- src/x86_64/Gis_signal_frame.c | 23 +++++++++++++++++------ src/x86_64/Gstep.c | 28 ++++++++++++++++++++++++---- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index 974d610e..f6a02897 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -63,7 +63,8 @@ struct cursor { X86_64_SCF_NONE, /* no signal frame encountered */ X86_64_SCF_LINUX_RT_SIGFRAME, /* Linux ucontext_t */ - X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD ucontext_t */ + X86_64_SCF_FREEBSD_SIGFRAME, /* FreeBSD signal frame */ + X86_64_SCF_FREEBSD_SYSCALL, /* FreeBSD syscall */ } sigcontext_format; unw_word_t sigcontext_addr; diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index 2b81e59a..d06c84ca 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -262,8 +262,9 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, if (hdr->table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { +#if 1 abort (); -#if 0 +#else /* If there is no search table or it has an unsupported encoding, fall back on linear search. */ if (hdr->table_enc == DW_EH_PE_omit) diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gis_signal_frame.c index fd6599c1..4e516663 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gis_signal_frame.c @@ -54,7 +54,8 @@ unw_is_signal_frame (unw_cursor_t *cursor) || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) return 0; w1 &= 0xff; - return (w0 == 0x0f0000000fc0c748 && w1 == 0x05); + return (w0 == 0x0f0000000fc0c748 && w1 == 0x05) ? + X86_64_SCF_LINUX_RT_SIGFRAME : X86_64_SCF_NONE; } #elif defined(__FreeBSD__) @@ -63,7 +64,7 @@ unw_is_signal_frame (unw_cursor_t *cursor) { /* XXXKIB */ struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, w2, w3, w4, ip; + unw_word_t w0, w1, w2, b0, ip; unw_addr_space_t as; unw_accessors_t *a; void *arg; @@ -88,10 +89,20 @@ eb fd jmp 0b || (ret = (*a->access_mem) (as, ip + 16, &w2, 0, arg)) < 0) return 0; w2 &= 0xffffff; - ret = w0 == 0x48006a10247c8d48 && - w1 == 0x050f000001a1c0c7 && - w2 == 0x0000000000fdebf4; - return ret; + if (w0 == 0x48006a10247c8d48 && + w1 == 0x050f000001a1c0c7 && + w2 == 0x0000000000fdebf4) + return X86_64_SCF_FREEBSD_SIGFRAME; + /* Check if RIP points at standard syscall sequence. +49 89 ca mov %rcx,%r10 +0f 05 syscall + */ + if ((ret = (*a->access_mem) (as, ip - 5, &b0, 0, arg)) < 0) + return (0); + b0 &= 0xffffffffff; + if (b0 == 0x000000050fca8949) + return X86_64_SCF_FREEBSD_SYSCALL; + return X86_64_SCF_NONE; } #else /* !__linux__ && !__FreeBSD__ */ diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 5a1654e1..96f1c902 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -83,7 +83,24 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); - if (unw_is_signal_frame (cursor)) + c->sigcontext_format = unw_is_signal_frame (cursor); + if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL) { + c->dwarf.loc[RCX] = c->dwarf.loc[R10]; +// rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); +// rbp_loc = c->dwarf.loc[RBP]; + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", + (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), + (unsigned long long) c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + c->dwarf.cfa += 8; + return 1; + } else if (c->sigcontext_format != X86_64_SCF_NONE) { unw_word_t ucontext; @@ -91,10 +108,13 @@ unw_step (unw_cursor_t *cursor) #if defined __linux__ ucontext = c->dwarf.cfa; - c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; + if (c->sigcontext_format != X86_64_SCF_LINUX_RT_SIGFRAME) + return -UNW_EBADFRAME; #elif defined __FreeBSD__ - ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); - c->sigcontext_format = X86_64_SCF_FREEBSD_SIGFRAME; + if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) + ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + else + return -UNW_EBADFRAME; #endif c->sigcontext_addr = c->dwarf.cfa; From 9f79621a298719b22744f6637269f0d4ef314c39 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 20:55:50 +0200 Subject: [PATCH 060/162] Enough for now for ptrace backend --- src/ptrace/_UPT_find_proc_info.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index d06c84ca..b9ef5ed1 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -168,7 +168,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, char *path, unw_word_t segbase, unw_word_t mapoff) { Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; - unw_word_t addr, eh_frame_start, fde_count, load_base; + unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, load_base; + unw_word_t max_load_addr = 0; struct dwarf_eh_frame_hdr *hdr; unw_proc_info_t pi; unw_accessors_t *a; @@ -190,6 +191,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, case PT_LOAD: if (phdr[i].p_offset == mapoff) ptxt = phdr + i; + if ((uintptr_t) ui->ei.image + phdr->p_filesz > max_load_addr) + max_load_addr = (uintptr_t) ui->ei.image + phdr->p_filesz; break; case PT_GNU_EH_FRAME: @@ -268,11 +271,10 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, /* If there is no search table or it has an unsupported encoding, fall back on linear search. */ if (hdr->table_enc == DW_EH_PE_omit) - Debug (4, "table `%s' lacks search table; doing linear search\n", - info->dlpi_name); + Debug (4, "EH lacks search table; doing linear search\n"); else - Debug (4, "table `%s' has encoding 0x%x; doing linear search\n", - info->dlpi_name, hdr->table_enc); + Debug (4, "EH table has encoding 0x%x; doing linear search\n", + hdr->table_enc); eh_frame_end = max_load_addr; /* XXX can we do better? */ @@ -281,7 +283,6 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, if (hdr->eh_frame_ptr_enc == DW_EH_PE_omit) abort (); - cb_data->single_fde = 1; return linear_search (unw_local_addr_space, ip, eh_frame_start, eh_frame_end, fde_count, pi, need_unwind_info, NULL); From 71cbdc697fade0d253f41ffdc6f286c0ea684560 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 8 Mar 2010 21:49:38 +0200 Subject: [PATCH 061/162] Provide real values for jmpbuf offsets for FreeBSD --- include/tdep-x86_64/jmpbuf.h | 13 +++++++++++++ include/x86_64/jmpbuf.h | 31 ------------------------------- 2 files changed, 13 insertions(+), 31 deletions(-) delete mode 100644 include/x86_64/jmpbuf.h diff --git a/include/tdep-x86_64/jmpbuf.h b/include/tdep-x86_64/jmpbuf.h index 92200689..ae1b2d94 100644 --- a/include/tdep-x86_64/jmpbuf.h +++ b/include/tdep-x86_64/jmpbuf.h @@ -23,9 +23,22 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined __linux__ + /* Use glibc's jump-buffer indices; NPTL peeks at SP: */ #define JB_SP 6 #define JB_RP 7 #define JB_MASK_SAVED 8 #define JB_MASK 9 + +#elif defined __FreeBSD__ + +#define JB_SP 2 +#define JB_RP 0 +/* Pretend the ip cannot be 0 and mask is always saved */ +#define JB_MASK_SAVED 0 +#define JB_MASK 9 + +#endif + diff --git a/include/x86_64/jmpbuf.h b/include/x86_64/jmpbuf.h deleted file mode 100644 index 92200689..00000000 --- a/include/x86_64/jmpbuf.h +++ /dev/null @@ -1,31 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2004 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -#define JB_SP 6 -#define JB_RP 7 -#define JB_MASK_SAVED 8 -#define JB_MASK 9 From c61e0b932cccc2b56068a527575cb09dfabfa32b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 9 Mar 2010 17:37:52 +0200 Subject: [PATCH 062/162] Add sys/types.h for x86. --- include/libunwind-x86.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/libunwind-x86.h b/include/libunwind-x86.h index 65d42baf..32533df9 100644 --- a/include/libunwind-x86.h +++ b/include/libunwind-x86.h @@ -30,6 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ extern "C" { #endif +#include #include #include From bb41eba56c44306e5bc2dcf8eeba574bd5a3702f Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 9 Mar 2010 18:01:08 +0200 Subject: [PATCH 063/162] FreeBSD/i386 port. get/setcontext need further work --- src/x86/Gcreate_addr_space.c | 4 +++ src/x86/Ginit.c | 22 +++++++++++++++ src/x86/getcontext.S | 52 +++++++++++++++++++++++++++++++++--- src/x86/offsets.h | 26 ++++++++++++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/x86/Gcreate_addr_space.c b/src/x86/Gcreate_addr_space.c index fd850c47..5dd6367a 100644 --- a/src/x86/Gcreate_addr_space.c +++ b/src/x86/Gcreate_addr_space.c @@ -27,6 +27,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" +#if defined(_LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN) +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#endif + PROTECTED unw_addr_space_t unw_create_addr_space (unw_accessors_t *a, int byte_order) { diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 9205fb43..00a5b075 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -47,6 +47,7 @@ uc_addr (ucontext_t *uc, int reg) switch (reg) { +#if defined __linux__ case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break; case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break; case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break; @@ -64,6 +65,27 @@ uc_addr (ucontext_t *uc, int reg) case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break; case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break; case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break; +#elif defined __FreeBSD__ + case UNW_X86_GS: addr = &uc->uc_mcontext.mc_gs; break; + case UNW_X86_FS: addr = &uc->uc_mcontext.mc_fs; break; + case UNW_X86_ES: addr = &uc->uc_mcontext.mc_es; break; + case UNW_X86_DS: addr = &uc->uc_mcontext.mc_ds; break; + case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break; + case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break; + case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break; + case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break; + case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break; + case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break; + case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break; + case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break; + case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break; + case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.mc_trapno; break; + case UNW_X86_CS: addr = &uc->uc_mcontext.mc_cs; break; + case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.mc_eflags; break; + case UNW_X86_SS: addr = &uc->uc_mcontext.mc_ss; break; +#else +#error Port me +#endif default: addr = NULL; diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index a2999bef..7dfa2c01 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -38,6 +38,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ _Ux86_getcontext: mov 4(%esp),%eax /* ucontext_t* */ +#if defined __linux__ /* EAX is not preserved. */ movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) @@ -63,11 +64,54 @@ _Ux86_getcontext: movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) fnstenv (%ecx) fldenv (%ecx) +#elif defined __FreeBSD__ + /* EAX is not preserved. */ + movl $0, (FREEBSD_UC_MCONTEXT_EAX_OFF)(%eax) + + movl %ebx, (FREEBSD_UC_MCONTEXT_EBX_OFF)(%eax) + movl %ecx, (FREEBSD_UC_MCONTEXT_ECX_OFF)(%eax) + movl %edx, (FREEBSD_UC_MCONTEXT_EDX_OFF)(%eax) + movl %edi, (FREEBSD_UC_MCONTEXT_EDI_OFF)(%eax) + movl %esi, (FREEBSD_UC_MCONTEXT_ESI_OFF)(%eax) + movl %ebp, (FREEBSD_UC_MCONTEXT_EBP_OFF)(%eax) + + movl (%esp), %ecx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_EIP)(%eax) + + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_ESP)(%eax) + + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_FS)(%eax) + movw %gs, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_GS)(%eax) + movw %ds, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_DS)(%eax) + movw %es, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_ES)(%eax) + movw %ss, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_SS)(%eax) + movw %cs, %cx + movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_CS)(%eax) + + pushfl + popl (FREEBSD_UC_MCONTEXT_OFF_EFLAGS)(%eax) + + movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,FREEBSD_UC_MCONTEXT_OWNEDFP(%eax) + movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,FREEBSD_UC_MCONTEXT_FPFORMAT(%eax) + + leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) + fnstenv (%ecx) + fldenv (%ecx) + + movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL, FREEBSD_UC_MCONTEXT_MC_LEN(%eax) +#endif xor %eax, %eax ret + .size _Ux86_getcontext, . - _Ux86_getcontext -#ifdef __linux__ - /* We do not need executable stack. */ - .section .note.GNU-stack,"",@progbits -#endif + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 94307c12..81f69f90 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -82,3 +82,29 @@ #define LINUX_FPSTATE_XMM5_OFF 0x160 #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 + +#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EDI_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_ESI_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_EBP_OFF 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_EIP 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_ESP 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_FS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_GS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_DS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_ES 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_SS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_CS 0x11 +#define FREEBSD_UC_MCONTEXT_OFF_EFLAGS 0x11 +#define FREEBSD_UC_MCONTEXT_OWNEDFP 0x11 +#define FREEBSD_UC_MCONTEXT_FPFORMAT 0x11 +#define FREEBSD_UC_MCONTEXT_FPSTATE 0x11 +#define FREEBSD_UC_MCONTEXT_MC_LEN 0x11 + +#define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x11 +#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001 +#define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002 From 3b026a7ed8e4c03e7d0177ac198b2649427f80d1 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 10 Mar 2010 23:51:09 +0200 Subject: [PATCH 064/162] Fix i386 distinctions between freebsd and linux for mcontext. --- tests/Gtest-bt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Gtest-bt.c b/tests/Gtest-bt.c index 9b07ec47..9f2e6a9b 100644 --- a/tests/Gtest-bt.c +++ b/tests/Gtest-bt.c @@ -181,7 +181,10 @@ sighandler (int signal, void *siginfo, void *context) } # endif #elif UNW_TARGET_X86 +#if defined __linux__ printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]); +#elif defined __FreeBSD__ + printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip); #endif printf ("\n"); } From 47dcc89457137caea648147d9578d75781bea750 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 10 Mar 2010 23:51:59 +0200 Subject: [PATCH 065/162] Remove unneeded braces --- src/x86/getcontext.S | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index 7dfa2c01..8a1ba3bf 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -66,37 +66,37 @@ _Ux86_getcontext: fldenv (%ecx) #elif defined __FreeBSD__ /* EAX is not preserved. */ - movl $0, (FREEBSD_UC_MCONTEXT_EAX_OFF)(%eax) + movl $0, FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) - movl %ebx, (FREEBSD_UC_MCONTEXT_EBX_OFF)(%eax) - movl %ecx, (FREEBSD_UC_MCONTEXT_ECX_OFF)(%eax) - movl %edx, (FREEBSD_UC_MCONTEXT_EDX_OFF)(%eax) - movl %edi, (FREEBSD_UC_MCONTEXT_EDI_OFF)(%eax) - movl %esi, (FREEBSD_UC_MCONTEXT_ESI_OFF)(%eax) - movl %ebp, (FREEBSD_UC_MCONTEXT_EBP_OFF)(%eax) + movl %ebx, FREEBSD_UC_MCONTEXT_EBX_OFF(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_ECX_OFF(%eax) + movl %edx, FREEBSD_UC_MCONTEXT_EDX_OFF(%eax) + movl %edi, FREEBSD_UC_MCONTEXT_EDI_OFF(%eax) + movl %esi, FREEBSD_UC_MCONTEXT_ESI_OFF(%eax) + movl %ebp, FREEBSD_UC_MCONTEXT_EBP_OFF(%eax) movl (%esp), %ecx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_EIP)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_EIP(%eax) leal 4(%esp), %ecx /* Exclude the return address. */ - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_ESP)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_ESP(%eax) xorl %ecx, %ecx movw %fs, %cx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_FS)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_FS(%eax) movw %gs, %cx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_GS)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_GS(%eax) movw %ds, %cx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_DS)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_DS(%eax) movw %es, %cx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_ES)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_ES(%eax) movw %ss, %cx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_SS)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_SS(%eax) movw %cs, %cx - movl %ecx, (FREEBSD_UC_MCONTEXT_OFF_CS)(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_OFF_CS(%eax) pushfl - popl (FREEBSD_UC_MCONTEXT_OFF_EFLAGS)(%eax) + popl FREEBSD_UC_MCONTEXT_OFF_EFLAGS(%eax) movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,FREEBSD_UC_MCONTEXT_OWNEDFP(%eax) movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,FREEBSD_UC_MCONTEXT_FPFORMAT(%eax) From d7377096400e73db989ebb6b0985a84754a413ca Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Mar 2010 00:02:11 +0200 Subject: [PATCH 066/162] Close #if --- tests/Gtest-bt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Gtest-bt.c b/tests/Gtest-bt.c index 9f2e6a9b..1b609644 100644 --- a/tests/Gtest-bt.c +++ b/tests/Gtest-bt.c @@ -185,6 +185,7 @@ sighandler (int signal, void *siginfo, void *context) printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]); #elif defined __FreeBSD__ printf (" @ %lx", (unsigned long) uc->uc_mcontext.mc_eip); +#endif #endif printf ("\n"); } From 54f8b2fdbe814d79cf52231ba38175c92b5c3c23 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Mar 2010 00:02:24 +0200 Subject: [PATCH 067/162] Fill real offsets for freebsd --- src/x86/offsets.h | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 81f69f90..f06ffd2d 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -83,28 +83,28 @@ #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 -#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_EDI_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_ESI_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_EBP_OFF 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_EIP 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_ESP 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_FS 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_GS 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_DS 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_ES 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_SS 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_CS 0x11 -#define FREEBSD_UC_MCONTEXT_OFF_EFLAGS 0x11 -#define FREEBSD_UC_MCONTEXT_OWNEDFP 0x11 -#define FREEBSD_UC_MCONTEXT_FPFORMAT 0x11 -#define FREEBSD_UC_MCONTEXT_FPSTATE 0x11 -#define FREEBSD_UC_MCONTEXT_MC_LEN 0x11 +#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x40 +#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x34 +#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x3c +#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x38 +#define FREEBSD_UC_MCONTEXT_EDI_OFF 0x24 +#define FREEBSD_UC_MCONTEXT_ESI_OFF 0x28 +#define FREEBSD_UC_MCONTEXT_EBP_OFF 0x2c +#define FREEBSD_UC_MCONTEXT_OFF_EIP 0x4c +#define FREEBSD_UC_MCONTEXT_OFF_ESP 0x58 +#define FREEBSD_UC_MCONTEXT_OFF_FS 0x18 +#define FREEBSD_UC_MCONTEXT_OFF_GS 0x14 +#define FREEBSD_UC_MCONTEXT_OFF_DS 0x20 +#define FREEBSD_UC_MCONTEXT_OFF_ES 0x1c +#define FREEBSD_UC_MCONTEXT_OFF_SS 0x5c +#define FREEBSD_UC_MCONTEXT_OFF_CS 0x50 +#define FREEBSD_UC_MCONTEXT_OFF_EFLAGS 0x54 +#define FREEBSD_UC_MCONTEXT_OWNEDFP 0x68 +#define FREEBSD_UC_MCONTEXT_FPFORMAT 0x64 +#define FREEBSD_UC_MCONTEXT_FPSTATE 0x70 +#define FREEBSD_UC_MCONTEXT_MC_LEN 0x60 -#define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x11 +#define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280 #define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 #define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001 #define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002 From a6b23dcb0c42198ad01764a27a084fd49116a544 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Thu, 11 Mar 2010 00:50:40 +0200 Subject: [PATCH 068/162] Add partial implementation for is_signal_frame for i386. --- src/x86/Gis_signal_frame.c | 46 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/x86/Gis_signal_frame.c b/src/x86/Gis_signal_frame.c index df381ebe..3bd4be1c 100644 --- a/src/x86/Gis_signal_frame.c +++ b/src/x86/Gis_signal_frame.c @@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) { -#ifdef __linux__ +#if defined __linux__ struct cursor *c = (struct cursor *) cursor; unw_word_t w0, w1, ip; unw_addr_space_t as; @@ -64,8 +64,50 @@ unw_is_signal_frame (unw_cursor_t *cursor) || (w0 == 0x0000adb8 && w1 == 0x9080cd00)); Debug (16, "returning %d\n", ret); return ret; +#elif defined __FreeBSD__ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, w2, w3, w4, w5, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors (as); + arg = c->dwarf.as_arg; + + /* Check if EIP points at sigreturn() sequence. It can be: +sigcode+4: +8d 44 24 20 lea 0x20(%esp),%eax +50 push %eax +f7 40 54 00 02 00 testl $0x20000,0x54(%eax) +75 03 jne sigcode+21 +8e 68 14 mov 0x14(%eax),%gs +b8 a1 01 00 00 mov $0x1a1,%eax +50 push %eax +cd 80 int $0x80 + +freebsd4_sigcode+4: +XXX +osigcode: +XXX + */ + ip = c->dwarf.ip; + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 || + (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0 || + (ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0 || + (ret = (*a->access_mem) (as, ip + 16, &w3, 0, arg)) < 0 || + (ret = (*a->access_mem) (as, ip + 20, &w4, 0, arg)) < 0 || + (ret = (*a->access_mem) (as, ip + 24, &w5, 0, arg)) < 0) + return ret; + ret = (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && + w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000); + if (ret != 0) + return (1); + Debug (16, "returning %d\n", ret); + return (0); #else - printf ("%s: implement me\n", __FUNCTION__); +#error Port me #endif return -UNW_ENOINFO; } From 24112f6d9b87554fe18b1ca0f939f30c76ac38fa Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 10 Mar 2010 21:13:26 -0800 Subject: [PATCH 069/162] Fix some test failures on x86_64 on distros with small default stacks. --- tests/Gtest-bt.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/Gtest-bt.c b/tests/Gtest-bt.c index 9b07ec47..62a70831 100644 --- a/tests/Gtest-bt.c +++ b/tests/Gtest-bt.c @@ -48,14 +48,17 @@ typedef RETSIGTYPE (*sighandler_t) (int); int verbose; int num_errors; +/* These variables are global because they + * cause the signal stack to overflow */ +char buf[512], name[256]; +unw_cursor_t cursor; +ucontext_t uc; + static void do_backtrace (void) { - char buf[512], name[256]; unw_word_t ip, sp, off; - unw_cursor_t cursor; unw_proc_info_t pi; - unw_context_t uc; int ret; if (verbose) @@ -182,6 +185,8 @@ sighandler (int signal, void *siginfo, void *context) # endif #elif UNW_TARGET_X86 printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_EIP]); +#elif UNW_TARGET_X86_64 + printf (" @ %lx", (unsigned long) uc->uc_mcontext.gregs[REG_RIP]); #endif printf ("\n"); } From f8a15e9679e59872ca2dc9a9f943862c09d7a103 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 10 Mar 2010 22:52:12 -0800 Subject: [PATCH 070/162] Fix a couple of test breakages on x86_64 setcontext() now restores the signal mask. Also remove a check in the test that doesn't seem to be valid. --- src/x86_64/setcontext.S | 14 ++++++++++++++ src/x86_64/ucontext_i.h | 1 + tests/Gtest-resume-sig.c | 13 +++++++------ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S index 6b06a7bb..bf8d9564 100644 --- a/src/x86_64/setcontext.S +++ b/src/x86_64/setcontext.S @@ -24,7 +24,10 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "ucontext_i.h" +#include +#define SIG_SETMASK 2 +#define SIGSET_BYTE_SIZE (64/8) /* int _Ux86_64_setcontext (const ucontext_t *ucp) @@ -36,6 +39,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ _Ux86_64_setcontext: + /* restore signal mask + sigprocmask(SIG_SETMASK, ucp->uc_sigmask, NULL, sizeof(sigset_t)) */ + push %rdi + mov $__NR_rt_sigprocmask, %rax + lea UC_SIGMASK(%rdi), %rsi + mov $SIG_SETMASK, %rdi + xor %rdx, %rdx + mov $SIGSET_BYTE_SIZE, %r10 + syscall + pop %rdi + /* restore fp state */ mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8 fldenv (%r8) diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h index 459c56a2..c5878b49 100644 --- a/src/x86_64/ucontext_i.h +++ b/src/x86_64/ucontext_i.h @@ -41,4 +41,5 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UC_MCONTEXT_GREGS_RIP 0xa8 #define UC_MCONTEXT_FPREGS_PTR 0x1a8 #define UC_MCONTEXT_FPREGS_MEM 0xe0 +#define UC_SIGMASK 0x128 #define FPREGS_OFFSET_MXCSR 0x18 diff --git a/tests/Gtest-resume-sig.c b/tests/Gtest-resume-sig.c index 0f0a6f97..68e17ebb 100644 --- a/tests/Gtest-resume-sig.c +++ b/tests/Gtest-resume-sig.c @@ -63,7 +63,7 @@ void handler (int sig) { unw_word_t ip; - sigset_t mask; + sigset_t mask, oldmask; unw_context_t uc; unw_cursor_t c; char foo; @@ -84,7 +84,7 @@ handler (int sig) sigemptyset (&mask); sigaddset (&mask, SIGUSR2); - sigprocmask (SIG_BLOCK, &mask, NULL); + sigprocmask (SIG_BLOCK, &mask, &oldmask); kill (getpid (), SIGUSR2); /* pend SIGUSR2 */ signal (SIGUSR1, SIG_IGN); @@ -92,6 +92,10 @@ handler (int sig) if ((ret = unw_getcontext (&uc)) < 0) panic ("unw_getcontext() failed: ret=%d\n", ret); +#if UNW_TARGET_X86_64 + /* unw_getcontext() doesn't save signal mask to avoid a syscall */ + uc.uc_sigmask = oldmask; +#endif if ((ret = unw_init_local (&c, &uc)) < 0) panic ("unw_init_local() failed: ret=%d\n", ret); @@ -113,10 +117,7 @@ handler (int sig) ++got_usr2; if (got_usr1) { - if (sigusr1_sp != &foo) - panic ("Stack pointer changed from %p to %p between signals\n", - sigusr1_sp, &foo); - else if (verbose) + if (verbose) printf ("OK: stack still at %p\n", &foo); } signal (SIGUSR2, SIG_IGN); From d3ddc9b96b57ff2d535178487669d081f8fecbb7 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 10 Mar 2010 22:57:43 -0800 Subject: [PATCH 071/162] Cap the runtime for rs-race --- tests/rs-race.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/rs-race.c b/tests/rs-race.c index 8f7be676..c67584c1 100644 --- a/tests/rs-race.c +++ b/tests/rs-race.c @@ -29,6 +29,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include +/* ITERS=1000, NTHREAD=10 caught some bugs in the past */ +#ifndef ITERS +#define ITERS 100 +#endif + +#ifndef NTHREAD +#define NTHREAD 2 +#endif + int verbose; void @@ -1325,7 +1334,7 @@ void * bar(void *p) { int i; - for (i = 0; i < 1000; ++i) { + for (i = 0; i < ITERS; ++i) { foo_0 (); foo_1 (); foo_2 (); @@ -1459,10 +1468,6 @@ bar(void *p) return NULL; } -#ifndef NTHREAD -#define NTHREAD 10 -#endif - int doit () { pthread_t tid[NTHREAD]; From bdee34d766d8f5b5a0680cb296cb7e1e49e7cc1e Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 13 Mar 2010 16:48:14 +0200 Subject: [PATCH 072/162] Jump buffer indices for FreeBSD/x86. --- include/tdep-x86/jmpbuf.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/tdep-x86/jmpbuf.h b/include/tdep-x86/jmpbuf.h index a0eb072e..17574144 100644 --- a/include/tdep-x86/jmpbuf.h +++ b/include/tdep-x86/jmpbuf.h @@ -25,7 +25,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Use glibc's jump-buffer indices; NPTL peeks at SP: */ +#if defined __linux__ + #define JB_SP 4 #define JB_RP 5 #define JB_MASK_SAVED 6 #define JB_MASK 7 + +#elif defined __FreeBSD__ + +#define JB_SP 1 +#define JB_RP 0 +/* Pretend the ip cannot be 0 and mask is always saved */ +#define JB_MASK_SAVED 0 +#define JB_MASK 7 + +#endif From 71c4161247638cb521fcfbe466c7a77f3f680295 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 13 Mar 2010 18:33:22 +0200 Subject: [PATCH 073/162] Remove extra empty line --- include/tdep-x86_64/jmpbuf.h | 1 - src/x86/Gresume.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/tdep-x86_64/jmpbuf.h b/include/tdep-x86_64/jmpbuf.h index ae1b2d94..44fcd69b 100644 --- a/include/tdep-x86_64/jmpbuf.h +++ b/include/tdep-x86_64/jmpbuf.h @@ -41,4 +41,3 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define JB_MASK 9 #endif - diff --git a/src/x86/Gresume.c b/src/x86/Gresume.c index cf914786..81754760 100644 --- a/src/x86/Gresume.c +++ b/src/x86/Gresume.c @@ -54,6 +54,26 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); setcontext (uc); } +#elif defined __FreeBSD__ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->uc; + + /* Ensure c->pi is up-to-date. On x86, it's relatively common to be + missing DWARF unwind info. We don't want to fail in that case, + because the frame-chain still would let us do a backtrace at + least. */ + dwarf_make_proc_info (&c->dwarf); + + if (c->sigcontext_format == X86_SCF_NONE) { + Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); + setcontext (uc); + } else if (c->sigcontext_format == XXX) { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); + sigreturn(sc); + } + else #else # warning Implement me! #endif From e9cd30040e2794ee586ff853b360b47881824fda Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 13 Mar 2010 20:28:12 +0200 Subject: [PATCH 074/162] Move x86 porting further. --- include/tdep-x86/libunwind_i.h | 8 +- src/x86/Gis_signal_frame.c | 19 +++-- src/x86/Gregs.c | 131 ++++++++++++++++++++++++++++++++- src/x86/Gresume.c | 10 ++- src/x86/Gstep.c | 62 +++++++++++++++- src/x86/getcontext.S | 32 ++++---- src/x86/offsets.h | 30 ++++---- 7 files changed, 248 insertions(+), 44 deletions(-) diff --git a/include/tdep-x86/libunwind_i.h b/include/tdep-x86/libunwind_i.h index e6ee149c..9af007d1 100644 --- a/include/tdep-x86/libunwind_i.h +++ b/include/tdep-x86/libunwind_i.h @@ -60,8 +60,12 @@ struct cursor enum { X86_SCF_NONE, /* no signal frame encountered */ - X86_SCF_LINUX_SIGFRAME, /* classic x86 sigcontext */ - X86_SCF_LINUX_RT_SIGFRAME /* POSIX ucontext_t */ + X86_SCF_LINUX_SIGFRAME, /* Linux x86 sigcontext */ + X86_SCF_LINUX_RT_SIGFRAME, /* POSIX ucontext_t */ + X86_SCF_FREEBSD_SIGFRAME, /* FreeBSD x86 sigcontext */ + X86_SCF_FREEBSD_SIGFRAME4, /* FreeBSD 4.x x86 sigcontext */ + X86_SCF_FREEBSD_OSIGFRAME, /* FreeBSD pre-4.x x86 sigcontext */ + X86_SCF_FREEBSD_SYSCALL, /* FreeBSD x86 syscall */ } sigcontext_format; unw_word_t sigcontext_addr; diff --git a/src/x86/Gis_signal_frame.c b/src/x86/Gis_signal_frame.c index 3bd4be1c..42af3486 100644 --- a/src/x86/Gis_signal_frame.c +++ b/src/x86/Gis_signal_frame.c @@ -59,9 +59,12 @@ unw_is_signal_frame (unw_cursor_t *cursor) ip = c->dwarf.ip; if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) - return ret; - ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000) - || (w0 == 0x0000adb8 && w1 == 0x9080cd00)); + return ret; + ret = X86_SCF_NONE; + if (w0 == 0x0077b858 && w1 == 0x80cd0000) + ret = X86_SCF_LINUX_SIGFRAME; + else if (w0 == 0x0000adb8 && w1 == 0x9080cd00) + ret = X86_SCF_LINUX_RT_SIGFRAME; Debug (16, "returning %d\n", ret); return ret; #elif defined __FreeBSD__ @@ -100,12 +103,12 @@ XXX (ret = (*a->access_mem) (as, ip + 20, &w4, 0, arg)) < 0 || (ret = (*a->access_mem) (as, ip + 24, &w5, 0, arg)) < 0) return ret; - ret = (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && - w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000); - if (ret != 0) - return (1); + ret = X86_SCF_NONE; + if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && + w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000) + ret = X86_SCF_FREEBSD_SIGFRAME; Debug (16, "returning %d\n", ret); - return (0); + return (ret); #else #error Port me #endif diff --git a/src/x86/Gregs.c b/src/x86/Gregs.c index 78cfabcc..9f251096 100644 --- a/src/x86/Gregs.c +++ b/src/x86/Gregs.c @@ -26,8 +26,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "offsets.h" #include "unwind_i.h" +#if defined __linux__ static inline dwarf_loc_t -linux_scratch_loc (struct cursor *c, unw_regnum_t reg) +get_scratch_loc (struct cursor *c, unw_regnum_t reg) { unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; int ret, is_fpstate = 0; @@ -132,12 +133,138 @@ linux_scratch_loc (struct cursor *c, unw_regnum_t reg) else return DWARF_MEM_LOC (c, addr + off); } +#elif defined __FreeBSD__ +static inline dwarf_loc_t +get_scratch_loc (struct cursor *c, unw_regnum_t reg) +{ + unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; + int ret, is_fpstate = 0; + + switch (c->sigcontext_format) + { + case X86_SCF_NONE: + return DWARF_REG_LOC (&c->dwarf, reg); + + case X86_SCF_FREEBSD_SIGFRAME: + addr += FREEBSD_UC_MCONTEXT_OFF; + break; + + case X86_SCF_FREEBSD_SIGFRAME4: + abort(); + break; + + case X86_SCF_FREEBSD_OSIGFRAME: + /* XXXKIB */ + abort(); + break; + + case X86_SCF_FREEBSD_SYSCALL: + /* XXXKIB */ + abort(); + break; + + default: + /* XXXKIB */ + abort(); + break; + } + + switch (reg) + { + case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; + case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break; + case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break; + case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; + case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break; + case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break; + case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break; + case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break; + case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break; + case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break; + case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break; + case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break; + case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break; + case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break; + case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break; + case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break; + case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; + + /* The following is probably not correct for all possible cases. + Somebody who understands this better should review this for + correctness. */ + + case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; + case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; + case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; + case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; + case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; + case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; + case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; + case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; + + /* stacked fp registers */ + case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: + case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: + is_fpstate = 1; + off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); + break; + + /* SSE fp registers */ + case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: + case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: + case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: + case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: + case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: + case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: + case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: + case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: + is_fpstate = 1; + off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); + break; + case UNW_X86_XMM0: + case UNW_X86_XMM1: + case UNW_X86_XMM2: + case UNW_X86_XMM3: + case UNW_X86_XMM4: + case UNW_X86_XMM5: + case UNW_X86_XMM6: + case UNW_X86_XMM7: + is_fpstate = 1; + off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); + break; + + case UNW_X86_FOP: + case UNW_X86_TSS: + case UNW_X86_LDT: + default: + return DWARF_REG_LOC (&c->dwarf, reg); + } + + if (is_fpstate) + { + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, + addr + LINUX_SC_FPSTATE_OFF), + &fpstate_addr)) < 0) + return DWARF_NULL_LOC; + + if (!fpstate_addr) + return DWARF_NULL_LOC; + + return DWARF_MEM_LOC (c, fpstate_addr + off); + } + else + return DWARF_MEM_LOC (c, addr + off); +} +#else +#error Port me +#endif HIDDEN dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg) { if (c->sigcontext_addr) - return linux_scratch_loc (c, reg); + return get_scratch_loc (c, reg); else return DWARF_REG_LOC (&c->dwarf, reg); } diff --git a/src/x86/Gresume.c b/src/x86/Gresume.c index 81754760..40ab82b2 100644 --- a/src/x86/Gresume.c +++ b/src/x86/Gresume.c @@ -26,6 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "unwind_i.h" +#include "offsets.h" #ifndef UNW_REMOTE_ONLY @@ -67,13 +68,16 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) if (c->sigcontext_format == X86_SCF_NONE) { Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); setcontext (uc); - } else if (c->sigcontext_format == XXX) { + } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn(sc); + sigreturn((const char *)sc + FREEBSD_UC_MCONTEXT_OFF); + } else { + Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", + c->sigcontext_format); + abort(); } - else #else # warning Implement me! #endif diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c index 266f89f4..daa52d36 100644 --- a/src/x86/Gstep.c +++ b/src/x86/Gstep.c @@ -23,6 +23,17 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#ifdef __FreeBSD__ +#include +#include +#endif + #include "unwind_i.h" #include "offsets.h" @@ -30,7 +41,7 @@ PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret, i; + int ret, i, format; Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); @@ -55,8 +66,10 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); - if (unw_is_signal_frame (cursor)) + format = unw_is_signal_frame (cursor); + if (format != X86_SCF_NONE) { +#if defined __linux__ /* XXX This code is Linux-specific! */ /* c->esp points at the arguments to the handler. Without @@ -119,6 +132,51 @@ unw_step (unw_cursor_t *cursor) c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC; c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC; c->dwarf.loc[ST0] = DWARF_NULL_LOC; +#elif defined __FreeBSD__ + if (format == X86_SCF_FREEBSD_SIGFRAME) { + struct sigframe *sf; + uintptr_t uc_addr; + struct dwarf_loc esp_loc; + + sf = (struct sigframe *)c->dwarf.cfa; + uc_addr = (uintptr_t)&(sf->sf_uc); + + esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); + ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning 0\n"); + return 0; + } + ebp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EBP_OFF, 0); + eip_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_EIP_OFF, 0); + + c->dwarf.loc[EAX] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EAX_OFF, 0); + c->dwarf.loc[ECX] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_ECX_OFF, 0); + c->dwarf.loc[EDX] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EDX_OFF, 0); + c->dwarf.loc[EBX] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EBX_OFF, 0); + c->dwarf.loc[EBP] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EBP_OFF, 0); + c->dwarf.loc[ESI] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_ESI_OFF, 0); + c->dwarf.loc[EDI] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EDI_OFF, 0); + c->dwarf.loc[EFLAGS] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0); + c->dwarf.loc[TRAPNO] = DWARF_LOC (uc_addr + + FREEBSD_UC_MCONTEXT_EFLAGS_OFF, 0); + c->dwarf.loc[ST0] = DWARF_NULL_LOC; + } else { + Debug (8, "Gstep: not handling frame format %d\n", format); + abort(); + } +#else +#error Port me +#endif } else { diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index 8a1ba3bf..e8db7031 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -76,37 +76,41 @@ _Ux86_getcontext: movl %ebp, FREEBSD_UC_MCONTEXT_EBP_OFF(%eax) movl (%esp), %ecx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_EIP(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_EIP_OFF(%eax) leal 4(%esp), %ecx /* Exclude the return address. */ - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_ESP(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_ESP_OFF(%eax) xorl %ecx, %ecx movw %fs, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_FS(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_FS_OFF(%eax) movw %gs, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_GS(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_GS_OFF(%eax) movw %ds, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_DS(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_DS_OFF(%eax) movw %es, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_ES(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_ES_OFF(%eax) movw %ss, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_SS(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_SS_OFF(%eax) movw %cs, %cx - movl %ecx, FREEBSD_UC_MCONTEXT_OFF_CS(%eax) + movl %ecx, FREEBSD_UC_MCONTEXT_CS_OFF(%eax) pushfl - popl FREEBSD_UC_MCONTEXT_OFF_EFLAGS(%eax) - - movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,FREEBSD_UC_MCONTEXT_OWNEDFP(%eax) - movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,FREEBSD_UC_MCONTEXT_FPFORMAT(%eax) + popl FREEBSD_UC_MCONTEXT_EFLAGS_OFF(%eax) + movl $0, FREEBSD_UC_MCONTEXT_TRAPNO_OFF(%eax) + movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,\ + FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) + movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,\ + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax) +/* leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) fnstenv (%ecx) fldenv (%ecx) - - movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL, FREEBSD_UC_MCONTEXT_MC_LEN(%eax) +*/ + movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ + FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) #endif xor %eax, %eax diff --git a/src/x86/offsets.h b/src/x86/offsets.h index f06ffd2d..7b32cab4 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -83,6 +83,9 @@ #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 +#define FREEBSD_SC_UCONTEXT_OFF 0x14 +#define FREEBSD_UC_MCONTEXT_OFF 0x10 + #define FREEBSD_UC_MCONTEXT_EAX_OFF 0x40 #define FREEBSD_UC_MCONTEXT_EBX_OFF 0x34 #define FREEBSD_UC_MCONTEXT_ECX_OFF 0x3c @@ -90,19 +93,20 @@ #define FREEBSD_UC_MCONTEXT_EDI_OFF 0x24 #define FREEBSD_UC_MCONTEXT_ESI_OFF 0x28 #define FREEBSD_UC_MCONTEXT_EBP_OFF 0x2c -#define FREEBSD_UC_MCONTEXT_OFF_EIP 0x4c -#define FREEBSD_UC_MCONTEXT_OFF_ESP 0x58 -#define FREEBSD_UC_MCONTEXT_OFF_FS 0x18 -#define FREEBSD_UC_MCONTEXT_OFF_GS 0x14 -#define FREEBSD_UC_MCONTEXT_OFF_DS 0x20 -#define FREEBSD_UC_MCONTEXT_OFF_ES 0x1c -#define FREEBSD_UC_MCONTEXT_OFF_SS 0x5c -#define FREEBSD_UC_MCONTEXT_OFF_CS 0x50 -#define FREEBSD_UC_MCONTEXT_OFF_EFLAGS 0x54 -#define FREEBSD_UC_MCONTEXT_OWNEDFP 0x68 -#define FREEBSD_UC_MCONTEXT_FPFORMAT 0x64 -#define FREEBSD_UC_MCONTEXT_FPSTATE 0x70 -#define FREEBSD_UC_MCONTEXT_MC_LEN 0x60 +#define FREEBSD_UC_MCONTEXT_EIP_OFF 0x4c +#define FREEBSD_UC_MCONTEXT_ESP_OFF 0x58 +#define FREEBSD_UC_MCONTEXT_FS_OFF 0x18 +#define FREEBSD_UC_MCONTEXT_GS_OFF 0x14 +#define FREEBSD_UC_MCONTEXT_DS_OFF 0x20 +#define FREEBSD_UC_MCONTEXT_ES_OFF 0x1c +#define FREEBSD_UC_MCONTEXT_SS_OFF 0x5c +#define FREEBSD_UC_MCONTEXT_CS_OFF 0x50 +#define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54 +#define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 +#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 +#define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70 +#define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60 +#define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 #define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280 #define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 From e51429280bd0238b1486a391eaca838944391ac7 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 13 Mar 2010 20:31:12 +0200 Subject: [PATCH 075/162] Handle error return from is_signal_frame --- src/x86/Gstep.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c index daa52d36..6af065d4 100644 --- a/src/x86/Gstep.c +++ b/src/x86/Gstep.c @@ -67,6 +67,10 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); format = unw_is_signal_frame (cursor); + if (format < 0) { + Debug (13, "unw_is_signal_frame() failed (ret=%d)\n", ret); + return format; + } if (format != X86_SCF_NONE) { #if defined __linux__ From 8a75ba971a295ce7e6b7b73b90272fb9c04e5b2f Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 13 Mar 2010 21:26:50 +0200 Subject: [PATCH 076/162] Signal trampoline on amd64 for ia32 is special. --- src/x86/Gis_signal_frame.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/x86/Gis_signal_frame.c b/src/x86/Gis_signal_frame.c index 42af3486..40f9f328 100644 --- a/src/x86/Gis_signal_frame.c +++ b/src/x86/Gis_signal_frame.c @@ -80,7 +80,14 @@ unw_is_signal_frame (unw_cursor_t *cursor) arg = c->dwarf.as_arg; /* Check if EIP points at sigreturn() sequence. It can be: -sigcode+4: +sigcode+4: from amd64 freebsd32 environment +8d 44 24 20 lea 0x20(%esp),%eax +50 push %eax +b8 a1 01 00 00 mov $0x1a1,%ea +50 push %eax +cd 80 int $0x80 + +sigcode+4: from real i386 8d 44 24 20 lea 0x20(%esp),%eax 50 push %eax f7 40 54 00 02 00 testl $0x20000,0x54(%eax) @@ -96,17 +103,23 @@ osigcode: XXX */ ip = c->dwarf.ip; - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 || - (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0 || - (ret = (*a->access_mem) (as, ip + 8, &w2, 0, arg)) < 0 || - (ret = (*a->access_mem) (as, ip + 16, &w3, 0, arg)) < 0 || - (ret = (*a->access_mem) (as, ip + 20, &w4, 0, arg)) < 0 || - (ret = (*a->access_mem) (as, ip + 24, &w5, 0, arg)) < 0) - return ret; ret = X86_SCF_NONE; - if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && - w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000) + if ((*a->access_mem) (as, ip, &w0, 0, arg) < 0 || + (*a->access_mem) (as, ip + 4, &w1, 0, arg) < 0 || + (*a->access_mem) (as, ip + 8, &w2, 0, arg) < 0 || + (*a->access_mem) (as, ip + 12, &w3, 0, arg) < 0) + return ret; + if (w0 == 0x2024448d && w1 == 0x01a1b850 && w2 == 0xcd500000 && + (w3 & 0xff) == 0x80) ret = X86_SCF_FREEBSD_SIGFRAME; + else { + if ((*a->access_mem) (as, ip + 16, &w4, 0, arg) < 0 || + (*a->access_mem) (as, ip + 20, &w5, 0, arg) < 0) + return ret; + if (w0 == 0x2024448d && w1 == 0x5440f750 && w2 == 0x75000200 && + w3 == 0x14688e03 && w4 == 0x0001a1b8 && w5 == 0x80cd5000) + ret = X86_SCF_FREEBSD_SIGFRAME; + } Debug (16, "returning %d\n", ret); return (ret); #else From 7bd264e292fa2bfe6f2cc435b827e6d66d3cd0b6 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Tue, 23 Mar 2010 10:37:21 -0700 Subject: [PATCH 077/162] Fix up what looks like an unintentional semi colon. Thanks to Lassi Tuura for noticing it. --- src/dwarf/Gparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 9dcf1a68..db64b920 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -422,7 +422,7 @@ put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi) if (c->pi_is_dynamic) unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg); - else if (pi->unwind_info); + else if (pi->unwind_info) { mempool_free (&dwarf_cie_info_pool, pi->unwind_info); pi->unwind_info = NULL; From 6203f1cd0f899085a35d2f553b592bd93580fdde Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Fri, 26 Mar 2010 15:54:14 -0700 Subject: [PATCH 078/162] Cleanup a mapped elf image. Without this, we end up with mmap leaks. Thanks to Humberto Abdelnur for suggesting this. --- src/ptrace/_UPT_destroy.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ptrace/_UPT_destroy.c b/src/ptrace/_UPT_destroy.c index 52cf5434..088bbe3d 100644 --- a/src/ptrace/_UPT_destroy.c +++ b/src/ptrace/_UPT_destroy.c @@ -26,7 +26,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UPT_internal.h" void -_UPT_destroy (void *ui) +_UPT_destroy (void *ptr) { - free (ui); + struct UPT_info *ui = (struct UPT_info *) ptr; + if (ui->ei.image) + { + munmap(ui->ei.image, ui->ei.size); + } + + free (ptr); } From ad97600f75be7ad9fd807fd8f820a6d7226c195d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 31 Mar 2010 23:01:46 +0300 Subject: [PATCH 079/162] Correct the configure check for -ldl. Submitted by: Arun Sharma --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 979816e5..2658e548 100644 --- a/configure.in +++ b/configure.in @@ -25,7 +25,7 @@ dnl Checks for libraries. AC_CHECK_LIB(uca, __uc_get_grs) AC_CHECK_LIB(util, kinfo_getvmmap) OLD_LIBS=${LIBS} -AC_SEARCH_LIBS(dl, dlopen) +AC_SEARCH_LIBS(dlopen, dl) LIBS=${OLD_LIBS} case "$ac_cv_search_dlopen" in -l*) DLLIB=$ac_cv_search_dlopen;; From 31ece3eaa120d09b36ad785b93f85f08fbbbfe6a Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 3 Apr 2010 18:28:31 +0300 Subject: [PATCH 080/162] Fix setcontext for amd64 freebsd --- src/x86_64/setcontext.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S index 5e69ae83..3d0f660a 100644 --- a/src/x86_64/setcontext.S +++ b/src/x86_64/setcontext.S @@ -63,11 +63,11 @@ _Ux86_64_setcontext: /* restore signal mask */ pushq %rdi xorl %edx,%edx - movq UC_SIGMASK(%rdi),%rsi + leaq UC_SIGMASK(%rdi),%rsi movl $3,%edi/* SIG_SETMASK */ movl $SYS_sigprocmask,%eax movq %rcx,%r10 - sysenter + syscall popq %rdi /* restore fp state */ From 5715d912f4f43041735031170d7f8ead6f70924d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 3 Apr 2010 19:02:43 +0300 Subject: [PATCH 081/162] Make setjmp/longjmp work at least on FreeBSD/amd64. FreeBSD-supplied setjmp() saves incremented stack pointer into jmpbuf. I have no idea whether siglongjmp ever worked on amd64, since UNW_NUM_EH_REGS == 2 and abort at siglongjmp.c:81 is firing. --- src/setjmp/longjmp.c | 4 ++++ src/setjmp/siglongjmp.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/setjmp/longjmp.c b/src/setjmp/longjmp.c index ca5f1e42..1b9f7c4e 100644 --- a/src/setjmp/longjmp.c +++ b/src/setjmp/longjmp.c @@ -50,7 +50,11 @@ _longjmp (jmp_buf env, int val) { if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) abort (); +#ifdef __FreeBSD__ + if (sp != wp[JB_SP] + sizeof(unw_word_t)) +#else if (sp != wp[JB_SP]) +#endif continue; if (!bsp_match (&c, wp)) diff --git a/src/setjmp/siglongjmp.c b/src/setjmp/siglongjmp.c index 49d6d9c6..da757e3c 100644 --- a/src/setjmp/siglongjmp.c +++ b/src/setjmp/siglongjmp.c @@ -53,7 +53,11 @@ siglongjmp (sigjmp_buf env, int val) { if (unw_get_reg (&c, UNW_REG_SP, &sp) < 0) abort (); +#ifdef __FreeBSD__ + if (sp != wp[JB_SP] + sizeof(unw_word_t)) +#else if (sp != wp[JB_SP]) +#endif continue; if (!bsp_match (&c, wp)) From bd2798805a68eac5491a4b096659a05e61e83580 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 3 Apr 2010 23:29:28 +0300 Subject: [PATCH 082/162] Reformat os-freebsd.c. --- src/os-freebsd.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index f5ad3643..1230bfd5 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -31,32 +31,34 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "libunwind_i.h" -int +PROTECTED int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, unsigned long *segbase, unsigned long *mapoff) { - struct kinfo_vmentry *freep, *kve; - int cnt, rc, i; + struct kinfo_vmentry *freep, *kve; + int cnt, rc, i; - freep = kinfo_getvmmap(pid, &cnt); - if (freep == NULL) - return (-1); - for (i = 0; i < cnt; i++) { - kve = &freep[i]; - if (ip < kve->kve_start || ip >= kve->kve_end) - continue; - if (kve->kve_type != KVME_TYPE_VNODE) { - free(freep); - return (-1); - } - *segbase = kve->kve_start; - *mapoff = kve->kve_offset; - rc = elf_map_image(ei, kve->kve_path); - free(freep); - return (rc); + freep = kinfo_getvmmap(pid, &cnt); + if (freep == NULL) + return (-1); + for (i = 0; i < cnt; i++) + { + kve = &freep[i]; + if (ip < kve->kve_start || ip >= kve->kve_end) + continue; + if (kve->kve_type != KVME_TYPE_VNODE) + { + free(freep); + return (-1); } - free(freep); - return (-1); + *segbase = kve->kve_start; + *mapoff = kve->kve_offset; + rc = elf_map_image(ei, kve->kve_path); + free(freep); + return (rc); + } + free(freep); + return (-1); } #endif /* UNW_REMOTE_ONLY */ From 22b17269cf508711b0ab209b50f6a65882672bc8 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 3 Apr 2010 23:34:33 +0300 Subject: [PATCH 083/162] Test for malloc.h. --- configure.in | 2 +- tests/Gtest-dyn1.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 2658e548..f65459a0 100644 --- a/configure.in +++ b/configure.in @@ -38,7 +38,7 @@ dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h sys/endian.h execinfo.h \ ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \ - sys/procfs.h) + sys/procfs.h malloc.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/tests/Gtest-dyn1.c b/tests/Gtest-dyn1.c index de9854dd..58ec8286 100644 --- a/tests/Gtest-dyn1.c +++ b/tests/Gtest-dyn1.c @@ -25,8 +25,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* This file tests dynamic code-generation via function-cloning. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include +#ifdef HAVE_MALLOC_H #include +#endif #include #include #include From 2b7ca45acc292a6e6dad04f99adde380ddaea2f7 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 3 Apr 2010 16:49:18 -0700 Subject: [PATCH 084/162] Fix handling of SA_SIGINFO frames on 32 bit x86 Submitted by: Arne de Bruijn --- src/x86/Gis_signal_frame.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/x86/Gis_signal_frame.c b/src/x86/Gis_signal_frame.c index df381ebe..686da02c 100644 --- a/src/x86/Gis_signal_frame.c +++ b/src/x86/Gis_signal_frame.c @@ -50,9 +50,9 @@ unw_is_signal_frame (unw_cursor_t *cursor) without SA_SIGINFO, and __restore_rt: - 0xb8 0xad 0x00 0x00 0x00 movl 0x80,%eax + 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax 0xcd 0x80 int 0x80 - 0x90 nop + 0x00 if SA_SIGINFO is specified. */ @@ -61,7 +61,7 @@ unw_is_signal_frame (unw_cursor_t *cursor) || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) return ret; ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000) - || (w0 == 0x0000adb8 && w1 == 0x9080cd00)); + || (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00)); Debug (16, "returning %d\n", ret); return ret; #else From 6e07e94d5dc29425d4f28995e7fed11ac618810d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 4 Apr 2010 11:57:57 +0300 Subject: [PATCH 085/162] Revert "Test for malloc.h." This reverts commit 22b17269cf508711b0ab209b50f6a65882672bc8. --- configure.in | 2 +- tests/Gtest-dyn1.c | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/configure.in b/configure.in index f65459a0..2658e548 100644 --- a/configure.in +++ b/configure.in @@ -38,7 +38,7 @@ dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(asm/ptrace_offsets.h endian.h sys/endian.h execinfo.h \ ia64intrin.h sys/uc_access.h unistd.h signal.h sys/types.h \ - sys/procfs.h malloc.h) + sys/procfs.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/tests/Gtest-dyn1.c b/tests/Gtest-dyn1.c index 58ec8286..de9854dd 100644 --- a/tests/Gtest-dyn1.c +++ b/tests/Gtest-dyn1.c @@ -25,14 +25,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* This file tests dynamic code-generation via function-cloning. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include -#ifdef HAVE_MALLOC_H #include -#endif #include #include #include From 574d32a8296567752507e45816a43346d6113137 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 4 Apr 2010 11:59:31 +0300 Subject: [PATCH 086/162] malloc.h is not needed. --- tests/Gtest-dyn1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Gtest-dyn1.c b/tests/Gtest-dyn1.c index de9854dd..ad49a5c2 100644 --- a/tests/Gtest-dyn1.c +++ b/tests/Gtest-dyn1.c @@ -26,7 +26,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* This file tests dynamic code-generation via function-cloning. */ #include -#include #include #include #include From 7169958221f50227342dc7972c2ed9917b5b8141 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 4 Apr 2010 12:03:15 +0300 Subject: [PATCH 087/162] Add some notes about FreeBSD. --- README | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README b/README index 7d599897..00b89166 100644 --- a/README +++ b/README @@ -9,6 +9,8 @@ several architecture/operating-system combinations: Linux/PARISC: Works well, but C library missing unwind-info. HP-UX/IA-64: Mostly works but known to have some serious limitations. Linux/PPC64: Newly added. + FreeBSD/i386: Newly added. + FreeBSD/x86-64: Newly added (FreeBSD architecture is known as amd64). * General Build Instructions @@ -80,6 +82,12 @@ If libunwind seems to not work (backtracing failing), try to compile it with -O0, without optimizations. There are some compiler problems depending on the version of your gcc. +* Building on FreeBSD + +General building instructions apply. To build and execute several tests, +you need libexecinfo library available in ports as devel/libexecinfo. + +Development of the port was done of FreeBSD 8.0-STABLE. * Regression Testing From 601919e2f8f71cf6e99082fd30bd54790ff78f7b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 4 Apr 2010 12:39:16 +0300 Subject: [PATCH 088/162] Update FreeBSD notes. --- README | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README b/README index 00b89166..cf98f4f5 100644 --- a/README +++ b/README @@ -87,7 +87,9 @@ depending on the version of your gcc. General building instructions apply. To build and execute several tests, you need libexecinfo library available in ports as devel/libexecinfo. -Development of the port was done of FreeBSD 8.0-STABLE. +Development of the port was done of FreeBSD 8.0-STABLE. The library +was build with the system compiler that is modified version of gcc 4.2.1, +as well as the gcc 4.4.3. * Regression Testing From 8fa95f347e8abe90952f873ac202c3107ed84c1b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 4 Apr 2010 12:39:28 +0300 Subject: [PATCH 089/162] Simplify the check for ptrace operations. --- configure.in | 108 +++++---------------------------------------------- 1 file changed, 9 insertions(+), 99 deletions(-) diff --git a/configure.in b/configure.in index 2658e548..64dd93a9 100644 --- a/configure.in +++ b/configure.in @@ -61,111 +61,21 @@ AC_CHECK_TYPES([sighandler_t], [], [], #endif ]) -AC_CHECK_DECLS(PTRACE_POKEUSER, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PTRACE_POKEDATA, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PTRACE_CONT, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PTRACE_TRACEME, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PTRACE_CONT, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PTRACE_SINGLESTEP, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PTRACE_SYSCALL, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_IO, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_GETREGS, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_GETFPREGS, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_CONTINUE, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_TRACE_ME, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_CONTINUE, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_STEP, [], [], -[$ac_includes_default -#if HAVE_SYS_TYPES_H -#include -#endif -#include -]) -AC_CHECK_DECLS(PT_SYSCALL, [], [], +AC_DEFUN([AC_CHECK_PTRACE_DECL], +[for pxxx in $1; do +AC_CHECK_DECLS($pxxx, [], [], [$ac_includes_default #if HAVE_SYS_TYPES_H #include #endif #include ]) +done] +) + +AC_CHECK_PTRACE_DECL([PTRACE_POKEUSER PTRACE_POKEDATA PTRACE_CONT \ +PTRACE_TRACEME PTRACE_CONT PTRACE_SIGNLESTEP PTRACE_SYSCALL PT_IO PT_GETREGS \ +PT_GETFPREGS PT_CONTINUE PT_TRACE_ME PT_STEP PT_SYSCALL]) dnl Checks for library functions. AC_FUNC_MEMCMP From 459b2a5ba89c3ae0002e741cadbc723e4b1dd0a6 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 4 Apr 2010 17:09:33 +0300 Subject: [PATCH 090/162] Normalize test code --- tests/test-async-sig.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test-async-sig.c b/tests/test-async-sig.c index eaa9ce90..5e906902 100644 --- a/tests/test-async-sig.c +++ b/tests/test-async-sig.c @@ -23,6 +23,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Check whether basic unwinding truly is async-signal safe. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include #include #include #include @@ -32,7 +37,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UNW_LOCAL_ONLY #include -#include "config.h" static const int nerrors_max = 100; @@ -182,4 +186,5 @@ main (int argc, char **argv) exit (-1); } } + return (0); } From 8e53e62db913470952b8eb541834b876f7a6882c Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 4 Apr 2010 16:17:32 -0700 Subject: [PATCH 091/162] Refactor os specific code for x86 (both 32 and 64 bit). Move Linux specific code into ${arch}/Gos-linux.c --- include/libunwind-common.h.in | 2 + src/Makefile.am | 22 ++- src/x86/Gis_signal_frame.c | 71 --------- src/x86/Gos-linux.c | 137 ++++++++++++++++++ src/x86/Gstep.c | 67 +-------- src/x86/{Lis_signal_frame.c => Los-linux.c} | 2 +- .../{Gis_signal_frame.c => Gos-linux.c} | 45 +++++- src/x86_64/Gstep.c | 42 +----- src/x86_64/Los-linux.c | 5 + tests/check-namespace.sh.in | 2 + 10 files changed, 213 insertions(+), 182 deletions(-) delete mode 100644 src/x86/Gis_signal_frame.c create mode 100644 src/x86/Gos-linux.c rename src/x86/{Lis_signal_frame.c => Los-linux.c} (78%) rename src/x86_64/{Gis_signal_frame.c => Gos-linux.c} (53%) create mode 100644 src/x86_64/Los-linux.c diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in index 9005a6c2..228460a9 100644 --- a/include/libunwind-common.h.in +++ b/include/libunwind-common.h.in @@ -220,6 +220,7 @@ unw_save_loc_t; #define unw_set_fpreg UNW_OBJ(set_fpreg) #define unw_get_save_loc UNW_OBJ(get_save_loc) #define unw_is_signal_frame UNW_OBJ(is_signal_frame) +#define unw_handle_signal_frame UNW_OBJ(handle_signal_frame) #define unw_get_proc_name UNW_OBJ(get_proc_name) #define unw_set_caching_policy UNW_OBJ(set_caching_policy) #define unw_regname UNW_ARCH_OBJ(regname) @@ -246,6 +247,7 @@ extern int unw_get_fpreg (unw_cursor_t *, int, unw_fpreg_t *); extern int unw_set_fpreg (unw_cursor_t *, int, unw_fpreg_t); extern int unw_get_save_loc (unw_cursor_t *, int, unw_save_loc_t *); extern int unw_is_signal_frame (unw_cursor_t *); +extern int unw_handle_signal_frame (unw_cursor_t *); extern int unw_get_proc_name (unw_cursor_t *, char *, size_t, unw_word_t *); extern const char *unw_strerror (int); diff --git a/src/Makefile.am b/src/Makefile.am index c110e768..2635d8d9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -221,22 +221,24 @@ libunwind_la_SOURCES_x86_common = $(libunwind_la_SOURCES_common) \ # The list of files that go into libunwind: libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ + $(libunwind_la_SOURCES_x86_os_local) \ $(libunwind_la_SOURCES_local) \ $(dwarf_SOURCES_local) \ dwarf/Lfind_proc_info-lsb.c \ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ - x86/Lis_signal_frame.c x86/Lget_proc_info.c x86/Lregs.c \ + x86/Lget_proc_info.c x86/Lregs.c \ x86/Lresume.c x86/Lstep.c x86/getcontext.S # The list of files that go into libunwind-x86: libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ + $(libunwind_la_SOURCES_x86_os) \ $(libunwind_la_SOURCES_generic) \ $(dwarf_SOURCES_generic) \ dwarf/Gfind_proc_info-lsb.c \ x86/Gcreate_addr_space.c x86/Gget_save_loc.c x86/Gglobal.c \ x86/Ginit.c x86/Ginit_local.c x86/Ginit_remote.c \ - x86/Gis_signal_frame.c x86/Gget_proc_info.c x86/Gregs.c \ + x86/Gget_proc_info.c x86/Gregs.c \ x86/Gresume.c x86/Gstep.c # The list of files that go both into libunwind and libunwind-x86_64: @@ -248,23 +250,25 @@ libunwind_la_SOURCES_x86_64_common = $(libunwind_la_SOURCES_common) \ # The list of files that go into libunwind: libunwind_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ + $(libunwind_la_SOURCES_x86_64_os_local) \ $(libunwind_la_SOURCES_local) \ $(dwarf_SOURCES_local) \ dwarf/Lfind_proc_info-lsb.c \ - x86_64/setcontext.S \ + x86_64/setcontext.S \ x86_64/Lcreate_addr_space.c x86_64/Lget_save_loc.c x86_64/Lglobal.c \ x86_64/Linit.c x86_64/Linit_local.c x86_64/Linit_remote.c \ - x86_64/Lis_signal_frame.c x86_64/Lget_proc_info.c x86_64/Lregs.c \ + x86_64/Lget_proc_info.c x86_64/Lregs.c \ x86_64/Lresume.c x86_64/Lstep.c x86_64/getcontext.S # The list of files that go into libunwind-x86_64: libunwind_x86_64_la_SOURCES_x86_64 = $(libunwind_la_SOURCES_x86_64_common) \ + $(libunwind_la_SOURCES_x86_64_os) \ $(libunwind_la_SOURCES_generic) \ $(dwarf_SOURCES_generic) \ dwarf/Gfind_proc_info-lsb.c \ x86_64/Gcreate_addr_space.c x86_64/Gget_save_loc.c x86_64/Gglobal.c \ x86_64/Ginit.c x86_64/Ginit_local.c x86_64/Ginit_remote.c \ - x86_64/Gis_signal_frame.c x86_64/Gget_proc_info.c x86_64/Gregs.c \ + x86_64/Gget_proc_info.c x86_64/Gregs.c \ x86_64/Gresume.c x86_64/Gstep.c # The list of local files that go to Power 64 and 32: @@ -342,8 +346,12 @@ install-exec-hook: endif if OS_LINUX - libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) - libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) + libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) + libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) + libunwind_la_SOURCES_x86_os = x86/Gos-linux.c + libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c + libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c + libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c endif if OS_HPUX diff --git a/src/x86/Gis_signal_frame.c b/src/x86/Gis_signal_frame.c deleted file mode 100644 index 686da02c..00000000 --- a/src/x86/Gis_signal_frame.c +++ /dev/null @@ -1,71 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2002-2003 Hewlett-Packard Co - Contributed by David Mosberger-Tang - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) -{ -#ifdef __linux__ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* Check if EIP points at sigreturn() sequence. On Linux, this is: - - __restore: - 0x58 pop %eax - 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax - 0xcd 0x80 int 0x80 - - without SA_SIGINFO, and - - __restore_rt: - 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax - 0xcd 0x80 int 0x80 - 0x00 - - if SA_SIGINFO is specified. - */ - ip = c->dwarf.ip; - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) - return ret; - ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000) - || (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00)); - Debug (16, "returning %d\n", ret); - return ret; -#else - printf ("%s: implement me\n", __FUNCTION__); -#endif - return -UNW_ENOINFO; -} diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c new file mode 100644 index 00000000..63888a5c --- /dev/null +++ b/src/x86/Gos-linux.c @@ -0,0 +1,137 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2002-2004 Hewlett-Packard Co + Contributed by David Mosberger-Tang + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +PROTECTED int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + as = c->dwarf.as; + a = unw_get_accessors (as); + arg = c->dwarf.as_arg; + + /* Check if EIP points at sigreturn() sequence. On Linux, this is: + + __restore: + 0x58 pop %eax + 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax + 0xcd 0x80 int 0x80 + + without SA_SIGINFO, and + + __restore_rt: + 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax + 0xcd 0x80 int 0x80 + 0x00 + + if SA_SIGINFO is specified. + */ + ip = c->dwarf.ip; + if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 + || (ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) + return ret; + ret = ((w0 == 0x0077b858 && w1 == 0x80cd0000) + || (w0 == 0x0000adb8 && (w1 & 0xffffff) == 0x80cd00)); + Debug (16, "returning %d\n", ret); + return ret; +} + +PROTECTED int +unw_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + /* c->esp points at the arguments to the handler. Without + SA_SIGINFO, the arguments consist of a signal number + followed by a struct sigcontext. With SA_SIGINFO, the + arguments consist a signal number, a siginfo *, and a + ucontext *. */ + unw_word_t sc_addr; + unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4; + unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8; + unw_word_t siginfo_ptr, sigcontext_ptr; + struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc; + + siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0); + sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0); + ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr) + | dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr)); + if (ret < 0) + { + Debug (2, "returning 0\n"); + return 0; + } + if (siginfo_ptr < c->dwarf.cfa + || siginfo_ptr > c->dwarf.cfa + 256 + || sigcontext_ptr < c->dwarf.cfa + || sigcontext_ptr > c->dwarf.cfa + 256) + { + /* Not plausible for SA_SIGINFO signal */ + c->sigcontext_format = X86_SCF_LINUX_SIGFRAME; + c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4; + } + else + { + /* If SA_SIGINFO were not specified, we actually read + various segment pointers instead. We believe that at + least fs and _fsh are always zero for linux, so it is + not just unlikely, but impossible that we would end + up here. */ + c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME; + c->sigcontext_addr = sigcontext_ptr; + sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF; + } + esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); + ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning 0\n"); + return 0; + } + + c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0); + c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0); + c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0); + c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0); + c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0); + c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0); + c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0); + c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC; + c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC; + c->dwarf.loc[ST0] = DWARF_NULL_LOC; + c->dwarf.loc[EIP] = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0); + c->dwarf.loc[ESP] = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); + + return 0; +} diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c index 266f89f4..e4055ae0 100644 --- a/src/x86/Gstep.c +++ b/src/x86/Gstep.c @@ -56,70 +56,14 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); if (unw_is_signal_frame (cursor)) - { - /* XXX This code is Linux-specific! */ - - /* c->esp points at the arguments to the handler. Without - SA_SIGINFO, the arguments consist of a signal number - followed by a struct sigcontext. With SA_SIGINFO, the - arguments consist a signal number, a siginfo *, and a - ucontext *. */ - unw_word_t sc_addr; - unw_word_t siginfo_ptr_addr = c->dwarf.cfa + 4; - unw_word_t sigcontext_ptr_addr = c->dwarf.cfa + 8; - unw_word_t siginfo_ptr, sigcontext_ptr; - struct dwarf_loc esp_loc, siginfo_ptr_loc, sigcontext_ptr_loc; - - siginfo_ptr_loc = DWARF_LOC (siginfo_ptr_addr, 0); - sigcontext_ptr_loc = DWARF_LOC (sigcontext_ptr_addr, 0); - ret = (dwarf_get (&c->dwarf, siginfo_ptr_loc, &siginfo_ptr) - | dwarf_get (&c->dwarf, sigcontext_ptr_loc, &sigcontext_ptr)); + { + ret = unw_handle_signal_frame(cursor); if (ret < 0) { Debug (2, "returning 0\n"); return 0; } - if (siginfo_ptr < c->dwarf.cfa - || siginfo_ptr > c->dwarf.cfa + 256 - || sigcontext_ptr < c->dwarf.cfa - || sigcontext_ptr > c->dwarf.cfa + 256) - { - /* Not plausible for SA_SIGINFO signal */ - c->sigcontext_format = X86_SCF_LINUX_SIGFRAME; - c->sigcontext_addr = sc_addr = c->dwarf.cfa + 4; - } - else - { - /* If SA_SIGINFO were not specified, we actually read - various segment pointers instead. We believe that at - least fs and _fsh are always zero for linux, so it is - not just unlikely, but impossible that we would end - up here. */ - c->sigcontext_format = X86_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = sigcontext_ptr; - sc_addr = sigcontext_ptr + LINUX_UC_MCONTEXT_OFF; - } - esp_loc = DWARF_LOC (sc_addr + LINUX_SC_ESP_OFF, 0); - ebp_loc = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0); - eip_loc = DWARF_LOC (sc_addr + LINUX_SC_EIP_OFF, 0); - ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning 0\n"); - return 0; - } - - c->dwarf.loc[EAX] = DWARF_LOC (sc_addr + LINUX_SC_EAX_OFF, 0); - c->dwarf.loc[ECX] = DWARF_LOC (sc_addr + LINUX_SC_ECX_OFF, 0); - c->dwarf.loc[EDX] = DWARF_LOC (sc_addr + LINUX_SC_EDX_OFF, 0); - c->dwarf.loc[EBX] = DWARF_LOC (sc_addr + LINUX_SC_EBX_OFF, 0); - c->dwarf.loc[EBP] = DWARF_LOC (sc_addr + LINUX_SC_EBP_OFF, 0); - c->dwarf.loc[ESI] = DWARF_LOC (sc_addr + LINUX_SC_ESI_OFF, 0); - c->dwarf.loc[EDI] = DWARF_LOC (sc_addr + LINUX_SC_EDI_OFF, 0); - c->dwarf.loc[EFLAGS] = DWARF_NULL_LOC; - c->dwarf.loc[TRAPNO] = DWARF_NULL_LOC; - c->dwarf.loc[ST0] = DWARF_NULL_LOC; - } + } else { ret = dwarf_get (&c->dwarf, c->dwarf.loc[EBP], &c->dwarf.cfa); @@ -141,9 +85,10 @@ unw_step (unw_cursor_t *cursor) EIP. */ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) c->dwarf.loc[i] = DWARF_NULL_LOC; + + c->dwarf.loc[EBP] = ebp_loc; + c->dwarf.loc[EIP] = eip_loc; } - c->dwarf.loc[EBP] = ebp_loc; - c->dwarf.loc[EIP] = eip_loc; c->dwarf.ret_addr_column = EIP; if (!DWARF_IS_NULL_LOC (c->dwarf.loc[EBP])) diff --git a/src/x86/Lis_signal_frame.c b/src/x86/Los-linux.c similarity index 78% rename from src/x86/Lis_signal_frame.c rename to src/x86/Los-linux.c index b9a7c4f5..3cc18aab 100644 --- a/src/x86/Lis_signal_frame.c +++ b/src/x86/Los-linux.c @@ -1,5 +1,5 @@ #define UNW_LOCAL_ONLY #include #if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" +#include "Gos-linux.c" #endif diff --git a/src/x86_64/Gis_signal_frame.c b/src/x86_64/Gos-linux.c similarity index 53% rename from src/x86_64/Gis_signal_frame.c rename to src/x86_64/Gos-linux.c index 72edf46e..4b99e280 100644 --- a/src/x86_64/Gis_signal_frame.c +++ b/src/x86_64/Gos-linux.c @@ -26,8 +26,8 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" +#include "ucontext_i.h" -#ifdef __linux__ PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) { @@ -57,12 +57,43 @@ unw_is_signal_frame (unw_cursor_t *cursor) return (w0 == 0x0f0000000fc0c748 && w1 == 0x05); } -#else /* __linux__ */ - PROTECTED int -unw_is_signal_frame (unw_cursor_t *cursor) +unw_handle_signal_frame (unw_cursor_t *cursor) { - printf ("%s: implement me\n", __FUNCTION__); - return -UNW_ENOINFO; + struct cursor *c = (struct cursor *) cursor; + int ret; + unw_word_t ucontext = c->dwarf.cfa; + + Debug(1, "signal frame, skip over trampoline\n"); + + c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; + c->sigcontext_addr = c->dwarf.cfa; + + struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); + c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); + c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); + c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); + c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); + c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); + c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); + c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); + c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); + c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); + c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); + c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); + c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); + c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); + c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); + c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); + + return 0; } -#endif /* __linux__ */ diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 2da1c25d..d23be8ea 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -26,7 +26,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" -#include "ucontext_i.h" #include PROTECTED int @@ -79,40 +78,12 @@ unw_step (unw_cursor_t *cursor) if (unw_is_signal_frame (cursor)) { - unw_word_t ucontext = c->dwarf.cfa; - - Debug(1, "signal frame, skip over trampoline\n"); - - c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = c->dwarf.cfa; - - rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - rbp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); - rip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); - - ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); + ret = unw_handle_signal_frame(cursor); if (ret < 0) { - Debug (2, "returning %d\n", ret); - return ret; + Debug (2, "returning 0\n"); + return 0; } - - c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); - c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); - c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); - c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); - c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); - c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); - c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); - c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); - c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); - c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); - c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); - c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); - c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); - c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); - c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); - c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); } else { @@ -153,11 +124,12 @@ unw_step (unw_cursor_t *cursor) /* Mark all registers unsaved */ for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) c->dwarf.loc[i] = DWARF_NULL_LOC; + + c->dwarf.loc[RBP] = rbp_loc; + c->dwarf.loc[RSP] = rsp_loc; + c->dwarf.loc[RIP] = rip_loc; } - c->dwarf.loc[RBP] = rbp_loc; - c->dwarf.loc[RSP] = rsp_loc; - c->dwarf.loc[RIP] = rip_loc; c->dwarf.ret_addr_column = RIP; if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) diff --git a/src/x86_64/Los-linux.c b/src/x86_64/Los-linux.c new file mode 100644 index 00000000..3cc18aab --- /dev/null +++ b/src/x86_64/Los-linux.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gos-linux.c" +#endif diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in index 66078a12..343349f7 100644 --- a/tests/check-namespace.sh.in +++ b/tests/check-namespace.sh.in @@ -83,6 +83,7 @@ check_local_unw_abi () { match _UL${plat}_init_local match _UL${plat}_init_remote match _UL${plat}_is_signal_frame + match _UL${plat}_handle_signal_frame match _UL${plat}_local_addr_space match _UL${plat}_resume match _UL${plat}_set_caching_policy @@ -144,6 +145,7 @@ check_generic_unw_abi () { match _U${plat}_init_local match _U${plat}_init_remote match _U${plat}_is_signal_frame + match _U${plat}_handle_signal_frame match _U${plat}_local_addr_space match _U${plat}_regname match _U${plat}_resume From a40641f326a5360af03e1788ef1c48568761a5be Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 16:25:20 +0300 Subject: [PATCH 092/162] Trim spaces --- src/x86_64/setcontext.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S index 3d0f660a..4bb3e109 100644 --- a/src/x86_64/setcontext.S +++ b/src/x86_64/setcontext.S @@ -40,7 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ */ .global _Ux86_64_setcontext .type _Ux86_64_setcontext, @function - + _Ux86_64_setcontext: #if defined __linux__ @@ -76,7 +76,7 @@ _Ux86_64_setcontext: cmpq $UC_MCONTEXT_FPFMT_XMM,UC_MCONTEXT_FPFORMAT(%rdi) jne 1f fxrstor UC_MCONTEXT_FPSTATE(%rdi) -1: +1: #else #error Port me #endif From ccc0ae665baa67ae3df8595ab7bb0ef8cbc0e5c4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 16:25:36 +0300 Subject: [PATCH 093/162] More move of osdep code. --- src/x86_64/Gos-freebsd.c | 78 +++++++++++++++++++++++++--------------- src/x86_64/Gstep.c | 19 +--------- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index 16a15895..95b9bfc2 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -94,37 +94,57 @@ unw_handle_signal_frame (unw_cursor_t *cursor) int ret; if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) + { ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + Debug(1, "signal frame, skip over trampoline\n"); + + struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + + c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); + c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); + c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); + c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); + c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); + c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); + c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); + c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); + c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); + c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); + c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); + c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); + c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); + c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); + c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); + c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); + c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); + + return 0; + } + else if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL) + { + c->dwarf.loc[RCX] = c->dwarf.loc[R10]; + /* rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); */ + /* rbp_loc = c->dwarf.loc[RBP]; */ + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", + (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), + (unsigned long long) c->dwarf.ip); + if (ret < 0) + { + Debug (2, "returning %d\n", ret); + return ret; + } + c->dwarf.cfa += 8; + return 1; + } else return -UNW_EBADFRAME; - Debug(1, "signal frame, skip over trampoline\n"); - - struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); - c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); - c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); - c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); - c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); - c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); - c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); - c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); - c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); - c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); - c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); - c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); - c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); - c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); - c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); - c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); - - return 0; } diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 2ff2bfe3..d286d445 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -77,24 +77,7 @@ unw_step (unw_cursor_t *cursor) Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); - c->sigcontext_format = unw_is_signal_frame (cursor); - if (c->sigcontext_format == X86_64_SCF_FREEBSD_SYSCALL) { - c->dwarf.loc[RCX] = c->dwarf.loc[R10]; -// rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); -// rbp_loc = c->dwarf.loc[RBP]; - c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); - ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); - Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", - (unsigned long long) DWARF_GET_LOC (c->dwarf.loc[RIP]), - (unsigned long long) c->dwarf.ip); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - c->dwarf.cfa += 8; - return 1; - } else if (c->sigcontext_format != X86_64_SCF_NONE) + if (unw_is_signal_frame (cursor)) { ret = unw_handle_signal_frame(cursor); if (ret < 0) From aeee03dd7429ebfe8ff5a5b16abe646cef52534d Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 16:28:46 +0300 Subject: [PATCH 094/162] Reduce diffs to master --- src/x86/Gstep.c | 9 +-------- src/x86_64/Gstep.c | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c index c1fff616..e4055ae0 100644 --- a/src/x86/Gstep.c +++ b/src/x86/Gstep.c @@ -23,13 +23,6 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - #include "unwind_i.h" #include "offsets.h" @@ -37,7 +30,7 @@ PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret, i, format; + int ret, i; Debug (1, "(cursor=%p, ip=0x%08x)\n", c, (unsigned) c->dwarf.ip); diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index d286d445..d23be8ea 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -27,7 +27,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include -#include PROTECTED int unw_step (unw_cursor_t *cursor) From 79d012348df333f191fcb10789dad12b655f2baa Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 22:22:55 +0300 Subject: [PATCH 095/162] Move get_scratch_loc() to os-specific file. --- src/x86/Gos-freebsd.c | 120 +++++++++++++++++++++ src/x86/Gos-linux.c | 107 +++++++++++++++++++ src/x86/Gregs.c | 236 +----------------------------------------- src/x86/unwind_i.h | 2 + 4 files changed, 230 insertions(+), 235 deletions(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index f901cd76..1658820f 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -135,3 +135,123 @@ unw_handle_signal_frame (unw_cursor_t *cursor) } return 0; } + +HIDDEN dwarf_loc_t +x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) +{ + unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; + int ret, is_fpstate = 0; + + switch (c->sigcontext_format) + { + case X86_SCF_NONE: + return DWARF_REG_LOC (&c->dwarf, reg); + + case X86_SCF_FREEBSD_SIGFRAME: + addr += FREEBSD_UC_MCONTEXT_OFF; + break; + + case X86_SCF_FREEBSD_SIGFRAME4: + abort(); + break; + + case X86_SCF_FREEBSD_OSIGFRAME: + /* XXXKIB */ + abort(); + break; + + case X86_SCF_FREEBSD_SYSCALL: + /* XXXKIB */ + abort(); + break; + + default: + /* XXXKIB */ + abort(); + break; + } + + switch (reg) + { + case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; + case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break; + case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break; + case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; + case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break; + case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break; + case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break; + case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break; + case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break; + case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break; + case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break; + case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break; + case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break; + case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break; + case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break; + case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break; + case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; + + /* XXXKIB fix */ + case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; + case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; + case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; + case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; + case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; + case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; + case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; + case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; + + /* stacked fp registers */ + case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: + case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: + is_fpstate = 1; + off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); + break; + + /* SSE fp registers */ + case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: + case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: + case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: + case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: + case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: + case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: + case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: + case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: + is_fpstate = 1; + off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); + break; + case UNW_X86_XMM0: + case UNW_X86_XMM1: + case UNW_X86_XMM2: + case UNW_X86_XMM3: + case UNW_X86_XMM4: + case UNW_X86_XMM5: + case UNW_X86_XMM6: + case UNW_X86_XMM7: + is_fpstate = 1; + off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); + break; + + case UNW_X86_FOP: + case UNW_X86_TSS: + case UNW_X86_LDT: + default: + return DWARF_REG_LOC (&c->dwarf, reg); + } + + if (is_fpstate) + { + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, + addr + LINUX_SC_FPSTATE_OFF), + &fpstate_addr)) < 0) + return DWARF_NULL_LOC; + + if (!fpstate_addr) + return DWARF_NULL_LOC; + + return DWARF_MEM_LOC (c, fpstate_addr + off); + } + else + return DWARF_MEM_LOC (c, addr + off); +} diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 63888a5c..529c6270 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -135,3 +135,110 @@ unw_handle_signal_frame (unw_cursor_t *cursor) return 0; } + +HIDDEN dwarf_loc_t +x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) +{ + unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; + int ret, is_fpstate = 0; + + switch (c->sigcontext_format) + { + case X86_SCF_NONE: + return DWARF_REG_LOC (&c->dwarf, reg); + + case X86_SCF_LINUX_SIGFRAME: + break; + + case X86_SCF_LINUX_RT_SIGFRAME: + addr += LINUX_UC_MCONTEXT_OFF; + break; + } + + switch (reg) + { + case UNW_X86_GS: off = LINUX_SC_GS_OFF; break; + case UNW_X86_FS: off = LINUX_SC_FS_OFF; break; + case UNW_X86_ES: off = LINUX_SC_ES_OFF; break; + case UNW_X86_DS: off = LINUX_SC_DS_OFF; break; + case UNW_X86_EDI: off = LINUX_SC_EDI_OFF; break; + case UNW_X86_ESI: off = LINUX_SC_ESI_OFF; break; + case UNW_X86_EBP: off = LINUX_SC_EBP_OFF; break; + case UNW_X86_ESP: off = LINUX_SC_ESP_OFF; break; + case UNW_X86_EBX: off = LINUX_SC_EBX_OFF; break; + case UNW_X86_EDX: off = LINUX_SC_EDX_OFF; break; + case UNW_X86_ECX: off = LINUX_SC_ECX_OFF; break; + case UNW_X86_EAX: off = LINUX_SC_EAX_OFF; break; + case UNW_X86_TRAPNO: off = LINUX_SC_TRAPNO_OFF; break; + case UNW_X86_EIP: off = LINUX_SC_EIP_OFF; break; + case UNW_X86_CS: off = LINUX_SC_CS_OFF; break; + case UNW_X86_EFLAGS: off = LINUX_SC_EFLAGS_OFF; break; + case UNW_X86_SS: off = LINUX_SC_SS_OFF; break; + + /* The following is probably not correct for all possible cases. + Somebody who understands this better should review this for + correctness. */ + + case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; + case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; + case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; + case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; + case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; + case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; + case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; + case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; + + /* stacked fp registers */ + case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: + case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: + is_fpstate = 1; + off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); + break; + + /* SSE fp registers */ + case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: + case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: + case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: + case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: + case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: + case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: + case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: + case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: + is_fpstate = 1; + off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); + break; + case UNW_X86_XMM0: + case UNW_X86_XMM1: + case UNW_X86_XMM2: + case UNW_X86_XMM3: + case UNW_X86_XMM4: + case UNW_X86_XMM5: + case UNW_X86_XMM6: + case UNW_X86_XMM7: + is_fpstate = 1; + off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); + break; + + case UNW_X86_FOP: + case UNW_X86_TSS: + case UNW_X86_LDT: + default: + return DWARF_REG_LOC (&c->dwarf, reg); + } + + if (is_fpstate) + { + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, + addr + LINUX_SC_FPSTATE_OFF), + &fpstate_addr)) < 0) + return DWARF_NULL_LOC; + + if (!fpstate_addr) + return DWARF_NULL_LOC; + + return DWARF_MEM_LOC (c, fpstate_addr + off); + } + else + return DWARF_MEM_LOC (c, addr + off); +} diff --git a/src/x86/Gregs.c b/src/x86/Gregs.c index 9f251096..05bc1a30 100644 --- a/src/x86/Gregs.c +++ b/src/x86/Gregs.c @@ -26,245 +26,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "offsets.h" #include "unwind_i.h" -#if defined __linux__ -static inline dwarf_loc_t -get_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; - int ret, is_fpstate = 0; - - switch (c->sigcontext_format) - { - case X86_SCF_NONE: - return DWARF_REG_LOC (&c->dwarf, reg); - - case X86_SCF_LINUX_SIGFRAME: - break; - - case X86_SCF_LINUX_RT_SIGFRAME: - addr += LINUX_UC_MCONTEXT_OFF; - break; - } - - switch (reg) - { - case UNW_X86_GS: off = LINUX_SC_GS_OFF; break; - case UNW_X86_FS: off = LINUX_SC_FS_OFF; break; - case UNW_X86_ES: off = LINUX_SC_ES_OFF; break; - case UNW_X86_DS: off = LINUX_SC_DS_OFF; break; - case UNW_X86_EDI: off = LINUX_SC_EDI_OFF; break; - case UNW_X86_ESI: off = LINUX_SC_ESI_OFF; break; - case UNW_X86_EBP: off = LINUX_SC_EBP_OFF; break; - case UNW_X86_ESP: off = LINUX_SC_ESP_OFF; break; - case UNW_X86_EBX: off = LINUX_SC_EBX_OFF; break; - case UNW_X86_EDX: off = LINUX_SC_EDX_OFF; break; - case UNW_X86_ECX: off = LINUX_SC_ECX_OFF; break; - case UNW_X86_EAX: off = LINUX_SC_EAX_OFF; break; - case UNW_X86_TRAPNO: off = LINUX_SC_TRAPNO_OFF; break; - case UNW_X86_EIP: off = LINUX_SC_EIP_OFF; break; - case UNW_X86_CS: off = LINUX_SC_CS_OFF; break; - case UNW_X86_EFLAGS: off = LINUX_SC_EFLAGS_OFF; break; - case UNW_X86_SS: off = LINUX_SC_SS_OFF; break; - - /* The following is probably not correct for all possible cases. - Somebody who understands this better should review this for - correctness. */ - - case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; - case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; - case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; - case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; - case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; - case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; - case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; - case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; - - /* stacked fp registers */ - case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: - case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: - is_fpstate = 1; - off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); - break; - - /* SSE fp registers */ - case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: - case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: - case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: - case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: - case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: - case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: - case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: - case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: - is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); - break; - case UNW_X86_XMM0: - case UNW_X86_XMM1: - case UNW_X86_XMM2: - case UNW_X86_XMM3: - case UNW_X86_XMM4: - case UNW_X86_XMM5: - case UNW_X86_XMM6: - case UNW_X86_XMM7: - is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); - break; - - case UNW_X86_FOP: - case UNW_X86_TSS: - case UNW_X86_LDT: - default: - return DWARF_REG_LOC (&c->dwarf, reg); - } - - if (is_fpstate) - { - if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, - addr + LINUX_SC_FPSTATE_OFF), - &fpstate_addr)) < 0) - return DWARF_NULL_LOC; - - if (!fpstate_addr) - return DWARF_NULL_LOC; - - return DWARF_MEM_LOC (c, fpstate_addr + off); - } - else - return DWARF_MEM_LOC (c, addr + off); -} -#elif defined __FreeBSD__ -static inline dwarf_loc_t -get_scratch_loc (struct cursor *c, unw_regnum_t reg) -{ - unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; - int ret, is_fpstate = 0; - - switch (c->sigcontext_format) - { - case X86_SCF_NONE: - return DWARF_REG_LOC (&c->dwarf, reg); - - case X86_SCF_FREEBSD_SIGFRAME: - addr += FREEBSD_UC_MCONTEXT_OFF; - break; - - case X86_SCF_FREEBSD_SIGFRAME4: - abort(); - break; - - case X86_SCF_FREEBSD_OSIGFRAME: - /* XXXKIB */ - abort(); - break; - - case X86_SCF_FREEBSD_SYSCALL: - /* XXXKIB */ - abort(); - break; - - default: - /* XXXKIB */ - abort(); - break; - } - - switch (reg) - { - case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; - case UNW_X86_FS: off = FREEBSD_UC_MCONTEXT_FS_OFF; break; - case UNW_X86_ES: off = FREEBSD_UC_MCONTEXT_ES_OFF; break; - case UNW_X86_DS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; - case UNW_X86_EDI: off = FREEBSD_UC_MCONTEXT_EDI_OFF; break; - case UNW_X86_ESI: off = FREEBSD_UC_MCONTEXT_ESI_OFF; break; - case UNW_X86_EBP: off = FREEBSD_UC_MCONTEXT_EBP_OFF; break; - case UNW_X86_ESP: off = FREEBSD_UC_MCONTEXT_ESP_OFF; break; - case UNW_X86_EBX: off = FREEBSD_UC_MCONTEXT_EBX_OFF; break; - case UNW_X86_EDX: off = FREEBSD_UC_MCONTEXT_EDX_OFF; break; - case UNW_X86_ECX: off = FREEBSD_UC_MCONTEXT_ECX_OFF; break; - case UNW_X86_EAX: off = FREEBSD_UC_MCONTEXT_EAX_OFF; break; - case UNW_X86_TRAPNO: off = FREEBSD_UC_MCONTEXT_TRAPNO_OFF; break; - case UNW_X86_EIP: off = FREEBSD_UC_MCONTEXT_EIP_OFF; break; - case UNW_X86_CS: off = FREEBSD_UC_MCONTEXT_CS_OFF; break; - case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break; - case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; - - /* The following is probably not correct for all possible cases. - Somebody who understands this better should review this for - correctness. */ - - case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; - case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; - case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; - case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; - case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; - case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; - case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; - case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; - - /* stacked fp registers */ - case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: - case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: - is_fpstate = 1; - off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); - break; - - /* SSE fp registers */ - case UNW_X86_XMM0_lo: case UNW_X86_XMM0_hi: - case UNW_X86_XMM1_lo: case UNW_X86_XMM1_hi: - case UNW_X86_XMM2_lo: case UNW_X86_XMM2_hi: - case UNW_X86_XMM3_lo: case UNW_X86_XMM3_hi: - case UNW_X86_XMM4_lo: case UNW_X86_XMM4_hi: - case UNW_X86_XMM5_lo: case UNW_X86_XMM5_hi: - case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: - case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: - is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); - break; - case UNW_X86_XMM0: - case UNW_X86_XMM1: - case UNW_X86_XMM2: - case UNW_X86_XMM3: - case UNW_X86_XMM4: - case UNW_X86_XMM5: - case UNW_X86_XMM6: - case UNW_X86_XMM7: - is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); - break; - - case UNW_X86_FOP: - case UNW_X86_TSS: - case UNW_X86_LDT: - default: - return DWARF_REG_LOC (&c->dwarf, reg); - } - - if (is_fpstate) - { - if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, - addr + LINUX_SC_FPSTATE_OFF), - &fpstate_addr)) < 0) - return DWARF_NULL_LOC; - - if (!fpstate_addr) - return DWARF_NULL_LOC; - - return DWARF_MEM_LOC (c, fpstate_addr + off); - } - else - return DWARF_MEM_LOC (c, addr + off); -} -#else -#error Port me -#endif - HIDDEN dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg) { if (c->sigcontext_addr) - return get_scratch_loc (c, reg); + return x86_get_scratch_loc (c, reg); else return DWARF_REG_LOC (&c->dwarf, reg); } diff --git a/src/x86/unwind_i.h b/src/x86/unwind_i.h index 63477191..1fe39008 100644 --- a/src/x86/unwind_i.h +++ b/src/x86/unwind_i.h @@ -51,10 +51,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define x86_local_resume UNW_OBJ(local_resume) #define x86_local_addr_space_init UNW_OBJ(local_addr_space_init) #define x86_scratch_loc UNW_OBJ(scratch_loc) +#define x86_get_scratch_loc UNW_OBJ(get_scratch_loc) extern void x86_local_addr_space_init (void); extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg); extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg); +extern dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg); #endif /* unwind_i_h */ From 0dbeeeb08dc9a7e46281954e9225a84d4629a3db Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 22:42:23 +0300 Subject: [PATCH 096/162] Move uc_addr to os-specific file --- src/x86/Ginit.c | 59 ++-------------------------------------- src/x86/Gos-freebsd.c | 33 ++++++++++++++++++++++ src/x86/Gos-linux.c | 34 +++++++++++++++++++++++ src/x86/unwind_i.h | 2 ++ src/x86_64/Ginit.c | 57 ++------------------------------------ src/x86_64/Gos-freebsd.c | 33 ++++++++++++++++++++++ src/x86_64/Gos-linux.c | 33 ++++++++++++++++++++++ src/x86_64/unwind_i.h | 3 ++ 8 files changed, 144 insertions(+), 110 deletions(-) diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 00a5b075..949bf28f 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -40,65 +40,12 @@ static struct unw_addr_space local_addr_space; PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - switch (reg) - { -#if defined __linux__ - case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break; - case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break; - case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break; - case UNW_X86_DS: addr = &uc->uc_mcontext.gregs[REG_DS]; break; - case UNW_X86_EAX: addr = &uc->uc_mcontext.gregs[REG_EAX]; break; - case UNW_X86_EBX: addr = &uc->uc_mcontext.gregs[REG_EBX]; break; - case UNW_X86_ECX: addr = &uc->uc_mcontext.gregs[REG_ECX]; break; - case UNW_X86_EDX: addr = &uc->uc_mcontext.gregs[REG_EDX]; break; - case UNW_X86_ESI: addr = &uc->uc_mcontext.gregs[REG_ESI]; break; - case UNW_X86_EDI: addr = &uc->uc_mcontext.gregs[REG_EDI]; break; - case UNW_X86_EBP: addr = &uc->uc_mcontext.gregs[REG_EBP]; break; - case UNW_X86_EIP: addr = &uc->uc_mcontext.gregs[REG_EIP]; break; - case UNW_X86_ESP: addr = &uc->uc_mcontext.gregs[REG_ESP]; break; - case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.gregs[REG_TRAPNO]; break; - case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break; - case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break; - case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break; -#elif defined __FreeBSD__ - case UNW_X86_GS: addr = &uc->uc_mcontext.mc_gs; break; - case UNW_X86_FS: addr = &uc->uc_mcontext.mc_fs; break; - case UNW_X86_ES: addr = &uc->uc_mcontext.mc_es; break; - case UNW_X86_DS: addr = &uc->uc_mcontext.mc_ds; break; - case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break; - case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break; - case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break; - case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break; - case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break; - case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break; - case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break; - case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break; - case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break; - case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.mc_trapno; break; - case UNW_X86_CS: addr = &uc->uc_mcontext.mc_cs; break; - case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.mc_eflags; break; - case UNW_X86_SS: addr = &uc->uc_mcontext.mc_ss; break; -#else -#error Port me -#endif - - default: - addr = NULL; - } - return addr; -} - # ifdef UNW_LOCAL_ONLY HIDDEN void * tdep_uc_addr (ucontext_t *uc, int reg) { - return uc_addr (uc, reg); + return x86_r_uc_addr (uc, reg); } # endif /* UNW_LOCAL_ONLY */ @@ -199,7 +146,7 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, if (unw_is_fpreg (reg)) goto badreg; - if (!(addr = uc_addr (uc, reg))) + if (!(addr = x86_r_uc_addr (uc, reg))) goto badreg; if (write) @@ -229,7 +176,7 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, if (!unw_is_fpreg (reg)) goto badreg; - if (!(addr = uc_addr (uc, reg))) + if (!(addr = x86_r_uc_addr (uc, reg))) goto badreg; if (write) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 1658820f..f3f04bcf 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -255,3 +255,36 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) else return DWARF_MEM_LOC (c, addr + off); } + +#ifndef UNW_REMOTE_ONLY +HIDDEN void * +x86_r_uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + switch (reg) + { + case UNW_X86_GS: addr = &uc->uc_mcontext.mc_gs; break; + case UNW_X86_FS: addr = &uc->uc_mcontext.mc_fs; break; + case UNW_X86_ES: addr = &uc->uc_mcontext.mc_es; break; + case UNW_X86_DS: addr = &uc->uc_mcontext.mc_ds; break; + case UNW_X86_EAX: addr = &uc->uc_mcontext.mc_eax; break; + case UNW_X86_EBX: addr = &uc->uc_mcontext.mc_ebx; break; + case UNW_X86_ECX: addr = &uc->uc_mcontext.mc_ecx; break; + case UNW_X86_EDX: addr = &uc->uc_mcontext.mc_edx; break; + case UNW_X86_ESI: addr = &uc->uc_mcontext.mc_esi; break; + case UNW_X86_EDI: addr = &uc->uc_mcontext.mc_edi; break; + case UNW_X86_EBP: addr = &uc->uc_mcontext.mc_ebp; break; + case UNW_X86_EIP: addr = &uc->uc_mcontext.mc_eip; break; + case UNW_X86_ESP: addr = &uc->uc_mcontext.mc_esp; break; + case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.mc_trapno; break; + case UNW_X86_CS: addr = &uc->uc_mcontext.mc_cs; break; + case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.mc_eflags; break; + case UNW_X86_SS: addr = &uc->uc_mcontext.mc_ss; break; + + default: + addr = NULL; + } + return addr; +} +#endif diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 529c6270..99f585ea 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -242,3 +242,37 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) else return DWARF_MEM_LOC (c, addr + off); } + +#ifndef UNW_REMOTE_ONLY + +HIDDEN void * +x86_r_uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + switch (reg) + { + case UNW_X86_GS: addr = &uc->uc_mcontext.gregs[REG_GS]; break; + case UNW_X86_FS: addr = &uc->uc_mcontext.gregs[REG_FS]; break; + case UNW_X86_ES: addr = &uc->uc_mcontext.gregs[REG_ES]; break; + case UNW_X86_DS: addr = &uc->uc_mcontext.gregs[REG_DS]; break; + case UNW_X86_EAX: addr = &uc->uc_mcontext.gregs[REG_EAX]; break; + case UNW_X86_EBX: addr = &uc->uc_mcontext.gregs[REG_EBX]; break; + case UNW_X86_ECX: addr = &uc->uc_mcontext.gregs[REG_ECX]; break; + case UNW_X86_EDX: addr = &uc->uc_mcontext.gregs[REG_EDX]; break; + case UNW_X86_ESI: addr = &uc->uc_mcontext.gregs[REG_ESI]; break; + case UNW_X86_EDI: addr = &uc->uc_mcontext.gregs[REG_EDI]; break; + case UNW_X86_EBP: addr = &uc->uc_mcontext.gregs[REG_EBP]; break; + case UNW_X86_EIP: addr = &uc->uc_mcontext.gregs[REG_EIP]; break; + case UNW_X86_ESP: addr = &uc->uc_mcontext.gregs[REG_ESP]; break; + case UNW_X86_TRAPNO: addr = &uc->uc_mcontext.gregs[REG_TRAPNO]; break; + case UNW_X86_CS: addr = &uc->uc_mcontext.gregs[REG_CS]; break; + case UNW_X86_EFLAGS: addr = &uc->uc_mcontext.gregs[REG_EFL]; break; + case UNW_X86_SS: addr = &uc->uc_mcontext.gregs[REG_SS]; break; + + default: + addr = NULL; + } + return addr; +} +#endif diff --git a/src/x86/unwind_i.h b/src/x86/unwind_i.h index 1fe39008..6d1d5e9f 100644 --- a/src/x86/unwind_i.h +++ b/src/x86/unwind_i.h @@ -52,11 +52,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define x86_local_addr_space_init UNW_OBJ(local_addr_space_init) #define x86_scratch_loc UNW_OBJ(scratch_loc) #define x86_get_scratch_loc UNW_OBJ(get_scratch_loc) +#define x86_r_uc_addr UNW_OBJ(r_uc_addr) extern void x86_local_addr_space_init (void); extern int x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg); extern dwarf_loc_t x86_scratch_loc (struct cursor *c, unw_regnum_t reg); extern dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg); +extern void *x86_r_uc_addr (ucontext_t *uc, int reg); #endif /* unwind_i_h */ diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index b6501009..f222bf54 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -43,63 +43,12 @@ static struct unw_addr_space local_addr_space; PROTECTED unw_addr_space_t unw_local_addr_space = &local_addr_space; -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - void *addr; - - switch (reg) - { -#ifdef __FreeBSD__ - case UNW_X86_64_R8: addr = &uc->uc_mcontext.mc_r8; break; - case UNW_X86_64_R9: addr = &uc->uc_mcontext.mc_r9; break; - case UNW_X86_64_R10: addr = &uc->uc_mcontext.mc_r10; break; - case UNW_X86_64_R11: addr = &uc->uc_mcontext.mc_r11; break; - case UNW_X86_64_R12: addr = &uc->uc_mcontext.mc_r12; break; - case UNW_X86_64_R13: addr = &uc->uc_mcontext.mc_r13; break; - case UNW_X86_64_R14: addr = &uc->uc_mcontext.mc_r14; break; - case UNW_X86_64_R15: addr = &uc->uc_mcontext.mc_r15; break; - case UNW_X86_64_RDI: addr = &uc->uc_mcontext.mc_rdi; break; - case UNW_X86_64_RSI: addr = &uc->uc_mcontext.mc_rsi; break; - case UNW_X86_64_RBP: addr = &uc->uc_mcontext.mc_rbp; break; - case UNW_X86_64_RBX: addr = &uc->uc_mcontext.mc_rbx; break; - case UNW_X86_64_RDX: addr = &uc->uc_mcontext.mc_rdx; break; - case UNW_X86_64_RAX: addr = &uc->uc_mcontext.mc_rax; break; - case UNW_X86_64_RCX: addr = &uc->uc_mcontext.mc_rcx; break; - case UNW_X86_64_RSP: addr = &uc->uc_mcontext.mc_rsp; break; - case UNW_X86_64_RIP: addr = &uc->uc_mcontext.mc_rip; break; -#else - case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break; - case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break; - case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break; - case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break; - case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break; - case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break; - case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break; - case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break; - case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break; - case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break; - case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break; - case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break; - case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break; - case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break; - case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break; - case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break; - case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break; -#endif - - default: - addr = NULL; - } - return addr; -} - # ifdef UNW_LOCAL_ONLY HIDDEN void * tdep_uc_addr (ucontext_t *uc, int reg) { - return uc_addr (uc, reg); + return x86_64_r_uc_addr (uc, reg); } # endif /* UNW_LOCAL_ONLY */ @@ -200,7 +149,7 @@ access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, if (unw_is_fpreg (reg)) goto badreg; - if (!(addr = uc_addr (uc, reg))) + if (!(addr = x86_64_r_uc_addr (uc, reg))) goto badreg; if (write) @@ -230,7 +179,7 @@ access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, if (!unw_is_fpreg (reg)) goto badreg; - if (!(addr = uc_addr (uc, reg))) + if (!(addr = x86_64_r_uc_addr (uc, reg))) goto badreg; if (write) diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index 95b9bfc2..a2b13bb7 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -148,3 +148,36 @@ unw_handle_signal_frame (unw_cursor_t *cursor) return -UNW_EBADFRAME; } + +#ifndef UNW_REMOTE_ONLY +HIDDEN void * +x86_64_r_uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + switch (reg) + { + case UNW_X86_64_R8: addr = &uc->uc_mcontext.mc_r8; break; + case UNW_X86_64_R9: addr = &uc->uc_mcontext.mc_r9; break; + case UNW_X86_64_R10: addr = &uc->uc_mcontext.mc_r10; break; + case UNW_X86_64_R11: addr = &uc->uc_mcontext.mc_r11; break; + case UNW_X86_64_R12: addr = &uc->uc_mcontext.mc_r12; break; + case UNW_X86_64_R13: addr = &uc->uc_mcontext.mc_r13; break; + case UNW_X86_64_R14: addr = &uc->uc_mcontext.mc_r14; break; + case UNW_X86_64_R15: addr = &uc->uc_mcontext.mc_r15; break; + case UNW_X86_64_RDI: addr = &uc->uc_mcontext.mc_rdi; break; + case UNW_X86_64_RSI: addr = &uc->uc_mcontext.mc_rsi; break; + case UNW_X86_64_RBP: addr = &uc->uc_mcontext.mc_rbp; break; + case UNW_X86_64_RBX: addr = &uc->uc_mcontext.mc_rbx; break; + case UNW_X86_64_RDX: addr = &uc->uc_mcontext.mc_rdx; break; + case UNW_X86_64_RAX: addr = &uc->uc_mcontext.mc_rax; break; + case UNW_X86_64_RCX: addr = &uc->uc_mcontext.mc_rcx; break; + case UNW_X86_64_RSP: addr = &uc->uc_mcontext.mc_rsp; break; + case UNW_X86_64_RIP: addr = &uc->uc_mcontext.mc_rip; break; + + default: + addr = NULL; + } + return addr; +} +#endif diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index 4b99e280..aa13e031 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -97,3 +97,36 @@ unw_handle_signal_frame (unw_cursor_t *cursor) return 0; } + +#ifndef UNW_REMOTE_ONLY +static inline void * +x86_64_r_uc_addr (ucontext_t *uc, int reg) +{ + void *addr; + + switch (reg) + { + case UNW_X86_64_R8: addr = &uc->uc_mcontext.gregs[REG_R8]; break; + case UNW_X86_64_R9: addr = &uc->uc_mcontext.gregs[REG_R9]; break; + case UNW_X86_64_R10: addr = &uc->uc_mcontext.gregs[REG_R10]; break; + case UNW_X86_64_R11: addr = &uc->uc_mcontext.gregs[REG_R11]; break; + case UNW_X86_64_R12: addr = &uc->uc_mcontext.gregs[REG_R12]; break; + case UNW_X86_64_R13: addr = &uc->uc_mcontext.gregs[REG_R13]; break; + case UNW_X86_64_R14: addr = &uc->uc_mcontext.gregs[REG_R14]; break; + case UNW_X86_64_R15: addr = &uc->uc_mcontext.gregs[REG_R15]; break; + case UNW_X86_64_RDI: addr = &uc->uc_mcontext.gregs[REG_RDI]; break; + case UNW_X86_64_RSI: addr = &uc->uc_mcontext.gregs[REG_RSI]; break; + case UNW_X86_64_RBP: addr = &uc->uc_mcontext.gregs[REG_RBP]; break; + case UNW_X86_64_RBX: addr = &uc->uc_mcontext.gregs[REG_RBX]; break; + case UNW_X86_64_RDX: addr = &uc->uc_mcontext.gregs[REG_RDX]; break; + case UNW_X86_64_RAX: addr = &uc->uc_mcontext.gregs[REG_RAX]; break; + case UNW_X86_64_RCX: addr = &uc->uc_mcontext.gregs[REG_RCX]; break; + case UNW_X86_64_RSP: addr = &uc->uc_mcontext.gregs[REG_RSP]; break; + case UNW_X86_64_RIP: addr = &uc->uc_mcontext.gregs[REG_RIP]; break; + + default: + addr = NULL; + } + return addr; +} +#endif diff --git a/src/x86_64/unwind_i.h b/src/x86_64/unwind_i.h index bc828006..f45f5ead 100644 --- a/src/x86_64/unwind_i.h +++ b/src/x86_64/unwind_i.h @@ -62,6 +62,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if 0 #define x86_64_scratch_loc UNW_OBJ(scratch_loc) #endif +#define x86_64_r_uc_addr UNW_OBJ(r_uc_addr) extern void x86_64_local_addr_space_init (void); extern int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, @@ -72,4 +73,6 @@ extern int setcontext (const ucontext_t *ucp); extern dwarf_loc_t x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg); #endif +extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg); + #endif /* unwind_i_h */ From 979af4502fe19b0d98459633731d004a4a010a0e Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 23:00:27 +0300 Subject: [PATCH 097/162] Move local_resume to os-specific file. --- src/x86/Gos-freebsd.c | 29 ++++++++++++++++++++ src/x86/Gos-linux.c | 27 +++++++++++++++++++ src/x86/Gresume.c | 58 ---------------------------------------- src/x86_64/Gos-freebsd.c | 11 ++++++++ src/x86_64/Gos-linux.c | 19 +++++++++++++ src/x86_64/Gresume.c | 30 +-------------------- src/x86_64/unwind_i.h | 2 ++ 7 files changed, 89 insertions(+), 87 deletions(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index f3f04bcf..0dd3b437 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -287,4 +287,33 @@ x86_r_uc_addr (ucontext_t *uc, int reg) } return addr; } + +HIDDEN int +x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->uc; + + /* Ensure c->pi is up-to-date. On x86, it's relatively common to be + missing DWARF unwind info. We don't want to fail in that case, + because the frame-chain still would let us do a backtrace at + least. */ + dwarf_make_proc_info (&c->dwarf); + + if (c->sigcontext_format == X86_SCF_NONE) { + Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); + setcontext (uc); + } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); + sigreturn((const char *)sc + FREEBSD_UC_MCONTEXT_OFF); + } else { + Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", + c->sigcontext_format); + abort(); + } + return -UNW_EINVAL; +} + #endif diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 99f585ea..b31f96a1 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -275,4 +275,31 @@ x86_r_uc_addr (ucontext_t *uc, int reg) } return addr; } + +HIDDEN int +x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->uc; + + /* Ensure c->pi is up-to-date. On x86, it's relatively common to be + missing DWARF unwind info. We don't want to fail in that case, + because the frame-chain still would let us do a backtrace at + least. */ + dwarf_make_proc_info (&c->dwarf); + + if (unlikely (c->sigcontext_format != X86_SCF_NONE)) + { + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); + sigreturn (sc); + } + else + { + Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); + setcontext (uc); + } + return -UNW_EINVAL; +} #endif diff --git a/src/x86/Gresume.c b/src/x86/Gresume.c index 40ab82b2..c39c5884 100644 --- a/src/x86/Gresume.c +++ b/src/x86/Gresume.c @@ -28,64 +28,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include "offsets.h" -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ -#if defined(__linux) - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->uc; - - /* Ensure c->pi is up-to-date. On x86, it's relatively common to be - missing DWARF unwind info. We don't want to fail in that case, - because the frame-chain still would let us do a backtrace at - least. */ - dwarf_make_proc_info (&c->dwarf); - - if (unlikely (c->sigcontext_format != X86_SCF_NONE)) - { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn (sc); - } - else - { - Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); - setcontext (uc); - } -#elif defined __FreeBSD__ - struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->uc; - - /* Ensure c->pi is up-to-date. On x86, it's relatively common to be - missing DWARF unwind info. We don't want to fail in that case, - because the frame-chain still would let us do a backtrace at - least. */ - dwarf_make_proc_info (&c->dwarf); - - if (c->sigcontext_format == X86_SCF_NONE) { - Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); - setcontext (uc); - } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn((const char *)sc + FREEBSD_UC_MCONTEXT_OFF); - } else { - Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", - c->sigcontext_format); - abort(); - } -#else -# warning Implement me! -#endif - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - /* This routine is responsible for copying the register values in cursor C and establishing them as the current machine state. */ diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index a2b13bb7..91d60a18 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -180,4 +180,15 @@ x86_64_r_uc_addr (ucontext_t *uc, int reg) } return addr; } + +HIDDEN NORETURN void +x86_64_sigreturn (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + ucontext_t *uc = c->uc; + + Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", + (unsigned long long) c->dwarf.ip, uc); + sigreturn(uc); +} #endif diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index aa13e031..b37ea4c5 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -28,6 +28,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include "ucontext_i.h" +#include + PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) { @@ -129,4 +131,21 @@ x86_64_r_uc_addr (ucontext_t *uc, int reg) } return addr; } + +/* sigreturn() is a no-op on x86_64 glibc. */ +HIDDEN NORETURN void +x86_64_sigreturn (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; + + Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", + (unsigned long long) c->dwarf.ip, sc); + __asm__ __volatile__ ("mov %0, %%rsp;" + "mov %1, %%rax;" + "syscall" + :: "r"(sc), "i"(SYS_rt_sigreturn) + : "memory"); +} + #endif diff --git a/src/x86_64/Gresume.c b/src/x86_64/Gresume.c index 13c8059a..d5239fc1 100644 --- a/src/x86_64/Gresume.c +++ b/src/x86_64/Gresume.c @@ -32,22 +32,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UNW_REMOTE_ONLY -#include - -#if defined __linux -/* sigreturn() is a no-op on x86_64 glibc. */ - -static NORETURN inline long -my_rt_sigreturn (void *new_sp) -{ - __asm__ __volatile__ ("mov %0, %%rsp;" - "mov %1, %%rax;" - "syscall" - :: "r"(new_sp), "i"(SYS_rt_sigreturn) - : "memory"); -} -#endif - HIDDEN inline int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) { @@ -62,19 +46,7 @@ x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) if (unlikely (c->sigcontext_format != X86_64_SCF_NONE)) { -#if defined __linux__ - struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; - - Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", - (unsigned long long) c->dwarf.ip, sc); - my_rt_sigreturn (sc); -#elif defined __FreeBSD__ - Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", - (unsigned long long) c->dwarf.ip, uc); - sigreturn(uc); -#else -#error Port me -#endif + x86_64_sigreturn(cursor); abort(); } else diff --git a/src/x86_64/unwind_i.h b/src/x86_64/unwind_i.h index f45f5ead..699a6b38 100644 --- a/src/x86_64/unwind_i.h +++ b/src/x86_64/unwind_i.h @@ -63,6 +63,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define x86_64_scratch_loc UNW_OBJ(scratch_loc) #endif #define x86_64_r_uc_addr UNW_OBJ(r_uc_addr) +#define x86_64_sigreturn UNW_OBJ(sigreturn) extern void x86_64_local_addr_space_init (void); extern int x86_64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, @@ -74,5 +75,6 @@ extern dwarf_loc_t x86_64_scratch_loc (struct cursor *c, unw_regnum_t reg); #endif extern void *x86_64_r_uc_addr (ucontext_t *uc, int reg); +extern NORETURN void x86_64_sigreturn (unw_cursor_t *cursor); #endif /* unwind_i_h */ From ad6b2f94b9cd9515f8bf1a09ea9160afb80706e3 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 5 Apr 2010 23:19:03 +0300 Subject: [PATCH 098/162] Fix tests for PTRACE_* and PT_*. Submitted by: Arun Sharma --- configure.in | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/configure.in b/configure.in index 64dd93a9..81b49b02 100644 --- a/configure.in +++ b/configure.in @@ -61,21 +61,17 @@ AC_CHECK_TYPES([sighandler_t], [], [], #endif ]) -AC_DEFUN([AC_CHECK_PTRACE_DECL], -[for pxxx in $1; do -AC_CHECK_DECLS($pxxx, [], [], +AC_CHECK_DECLS([PTRACE_POKEUSER, PTRACE_POKEDATA, PTRACE_CONT, +PTRACE_TRACEME, PTRACE_CONT, PTRACE_SIGNLESTEP, +PTRACE_SYSCALL, PT_IO, PT_GETREGS, +PT_GETFPREGS, PT_CONTINUE, PT_TRACE_ME, +PT_STEP, PT_SYSCALL], [], [], [$ac_includes_default #if HAVE_SYS_TYPES_H #include #endif #include ]) -done] -) - -AC_CHECK_PTRACE_DECL([PTRACE_POKEUSER PTRACE_POKEDATA PTRACE_CONT \ -PTRACE_TRACEME PTRACE_CONT PTRACE_SIGNLESTEP PTRACE_SYSCALL PT_IO PT_GETREGS \ -PT_GETFPREGS PT_CONTINUE PT_TRACE_ME PT_STEP PT_SYSCALL]) dnl Checks for library functions. AC_FUNC_MEMCMP From caa6095aec43541bdbca1ad58d6f65b3de53a1ef Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 7 Apr 2010 19:59:06 -0700 Subject: [PATCH 099/162] Fix compile errors on Linux --- src/x86/Gos-linux.c | 1 - src/x86_64/Gos-linux.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index b31f96a1..255696ca 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -244,7 +244,6 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) } #ifndef UNW_REMOTE_ONLY - HIDDEN void * x86_r_uc_addr (ucontext_t *uc, int reg) { diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index b37ea4c5..b0c096c2 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -101,7 +101,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) } #ifndef UNW_REMOTE_ONLY -static inline void * +HIDDEN void * x86_64_r_uc_addr (ucontext_t *uc, int reg) { void *addr; From d1676f192e687ba220c655789f3a53bcbd20c52e Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Thu, 8 Apr 2010 03:12:05 -0700 Subject: [PATCH 100/162] Fix warnings on 32 bit x86 --- src/x86/Gos-linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 255696ca..31f83bae 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -153,6 +153,9 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case X86_SCF_LINUX_RT_SIGFRAME: addr += LINUX_UC_MCONTEXT_OFF; break; + + default: + return DWARF_NULL_LOC; } switch (reg) From 2c50c95cde4e2a7f69b7f14ff48934f34003aabd Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 00:38:54 +0300 Subject: [PATCH 101/162] Correct arguments for Debug(). Shut up warning by using the cast. --- src/x86/Gos-freebsd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 0dd3b437..b4495686 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -307,10 +307,10 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn((const char *)sc + FREEBSD_UC_MCONTEXT_OFF); + sigreturn((ucontext_t *)((const char *)sc + FREEBSD_UC_MCONTEXT_OFF)); } else { Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", - c->sigcontext_format); + c->dwarf.ip, c->sigcontext_format); abort(); } return -UNW_EINVAL; From f6546e27ed70661c1b148521e15c539559ee4e25 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 00:40:39 +0300 Subject: [PATCH 102/162] Implement the base code to fetch x86/xmm state on x86. Offsets to be filled. --- src/x86/Gos-freebsd.c | 85 ++++++++++++++++++++++++++++++++----------- src/x86/offsets.h | 28 +++++++++++++- 2 files changed, 89 insertions(+), 24 deletions(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index b4495686..9fbf854b 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -139,8 +139,9 @@ unw_handle_signal_frame (unw_cursor_t *cursor) HIDDEN dwarf_loc_t x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) { - unw_word_t addr = c->sigcontext_addr, fpstate_addr, off; - int ret, is_fpstate = 0; + unw_word_t addr = c->sigcontext_addr, off, xmm_off; + unw_word_t fpstate, fpformat; + int ret, is_fpstate = 0, is_xmmstate = 0; switch (c->sigcontext_format) { @@ -171,6 +172,7 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) break; } + off = 0; /* shut gcc warning */ switch (reg) { case UNW_X86_GS: off = FREEBSD_UC_MCONTEXT_GS_OFF; break; @@ -191,21 +193,53 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case UNW_X86_EFLAGS: off = FREEBSD_UC_MCONTEXT_EFLAGS_OFF; break; case UNW_X86_SS: off = FREEBSD_UC_MCONTEXT_SS_OFF; break; - /* XXXKIB fix */ - case UNW_X86_FCW: is_fpstate = 1; off = LINUX_FPSTATE_CW_OFF; break; - case UNW_X86_FSW: is_fpstate = 1; off = LINUX_FPSTATE_SW_OFF; break; - case UNW_X86_FTW: is_fpstate = 1; off = LINUX_FPSTATE_TAG_OFF; break; - case UNW_X86_FCS: is_fpstate = 1; off = LINUX_FPSTATE_CSSEL_OFF; break; - case UNW_X86_FIP: is_fpstate = 1; off = LINUX_FPSTATE_IPOFF_OFF; break; - case UNW_X86_FEA: is_fpstate = 1; off = LINUX_FPSTATE_DATAOFF_OFF; break; - case UNW_X86_FDS: is_fpstate = 1; off = LINUX_FPSTATE_DATASEL_OFF; break; - case UNW_X86_MXCSR: is_fpstate = 1; off = LINUX_FPSTATE_MXCSR_OFF; break; + case UNW_X86_FCW: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_CW_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_CW_XMM_OFF; + break; + case UNW_X86_FSW: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_SW_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_SW_XMM_OFF; + break; + case UNW_X86_FTW: + is_fpstate = 1; + xmm_off = FREEBSD_UC_MCONTEXT_TAG_XMM_OFF; + off = FREEBSD_UC_MCONTEXT_TAG_OFF; + break; + case UNW_X86_FCS: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_CSSEL_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF; + break; + case UNW_X86_FIP: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_IPOFF_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF; + break; + case UNW_X86_FEA: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_DATAOFF_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF; + break; + case UNW_X86_FDS: + is_fpstate = 1; + off = FREEBSD_US_MCONTEXT_DATASEL_OFF; + xmm_off = FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF; + break; + case UNW_X86_MXCSR: + is_fpstate = 1; + off = FREEBSD_UC_MCONTEXT_MXCSR_OFF; + xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF; + break; /* stacked fp registers */ case UNW_X86_ST0: case UNW_X86_ST1: case UNW_X86_ST2: case UNW_X86_ST3: case UNW_X86_ST4: case UNW_X86_ST5: case UNW_X86_ST6: case UNW_X86_ST7: is_fpstate = 1; - off = LINUX_FPSTATE_ST0_OFF + 10*(reg - UNW_X86_ST0); + off = FREEBSD_UC_MCONTEXT_ST0_OFF + 10*(reg - UNW_X86_ST0); + xmm_off = FREEBSD_UC_MCONTEXT_ST0_XMM_OFF + 10*(reg - UNW_X86_ST0); break; /* SSE fp registers */ @@ -218,7 +252,8 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case UNW_X86_XMM6_lo: case UNW_X86_XMM6_hi: case UNW_X86_XMM7_lo: case UNW_X86_XMM7_hi: is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); + is_xmmstate = 1; + xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo); break; case UNW_X86_XMM0: case UNW_X86_XMM1: @@ -229,7 +264,8 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case UNW_X86_XMM6: case UNW_X86_XMM7: is_fpstate = 1; - off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0); + is_xmmstate = 1; + xmm_off = FREEBSD_UC_MCONTEXT_XMM0_OFF + 16*(reg - UNW_X86_XMM0); break; case UNW_X86_FOP: @@ -242,17 +278,22 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) if (is_fpstate) { if ((ret = dwarf_get (&c->dwarf, - DWARF_MEM_LOC (&c->dwarf, - addr + LINUX_SC_FPSTATE_OFF), - &fpstate_addr)) < 0) + DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPSTATE_OFF), + &fpstate)) < 0) return DWARF_NULL_LOC; - - if (!fpstate_addr) + if (fpstate == FREEBSD_UC_MCONTEXT_FPOWNED_NONE) return DWARF_NULL_LOC; - - return DWARF_MEM_LOC (c, fpstate_addr + off); + if ((ret = dwarf_get (&c->dwarf, + DWARF_MEM_LOC (&c->dwarf, addr + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF), + &fpformat)) < 0) + return DWARF_NULL_LOC; + if (fpformat == FREEBSD_UC_MCONTEXT_FPFMT_NODEV || + (is_xmmstate && fpformat != FREEBSD_UC_MCONTEXT_FPFMT_XMM)) + return DWARF_NULL_LOC; + if (is_xmmstate) + off = xmm_off; } - else + return DWARF_MEM_LOC (c, addr + off); } diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 7b32cab4..a708cfcc 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -103,12 +103,36 @@ #define FREEBSD_UC_MCONTEXT_CS_OFF 0x50 #define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54 #define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 -#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 +#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 #define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70 #define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60 #define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 +#define FREEBSD_UC_MCONTEXT_CW_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_SW_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_TAG_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x11111 +#define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x11111 +#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_MXCSR_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_ST0_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x11111 + #define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280 -#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define FREEBSD_UC_MCONTEXT_FPFMT_NODEV 0x10000 #define FREEBSD_UC_MCONTEXT_FPFMT_387 0x10001 #define FREEBSD_UC_MCONTEXT_FPFMT_XMM 0x10002 +#define FREEBSD_UC_MCONTEXT_FPOWNED_NONE 0x20000 +#define FREEBSD_UC_MCONTEXT_FPOWNED_FPU 0x20001 +#define FREEBSD_UC_MCONTEXT_FPOWNED_PCB 0x20002 + From 117ccd246de163dddd451cf98019e0fa90c6272a Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 00:46:51 +0300 Subject: [PATCH 103/162] Move all XMM offsets into one place. --- src/x86/offsets.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/x86/offsets.h b/src/x86/offsets.h index a708cfcc..fc60bb01 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -109,22 +109,23 @@ #define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 #define FREEBSD_UC_MCONTEXT_CW_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_SW_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_TAG_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x11111 #define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x11111 -#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_MXCSR_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_ST0_OFF 0x11111 + +#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x11111 +#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x11111 #define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x11111 From 9fe75c7d930f6f590e2a1b24fdb84d6859cb0175 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 00:47:08 +0300 Subject: [PATCH 104/162] Save FPU state when saving context. For XMM-capable CPUs only (for now). --- src/x86/getcontext.S | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index e8db7031..5f8ff45c 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -103,12 +103,10 @@ _Ux86_getcontext: FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,\ FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax) -/* - leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) - fnstenv (%ecx) - fldenv (%ecx) -*/ + + /* Require CPU with fxsave implemented, and enabled by OS. */ + fxsave FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax) + movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) #endif From 6f7b335e89e1b7f9c539fc0ebb3f789e34d0b7e4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 01:42:26 +0300 Subject: [PATCH 105/162] Add my copyrights to several files that contain essential modifications --- src/os-freebsd.c | 2 +- src/ptrace/_UPT_access_fpreg.c | 1 + src/ptrace/_UPT_access_mem.c | 1 + src/ptrace/_UPT_access_reg.c | 1 + src/x86/getcontext.S | 1 + src/x86_64/getcontext.S | 1 + src/x86_64/setcontext.S | 1 + 7 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index 1230bfd5..e9696e23 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -1,5 +1,5 @@ /* libunwind - a platform-independent unwind library - Copyright (C) 2010 Konstantin Belousov + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. diff --git a/src/ptrace/_UPT_access_fpreg.c b/src/ptrace/_UPT_access_fpreg.c index 23c34bfc..d4a5f6a0 100644 --- a/src/ptrace/_UPT_access_fpreg.c +++ b/src/ptrace/_UPT_access_fpreg.c @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2003 Hewlett-Packard Co Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. diff --git a/src/ptrace/_UPT_access_mem.c b/src/ptrace/_UPT_access_mem.c index 8c36387b..b0c2ef04 100644 --- a/src/ptrace/_UPT_access_mem.c +++ b/src/ptrace/_UPT_access_mem.c @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2003-2004 Hewlett-Packard Co Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. diff --git a/src/ptrace/_UPT_access_reg.c b/src/ptrace/_UPT_access_reg.c index a85b900f..00ba0cc7 100644 --- a/src/ptrace/_UPT_access_reg.c +++ b/src/ptrace/_UPT_access_reg.c @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2003-2005 Hewlett-Packard Co Contributed by David Mosberger-Tang + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index 5f8ff45c..b7654465 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2009 Google, Inc Contributed by Paul Pluzhnikov + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S index ce7cbcc1..a0df6f15 100644 --- a/src/x86_64/getcontext.S +++ b/src/x86_64/getcontext.S @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2008 Google, Inc Contributed by Paul Pluzhnikov + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S index 4bb3e109..1af8b673 100644 --- a/src/x86_64/setcontext.S +++ b/src/x86_64/setcontext.S @@ -1,6 +1,7 @@ /* libunwind - a platform-independent unwind library Copyright (C) 2007 Google, Inc Contributed by Arun Sharma + Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. From 53f7e650e0fb641af08a0f40c9fae1fd037caab9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 18:48:16 +0300 Subject: [PATCH 106/162] For FreeBSD/i386, add real offset values for FPU context fields. --- src/x86/offsets.h | 65 ++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/x86/offsets.h b/src/x86/offsets.h index fc60bb01..0f07352b 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -83,51 +83,52 @@ #define LINUX_FPSTATE_XMM6_OFF 0x170 #define LINUX_FPSTATE_XMM7_OFF 0x180 +/* FreeBSD-specific definitions: */ + #define FREEBSD_SC_UCONTEXT_OFF 0x14 #define FREEBSD_UC_MCONTEXT_OFF 0x10 -#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x40 -#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x34 -#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x3c -#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x38 +#define FREEBSD_UC_MCONTEXT_GS_OFF 0x14 +#define FREEBSD_UC_MCONTEXT_FS_OFF 0x18 +#define FREEBSD_UC_MCONTEXT_ES_OFF 0x1c +#define FREEBSD_UC_MCONTEXT_DS_OFF 0x20 #define FREEBSD_UC_MCONTEXT_EDI_OFF 0x24 #define FREEBSD_UC_MCONTEXT_ESI_OFF 0x28 #define FREEBSD_UC_MCONTEXT_EBP_OFF 0x2c +#define FREEBSD_UC_MCONTEXT_EBX_OFF 0x34 +#define FREEBSD_UC_MCONTEXT_EDX_OFF 0x38 +#define FREEBSD_UC_MCONTEXT_ECX_OFF 0x3c +#define FREEBSD_UC_MCONTEXT_EAX_OFF 0x40 +#define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 #define FREEBSD_UC_MCONTEXT_EIP_OFF 0x4c #define FREEBSD_UC_MCONTEXT_ESP_OFF 0x58 -#define FREEBSD_UC_MCONTEXT_FS_OFF 0x18 -#define FREEBSD_UC_MCONTEXT_GS_OFF 0x14 -#define FREEBSD_UC_MCONTEXT_DS_OFF 0x20 -#define FREEBSD_UC_MCONTEXT_ES_OFF 0x1c -#define FREEBSD_UC_MCONTEXT_SS_OFF 0x5c #define FREEBSD_UC_MCONTEXT_CS_OFF 0x50 #define FREEBSD_UC_MCONTEXT_EFLAGS_OFF 0x54 -#define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 -#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 -#define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70 +#define FREEBSD_UC_MCONTEXT_SS_OFF 0x5c #define FREEBSD_UC_MCONTEXT_MC_LEN_OFF 0x60 -#define FREEBSD_UC_MCONTEXT_TRAPNO_OFF 0x44 +#define FREEBSD_UC_MCONTEXT_FPFORMAT_OFF 0x64 +#define FREEBSD_UC_MCONTEXT_OWNEDFP_OFF 0x68 +#define FREEBSD_UC_MCONTEXT_FPSTATE_OFF 0x70 -#define FREEBSD_UC_MCONTEXT_CW_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_SW_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_TAG_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x11111 -#define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_MXCSR_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_ST0_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CW_OFF 0x70 +#define FREEBSD_UC_MCONTEXT_SW_OFF 0x74 +#define FREEBSD_UC_MCONTEXT_TAG_OFF 0x78 +#define FREEBSD_UC_MCONTEXT_IPOFF_OFF 0x7c +#define FREEBSD_UC_MCONTEXT_CSSEL_OFF 0x80 +#define FREEBSD_UC_MCONTEXT_DATAOFF_OFF 0x84 +#define FREEBSD_US_MCONTEXT_DATASEL_OFF 0x88 +#define FREEBSD_UC_MCONTEXT_ST0_OFF 0x8c -#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x11111 -#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x11111 -#define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x11111 +#define FREEBSD_UC_MCONTEXT_CW_XMM_OFF 0x70 +#define FREEBSD_UC_MCONTEXT_SW_XMM_OFF 0x72 +#define FREEBSD_UC_MCONTEXT_TAG_XMM_OFF 0x74 +#define FREEBSD_UC_MCONTEXT_IPOFF_XMM_OFF 0x78 +#define FREEBSD_UC_MCONTEXT_CSSEL_XMM_OFF 0x7c +#define FREEBSD_UC_MCONTEXT_DATAOFF_XMM_OFF 0x80 +#define FREEBSD_US_MCONTEXT_DATASEL_XMM_OFF 0x84 +#define FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF 0x88 +#define FREEBSD_UC_MCONTEXT_ST0_XMM_OFF 0x90 +#define FREEBSD_UC_MCONTEXT_XMM0_OFF 0x110 #define FREEBSD_UC_MCONTEXT_MC_LEN_VAL 0x280 #define FREEBSD_UC_MCONTEXT_FPFMT_NODEV 0x10000 From dd1c7b6c1a4fc4c6f833b3f3ef21cde1eebcf03b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 18:48:35 +0300 Subject: [PATCH 107/162] Declare mxcsr as XMM --- src/x86/Gos-freebsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 9fbf854b..592bf1f2 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -230,7 +230,7 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) break; case UNW_X86_MXCSR: is_fpstate = 1; - off = FREEBSD_UC_MCONTEXT_MXCSR_OFF; + is_xmmstate = 1; xmm_off = FREEBSD_UC_MCONTEXT_MXCSR_XMM_OFF; break; From a688d6c4c9c82d504e08606002b081da42f531e0 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2010 18:51:17 +0300 Subject: [PATCH 108/162] Remove unused variable. --- src/ptrace/_UPT_access_fpreg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ptrace/_UPT_access_fpreg.c b/src/ptrace/_UPT_access_fpreg.c index d4a5f6a0..283dcd4f 100644 --- a/src/ptrace/_UPT_access_fpreg.c +++ b/src/ptrace/_UPT_access_fpreg.c @@ -71,7 +71,6 @@ int _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, int write, void *arg) { - unw_word_t *wp = (unw_word_t *) val; struct UPT_info *ui = arg; pid_t pid = ui->pid; fpregset_t fpreg; From f01a04371287037ca884ec16b4316edc2a08458c Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 13:47:28 +0300 Subject: [PATCH 109/162] Convince gcc that x86_64_sigreturn cannot return, as declared. --- src/x86_64/Gos-freebsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index 91d60a18..6d571254 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -190,5 +190,6 @@ x86_64_sigreturn (unw_cursor_t *cursor) Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", (unsigned long long) c->dwarf.ip, uc); sigreturn(uc); + abort(); } #endif From 69001646fa81d4692ee4b3a5ce942aa2d957bbe0 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 13:48:14 +0300 Subject: [PATCH 110/162] Store the ucontext_t pointer to properly handle resume across signal frames. --- src/x86/Gos-freebsd.c | 1 + src/x86_64/Gos-freebsd.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 592bf1f2..2a2b8d18 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -108,6 +108,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) sf = (struct sigframe *)c->dwarf.cfa; uc_addr = (uintptr_t)&(sf->sf_uc); + c->uc = (ucontext_t *)uc_addr; esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index 6d571254..dcbc4922 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -96,6 +96,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) { ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + c->uc = (ucontext_t *)ucontext; Debug(1, "signal frame, skip over trampoline\n"); struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); From e33fa9f73c8eefafc2c1b580e78a5c87bcc4dc44 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 14:36:24 +0300 Subject: [PATCH 111/162] Ditch using the libutil, it is not async-signal safe. --- src/os-freebsd.c | 77 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index e9696e23..b3c292a9 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -24,41 +24,74 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UNW_REMOTE_ONLY +#include #include +#include +#include #include #include #include #include "libunwind_i.h" +static void * +get_mem(size_t sz) +{ + void *res; + + res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (res == MAP_FAILED) + return (NULL); + return (res); +} + +static void +free_mem(void *ptr, size_t sz) +{ + munmap(ptr, sz); +} + PROTECTED int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, unsigned long *segbase, unsigned long *mapoff) { - struct kinfo_vmentry *freep, *kve; - int cnt, rc, i; + int mib[4], error, ret; + size_t len, len1; + char *buf, *bp, *eb; + struct kinfo_vmentry *kv; - freep = kinfo_getvmmap(pid, &cnt); - if (freep == NULL) + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_VMMAP; + mib[3] = pid; + + error = sysctl(mib, 4, NULL, &len, NULL, 0); + if (error) return (-1); - for (i = 0; i < cnt; i++) - { - kve = &freep[i]; - if (ip < kve->kve_start || ip >= kve->kve_end) - continue; - if (kve->kve_type != KVME_TYPE_VNODE) - { - free(freep); - return (-1); - } - *segbase = kve->kve_start; - *mapoff = kve->kve_offset; - rc = elf_map_image(ei, kve->kve_path); - free(freep); - return (rc); - } - free(freep); - return (-1); + len1 = len * 4 / 3; + buf = get_mem(len1); + if (buf == NULL) + return (-1); + error = sysctl(mib, 4, buf, &len, NULL, 0); + if (error) { + free_mem(buf, len1); + return (-1); + } + ret = -1; + for (bp = buf, eb = buf + len; bp < eb; bp += kv->kve_structsize) { + kv = (struct kinfo_vmentry *)(uintptr_t)bp; + if (ip < kv->kve_start || ip >= kv->kve_end) + continue; + if (kv->kve_type != KVME_TYPE_VNODE) + break; + *segbase = kv->kve_start; + *mapoff = kv->kve_offset; + ret = elf_map_image(ei, kv->kve_path); + break; + } + free_mem(buf, len1); + return (ret); } #endif /* UNW_REMOTE_ONLY */ From 8d6b00b0821fefb17deb31cfd1ad2b76fb4887d9 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 14:44:21 +0300 Subject: [PATCH 112/162] Remove no more needed check. --- configure.in | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.in b/configure.in index 81b49b02..fcc88137 100644 --- a/configure.in +++ b/configure.in @@ -23,7 +23,6 @@ AM_PROG_CC_C_O dnl Checks for libraries. AC_CHECK_LIB(uca, __uc_get_grs) -AC_CHECK_LIB(util, kinfo_getvmmap) OLD_LIBS=${LIBS} AC_SEARCH_LIBS(dlopen, dl) LIBS=${OLD_LIBS} From f10f8519164c472ee9392f7f037cfd56ba821d53 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 14:59:36 +0300 Subject: [PATCH 113/162] Add slightly more debug output --- src/x86/Gstep.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c index e4055ae0..0965db2f 100644 --- a/src/x86/Gstep.c +++ b/src/x86/Gstep.c @@ -96,9 +96,15 @@ unw_step (unw_cursor_t *cursor) ret = dwarf_get (&c->dwarf, c->dwarf.loc[EIP], &c->dwarf.ip); if (ret < 0) { + Debug (13, "dwarf_get([EIP=0x%x]) failed\n", DWARF_GET_LOC (c->dwarf.loc[EIP])); Debug (2, "returning %d\n", ret); return ret; } + else + { + Debug (13, "[EIP=0x%x] = 0x%x\n", DWARF_GET_LOC (c->dwarf.loc[EIP]), + c->dwarf.ip); + } } else c->dwarf.ip = 0; From 42bc15c72c7292f71b12b345e932301f10c91e68 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 19:18:07 +0300 Subject: [PATCH 114/162] Provide proper register offsets in the gregset for FreeBSD/i386 --- src/ptrace/_UPT_reg_offset.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c index 83dbcc31..40f3b1ba 100644 --- a/src/ptrace/_UPT_reg_offset.c +++ b/src/ptrace/_UPT_reg_offset.c @@ -249,6 +249,22 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = [UNW_HPPA_IP] = 0x1a8 /* IAOQ[0] */ #elif defined(UNW_TARGET_X86) +#if defined __FreeBSD__ +#define UNW_R_OFF(R, r) \ + [UNW_X86_##R] = offsetof(gregset_t, r_##r), + UNW_R_OFF(EAX, eax) + UNW_R_OFF(EDX, edx) + UNW_R_OFF(ECX, ecx) + UNW_R_OFF(EBX, ebx) + UNW_R_OFF(ESI, esi) + UNW_R_OFF(EDI, edi) + UNW_R_OFF(EBP, ebp) + UNW_R_OFF(ESP, esp) + UNW_R_OFF(EIP, eip) +// UNW_R_OFF(CS, cs) +// UNW_R_OFF(EFLAGS, eflags) +// UNW_R_OFF(SS, ss) +#elif defined __linux__ [UNW_X86_EAX] = 0x18, [UNW_X86_EBX] = 0x00, [UNW_X86_ECX] = 0x04, @@ -266,8 +282,11 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = /* ORIG_EAX = 0x2c, */ /* EFLAGS = 0x38, */ /* SS = 0x40 */ +#else +#error Port me +#endif #elif defined(UNW_TARGET_X86_64) -#if defined(__FreeBSD__) +#if defined __FreeBSD__ #define UNW_R_OFF(R, r) \ [UNW_X86_64_##R] = offsetof(gregset_t, r_##r), UNW_R_OFF(RAX, rax) @@ -291,7 +310,7 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = // UNW_R_OFF(EFLAGS, rflags) // UNW_R_OFF(SS, ss) #undef UNW_R_OFF -#else +#elif defined __linux__ [UNW_X86_64_RAX] = 0x50, [UNW_X86_64_RDX] = 0x60, [UNW_X86_64_RCX] = 0x58, @@ -313,6 +332,8 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = // [UNW_X86_64_EFLAGS] = 0x90, // [UNW_X86_64_RSP] = 0x98, // [UNW_X86_64_SS] = 0xa0 +#else +#error Port me #endif #elif defined(UNW_TARGET_PPC32) #elif defined(UNW_TARGET_PPC64) From 21f0e90ce85da99c2897d5e2163e8183436becdc Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 22:01:08 +0300 Subject: [PATCH 115/162] Rework 69001646fa8, store sigframe address into sigcontext_addr. --- src/x86/Gos-freebsd.c | 5 +++-- src/x86_64/Gos-freebsd.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 2a2b8d18..e88b4439 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -28,6 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include +#include #include #include @@ -108,7 +109,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) sf = (struct sigframe *)c->dwarf.cfa; uc_addr = (uintptr_t)&(sf->sf_uc); - c->uc = (ucontext_t *)uc_addr; + c->sigcontext_addr = c->dwarf.cfa; esp_loc = DWARF_LOC (uc_addr + FREEBSD_UC_MCONTEXT_ESP_OFF, 0); ret = dwarf_get (&c->dwarf, esp_loc, &c->dwarf.cfa); @@ -150,7 +151,7 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) return DWARF_REG_LOC (&c->dwarf, reg); case X86_SCF_FREEBSD_SIGFRAME: - addr += FREEBSD_UC_MCONTEXT_OFF; + addr += offsetof(struct sigframe, sf_uc) + FREEBSD_UC_MCONTEXT_OFF; break; case X86_SCF_FREEBSD_SIGFRAME4: diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index dcbc4922..0e33aa8f 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -96,7 +96,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) if (c->sigcontext_format == X86_64_SCF_FREEBSD_SIGFRAME) { ucontext = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); - c->uc = (ucontext_t *)ucontext; + c->sigcontext_addr = c->dwarf.cfa; Debug(1, "signal frame, skip over trampoline\n"); struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); @@ -186,7 +186,7 @@ HIDDEN NORETURN void x86_64_sigreturn (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->uc; + ucontext_t *uc = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", (unsigned long long) c->dwarf.ip, uc); From 843190597c5a482ad7f8ae5483a4f716db3c0719 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 11 Apr 2010 22:07:31 +0300 Subject: [PATCH 116/162] Remove unneeded include. Noted by: Arun Sharma --- src/os-freebsd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index b3c292a9..a88b908d 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -29,7 +29,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include -#include #include #include "libunwind_i.h" From eb8857a324ba9d2c721351ab57e62e47d153909f Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 12 Apr 2010 10:45:31 -0700 Subject: [PATCH 117/162] Silence a compiler warning --- src/x86/Gos-linux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 31f83bae..255696ca 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -153,9 +153,6 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case X86_SCF_LINUX_RT_SIGFRAME: addr += LINUX_UC_MCONTEXT_OFF; break; - - default: - return DWARF_NULL_LOC; } switch (reg) From c2d78041cc41e8455bd97584d5a5bb3638554632 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Mon, 12 Apr 2010 12:08:21 -0700 Subject: [PATCH 118/162] GCC compatibility on x86 for C++ exception handling --- src/unwind/SetGR.c | 6 +++ tests/Ltest-cxx-exceptions.cxx | 78 ++++++++++++++++++++++++++++++++++ tests/Makefile.am | 6 +++ 3 files changed, 90 insertions(+) create mode 100644 tests/Ltest-cxx-exceptions.cxx diff --git a/src/unwind/SetGR.c b/src/unwind/SetGR.c index 056bfc70..96533643 100644 --- a/src/unwind/SetGR.c +++ b/src/unwind/SetGR.c @@ -24,11 +24,17 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind-internal.h" +#ifdef UNW_TARGET_X86 +#include "dwarf_i.h" +#endif PROTECTED void _Unwind_SetGR (struct _Unwind_Context *context, int index, unsigned long new_value) { +#ifdef UNW_TARGET_X86 + index = dwarf_to_unw_regnum(index); +#endif unw_set_reg (&context->cursor, index, new_value); #ifdef UNW_TARGET_IA64 if (index >= UNW_IA64_GR && index <= UNW_IA64_GR + 127) diff --git a/tests/Ltest-cxx-exceptions.cxx b/tests/Ltest-cxx-exceptions.cxx new file mode 100644 index 00000000..827ba98a --- /dev/null +++ b/tests/Ltest-cxx-exceptions.cxx @@ -0,0 +1,78 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2010 stefan.demharter@gmx.net + Copyright (C) 2010 arun.sharma@google.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#define panic(args...) \ + { fprintf (stderr, args); exit (-1); } + +struct Test +{ + public: // --- ctor/dtor --- + Test() { ++counter_; } + ~Test() { -- counter_; } + Test(const Test&) { ++counter_; } + + public: // --- static members --- + static int counter_; +}; + +int Test::counter_ = 0; + +// Called by foo +extern "C" void bar() +{ + Test t; + try { + Test t; + throw 5; + } catch (...) { + Test t; + printf("Throwing an int\n"); + throw 6; + } +} + +int main() +{ + try { + Test t; + bar(); + } catch (int) { + // Dtor of all Test-object has to be called. + if (Test::counter_ != 0) + panic("Counter non-zero\n"); + return Test::counter_; + } catch (...) { + // An int was thrown - we should not get here. + panic("Int was thrown why are we here?\n"); + } + exit(0); +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 1dd331c1..8786923e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -45,6 +45,10 @@ endif #ARCH_IA64 noinst_PROGRAMS_cdep = forker mapper test-ptrace-misc test-varargs \ Gperf-simple Lperf-simple +if SUPPORT_CXX_EXCEPTIONS + check_PROGRAMS_cdep += Ltest-cxx-exceptions +endif + perf: perf-startup Gperf-simple Lperf-simple @echo "########## Basic performance of generic libunwind:" @./Gperf-simple @@ -81,6 +85,8 @@ ppc64_test_altivec_SOURCES = ppc64-test-altivec.c ppc64-test-altivec-utils.c ppc64_test_wchar_SOURCES = ppc64-test-wchar.c Gtest_init_SOURCES = Gtest-init.cxx Ltest_init_SOURCES = Ltest-init.cxx +Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx + Gtest_dyn1_SOURCES = Gtest-dyn1.c flush-cache.S Ltest_dyn1_SOURCES = Ltest-dyn1.c flush-cache.S test_static_link_SOURCES = test-static-link-loc.c test-static-link-gen.c From 66e49bdd415ec6c3d6479e2fc2a59a50b5f16d93 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 13 Apr 2010 13:55:23 +0300 Subject: [PATCH 119/162] Save %eax for i386 --- src/x86/getcontext.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/x86/getcontext.S b/src/x86/getcontext.S index b7654465..f97fff45 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext.S @@ -37,9 +37,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .global _Ux86_getcontext .type _Ux86_getcontext, @function _Ux86_getcontext: +#if defined __linux__ mov 4(%esp),%eax /* ucontext_t* */ -#if defined __linux__ /* EAX is not preserved. */ movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) @@ -66,9 +66,9 @@ _Ux86_getcontext: fnstenv (%ecx) fldenv (%ecx) #elif defined __FreeBSD__ - /* EAX is not preserved. */ - movl $0, FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) - + pushl %eax + mov 8(%esp),%eax /* ucontext_t* */ + popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) movl %ebx, FREEBSD_UC_MCONTEXT_EBX_OFF(%eax) movl %ecx, FREEBSD_UC_MCONTEXT_ECX_OFF(%eax) movl %edx, FREEBSD_UC_MCONTEXT_EDX_OFF(%eax) From ae7eebb839491b9d313923e38414b83c1fddcbf4 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 13 Apr 2010 14:11:39 +0300 Subject: [PATCH 120/162] Separate getcontext implementation for x86 --- src/Makefile.am | 6 +- .../{getcontext.S => getcontext-freebsd.S} | 42 +---------- src/x86/getcontext-linux.S | 72 +++++++++++++++++++ 3 files changed, 77 insertions(+), 43 deletions(-) rename src/x86/{getcontext.S => getcontext-freebsd.S} (67%) create mode 100644 src/x86/getcontext-linux.S diff --git a/src/Makefile.am b/src/Makefile.am index 1c94e161..be547710 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -230,7 +230,7 @@ libunwind_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ x86/Lcreate_addr_space.c x86/Lget_save_loc.c x86/Lglobal.c \ x86/Linit.c x86/Linit_local.c x86/Linit_remote.c \ x86/Lget_proc_info.c x86/Lregs.c \ - x86/Lresume.c x86/Lstep.c x86/getcontext.S + x86/Lresume.c x86/Lstep.c # The list of files that go into libunwind-x86: libunwind_x86_la_SOURCES_x86 = $(libunwind_la_SOURCES_x86_common) \ @@ -351,6 +351,7 @@ if OS_LINUX libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_linux) libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_linux_local) libunwind_la_SOURCES_x86_os = x86/Gos-linux.c + libunwind_x86_la_SOURCES_os = x86/getcontext-linux.S libunwind_la_SOURCES_x86_os_local = x86/Los-linux.c libunwind_la_SOURCES_x86_64_os = x86_64/Gos-linux.c libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-linux.c @@ -365,6 +366,7 @@ if OS_FREEBSD libunwind_la_SOURCES_os = $(libunwind_la_SOURCES_os_freebsd) libunwind_la_SOURCES_os_local = $(libunwind_la_SOURCES_os_freebsd_local) libunwind_la_SOURCES_x86_os = x86/Gos-freebsd.c + libunwind_x86_la_SOURCES_os = x86/getcontext-freebsd.S libunwind_la_SOURCES_x86_os_local = x86/Los-freebsd.c libunwind_la_SOURCES_x86_64_os = x86_64/Gos-freebsd.c libunwind_la_SOURCES_x86_64_os_local = x86_64/Los-freebsd.c @@ -424,7 +426,7 @@ endif else if ARCH_X86 lib_LTLIBRARIES_arch = libunwind-x86.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) + libunwind_la_SOURCES = $(libunwind_la_SOURCES_x86) $(libunwind_x86_la_SOURCES_os) libunwind_x86_la_SOURCES = $(libunwind_x86_la_SOURCES_x86) libunwind_x86_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) if !REMOTE_ONLY diff --git a/src/x86/getcontext.S b/src/x86/getcontext-freebsd.S similarity index 67% rename from src/x86/getcontext.S rename to src/x86/getcontext-freebsd.S index f97fff45..42478d29 100644 --- a/src/x86/getcontext.S +++ b/src/x86/getcontext-freebsd.S @@ -1,6 +1,4 @@ /* libunwind - a platform-independent unwind library - Copyright (C) 2009 Google, Inc - Contributed by Paul Pluzhnikov Copyright (C) 2010 Konstantin Belousov This file is part of libunwind. @@ -26,46 +24,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "offsets.h" -/* int _Ux86_getcontext (ucontext_t *ucp) - - Saves the machine context in UCP necessary for libunwind. - Unlike the libc implementation, we don't save the signal mask - and hence avoid the cost of a system call per unwind. - -*/ - .global _Ux86_getcontext .type _Ux86_getcontext, @function _Ux86_getcontext: -#if defined __linux__ - mov 4(%esp),%eax /* ucontext_t* */ - - /* EAX is not preserved. */ - movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) - - movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax) - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax) - movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax) - movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax) - movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax) - movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax) - - movl (%esp), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax) - - leal 4(%esp), %ecx /* Exclude the return address. */ - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax) - - /* glibc getcontext saves FS, but not GS */ - xorl %ecx, %ecx - movw %fs, %cx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax) - - leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx - movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) - fnstenv (%ecx) - fldenv (%ecx) -#elif defined __FreeBSD__ pushl %eax mov 8(%esp),%eax /* ucontext_t* */ popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) @@ -110,9 +71,8 @@ _Ux86_getcontext: movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) -#endif - xor %eax, %eax + xorl %eax, %eax ret .size _Ux86_getcontext, . - _Ux86_getcontext diff --git a/src/x86/getcontext-linux.S b/src/x86/getcontext-linux.S new file mode 100644 index 00000000..a0714cd1 --- /dev/null +++ b/src/x86/getcontext-linux.S @@ -0,0 +1,72 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2009 Google, Inc + Contributed by Paul Pluzhnikov + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" + +/* int _Ux86_getcontext (ucontext_t *ucp) + + Saves the machine context in UCP necessary for libunwind. + Unlike the libc implementation, we don't save the signal mask + and hence avoid the cost of a system call per unwind. + +*/ + + .global _Ux86_getcontext + .type _Ux86_getcontext, @function +_Ux86_getcontext: + mov 4(%esp),%eax /* ucontext_t* */ + + /* EAX is not preserved. */ + movl $0, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EAX_OFF)(%eax) + + movl %ebx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBX_OFF)(%eax) + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ECX_OFF)(%eax) + movl %edx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDX_OFF)(%eax) + movl %edi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EDI_OFF)(%eax) + movl %esi, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESI_OFF)(%eax) + movl %ebp, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EBP_OFF)(%eax) + + movl (%esp), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_EIP_OFF)(%eax) + + leal 4(%esp), %ecx /* Exclude the return address. */ + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_ESP_OFF)(%eax) + + /* glibc getcontext saves FS, but not GS */ + xorl %ecx, %ecx + movw %fs, %cx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FS_OFF)(%eax) + + leal LINUX_UC_FPREGS_MEM_OFF(%eax), %ecx + movl %ecx, (LINUX_UC_MCONTEXT_OFF+LINUX_SC_FPSTATE_OFF)(%eax) + fnstenv (%ecx) + fldenv (%ecx) + + xor %eax, %eax + ret + .size _Ux86_getcontext, . - _Ux86_getcontext + + /* We do not need executable stack. */ + .section .note.GNU-stack,"",@progbits From 02d0cb6f716d9fc3587b3ed07047f5fedf8724e6 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 13 Apr 2010 14:20:22 +0300 Subject: [PATCH 121/162] Do not save FPU context on x86 for now; XMM save area must be 16-bytes aligned --- src/x86/getcontext-freebsd.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/x86/getcontext-freebsd.S b/src/x86/getcontext-freebsd.S index 42478d29..92ae26f4 100644 --- a/src/x86/getcontext-freebsd.S +++ b/src/x86/getcontext-freebsd.S @@ -61,6 +61,7 @@ _Ux86_getcontext: popl FREEBSD_UC_MCONTEXT_EFLAGS_OFF(%eax) movl $0, FREEBSD_UC_MCONTEXT_TRAPNO_OFF(%eax) +#if 0 movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,\ FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,\ @@ -68,6 +69,12 @@ _Ux86_getcontext: /* Require CPU with fxsave implemented, and enabled by OS. */ fxsave FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax) +#else + movl $FREEBSD_UC_MCONTEXT_FPOWNED_NONE,\ + FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) + movl $FREEBSD_UC_MCONTEXT_FPFMT_NODEV,\ + FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax) +#endif movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) From 61f4345a9e812713287e9f04949100416180b38f Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 13 Apr 2010 15:33:11 +0300 Subject: [PATCH 122/162] Fix an issue where len was too short for sysctl to recieve the process vm map. --- src/os-freebsd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index a88b908d..a6c42fee 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -72,6 +72,7 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, buf = get_mem(len1); if (buf == NULL) return (-1); + len = len1; error = sysctl(mib, 4, buf, &len, NULL, 0); if (error) { free_mem(buf, len1); From 1e77c66a51102090f429087fccc28cb6c383cce5 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 14 Apr 2010 12:04:28 +0300 Subject: [PATCH 123/162] Fix FreeBSD/x86_64 sigcontext restore --- src/x86_64/Gos-freebsd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c index 0e33aa8f..50ee60bd 100644 --- a/src/x86_64/Gos-freebsd.c +++ b/src/x86_64/Gos-freebsd.c @@ -186,7 +186,8 @@ HIDDEN NORETURN void x86_64_sigreturn (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - ucontext_t *uc = c->dwarf.cfa + offsetof(struct sigframe, sf_uc); + ucontext_t *uc = (ucontext_t *)(c->sigcontext_addr + + offsetof(struct sigframe, sf_uc)); Debug (8, "resuming at ip=%llx via sigreturn(%p)\n", (unsigned long long) c->dwarf.ip, uc); From 34b064bf2233ec8c9223786f4bc714585bbce4f7 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 14 Apr 2010 12:10:14 +0300 Subject: [PATCH 124/162] Fix typo. --- src/x86/Gos-freebsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index e88b4439..6a6406e7 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -53,7 +53,7 @@ unw_is_signal_frame (unw_cursor_t *cursor) sigcode+4: from amd64 freebsd32 environment 8d 44 24 20 lea 0x20(%esp),%eax 50 push %eax -b8 a1 01 00 00 mov $0x1a1,%ea +b8 a1 01 00 00 mov $0x1a1,%eax 50 push %eax cd 80 int $0x80 From 0d311ea1617fd0ebff52dfacc85746fcc165bb10 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 14 Apr 2010 12:10:34 +0300 Subject: [PATCH 125/162] Add abort() after sigreturn calls --- src/x86/Gos-freebsd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 6a6406e7..928955b4 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -346,11 +346,13 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) if (c->sigcontext_format == X86_SCF_NONE) { Debug (8, "resuming at ip=%x via setcontext()\n", c->dwarf.ip); setcontext (uc); + abort(); } else if (c->sigcontext_format == X86_SCF_FREEBSD_SIGFRAME) { struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); sigreturn((ucontext_t *)((const char *)sc + FREEBSD_UC_MCONTEXT_OFF)); + abort(); } else { Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", c->dwarf.ip, c->sigcontext_format); From 127acf8e97047f0c5faf31114b1fea370c0c6389 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 14 Apr 2010 12:15:05 +0300 Subject: [PATCH 126/162] Use correct offset name and value for ucontext offset in struct sigframe --- src/x86/Gos-freebsd.c | 2 +- src/x86/offsets.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c index 928955b4..247c35fa 100644 --- a/src/x86/Gos-freebsd.c +++ b/src/x86/Gos-freebsd.c @@ -351,7 +351,7 @@ x86_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) struct sigcontext *sc = (struct sigcontext *) c->sigcontext_addr; Debug (8, "resuming at ip=%x via sigreturn(%p)\n", c->dwarf.ip, sc); - sigreturn((ucontext_t *)((const char *)sc + FREEBSD_UC_MCONTEXT_OFF)); + sigreturn((ucontext_t *)((const char *)sc + FREEBSD_SC_UCONTEXT_OFF)); abort(); } else { Debug (8, "resuming at ip=%x for sigcontext format %d not implemented\n", diff --git a/src/x86/offsets.h b/src/x86/offsets.h index 0f07352b..e8a255cd 100644 --- a/src/x86/offsets.h +++ b/src/x86/offsets.h @@ -85,7 +85,7 @@ /* FreeBSD-specific definitions: */ -#define FREEBSD_SC_UCONTEXT_OFF 0x14 +#define FREEBSD_SC_UCONTEXT_OFF 0x20 #define FREEBSD_UC_MCONTEXT_OFF 0x10 #define FREEBSD_UC_MCONTEXT_GS_OFF 0x14 From 5a70fab4513e7215cc0a94b40905d5a2279be9bb Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 14 Apr 2010 18:54:20 -0700 Subject: [PATCH 127/162] Fix compiler warnings on x86 Linux --- src/x86/Gos-linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/x86/Gos-linux.c b/src/x86/Gos-linux.c index 255696ca..31f83bae 100644 --- a/src/x86/Gos-linux.c +++ b/src/x86/Gos-linux.c @@ -153,6 +153,9 @@ x86_get_scratch_loc (struct cursor *c, unw_regnum_t reg) case X86_SCF_LINUX_RT_SIGFRAME: addr += LINUX_UC_MCONTEXT_OFF; break; + + default: + return DWARF_NULL_LOC; } switch (reg) From 1d9c5a356d72993d8e9f5ac70811a723ea156403 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 14 Apr 2010 12:01:37 -0700 Subject: [PATCH 128/162] Fix compiler warnings on x86_64 Linux --- src/x86_64/Gos-linux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index b0c096c2..1bf4ba2f 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -146,6 +146,7 @@ x86_64_sigreturn (unw_cursor_t *cursor) "syscall" :: "r"(sc), "i"(SYS_rt_sigreturn) : "memory"); + abort(); } #endif From a67654e86f915051e6a3f1220facfb3619ffb837 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 14 Apr 2010 12:11:29 -0700 Subject: [PATCH 129/162] [PATCH] Reduce scope of the eh_frame_end local variable --- src/ptrace/_UPT_find_proc_info.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index b9ef5ed1..fedda639 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -168,7 +168,7 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, char *path, unw_word_t segbase, unw_word_t mapoff) { Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; - unw_word_t addr, eh_frame_start, eh_frame_end, fde_count, load_base; + unw_word_t addr, eh_frame_start, fde_count, load_base; unw_word_t max_load_addr = 0; struct dwarf_eh_frame_hdr *hdr; unw_proc_info_t pi; @@ -268,6 +268,8 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, #if 1 abort (); #else + unw_word_t eh_frame_end; + /* If there is no search table or it has an unsupported encoding, fall back on linear search. */ if (hdr->table_enc == DW_EH_PE_omit) From b1c68e060ca8b75c511d7c056fe951cdc83b0b1b Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 17 Apr 2010 00:17:58 +0300 Subject: [PATCH 130/162] Arrange the FreeBSD ucontext offset definitions in ascending order. --- src/x86_64/ucontext_i.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/x86_64/ucontext_i.h b/src/x86_64/ucontext_i.h index 10816d70..c1249bf6 100644 --- a/src/x86_64/ucontext_i.h +++ b/src/x86_64/ucontext_i.h @@ -45,38 +45,38 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define UC_SIGMASK 0x128 #define FPREGS_OFFSET_MXCSR 0x18 #elif defined __FreeBSD__ +#define UC_SIGMASK 0x0 +#define UC_MCONTEXT_GREGS_RDI 0x18 +#define UC_MCONTEXT_GREGS_RSI 0x20 +#define UC_MCONTEXT_GREGS_RDX 0x28 +#define UC_MCONTEXT_GREGS_RCX 0x30 #define UC_MCONTEXT_GREGS_R8 0x38 #define UC_MCONTEXT_GREGS_R9 0x40 +#define UC_MCONTEXT_GREGS_RAX 0x48 +#define UC_MCONTEXT_GREGS_RBX 0x50 +#define UC_MCONTEXT_GREGS_RBP 0x58 #define UC_MCONTEXT_GREGS_R10 0x60 #define UC_MCONTEXT_GREGS_R11 0x68 #define UC_MCONTEXT_GREGS_R12 0x70 #define UC_MCONTEXT_GREGS_R13 0x78 #define UC_MCONTEXT_GREGS_R14 0x80 #define UC_MCONTEXT_GREGS_R15 0x88 -#define UC_MCONTEXT_GREGS_RDI 0x18 -#define UC_MCONTEXT_GREGS_RSI 0x20 -#define UC_MCONTEXT_GREGS_RBP 0x58 -#define UC_MCONTEXT_GREGS_RBX 0x50 -#define UC_MCONTEXT_GREGS_RDX 0x28 -#define UC_MCONTEXT_GREGS_RAX 0x48 -#define UC_MCONTEXT_GREGS_RCX 0x30 -#define UC_MCONTEXT_GREGS_RSP 0xc8 -#define UC_MCONTEXT_GREGS_RIP 0xb0 -#define UC_MCONTEXT_RFLAGS 0xc0 -#define UC_MCONTEXT_FLAGS 0xa0 -#define UC_MCONTEXT_CS 0xb8 -#define UC_MCONTEXT_SS 0xd0 -#define UC_MCONTEXT_DS 0xa6 -#define UC_MCONTEXT_ES 0xa4 #define UC_MCONTEXT_FS 0x94 #define UC_MCONTEXT_GS 0x96 +#define UC_MCONTEXT_FLAGS 0xa0 +#define UC_MCONTEXT_ES 0xa4 +#define UC_MCONTEXT_DS 0xa6 +#define UC_MCONTEXT_GREGS_RIP 0xb0 +#define UC_MCONTEXT_CS 0xb8 +#define UC_MCONTEXT_RFLAGS 0xc0 +#define UC_MCONTEXT_GREGS_RSP 0xc8 +#define UC_MCONTEXT_SS 0xd0 #define UC_MCONTEXT_MC_LEN 0xd8 -#define UC_MCONTEXT_FPSTATE 0xf0 -#define UC_MCONTEXT_OWNEDFP 0xe8 #define UC_MCONTEXT_FPFORMAT 0xe0 +#define UC_MCONTEXT_OWNEDFP 0xe8 +#define UC_MCONTEXT_FPSTATE 0xf0 #define UC_MCONTEXT_FPOWNED_FPU 0x20001 #define UC_MCONTEXT_FPFMT_XMM 0x10002 #define UC_MCONTEXT_MC_LEN_VAL 0x320 -#define UC_SIGMASK 0x0 #endif From 75b76d1f45a78e82d8506e90ef6969a8b725ce04 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 17 Apr 2010 00:18:33 +0300 Subject: [PATCH 131/162] Save FPU context for i386. --- src/x86/getcontext-freebsd.S | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/x86/getcontext-freebsd.S b/src/x86/getcontext-freebsd.S index 92ae26f4..17adade8 100644 --- a/src/x86/getcontext-freebsd.S +++ b/src/x86/getcontext-freebsd.S @@ -61,20 +61,36 @@ _Ux86_getcontext: popl FREEBSD_UC_MCONTEXT_EFLAGS_OFF(%eax) movl $0, FREEBSD_UC_MCONTEXT_TRAPNO_OFF(%eax) -#if 0 + movl $FREEBSD_UC_MCONTEXT_FPOWNED_FPU,\ FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) movl $FREEBSD_UC_MCONTEXT_FPFMT_XMM,\ FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax) - /* Require CPU with fxsave implemented, and enabled by OS. */ - fxsave FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax) -#else - movl $FREEBSD_UC_MCONTEXT_FPOWNED_NONE,\ - FREEBSD_UC_MCONTEXT_OWNEDFP_OFF(%eax) - movl $FREEBSD_UC_MCONTEXT_FPFMT_NODEV,\ - FREEBSD_UC_MCONTEXT_FPFORMAT_OFF(%eax) -#endif + /* + * Require CPU with fxsave implemented, and enabled by OS. + * + * If passed ucontext is not aligned to 16-byte boundary, + * save fpu context into temporary aligned location on stack + * and then copy. + */ + leal FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax), %edx + testl $0xf, %edx + je 1f + movl %edx, %edi + movl %esp, %edx + subl $512, %esp + andl $~0xf, %esp + fxsave (%esp) + movl %esp, %esi + movl $512/4,%ecx + rep; movsl + movl %edx, %esp + movl FREEBSD_UC_MCONTEXT_ESI_OFF(%eax), %esi + movl FREEBSD_UC_MCONTEXT_EDI_OFF(%eax), %edi + jmp 2f +1: fxsave (%edx) +2: movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) From ee99dbec879212406d813b1bae56b988b4ab1e00 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 20 Apr 2010 17:45:18 +0300 Subject: [PATCH 132/162] Use mincore instead of msync when available --- configure.in | 2 +- src/x86/Ginit.c | 11 +++++++++++ src/x86_64/Ginit.c | 7 +++++++ tests/Makefile.am | 2 ++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index fcc88137..100df65d 100644 --- a/configure.in +++ b/configure.in @@ -76,7 +76,7 @@ dnl Checks for library functions. AC_FUNC_MEMCMP AC_TYPE_SIGNAL AC_CHECK_FUNCS(dl_iterate_phdr dl_phdr_removals_counter dlmodinfo getunwind \ - ttrace) + ttrace mincore) is_gcc_m64() { if test `echo $CFLAGS | grep "\-m64" -c` -eq 1 ; then echo ppc64; else diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 949bf28f..bfcbe183 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -24,6 +24,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include @@ -83,6 +87,9 @@ static int validate_mem (unw_word_t addr) { int i, victim; +#ifdef HAVE_MINCORE + char mvec[1]; +#endif addr = PAGE_START(addr); @@ -95,7 +102,11 @@ validate_mem (unw_word_t addr) return 0; } +#ifdef HAVE_MINCORE + if (mincore ((void *) addr, 1, mvec) == -1) +#else if (msync ((void *) addr, 1, MS_ASYNC) == -1) +#endif return -1; victim = lga_victim; diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index f222bf54..c67dde57 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -86,6 +86,9 @@ static int validate_mem (unw_word_t addr) { int i, victim; +#ifdef HAVE_MINCORE + char mvec[1]; +#endif addr = PAGE_START(addr); @@ -98,7 +101,11 @@ validate_mem (unw_word_t addr) return 0; } +#ifdef HAVE_MINCORE + if (mincore ((void *) addr, 1, mvec) == -1) +#else if (msync ((void *) addr, 1, MS_ASYNC) == -1) +#endif return -1; victim = lga_victim; diff --git a/tests/Makefile.am b/tests/Makefile.am index 8786923e..e794b751 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -39,6 +39,7 @@ endif #ARCH_IA64 Gtest-concurrent Ltest-concurrent \ Gtest-resume-sig Ltest-resume-sig \ Gtest-dyn1 Ltest-dyn1 \ + Gtest-simple \ test-async-sig test-flush-cache test-init-remote \ test-mem test-setjmp test-ptrace \ Ltest-nomalloc rs-race @@ -89,6 +90,7 @@ Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx Gtest_dyn1_SOURCES = Gtest-dyn1.c flush-cache.S Ltest_dyn1_SOURCES = Ltest-dyn1.c flush-cache.S +Gtest_simple_SOURCES = Gtest-simple.cxx test_static_link_SOURCES = test-static-link-loc.c test-static-link-gen.c test_static_link_LDFLAGS = -static forker_LDFLAGS = -static From 74677edb23a4b9ae5bd61c4db3d853d875084895 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 20 Apr 2010 17:54:16 +0300 Subject: [PATCH 133/162] Reverse local change --- tests/Makefile.am | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index e794b751..8786923e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -39,7 +39,6 @@ endif #ARCH_IA64 Gtest-concurrent Ltest-concurrent \ Gtest-resume-sig Ltest-resume-sig \ Gtest-dyn1 Ltest-dyn1 \ - Gtest-simple \ test-async-sig test-flush-cache test-init-remote \ test-mem test-setjmp test-ptrace \ Ltest-nomalloc rs-race @@ -90,7 +89,6 @@ Ltest_cxx_exceptions_SOURCES = Ltest-cxx-exceptions.cxx Gtest_dyn1_SOURCES = Gtest-dyn1.c flush-cache.S Ltest_dyn1_SOURCES = Ltest-dyn1.c flush-cache.S -Gtest_simple_SOURCES = Gtest-simple.cxx test_static_link_SOURCES = test-static-link-loc.c test-static-link-gen.c test_static_link_LDFLAGS = -static forker_LDFLAGS = -static From 44544132422ef87047490be3041da0bfebf27d69 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 21 Apr 2010 15:18:02 +0300 Subject: [PATCH 134/162] Account for possible unaligned access. --- src/x86/Ginit.c | 2 +- src/x86_64/Ginit.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index bfcbe183..4ed88bbd 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -88,7 +88,7 @@ validate_mem (unw_word_t addr) { int i, victim; #ifdef HAVE_MINCORE - char mvec[1]; + char mvec[2]; /* Unaligned access may cross page boundary */ #endif addr = PAGE_START(addr); diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index c67dde57..790f88be 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -87,7 +87,7 @@ validate_mem (unw_word_t addr) { int i, victim; #ifdef HAVE_MINCORE - char mvec[1]; + char mvec[2]; /* Unaligned access may cross page boundary */ #endif addr = PAGE_START(addr); @@ -102,7 +102,7 @@ validate_mem (unw_word_t addr) } #ifdef HAVE_MINCORE - if (mincore ((void *) addr, 1, mvec) == -1) + if (mincore ((void *) addr, sizeof (unw_word_t), mvec) == -1) #else if (msync ((void *) addr, 1, MS_ASYNC) == -1) #endif From 2709abc88376efe80d7d5ef6d9d4e740d5c9afcb Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 21 Apr 2010 15:33:37 +0300 Subject: [PATCH 135/162] msync() also may be called on unaligned address. --- src/x86/Ginit.c | 4 ++-- src/x86_64/Ginit.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 4ed88bbd..0af616a5 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -103,9 +103,9 @@ validate_mem (unw_word_t addr) } #ifdef HAVE_MINCORE - if (mincore ((void *) addr, 1, mvec) == -1) + if (mincore ((void *) addr, sizeof (unw_word_t), mvec) == -1) #else - if (msync ((void *) addr, 1, MS_ASYNC) == -1) + if (msync ((void *) addr, sizeof (unw_word_t), MS_ASYNC) == -1) #endif return -1; diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index 790f88be..ac5ea66f 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -104,7 +104,7 @@ validate_mem (unw_word_t addr) #ifdef HAVE_MINCORE if (mincore ((void *) addr, sizeof (unw_word_t), mvec) == -1) #else - if (msync ((void *) addr, 1, MS_ASYNC) == -1) + if (msync ((void *) addr, sizeof (unw_word_t), MS_ASYNC) == -1) #endif return -1; From 58f290e1ce5950beac3767acbde08fcb0e1ca03f Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Wed, 21 Apr 2010 15:43:05 +0300 Subject: [PATCH 136/162] Add config.h. --- src/x86_64/Ginit.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index ac5ea66f..14614f13 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -26,6 +26,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include From 250382c56d2c84fc3976cf8a4c834433bb68990d Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Tue, 20 Apr 2010 23:13:05 +0200 Subject: [PATCH 137/162] Use wider format when printing addresses in debug format. --- src/dwarf/Gfde.c | 2 +- src/dwarf/Gfind_proc_info-lsb.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/dwarf/Gfde.c b/src/dwarf/Gfde.c index 49e21db8..16e36ee2 100644 --- a/src/dwarf/Gfde.c +++ b/src/dwarf/Gfde.c @@ -293,7 +293,7 @@ dwarf_extract_proc_info_from_fde (unw_addr_space_t as, unw_accessors_t *a, cie_addr = (unw_word_t) ((uint64_t) cie_offset_addr - cie_offset); } - Debug (15, "looking for CIE at address %x\n", (int) cie_addr); + Debug (15, "looking for CIE at address %lx\n", (long) cie_addr); if ((ret = parse_cie (as, a, cie_addr, pi, &dci, base, arg)) < 0) return ret; diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index d7405301..1b0a5292 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -275,7 +275,7 @@ locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info, for (w = as->debug_frames; w; w = w->next) { - Debug (4, "checking %p: %x-%x\n", w, (int)w->start, (int)w->end); + Debug (4, "checking %p: %lx-%lx\n", w, (long)w->start, (long)w->end); if (addr >= w->start && addr < w->end) return w; } @@ -316,7 +316,7 @@ locate_debug_info (unw_addr_space_t as, struct dl_phdr_info *info, end = hdrlimit; } - Debug (4, "calculated bounds of %x-%x for '%s'\n", (int)start, (int)end, + Debug (4, "calculated bounds of %lx-%lx for '%s'\n", (long)start, (long)end, name); err = load_debug_frame (name, &buf, &bufsize, as == unw_local_addr_space); @@ -667,8 +667,8 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) NULL); if (err == 0) { - Debug (15, "start_ip = %x, end_ip = %x\n", - (int) this_pi.start_ip, (int) this_pi.end_ip); + Debug (15, "start_ip = %lx, end_ip = %lx\n", + (long) this_pi.start_ip, (long) this_pi.end_ip); debug_frame_tab_append (tab, item_start - (unw_word_t) (uintptr_t) buf, this_pi.start_ip); @@ -771,7 +771,7 @@ lookup (const struct table_entry *table, size_t table_size, int32_t rel_ip) { mid = (lo + hi) / 2; e = table + mid; - Debug (1, "e->start_ip_offset = %x\n", (int) e->start_ip_offset); + Debug (1, "e->start_ip_offset = %lx\n", (long) e->start_ip_offset); if (rel_ip < e->start_ip_offset) hi = mid; else @@ -897,8 +897,8 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, } if (!e) { - Debug (1, "IP %x inside range %x-%x, but no explicit unwind info found\n", - (int) ip, (int) di->start_ip, (int) di->end_ip); + Debug (1, "IP %lx inside range %lx-%lx, but no explicit unwind info found\n", + (long) ip, (long) di->start_ip, (long) di->end_ip); /* IP is inside this table's range, but there is no explicit unwind info. */ return -UNW_ENOINFO; @@ -909,9 +909,9 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, fde_addr = e->fde_offset + debug_frame_base; else fde_addr = e->fde_offset + segbase; - Debug (1, "e->fde_offset = %x, segbase = %x, debug_frame_base = %x, " - "fde_addr = %x\n", (int) e->fde_offset, (int) segbase, - (int) debug_frame_base, (int) fde_addr); + Debug (1, "e->fde_offset = %lx, segbase = %lx, debug_frame_base = %lx, " + "fde_addr = %lx\n", (long) e->fde_offset, (long) segbase, + (long) debug_frame_base, (long) fde_addr); if ((ret = dwarf_extract_proc_info_from_fde (as, a, &fde_addr, pi, need_unwind_info, debug_frame_base, arg)) < 0) From dac2d001afb1fa7040ca7d8ae57032f684d7023e Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Tue, 20 Apr 2010 23:13:09 +0200 Subject: [PATCH 138/162] Identify signal frames by augmentation attribute. --- include/dwarf.h | 2 + include/tdep-arm/libunwind_i.h | 3 ++ include/tdep-hppa/libunwind_i.h | 3 ++ include/tdep-ia64/libunwind_i.h | 3 ++ include/tdep-mips/libunwind_i.h | 3 ++ include/tdep-ppc32/libunwind_i.h | 3 ++ include/tdep-ppc64/libunwind_i.h | 3 ++ include/tdep-x86/libunwind_i.h | 3 ++ include/tdep-x86_64/libunwind_i.h | 18 ++++++++ src/dwarf/Gfde.c | 3 ++ src/dwarf/Gparser.c | 9 ++++ src/x86_64/Gos-linux.c | 72 +++++++++++++++++++++++++++---- src/x86_64/Gstep.c | 1 + 13 files changed, 117 insertions(+), 9 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index 37b5ec1c..53c803b2 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -247,6 +247,7 @@ typedef struct dwarf_reg_state unsigned short lru_chain; /* used for least-recently-used chain */ unsigned short coll_chain; /* used for hash collisions */ unsigned short hint; /* hint for next rs to try (or -1) */ + unsigned short signal_frame; /* optional machine-dependent signal info */ } dwarf_reg_state_t; @@ -266,6 +267,7 @@ typedef struct dwarf_cie_info uint8_t lsda_encoding; unsigned int sized_augmentation : 1; unsigned int have_abi_marker : 1; + unsigned int signal_frame : 1; } dwarf_cie_info_t; diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h index 3424d86a..2e1c4285 100644 --- a/include/tdep-arm/libunwind_i.h +++ b/include/tdep-arm/libunwind_i.h @@ -217,6 +217,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #ifdef UNW_LOCAL_ONLY # define tdep_find_proc_info(c,ip,n) \ diff --git a/include/tdep-hppa/libunwind_i.h b/include/tdep-hppa/libunwind_i.h index 553e97d8..d89cc65e 100644 --- a/include/tdep-hppa/libunwind_i.h +++ b/include/tdep-hppa/libunwind_i.h @@ -224,6 +224,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #ifdef UNW_LOCAL_ONLY # define tdep_find_proc_info(c,ip,n) \ diff --git a/include/tdep-ia64/libunwind_i.h b/include/tdep-ia64/libunwind_i.h index 552c9498..4936d516 100644 --- a/include/tdep-ia64/libunwind_i.h +++ b/include/tdep-ia64/libunwind_i.h @@ -220,6 +220,9 @@ struct ia64_global_unwind_state #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #define tdep_get_as(c) ((c)->as) #define tdep_get_as_arg(c) ((c)->as_arg) #define tdep_get_ip(c) ((c)->ip) diff --git a/include/tdep-mips/libunwind_i.h b/include/tdep-mips/libunwind_i.h index c2f756a1..298fae81 100644 --- a/include/tdep-mips/libunwind_i.h +++ b/include/tdep-mips/libunwind_i.h @@ -279,6 +279,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #ifdef UNW_LOCAL_ONLY # define tdep_find_proc_info(c,ip,n) \ diff --git a/include/tdep-ppc32/libunwind_i.h b/include/tdep-ppc32/libunwind_i.h index 05dd1356..b963bca8 100644 --- a/include/tdep-ppc32/libunwind_i.h +++ b/include/tdep-ppc32/libunwind_i.h @@ -256,6 +256,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #define tdep_get_func_addr UNW_OBJ(get_func_addr) #ifdef UNW_LOCAL_ONLY diff --git a/include/tdep-ppc64/libunwind_i.h b/include/tdep-ppc64/libunwind_i.h index 192a0343..799b511f 100644 --- a/include/tdep-ppc64/libunwind_i.h +++ b/include/tdep-ppc64/libunwind_i.h @@ -256,6 +256,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #define tdep_get_func_addr UNW_OBJ(get_func_addr) #ifdef UNW_LOCAL_ONLY diff --git a/include/tdep-x86/libunwind_i.h b/include/tdep-x86/libunwind_i.h index 9af007d1..bed8cbf0 100644 --- a/include/tdep-x86/libunwind_i.h +++ b/include/tdep-x86/libunwind_i.h @@ -240,6 +240,9 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c,rs) do {} while(0) +#define tdep_reuse_frame(c,rs) do {} while(0) #ifdef UNW_LOCAL_ONLY # define tdep_find_proc_info(c,ip,n) \ diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index f6a02897..c0227251 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -163,6 +163,15 @@ dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) #define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) #define tdep_access_reg UNW_OBJ(access_reg) #define tdep_access_fpreg UNW_OBJ(access_fpreg) +#if __linux__ +# define tdep_fetch_frame UNW_OBJ(fetch_frame) +# define tdep_cache_frame UNW_OBJ(cache_frame) +# define tdep_reuse_frame UNW_OBJ(reuse_frame) +#else +# define tdep_fetch_frame(c,ip,n) do {} while(0) +# define tdep_cache_frame(c,rs) do {} while(0) +# define tdep_reuse_frame(c,rs) do {} while(0) +#endif #ifdef UNW_LOCAL_ONLY # define tdep_find_proc_info(c,ip,n) \ @@ -196,5 +205,14 @@ extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, int write); +#if __linux__ +extern void tdep_fetch_frame (struct dwarf_cursor *c, unw_word_t ip, + int need_unwind_info); +extern void tdep_cache_frame (struct dwarf_cursor *c, + struct dwarf_reg_state *rs); +extern void tdep_reuse_frame (struct dwarf_cursor *c, + struct dwarf_reg_state *rs); +#endif + #endif /* X86_64_LIBUNWIND_I_H */ diff --git a/src/dwarf/Gfde.c b/src/dwarf/Gfde.c index 16e36ee2..8659624b 100644 --- a/src/dwarf/Gfde.c +++ b/src/dwarf/Gfde.c @@ -187,6 +187,9 @@ parse_cie (unw_addr_space_t as, unw_accessors_t *a, unw_word_t addr, break; case 'S': + /* This is a signal frame. */ + dci->signal_frame = 1; + /* Temporarily set it to one so dwarf_parse_fde() knows that it should fetch the actual ABI/TAG pair from the FDE. */ dci->have_abi_marker = 1; diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index db64b920..ccb710a3 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -400,6 +400,11 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info) c->pi_valid = 1; c->pi_is_dynamic = dynamic; + + /* Let system/machine-dependent code determine frame-specific attributes. */ + if (ret >= 0) + tdep_fetch_frame (c, ip, need_unwind_info); + return ret; } @@ -604,6 +609,8 @@ rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c) rs->hint = 0; rs->ip = c->ip; rs->ret_addr_column = c->ret_addr_column; + rs->signal_frame = 0; + tdep_cache_frame (c, rs); return rs; } @@ -818,6 +825,8 @@ dwarf_find_save_locs (struct dwarf_cursor *c) memcpy (&rs_copy, rs, sizeof (rs_copy)); put_rs_cache (c->as, cache, &saved_mask); + + tdep_reuse_frame (c, &rs_copy); if ((ret = apply_reg_state (c, &rs_copy)) < 0) return ret; diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index 1bf4ba2f..8337fa55 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -30,10 +30,59 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +HIDDEN void +tdep_fetch_frame (struct dwarf_cursor *dw, unw_word_t ip, int need_unwind_info) +{ + struct cursor *c = (struct cursor *) dw; + assert(! need_unwind_info || dw->pi_valid); + assert(! need_unwind_info || dw->pi.unwind_info); + if (dw->pi_valid + && dw->pi.unwind_info + && ((struct dwarf_cie_info *) dw->pi.unwind_info)->signal_frame) + { + c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; + c->sigcontext_addr = dw->cfa; + } + else + { + c->sigcontext_format = X86_64_SCF_NONE; + c->sigcontext_addr = 0; + } + + Debug(15, "fetch frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n", + dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr); +} + +HIDDEN void +tdep_cache_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs) +{ + struct cursor *c = (struct cursor *) dw; + rs->signal_frame = c->sigcontext_format; + + Debug(15, "cache frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n", + dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr); +} + +HIDDEN void +tdep_reuse_frame (struct dwarf_cursor *dw, struct dwarf_reg_state *rs) +{ + struct cursor *c = (struct cursor *) dw; + c->sigcontext_format = rs->signal_frame; + if (c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME) + c->sigcontext_addr = dw->cfa; + else + c->sigcontext_addr = 0; + + Debug(15, "reuse frame ip=0x%lx cfa=0x%lx format=%d addr=0x%lx\n", + dw->ip, dw->cfa, c->sigcontext_format, c->sigcontext_addr); +} + PROTECTED int unw_is_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; + return c->sigcontext_format != X86_64_SCF_NONE; +#if 0 unw_word_t w0, w1, ip; unw_addr_space_t as; unw_accessors_t *a; @@ -57,20 +106,24 @@ unw_is_signal_frame (unw_cursor_t *cursor) return 0; w1 &= 0xff; return (w0 == 0x0f0000000fc0c748 && w1 == 0x05); +#endif } PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { + /* Should not get here because we now use kernel-provided dwarf + information for the signal trampoline and dwarf_step() works. + Hence dwarf_step() should never call this function. Maybe + restore old non-dwarf signal handling here, but then the + gating on unw_is_signal_frame() needs to be removed. */ struct cursor *c = (struct cursor *) cursor; - int ret; - unw_word_t ucontext = c->dwarf.cfa; - - Debug(1, "signal frame, skip over trampoline\n"); - - c->sigcontext_format = X86_64_SCF_LINUX_RT_SIGFRAME; - c->sigcontext_addr = c->dwarf.cfa; - + Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", + c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); + assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME); + assert(c->sigcontext_addr == c->dwarf.cfa); + assert(0); +#if 0 struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); if (ret < 0) @@ -96,8 +149,9 @@ unw_handle_signal_frame (unw_cursor_t *cursor) c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); +#endif - return 0; + return 1; } #ifndef UNW_REMOTE_ONLY diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index d23be8ea..01022a19 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -38,6 +38,7 @@ unw_step (unw_cursor_t *cursor) c, (unsigned long long) c->dwarf.ip); /* Try DWARF-based unwinding... */ + c->sigcontext_format = X86_64_SCF_NONE; ret = dwarf_step (&c->dwarf); if (ret < 0 && ret != -UNW_ENOINFO) From 4c553ceb2c3fcde6248b05953abc34e162917c4a Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Tue, 20 Apr 2010 23:13:11 +0200 Subject: [PATCH 139/162] Identify end-of-stack by undefined return address location. --- src/dwarf/Gparser.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index ccb710a3..21b042c4 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -750,13 +750,20 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) break; } } - c->cfa = cfa; - ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip); - if (ret < 0) - return ret; - c->ip = ip; - /* XXX: check for ip to be code_aligned */ + c->cfa = cfa; + /* DWARF spec says undefined return address location means end of stack. */ + if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column])) + c->ip = 0; + else + { + ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip); + if (ret < 0) + return ret; + c->ip = ip; + } + + /* XXX: check for ip to be code_aligned */ if (c->ip == prev_ip && c->cfa == prev_cfa) { Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n", From a9dce3c06e6ffcb83957e734d960505415118f00 Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Sat, 24 Apr 2010 19:16:09 -0700 Subject: [PATCH 140/162] During the stack unwinding process, the return address points to the instruction after the call for a normal frame. libunwind uses IP-1 to lookup unwind information. However, this is not necessary for interrupted frames such as signal frames (or interrupt frames) in the kernel context. This patch handles both cases correctly. Based on work by Mark Wielaard --- include/dwarf.h | 1 + src/arm/Ginit_local.c | 2 +- src/arm/Ginit_remote.c | 2 +- src/arm/init.h | 3 ++- src/dwarf/Gparser.c | 36 +++++++++++++++++++++++++++++++++--- src/hppa/Ginit_local.c | 2 +- src/hppa/Ginit_remote.c | 2 +- src/hppa/init.h | 4 +++- src/mips/Ginit_local.c | 2 +- src/mips/Ginit_remote.c | 2 +- src/mips/init.h | 3 ++- src/ppc/Ginit_local.c | 4 ++-- src/ppc/Ginit_remote.c | 4 ++-- src/ppc32/init.h | 3 ++- src/ppc64/init.h | 3 ++- src/x86/Ginit_local.c | 2 +- src/x86/Ginit_remote.c | 2 +- src/x86/init.h | 3 ++- src/x86_64/Ginit_local.c | 2 +- src/x86_64/Ginit_remote.c | 2 +- src/x86_64/init.h | 3 ++- 21 files changed, 63 insertions(+), 24 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index 53c803b2..5dcc6ec9 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -295,6 +295,7 @@ typedef struct dwarf_cursor dwarf_loc_t loc[DWARF_NUM_PRESERVED_REGS]; + unsigned int use_prev_instr :1; /* use previous (= call) or current (= signal) instruction? */ unsigned int pi_valid :1; /* is proc_info valid? */ unsigned int pi_is_dynamic :1; /* proc_info found via dynamic proc info? */ unw_proc_info_t pi; /* info about current procedure */ diff --git a/src/arm/Ginit_local.c b/src/arm/Ginit_local.c index 7b2881e3..debf5bb5 100644 --- a/src/arm/Ginit_local.c +++ b/src/arm/Ginit_local.c @@ -47,7 +47,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as = unw_local_addr_space; c->dwarf.as_arg = uc; - return common_init (c); + return common_init (c, 1); } #endif /* !UNW_REMOTE_ONLY */ diff --git a/src/arm/Ginit_remote.c b/src/arm/Ginit_remote.c index 3baf3f60..854f3b62 100644 --- a/src/arm/Ginit_remote.c +++ b/src/arm/Ginit_remote.c @@ -40,6 +40,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) c->dwarf.as = as; c->dwarf.as_arg = as_arg; - return common_init (c); + return common_init (c, 0); #endif /* !UNW_LOCAL_ONLY */ } diff --git a/src/arm/init.h b/src/arm/init.h index 5b3f927d..a3025698 100644 --- a/src/arm/init.h +++ b/src/arm/init.h @@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" static inline int -common_init (struct cursor *c) +common_init (struct cursor *c, unsigned use_prev_instr) { int ret, i; @@ -62,6 +62,7 @@ common_init (struct cursor *c) c->dwarf.args_size = 0; c->dwarf.ret_addr_column = 0; + c->dwarf.use_prev_instr = use_prev_instr; c->dwarf.pi_valid = 0; c->dwarf.pi_is_dynamic = 0; c->dwarf.hint = 0; diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 21b042c4..3b1a2b40 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -76,7 +76,10 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, a = unw_get_accessors (as); curr_ip = c->pi.start_ip; - while (curr_ip < ip && *addr < end_addr) + /* Process everything up to and including the current 'ip', + including all the DW_CFA_advance_loc instructions. See + 'c->use_prev_instr' use in 'fetch_proc_info' for details. */ + while (curr_ip <= ip && *addr < end_addr) { if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0) return ret; @@ -381,7 +384,23 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info) { int ret, dynamic = 1; - --ip; + /* The 'ip' can point either to the previous or next instruction + depending on what type of frame we have: normal call or a place + to resume execution (e.g. after signal frame). + + For a normal call frame we need to back up so we point within the + call itself; this is important because a) the call might be the + very last instruction of the function and the edge of the FDE, + and b) so that run_cfi_program() runs locations up to the call + but not more. + + For execution resume, we need to do the exact opposite and look + up using the current 'ip' value. That is where execution will + continue, and it's important we get this right, as 'ip' could be + right at the function entry and hence FDE edge, or at instruction + that manipulates CFA (push/pop). */ + if (c->use_prev_instr) + --ip; if (c->pi_valid && !need_unwind_info) return 0; @@ -405,6 +424,14 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info) if (ret >= 0) tdep_fetch_frame (c, ip, need_unwind_info); + /* Update use_prev_instr for the next frame. */ + if (need_unwind_info) + { + assert(c->pi.unwind_info); + struct dwarf_cie_info *dci = c->pi.unwind_info; + c->use_prev_instr = ! dci->signal_frame; + } + return ret; } @@ -810,7 +837,10 @@ dwarf_find_save_locs (struct dwarf_cursor *c) rs = rs_lookup(cache, c); if (rs) - c->ret_addr_column = rs->ret_addr_column; + { + c->ret_addr_column = rs->ret_addr_column; + c->use_prev_instr = ! rs->signal_frame; + } else { if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 || diff --git a/src/hppa/Ginit_local.c b/src/hppa/Ginit_local.c index 243ffd49..6d4dd3df 100644 --- a/src/hppa/Ginit_local.c +++ b/src/hppa/Ginit_local.c @@ -48,7 +48,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as = unw_local_addr_space; c->dwarf.as_arg = uc; - return common_init (c); + return common_init (c, 1); } #endif /* !UNW_REMOTE_ONLY */ diff --git a/src/hppa/Ginit_remote.c b/src/hppa/Ginit_remote.c index 3d6606df..bd6093f1 100644 --- a/src/hppa/Ginit_remote.c +++ b/src/hppa/Ginit_remote.c @@ -41,6 +41,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) c->dwarf.as = as; c->dwarf.as_arg = as_arg; - return common_init (c); + return common_init (c, 0); #endif /* !UNW_LOCAL_ONLY */ } diff --git a/src/hppa/init.h b/src/hppa/init.h index d5f900d4..d14354f6 100644 --- a/src/hppa/init.h +++ b/src/hppa/init.h @@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" static inline int -common_init (struct cursor *c) +common_init (struct cursor *c, unsigned use_prev_instr) { int ret; @@ -40,5 +40,7 @@ common_init (struct cursor *c) ret = hppa_get (c, HPPA_REG_LOC (c, UNW_HPPA_SP), &c->sp); if (ret < 0) return ret; + + c->dwarf.use_prev_instr = use_prev_instr; return 0; } diff --git a/src/mips/Ginit_local.c b/src/mips/Ginit_local.c index 7b2881e3..debf5bb5 100644 --- a/src/mips/Ginit_local.c +++ b/src/mips/Ginit_local.c @@ -47,7 +47,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as = unw_local_addr_space; c->dwarf.as_arg = uc; - return common_init (c); + return common_init (c, 1); } #endif /* !UNW_REMOTE_ONLY */ diff --git a/src/mips/Ginit_remote.c b/src/mips/Ginit_remote.c index 3baf3f60..854f3b62 100644 --- a/src/mips/Ginit_remote.c +++ b/src/mips/Ginit_remote.c @@ -40,6 +40,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) c->dwarf.as = as; c->dwarf.as_arg = as_arg; - return common_init (c); + return common_init (c, 0); #endif /* !UNW_LOCAL_ONLY */ } diff --git a/src/mips/init.h b/src/mips/init.h index 98956d4a..e32e3c9e 100644 --- a/src/mips/init.h +++ b/src/mips/init.h @@ -25,7 +25,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" static inline int -common_init (struct cursor *c) +common_init (struct cursor *c, unsigned use_prev_instr) { int ret, i; @@ -47,6 +47,7 @@ common_init (struct cursor *c) c->dwarf.args_size = 0; c->dwarf.ret_addr_column = 0; + c->dwarf.use_prev_instr = use_prev_instr; c->dwarf.pi_valid = 0; c->dwarf.pi_is_dynamic = 0; c->dwarf.hint = 0; diff --git a/src/ppc/Ginit_local.c b/src/ppc/Ginit_local.c index 2d9ab2ce..b931b5b6 100644 --- a/src/ppc/Ginit_local.c +++ b/src/ppc/Ginit_local.c @@ -56,9 +56,9 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as = unw_local_addr_space; c->dwarf.as_arg = uc; #ifdef UNW_TARGET_PPC64 - return common_init_ppc64 (c); + return common_init_ppc64 (c, 1); #else - return common_init_ppc32 (c); + return common_init_ppc32 (c, 1); #endif } diff --git a/src/ppc/Ginit_remote.c b/src/ppc/Ginit_remote.c index 66269d2c..0f4b0fdb 100644 --- a/src/ppc/Ginit_remote.c +++ b/src/ppc/Ginit_remote.c @@ -50,9 +50,9 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) c->dwarf.as_arg = as_arg; #ifdef UNW_TARGET_PPC64 - return common_init_ppc64(c); + return common_init_ppc64 (c, 0); #elif UNW_TARGET_PPC32 - return common_init_ppc32 (c); + return common_init_ppc32 (c, 0); #else #error init_remote :: NO VALID PPC ARCH! #endif diff --git a/src/ppc32/init.h b/src/ppc32/init.h index 8badb178..c2208ad9 100644 --- a/src/ppc32/init.h +++ b/src/ppc32/init.h @@ -30,7 +30,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Here is the "common" init, for remote and local debuging" */ static inline int -common_init_ppc32 (struct cursor *c) +common_init_ppc32 (struct cursor *c, unsigned use_prev_instr) { int ret; int i; @@ -62,6 +62,7 @@ common_init_ppc32 (struct cursor *c) c->dwarf.args_size = 0; c->dwarf.ret_addr_column = 0; + c->dwarf.use_prev_instr = use_prev_instr; c->dwarf.pi_valid = 0; c->dwarf.pi_is_dynamic = 0; c->dwarf.hint = 0; diff --git a/src/ppc64/init.h b/src/ppc64/init.h index 886f14c4..64847b84 100644 --- a/src/ppc64/init.h +++ b/src/ppc64/init.h @@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" static inline int -common_init_ppc64 (struct cursor *c) +common_init_ppc64 (struct cursor *c, unsigned use_prev_instr) { int ret; int i; @@ -72,6 +72,7 @@ common_init_ppc64 (struct cursor *c) c->dwarf.args_size = 0; c->dwarf.ret_addr_column = 0; + c->dwarf.use_prev_instr = use_prev_instr; c->dwarf.pi_valid = 0; c->dwarf.pi_is_dynamic = 0; c->dwarf.hint = 0; diff --git a/src/x86/Ginit_local.c b/src/x86/Ginit_local.c index 55ab7490..5e8b6972 100644 --- a/src/x86/Ginit_local.c +++ b/src/x86/Ginit_local.c @@ -50,7 +50,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as_arg = c; c->uc = uc; c->validate = 0; - return common_init (c); + return common_init (c, 1); } #endif /* !UNW_REMOTE_ONLY */ diff --git a/src/x86/Ginit_remote.c b/src/x86/Ginit_remote.c index 6949a73e..aa924052 100644 --- a/src/x86/Ginit_remote.c +++ b/src/x86/Ginit_remote.c @@ -51,6 +51,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) c->dwarf.as_arg = as_arg; c->uc = 0; } - return common_init (c); + return common_init (c, 0); #endif /* !UNW_LOCAL_ONLY */ } diff --git a/src/x86/init.h b/src/x86/init.h index 675b77e5..b59ad842 100644 --- a/src/x86/init.h +++ b/src/x86/init.h @@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" static inline int -common_init (struct cursor *c) +common_init (struct cursor *c, unsigned use_prev_instr) { int ret, i; @@ -59,6 +59,7 @@ common_init (struct cursor *c) c->dwarf.args_size = 0; c->dwarf.ret_addr_column = 0; + c->dwarf.use_prev_instr = use_prev_instr; c->dwarf.pi_valid = 0; c->dwarf.pi_is_dynamic = 0; c->dwarf.hint = 0; diff --git a/src/x86_64/Ginit_local.c b/src/x86_64/Ginit_local.c index 1e80cb85..70bef3e1 100644 --- a/src/x86_64/Ginit_local.c +++ b/src/x86_64/Ginit_local.c @@ -52,7 +52,7 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as_arg = c; c->uc = uc; c->validate = 0; - return common_init (c); + return common_init (c, 1); } #endif /* !UNW_REMOTE_ONLY */ diff --git a/src/x86_64/Ginit_remote.c b/src/x86_64/Ginit_remote.c index 8aa644d3..25dd6860 100644 --- a/src/x86_64/Ginit_remote.c +++ b/src/x86_64/Ginit_remote.c @@ -52,6 +52,6 @@ unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) c->dwarf.as_arg = as_arg; c->uc = 0; } - return common_init (c); + return common_init (c, 0); #endif /* !UNW_LOCAL_ONLY */ } diff --git a/src/x86_64/init.h b/src/x86_64/init.h index ae108b24..dcd4aea2 100644 --- a/src/x86_64/init.h +++ b/src/x86_64/init.h @@ -28,7 +28,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" static inline int -common_init (struct cursor *c) +common_init (struct cursor *c, unsigned use_prev_instr) { int ret; @@ -64,6 +64,7 @@ common_init (struct cursor *c) c->dwarf.args_size = 0; c->dwarf.ret_addr_column = RIP; + c->dwarf.use_prev_instr = use_prev_instr; c->dwarf.pi_valid = 0; c->dwarf.pi_is_dynamic = 0; c->dwarf.hint = 0; From f252f5ff4e51af90fd6629f122f72556db94ccb7 Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Tue, 20 Apr 2010 23:13:14 +0200 Subject: [PATCH 141/162] Recognise and unwind through PLT. --- src/x86_64/Gstep.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 01022a19..d691aa6e 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -28,14 +28,38 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include +/* Recognise PLT entries such as: + 3bdf0: ff 25 e2 49 13 00 jmpq *0x1349e2(%rip) + 3bdf6: 68 ae 03 00 00 pushq $0x3ae + 3bdfb: e9 00 c5 ff ff jmpq 38300 <_init+0x18> */ +static int +is_plt_entry (struct dwarf_cursor *c) +{ + unw_word_t w0, w1; + unw_accessors_t *a; + int ret; + + a = unw_get_accessors (c->as); + if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 + || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) + return 0; + + ret = (((w0 & 0xffff) == 0x25ff) + && (((w0 >> 48) & 0xff) == 0x68) + && (((w1 >> 24) & 0xff) == 0xe9)); + + Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); + return ret; +} + PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret, i; - Debug (1, "(cursor=%p, ip=0x%016llx)\n", - c, (unsigned long long) c->dwarf.ip); + Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n", + c, c->dwarf.ip, c->dwarf.cfa); /* Try DWARF-based unwinding... */ c->sigcontext_format = X86_64_SCF_NONE; @@ -86,6 +110,12 @@ unw_step (unw_cursor_t *cursor) return 0; } } + else if (is_plt_entry (&c->dwarf)) + { + Debug (2, "found plt entry\n"); + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + c->dwarf.cfa += 8; + } else { unw_word_t rbp; @@ -133,7 +163,7 @@ unw_step (unw_cursor_t *cursor) c->dwarf.ret_addr_column = RIP; - if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) + if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP])) { ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", From 92cc7fd78a5a79c4bb5f85bfb7d7fb025df9cd5a Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Tue, 20 Apr 2010 23:13:16 +0200 Subject: [PATCH 142/162] Remove obsolete code for 'old way' of handling x86-64 signal frames. --- src/x86_64/Gos-linux.c | 53 ------------------------------------------ 1 file changed, 53 deletions(-) diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index 8337fa55..e2929beb 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -82,31 +82,6 @@ unw_is_signal_frame (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; return c->sigcontext_format != X86_64_SCF_NONE; -#if 0 - unw_word_t w0, w1, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* Check if RIP points at sigreturn sequence. - on x86_64 Linux that is (see libc.so): - 48 c7 c0 0f 00 00 00 mov $0xf,%rax - 0f 05 syscall - 66 data16 - */ - - ip = c->dwarf.ip; - if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0 - || (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0) - return 0; - w1 &= 0xff; - return (w0 == 0x0f0000000fc0c748 && w1 == 0x05); -#endif } PROTECTED int @@ -123,34 +98,6 @@ unw_handle_signal_frame (unw_cursor_t *cursor) assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME); assert(c->sigcontext_addr == c->dwarf.cfa); assert(0); -#if 0 - struct dwarf_loc rsp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - ret = dwarf_get (&c->dwarf, rsp_loc, &c->dwarf.cfa); - if (ret < 0) - { - Debug (2, "returning %d\n", ret); - return ret; - } - - c->dwarf.loc[RAX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RAX, 0); - c->dwarf.loc[RDX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDX, 0); - c->dwarf.loc[RCX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RCX, 0); - c->dwarf.loc[RBX] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBX, 0); - c->dwarf.loc[RSI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSI, 0); - c->dwarf.loc[RDI] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RDI, 0); - c->dwarf.loc[RBP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RBP, 0); - c->dwarf.loc[RSP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RSP, 0); - c->dwarf.loc[ R8] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0); - c->dwarf.loc[ R9] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0); - c->dwarf.loc[R10] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0); - c->dwarf.loc[R11] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0); - c->dwarf.loc[R12] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0); - c->dwarf.loc[R13] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0); - c->dwarf.loc[R14] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0); - c->dwarf.loc[R15] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0); - c->dwarf.loc[RIP] = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_RIP, 0); -#endif - return 1; } From d4fbc8326a91d246af29ff17131a12ed7ae87140 Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Tue, 20 Apr 2010 23:13:18 +0200 Subject: [PATCH 143/162] Detect end of stack in x86-64 rbp-based walk. --- src/x86_64/Gstep.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index d691aa6e..85e3989a 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -116,6 +116,11 @@ unw_step (unw_cursor_t *cursor) c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); c->dwarf.cfa += 8; } + else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) + { + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + } else { unw_word_t rbp; @@ -123,7 +128,8 @@ unw_step (unw_cursor_t *cursor) ret = dwarf_get (&c->dwarf, c->dwarf.loc[RBP], &rbp); if (ret < 0) { - Debug (2, "returning %d\n", ret); + Debug (2, "returning %d [RBP=0x%lx]\n", ret, + DWARF_GET_LOC (c->dwarf.loc[RBP])); return ret; } From 045c55b2a296988c16a4c1b90f3d8b7e8b78752b Mon Sep 17 00:00:00 2001 From: Lassi Tuura Date: Sat, 24 Apr 2010 19:24:49 -0700 Subject: [PATCH 144/162] Be conservative in all pointer derefrences by default. Since most people can't completely control their compile or runtime environment, it becomes hard to ensure that unwind data is perfect. --- configure.in | 6 ++++++ src/x86_64/Ginit_local.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/configure.in b/configure.in index fcc88137..e42445b2 100644 --- a/configure.in +++ b/configure.in @@ -169,6 +169,12 @@ if test x$enable_block_signals = xyes; then AC_DEFINE([CONFIG_BLOCK_SIGNALS], [], [Block signals before mutex operations]) fi +AC_ARG_ENABLE(conservative_checks, +[ --enable-conservative-checks Validate all memory addresses before use], +[enable_conservative_checks=$enableval], [enable_conservative_checks=yes]) +if test x$enable_conservative_checks = xyes; then + CPPFLAGS="${CPPFLAGS} -DCONSERVATIVE_CHECKS" +fi LIBUNWIND___THREAD diff --git a/src/x86_64/Ginit_local.c b/src/x86_64/Ginit_local.c index 70bef3e1..18b3d989 100644 --- a/src/x86_64/Ginit_local.c +++ b/src/x86_64/Ginit_local.c @@ -51,7 +51,11 @@ unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) c->dwarf.as = unw_local_addr_space; c->dwarf.as_arg = c; c->uc = uc; +#if CONSERVATIVE_CHECKS + c->validate = 1; +#else c->validate = 0; +#endif return common_init (c, 1); } From d3c4bc42952a1aad0297b6f86569178814275a83 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 25 Apr 2010 09:24:40 -0700 Subject: [PATCH 145/162] Fix a compiler warning --- src/x86_64/Gos-linux.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index e2929beb..826489f0 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -92,7 +92,6 @@ unw_handle_signal_frame (unw_cursor_t *cursor) Hence dwarf_step() should never call this function. Maybe restore old non-dwarf signal handling here, but then the gating on unw_is_signal_frame() needs to be removed. */ - struct cursor *c = (struct cursor *) cursor; Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME); From c140d8598d86c699ec619f3652aedbbddb142b69 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sun, 25 Apr 2010 09:44:59 -0700 Subject: [PATCH 146/162] Undo commit f252f5ff4e51af90fd6629f122f72556db94ccb7 for now. Seems to introduce a couple of test breakages. --- src/x86_64/Gstep.c | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 85e3989a..237811ce 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -28,38 +28,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include -/* Recognise PLT entries such as: - 3bdf0: ff 25 e2 49 13 00 jmpq *0x1349e2(%rip) - 3bdf6: 68 ae 03 00 00 pushq $0x3ae - 3bdfb: e9 00 c5 ff ff jmpq 38300 <_init+0x18> */ -static int -is_plt_entry (struct dwarf_cursor *c) -{ - unw_word_t w0, w1; - unw_accessors_t *a; - int ret; - - a = unw_get_accessors (c->as); - if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 - || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) - return 0; - - ret = (((w0 & 0xffff) == 0x25ff) - && (((w0 >> 48) & 0xff) == 0x68) - && (((w1 >> 24) & 0xff) == 0xe9)); - - Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); - return ret; -} - PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret, i; - Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n", - c, c->dwarf.ip, c->dwarf.cfa); + Debug (1, "(cursor=%p, ip=0x%016llx)\n", + c, (unsigned long long) c->dwarf.ip); /* Try DWARF-based unwinding... */ c->sigcontext_format = X86_64_SCF_NONE; @@ -110,12 +86,6 @@ unw_step (unw_cursor_t *cursor) return 0; } } - else if (is_plt_entry (&c->dwarf)) - { - Debug (2, "found plt entry\n"); - c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); - c->dwarf.cfa += 8; - } else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) { for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) @@ -169,7 +139,7 @@ unw_step (unw_cursor_t *cursor) c->dwarf.ret_addr_column = RIP; - if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP])) + if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) { ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", From 215afa30b782970479e956b7bb96dca7cd9325ea Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 28 Apr 2010 16:32:30 -0700 Subject: [PATCH 147/162] Add unwind descriptors to getcontext.S --- src/x86/getcontext-freebsd.S | 2 ++ src/x86/getcontext-linux.S | 2 ++ src/x86_64/getcontext.S | 4 ++++ tests/run-ptrace-mapper | 2 +- 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/x86/getcontext-freebsd.S b/src/x86/getcontext-freebsd.S index 92ae26f4..eb435394 100644 --- a/src/x86/getcontext-freebsd.S +++ b/src/x86/getcontext-freebsd.S @@ -27,6 +27,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .global _Ux86_getcontext .type _Ux86_getcontext, @function _Ux86_getcontext: + .cfi_startproc pushl %eax mov 8(%esp),%eax /* ucontext_t* */ popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) @@ -81,6 +82,7 @@ _Ux86_getcontext: xorl %eax, %eax ret + .cfi_endproc .size _Ux86_getcontext, . - _Ux86_getcontext /* We do not need executable stack. */ diff --git a/src/x86/getcontext-linux.S b/src/x86/getcontext-linux.S index a0714cd1..c469dadb 100644 --- a/src/x86/getcontext-linux.S +++ b/src/x86/getcontext-linux.S @@ -36,6 +36,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .global _Ux86_getcontext .type _Ux86_getcontext, @function _Ux86_getcontext: + .cfi_startproc mov 4(%esp),%eax /* ucontext_t* */ /* EAX is not preserved. */ @@ -66,6 +67,7 @@ _Ux86_getcontext: xor %eax, %eax ret + .cfi_endproc .size _Ux86_getcontext, . - _Ux86_getcontext /* We do not need executable stack. */ diff --git a/src/x86_64/getcontext.S b/src/x86_64/getcontext.S index a0df6f15..15fff283 100644 --- a/src/x86_64/getcontext.S +++ b/src/x86_64/getcontext.S @@ -37,6 +37,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ .global _Ux86_64_getcontext .type _Ux86_64_getcontext, @function _Ux86_64_getcontext: + .cfi_startproc /* Callee saved: RBX, RBP, R12-R15 */ movq %r12, UC_MCONTEXT_GREGS_R12(%rdi) @@ -70,7 +71,9 @@ _Ux86_64_getcontext: /* Save rflags and segment registers, so that sigreturn(2) does not complain. */ pushfq + .cfi_adjust_cfa_offset 8 popq UC_MCONTEXT_RFLAGS(%rdi) + .cfi_adjust_cfa_offset -8 movl $0, UC_MCONTEXT_FLAGS(%rdi) movw %cs, UC_MCONTEXT_CS(%rdi) movw %ss, UC_MCONTEXT_SS(%rdi) @@ -95,6 +98,7 @@ _Ux86_64_getcontext: xorq %rax, %rax retq + .cfi_endproc .size _Ux86_64_getcontext, . - _Ux86_64_getcontext /* We do not need executable stack. */ diff --git a/tests/run-ptrace-mapper b/tests/run-ptrace-mapper index f51cf9a1..dc3010d4 100755 --- a/tests/run-ptrace-mapper +++ b/tests/run-ptrace-mapper @@ -1,2 +1,2 @@ #!/bin/sh -./test-ptrace -c -n -t ./mapper +./test-ptrace -c -n -t ./mapper $* From fdc534ccb05d1e6c0438345d292203343a811701 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 28 Apr 2010 16:38:27 -0700 Subject: [PATCH 148/162] Silence a compiler warning --- src/x86_64/Gos-linux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index e2929beb..b7f832ca 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -87,6 +87,7 @@ unw_is_signal_frame (unw_cursor_t *cursor) PROTECTED int unw_handle_signal_frame (unw_cursor_t *cursor) { +#if UNW_DEBUG /* To silence compiler warnings */ /* Should not get here because we now use kernel-provided dwarf information for the signal trampoline and dwarf_step() works. Hence dwarf_step() should never call this function. Maybe @@ -98,6 +99,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME); assert(c->sigcontext_addr == c->dwarf.cfa); assert(0); +#endif return 1; } From c84005e9c8226917747c1e8ba31a13bff25b0c84 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 2 May 2010 17:06:24 +0300 Subject: [PATCH 149/162] Add unwind annotations for freebsd/x86 getcontext.S. Rearrange the code to put the slow branch out of main body, and pinch the fixed amount of stack space to be able to annotate the code. --- src/x86/getcontext-freebsd.S | 41 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/x86/getcontext-freebsd.S b/src/x86/getcontext-freebsd.S index dfeb4328..670eff1a 100644 --- a/src/x86/getcontext-freebsd.S +++ b/src/x86/getcontext-freebsd.S @@ -29,8 +29,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ _Ux86_getcontext: .cfi_startproc pushl %eax + .cfi_adjust_cfa_offset 4 mov 8(%esp),%eax /* ucontext_t* */ popl FREEBSD_UC_MCONTEXT_EAX_OFF(%eax) + .cfi_adjust_cfa_offset 4 movl %ebx, FREEBSD_UC_MCONTEXT_EBX_OFF(%eax) movl %ecx, FREEBSD_UC_MCONTEXT_ECX_OFF(%eax) movl %edx, FREEBSD_UC_MCONTEXT_EDX_OFF(%eax) @@ -59,7 +61,9 @@ _Ux86_getcontext: movl %ecx, FREEBSD_UC_MCONTEXT_CS_OFF(%eax) pushfl + .cfi_adjust_cfa_offset 4 popl FREEBSD_UC_MCONTEXT_EFLAGS_OFF(%eax) + .cfi_adjust_cfa_offset -4 movl $0, FREEBSD_UC_MCONTEXT_TRAPNO_OFF(%eax) @@ -77,27 +81,30 @@ _Ux86_getcontext: */ leal FREEBSD_UC_MCONTEXT_FPSTATE_OFF(%eax), %edx testl $0xf, %edx - je 1f - movl %edx, %edi - movl %esp, %edx - subl $512, %esp - andl $~0xf, %esp - fxsave (%esp) - movl %esp, %esi - movl $512/4,%ecx - rep; movsl - movl %edx, %esp - movl FREEBSD_UC_MCONTEXT_ESI_OFF(%eax), %esi - movl FREEBSD_UC_MCONTEXT_EDI_OFF(%eax), %edi - jmp 2f -1: fxsave (%edx) -2: - - movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ + jne 2f + fxsave (%edx) /* fast path, passed ucontext save area was aligned */ +1: movl $FREEBSD_UC_MCONTEXT_MC_LEN_VAL,\ FREEBSD_UC_MCONTEXT_MC_LEN_OFF(%eax) xorl %eax, %eax ret + +2: movl %edx, %edi /* not aligned, do the dance */ + subl $512 + 16, %esp /* save area and 16 bytes for alignment */ + .cfi_adjust_cfa_offset 512 + 16 + movl %esp, %edx + orl $0xf, %edx /* align *%edx to 16-byte up */ + incl %edx + fxsave (%edx) + movl %edx, %esi /* copy to the final destination */ + movl $512/4,%ecx + rep; movsl + addl $512 + 16, %esp /* restore the stack */ + .cfi_adjust_cfa_offset -512 - 16 + movl FREEBSD_UC_MCONTEXT_ESI_OFF(%eax), %esi + movl FREEBSD_UC_MCONTEXT_EDI_OFF(%eax), %edi + jmp 1b + .cfi_endproc .size _Ux86_getcontext, . - _Ux86_getcontext From aa3bb307a30a5b78bf1ae4ac843ae53e354736f5 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Mon, 3 May 2010 07:47:28 -0700 Subject: [PATCH 150/162] Fix merge errors --- src/x86_64/Gos-linux.c | 1 + src/x86_64/Gstep.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/x86_64/Gos-linux.c b/src/x86_64/Gos-linux.c index 957f3e30..b7f832ca 100644 --- a/src/x86_64/Gos-linux.c +++ b/src/x86_64/Gos-linux.c @@ -93,6 +93,7 @@ unw_handle_signal_frame (unw_cursor_t *cursor) Hence dwarf_step() should never call this function. Maybe restore old non-dwarf signal handling here, but then the gating on unw_is_signal_frame() needs to be removed. */ + struct cursor *c = (struct cursor *) cursor; Debug(1, "old format signal frame? format=%d addr=0x%lx cfa=0x%lx\n", c->sigcontext_format, c->sigcontext_addr, c->dwarf.cfa); assert(c->sigcontext_format == X86_64_SCF_LINUX_RT_SIGFRAME); diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c index 237811ce..85e3989a 100644 --- a/src/x86_64/Gstep.c +++ b/src/x86_64/Gstep.c @@ -28,14 +28,38 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "unwind_i.h" #include +/* Recognise PLT entries such as: + 3bdf0: ff 25 e2 49 13 00 jmpq *0x1349e2(%rip) + 3bdf6: 68 ae 03 00 00 pushq $0x3ae + 3bdfb: e9 00 c5 ff ff jmpq 38300 <_init+0x18> */ +static int +is_plt_entry (struct dwarf_cursor *c) +{ + unw_word_t w0, w1; + unw_accessors_t *a; + int ret; + + a = unw_get_accessors (c->as); + if ((ret = (*a->access_mem) (c->as, c->ip, &w0, 0, c->as_arg)) < 0 + || (ret = (*a->access_mem) (c->as, c->ip + 8, &w1, 0, c->as_arg)) < 0) + return 0; + + ret = (((w0 & 0xffff) == 0x25ff) + && (((w0 >> 48) & 0xff) == 0x68) + && (((w1 >> 24) & 0xff) == 0xe9)); + + Debug (14, "ip=0x%lx => 0x%016lx 0x%016lx, ret = %d\n", c->ip, w0, w1, ret); + return ret; +} + PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; int ret, i; - Debug (1, "(cursor=%p, ip=0x%016llx)\n", - c, (unsigned long long) c->dwarf.ip); + Debug (1, "(cursor=%p, ip=0x%016lx, cfa=0x%016lx)\n", + c, c->dwarf.ip, c->dwarf.cfa); /* Try DWARF-based unwinding... */ c->sigcontext_format = X86_64_SCF_NONE; @@ -86,6 +110,12 @@ unw_step (unw_cursor_t *cursor) return 0; } } + else if (is_plt_entry (&c->dwarf)) + { + Debug (2, "found plt entry\n"); + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + c->dwarf.cfa += 8; + } else if (DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) { for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) @@ -139,7 +169,7 @@ unw_step (unw_cursor_t *cursor) c->dwarf.ret_addr_column = RIP; - if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RBP])) + if (!DWARF_IS_NULL_LOC (c->dwarf.loc[RIP])) { ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", From 66b7335ff3d10210e43bdd0cb8a3af80b7dba4e9 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 15 May 2010 11:56:37 -0700 Subject: [PATCH 151/162] Adds missing register offsets for ARM Signed-off-by: Andris Zeila --- src/ptrace/_UPT_reg_offset.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c index 40f3b1ba..d6e12741 100644 --- a/src/ptrace/_UPT_reg_offset.c +++ b/src/ptrace/_UPT_reg_offset.c @@ -338,6 +338,22 @@ int _UPT_reg_offset[UNW_REG_LAST + 1] = #elif defined(UNW_TARGET_PPC32) #elif defined(UNW_TARGET_PPC64) #elif defined(UNW_TARGET_ARM) + [UNW_ARM_R0] = 0x00, + [UNW_ARM_R1] = 0x04, + [UNW_ARM_R2] = 0x08, + [UNW_ARM_R3] = 0x0c, + [UNW_ARM_R4] = 0x10, + [UNW_ARM_R5] = 0x14, + [UNW_ARM_R6] = 0x18, + [UNW_ARM_R7] = 0x1c, + [UNW_ARM_R8] = 0x20, + [UNW_ARM_R9] = 0x24, + [UNW_ARM_R10] = 0x28, + [UNW_ARM_R11] = 0x2c, + [UNW_ARM_R12] = 0x30, + [UNW_ARM_R13] = 0x34, + [UNW_ARM_R14] = 0x38, + [UNW_ARM_R15] = 0x3c, #elif defined(UNW_TARGET_MIPS) #else # error Fix me. From b115ab645a44071f0a51742f5804dbceebd3f1ac Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 15 May 2010 11:57:35 -0700 Subject: [PATCH 152/162] Ignore separate debug files which contain a .gnu_debuglink section. Current implementation fails to find separate debug symbols when .gnu_debuglink is set to the same name of the target ELF basename (e.g. "libc.so.6" for /lib/libc.so.6). This patch fixes this by ignoring separate debug files that contain a .gnu_debuglink section. It also fixes a small typo in a related Debug() line. Signed-off-by: Andris Zeila --- src/dwarf/Gfind_proc_info-lsb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 1b0a5292..1abdd0b0 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -154,7 +154,7 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) Debug (4, "read %zd bytes of .debug_frame from offset %zd\n", *bufsize, sec_hdrs[i].sh_offset); } - else if (is_local >= 0 && strcmp (secname, ".gnu_debuglink") == 0) + else if (strcmp (secname, ".gnu_debuglink") == 0) { linksize = sec_hdrs[i].sh_size; linkbuf = malloc (linksize); @@ -163,7 +163,7 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) fread (linkbuf, 1, linksize, f); Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n", - *bufsize, sec_hdrs[i].sh_offset); + linksize, sec_hdrs[i].sh_offset); } } @@ -172,6 +172,13 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) fclose (f); + /* Ignore separate debug files which contain a .gnu_debuglink section. */ + if (linkbuf && is_local == -1) + { + free (linkbuf); + return 1; + } + if (*buf == NULL && linkbuf != NULL && memchr (linkbuf, 0, linksize) != NULL) { char *newname, *basedir, *p; From 1787a2fd284a786b409af74047a12de02c644cd1 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 15 May 2010 12:14:09 -0700 Subject: [PATCH 153/162] Add path and pathlen arguments to tdep_get_elf_image() Signed-off-by: Andris Zeila --- include/tdep-arm/libunwind_i.h | 3 ++- include/tdep-hppa/libunwind_i.h | 3 ++- include/tdep-ia64/libunwind_i.h | 3 ++- include/tdep-mips/libunwind_i.h | 3 ++- include/tdep-ppc32/libunwind_i.h | 3 ++- include/tdep-ppc64/libunwind_i.h | 3 ++- include/tdep-x86/libunwind_i.h | 3 ++- include/tdep-x86_64/libunwind_i.h | 3 ++- src/elfxx.c | 3 ++- src/os-freebsd.c | 6 +++++- src/os-hpux.c | 18 +++++++++++++----- src/os-linux.c | 8 ++++++-- src/ptrace/_UPT_find_proc_info.c | 3 ++- 13 files changed, 44 insertions(+), 18 deletions(-) diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h index 2e1c4285..faa35fce 100644 --- a/include/tdep-arm/libunwind_i.h +++ b/include/tdep-arm/libunwind_i.h @@ -248,7 +248,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t *uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-hppa/libunwind_i.h b/include/tdep-hppa/libunwind_i.h index d89cc65e..50d1aabd 100644 --- a/include/tdep-hppa/libunwind_i.h +++ b/include/tdep-hppa/libunwind_i.h @@ -255,7 +255,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t *uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-ia64/libunwind_i.h b/include/tdep-ia64/libunwind_i.h index 4936d516..75cc220d 100644 --- a/include/tdep-ia64/libunwind_i.h +++ b/include/tdep-ia64/libunwind_i.h @@ -247,7 +247,8 @@ extern void tdep_put_unwind_info (unw_addr_space_t as, extern void *tdep_uc_addr (ucontext_t *uc, unw_regnum_t regnum, uint8_t *nat_bitnr); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-mips/libunwind_i.h b/include/tdep-mips/libunwind_i.h index 298fae81..160a6372 100644 --- a/include/tdep-mips/libunwind_i.h +++ b/include/tdep-mips/libunwind_i.h @@ -309,7 +309,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t *uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-ppc32/libunwind_i.h b/include/tdep-ppc32/libunwind_i.h index b963bca8..e775dd64 100644 --- a/include/tdep-ppc32/libunwind_i.h +++ b/include/tdep-ppc32/libunwind_i.h @@ -292,7 +292,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t * uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t * valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-ppc64/libunwind_i.h b/include/tdep-ppc64/libunwind_i.h index 799b511f..bb6c977b 100644 --- a/include/tdep-ppc64/libunwind_i.h +++ b/include/tdep-ppc64/libunwind_i.h @@ -292,7 +292,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t * uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t * valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-x86/libunwind_i.h b/include/tdep-x86/libunwind_i.h index bed8cbf0..bc381e91 100644 --- a/include/tdep-x86/libunwind_i.h +++ b/include/tdep-x86/libunwind_i.h @@ -271,7 +271,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t *uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index c0227251..ea502ec4 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -200,7 +200,8 @@ extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, int need_unwind_info, void *arg); extern void *tdep_uc_addr (ucontext_t *uc, int reg); extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff); + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, int write); extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, diff --git a/src/elfxx.c b/src/elfxx.c index 05b99438..06cc9bb6 100644 --- a/src/elfxx.c +++ b/src/elfxx.c @@ -25,6 +25,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#include #include "libunwind_i.h" @@ -147,7 +148,7 @@ elf_w (get_proc_name) (unw_addr_space_t as, pid_t pid, unw_word_t ip, Elf_W (Phdr) *phdr; int i, ret; - ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff); + ret = tdep_get_elf_image (&ei, pid, ip, &segbase, &mapoff, NULL, 0); if (ret < 0) return ret; diff --git a/src/os-freebsd.c b/src/os-freebsd.c index a6c42fee..6b1a6e17 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -52,7 +52,7 @@ free_mem(void *ptr, size_t sz) PROTECTED int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff) + unsigned long *segbase, unsigned long *mapoff, char *path, size_t pathlen) { int mib[4], error, ret; size_t len, len1; @@ -87,6 +87,10 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, break; *segbase = kv->kve_start; *mapoff = kv->kve_offset; + if (path) + { + strncpy(path, kb->kve_path, pathlen); + } ret = elf_map_image(ei, kv->kve_path); break; } diff --git a/src/os-hpux.c b/src/os-hpux.c index 586ace2e..09100d0f 100644 --- a/src/os-hpux.c +++ b/src/os-hpux.c @@ -26,6 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef UNW_REMOTE_ONLY #include +#include #include #include "libunwind_i.h" @@ -34,10 +35,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ HIDDEN int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff) + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); { struct load_module_desc lmd; - const char *path; + const char *path2; if (pid != getpid ()) { @@ -51,10 +53,16 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, *segbase = lmd.text_base; *mapoff = 0; /* XXX fix me? */ - path = dlgetname (&lmd, sizeof (lmd), NULL, 0, 0); - if (!path) + path2 = dlgetname (&lmd, sizeof (lmd), NULL, 0, 0); + if (!path2) return -UNW_ENOINFO; - + if (path) + { + strncpy(path, path2, pathlen); + path[pathlen - 1] = '\0'; + if (strcmp(path, path2) != 0) + Debug(1, "buffer size (%d) not big enough to hold path\n", pathlen); + } Debug(1, "segbase=%lx, mapoff=%lx, path=%s\n", *segbase, *mapoff, path); return elf_map_image (ei, path); diff --git a/src/os-linux.c b/src/os-linux.c index 210edd05..791b27eb 100644 --- a/src/os-linux.c +++ b/src/os-linux.c @@ -33,7 +33,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ PROTECTED int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff) + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen) { struct map_iterator mi; int found = 0, rc; @@ -54,7 +55,10 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, maps_close (&mi); return -1; } - + if (path) + { + strncpy(path, mi.path, pathlen); + } rc = elf_map_image (ei, mi.path); maps_close (&mi); return rc; diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index fedda639..4d70bf59 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -342,7 +342,8 @@ get_unwind_info (struct UPT_info *ui, unw_addr_space_t as, unw_word_t ip) ui->di_cache.start_ip = ui->di_cache.end_ip = 0; } - if (tdep_get_elf_image (&ui->ei, ui->pid, ip, &segbase, &mapoff) < 0) + if (tdep_get_elf_image (&ui->ei, ui->pid, ip, &segbase, &mapoff, path, + sizeof(path)) < 0) return NULL; /* Here, SEGBASE is the starting-address of the (mmap'ped) segment From 8ee7b1762ed76957a86d6c84a1d34ee49eda37a3 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Sat, 15 May 2010 12:15:49 -0700 Subject: [PATCH 154/162] Add ip argument to _UPTi_find_unwind_table. Signed-off-by: Andris Zeila --- src/ptrace/_UPT_find_proc_info.c | 8 +++++--- src/ptrace/_UPT_internal.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index 4d70bf59..a0bd52c4 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -97,7 +97,8 @@ find_gp (struct UPT_info *ui, Elf64_Phdr *pdyn, Elf64_Addr load_base) HIDDEN unw_dyn_info_t * _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff) + char *path, unw_word_t segbase, unw_word_t mapoff, + unw_word_t ip) { Elf64_Phdr *phdr, *ptxt = NULL, *punw = NULL, *pdyn = NULL; Elf64_Ehdr *ehdr; @@ -165,7 +166,8 @@ dwarf_read_encoded_pointer (unw_addr_space_t as, unw_accessors_t *a, HIDDEN unw_dyn_info_t * _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, - char *path, unw_word_t segbase, unw_word_t mapoff) + char *path, unw_word_t segbase, unw_word_t mapoff, + unw_word_t ip) { Elf_W(Phdr) *phdr, *ptxt = NULL, *peh_hdr = NULL, *pdyn = NULL; unw_word_t addr, eh_frame_start, fde_count, load_base; @@ -348,7 +350,7 @@ get_unwind_info (struct UPT_info *ui, unw_addr_space_t as, unw_word_t ip) /* Here, SEGBASE is the starting-address of the (mmap'ped) segment which covers the IP we're looking for. */ - di = _UPTi_find_unwind_table (ui, as, path, segbase, mapoff); + di = _UPTi_find_unwind_table (ui, as, path, segbase, mapoff, ip); if (!di /* This can happen in corner cases where dynamically generated code falls into the same page that contains the data-segment diff --git a/src/ptrace/_UPT_internal.h b/src/ptrace/_UPT_internal.h index bc7bf9c1..ff11e738 100644 --- a/src/ptrace/_UPT_internal.h +++ b/src/ptrace/_UPT_internal.h @@ -62,6 +62,7 @@ extern unw_dyn_info_t *_UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, char *path, unw_word_t segbase, - unw_word_t mapoff); + unw_word_t mapoff, + unw_word_t ip); #endif /* _UPT_internal_h */ From 298e575f2cbb4616004717812f28879b2633a6ac Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Mon, 17 May 2010 21:57:59 +0300 Subject: [PATCH 155/162] Fix freebsd build --- src/os-freebsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os-freebsd.c b/src/os-freebsd.c index 6b1a6e17..a3151886 100644 --- a/src/os-freebsd.c +++ b/src/os-freebsd.c @@ -89,7 +89,7 @@ tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, *mapoff = kv->kve_offset; if (path) { - strncpy(path, kb->kve_path, pathlen); + strncpy(path, kv->kve_path, pathlen); } ret = elf_map_image(ei, kv->kve_path); break; From 546463d1e78d52197ff2c204f793c343abb97dc5 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 26 May 2010 19:21:30 -0700 Subject: [PATCH 156/162] Factor out and export dwarf_find_debug_frame() function Signed-off-by: Andris Zeila --- configure.in | 1 + include/dwarf.h | 4 + src/dwarf/Gfind_proc_info-lsb.c | 308 +++++++++++++++++--------------- tests/check-namespace.sh.in | 9 + 4 files changed, 182 insertions(+), 140 deletions(-) diff --git a/configure.in b/configure.in index f09a3230..8e2d138e 100644 --- a/configure.in +++ b/configure.in @@ -217,6 +217,7 @@ AC_SUBST(PKG_MINOR) AC_SUBST(PKG_EXTRA) AC_SUBST(PKG_MAINTAINER) AC_SUBST(enable_cxx_exceptions) +AC_SUBST(enable_debug_frame) AC_SUBST(DLLIB) AC_CONFIG_FILES(Makefile src/Makefile tests/Makefile tests/check-namespace.sh diff --git a/include/dwarf.h b/include/dwarf.h index 5dcc6ec9..82d1f9f8 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -39,6 +39,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ struct dwarf_cursor; /* forward-declaration */ #include "dwarf-config.h" +#include /* DWARF expression opcodes. */ @@ -348,6 +349,7 @@ struct unw_debug_frame_list /* Convenience macros: */ #define dwarf_init UNW_ARCH_OBJ (dwarf_init) #define dwarf_find_proc_info UNW_OBJ (dwarf_find_proc_info) +#define dwarf_find_debug_frame UNW_OBJ (dwarf_find_debug_frame) #define dwarf_search_unwind_table UNW_OBJ (dwarf_search_unwind_table) #define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info) #define dwarf_put_unwind_info UNW_OBJ (dwarf_put_unwind_info) @@ -364,6 +366,8 @@ extern int dwarf_init (void); extern int dwarf_find_proc_info (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, int need_unwind_info, void *arg); +extern int dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, + struct dl_phdr_info *info, unw_word_t ip); extern int dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, unw_dyn_info_t *di, diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 1abdd0b0..9718260d 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -108,8 +108,8 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) FILE *f; Elf_W (Ehdr) ehdr; Elf_W (Half) shstrndx; - Elf_W (Shdr) *sec_hdrs; - char *stringtab; + Elf_W (Shdr) *sec_hdrs = NULL; + char *stringtab = NULL; unsigned int i; size_t linksize = 0; char *linkbuf = NULL; @@ -122,7 +122,8 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) if (!f) return 1; - fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f); + if (fread (&ehdr, sizeof (Elf_W (Ehdr)), 1, f) != 1) + goto file_error; shstrndx = ehdr.e_shstrndx; @@ -131,13 +132,15 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) fseek (f, ehdr.e_shoff, SEEK_SET); sec_hdrs = calloc (ehdr.e_shnum, sizeof (Elf_W (Shdr))); - fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f); + if (fread (sec_hdrs, sizeof (Elf_W (Shdr)), ehdr.e_shnum, f) != ehdr.e_shnum) + goto file_error; Debug (4, "loading string table of size %zd\n", sec_hdrs[shstrndx].sh_size); stringtab = malloc (sec_hdrs[shstrndx].sh_size); fseek (f, sec_hdrs[shstrndx].sh_offset, SEEK_SET); - fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f); + if (fread (stringtab, 1, sec_hdrs[shstrndx].sh_size, f) != sec_hdrs[shstrndx].sh_size) + goto file_error; for (i = 1; i < ehdr.e_shnum && *buf == NULL; i++) { @@ -149,7 +152,8 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) *buf = malloc (*bufsize); fseek (f, sec_hdrs[i].sh_offset, SEEK_SET); - fread (*buf, 1, *bufsize, f); + if (fread (*buf, 1, *bufsize, f) != *bufsize) + goto file_error; Debug (4, "read %zd bytes of .debug_frame from offset %zd\n", *bufsize, sec_hdrs[i].sh_offset); @@ -160,7 +164,8 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) linkbuf = malloc (linksize); fseek (f, sec_hdrs[i].sh_offset, SEEK_SET); - fread (linkbuf, 1, linksize, f); + if (fread (linkbuf, 1, linksize, f) != linksize) + goto file_error; Debug (4, "read %zd bytes of .gnu_debuglink from offset %zd\n", linksize, sec_hdrs[i].sh_offset); @@ -227,6 +232,15 @@ load_debug_frame (const char *file, char **buf, size_t *bufsize, int is_local) free (linkbuf); return 0; + +/* An error reading image file. Release resources and return error code */ +file_error: + if (stringtab) free(stringtab); + if (sec_hdrs) free(sec_hdrs); + if (linkbuf) free(linkbuf); + fclose(f); + + return 1; } /* Locate the binary which originated the contents of address ADDR. Return @@ -405,6 +419,152 @@ debug_frame_tab_compare (const void *a, const void *b) return 0; } +PROTECTED int +dwarf_find_debug_frame (int found, unw_dyn_info_t *di_debug, + struct dl_phdr_info *info, unw_word_t ip) +{ + unw_dyn_info_t *di; + struct unw_debug_frame_list *fdesc = 0; + unw_accessors_t *a; + unw_word_t addr; + + Debug (15, "Trying to find .debug_frame info->dlpi_name=%s\n", + info->dlpi_name); + di = di_debug; + + fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name); + + if (!fdesc) + { + Debug (15, "couldn't load .debug_frame\n"); + return found; + } + else + { + char *buf; + size_t bufsize; + unw_word_t item_start, item_end = 0; + uint32_t u32val = 0; + uint64_t cie_id = 0; + struct debug_frame_tab *tab; + + Debug (15, "loaded .debug_frame\n"); + + buf = fdesc->debug_frame; + bufsize = fdesc->debug_frame_size; + + if (bufsize == 0) + { + Debug (15, "zero-length .debug_frame\n"); + return found; + } + + /* Now create a binary-search table, if it does not already exist. */ + if (!fdesc->index) + { + addr = (unw_word_t) (uintptr_t) buf; + + a = unw_get_accessors (unw_local_addr_space); + + /* Find all FDE entries in debug_frame, and make into a sorted + index. */ + + tab = debug_frame_tab_new (16); + + while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) + { + uint64_t id_for_cie; + item_start = addr; + + dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); + + if (u32val == 0) + break; + else if (u32val != 0xffffffff) + { + uint32_t cie_id32 = 0; + item_end = addr + u32val; + dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, + NULL); + cie_id = cie_id32; + id_for_cie = 0xffffffff; + } + else + { + uint64_t u64val = 0; + /* Extended length. */ + dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); + item_end = addr + u64val; + + dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); + id_for_cie = 0xffffffffffffffffull; + } + + /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ + + if (cie_id == id_for_cie) + ; + /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ + else + { + unw_word_t fde_addr = item_start; + unw_proc_info_t this_pi; + int err; + + /*Debug (1, "Found FDE at %.8x\n", item_start);*/ + + err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, + a, &fde_addr, + &this_pi, 0, + (uintptr_t) buf, + NULL); + if (err == 0) + { + Debug (15, "start_ip = %lx, end_ip = %lx\n", + (long) this_pi.start_ip, (long) this_pi.end_ip); + debug_frame_tab_append (tab, + item_start - (unw_word_t) (uintptr_t) buf, + this_pi.start_ip); + } + /*else + Debug (1, "FDE parse failed\n");*/ + } + + addr = item_end; + } + + debug_frame_tab_shrink (tab); + qsort (tab->tab, tab->length, sizeof (struct table_entry), + debug_frame_tab_compare); + /* for (i = 0; i < tab->length; i++) + { + fprintf (stderr, "ip %x, fde offset %x\n", + (int) tab->tab[i].start_ip_offset, + (int) tab->tab[i].fde_offset); + }*/ + fdesc->index = tab->tab; + fdesc->index_size = tab->length; + free (tab); + } + + di->format = UNW_INFO_FORMAT_TABLE; + di->start_ip = fdesc->start; + di->end_ip = fdesc->end; + di->u.ti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; + di->u.ti.table_data = (unw_word_t *) fdesc; + di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); + di->u.ti.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr; + + found = 1; + Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " + "gp=0x%lx, table_data=0x%lx\n", + (char *) (uintptr_t) di->u.ti.name_ptr, + (long) di->u.ti.segbase, (long) di->u.ti.table_len, + (long) di->gp, (long) di->u.ti.table_data); + } + return found; +} + #endif /* CONFIG_DEBUG_FRAME */ /* ptr is a pointer to a callback_data structure and, on entry, @@ -583,139 +743,7 @@ callback (struct dl_phdr_info *info, size_t size, void *ptr) #ifdef CONFIG_DEBUG_FRAME { - struct unw_debug_frame_list *fdesc = 0; - Debug (15, "Trying to find .debug_frame\n"); - di = &cb_data->di_debug; - fdesc = locate_debug_info (unw_local_addr_space, info, ip, info->dlpi_name); - - if (!fdesc) - { - Debug (15, "couldn't load .debug_frame\n"); - return found; - } - else - { - char *buf; - size_t bufsize; - unw_word_t item_start, item_end = 0; - uint32_t u32val = 0; - uint64_t cie_id = 0; - struct debug_frame_tab *tab; - - Debug (15, "loaded .debug_frame\n"); - - buf = fdesc->debug_frame; - bufsize = fdesc->debug_frame_size; - - if (bufsize == 0) - { - Debug (15, "zero-length .debug_frame\n"); - return found; - } - - /* Now create a binary-search table, if it does not already exist. */ - if (!fdesc->index) - { - addr = (unw_word_t) (uintptr_t) buf; - - a = unw_get_accessors (unw_local_addr_space); - - /* Find all FDE entries in debug_frame, and make into a sorted - index. */ - - tab = debug_frame_tab_new (16); - - while (addr < (unw_word_t) (uintptr_t) (buf + bufsize)) - { - uint64_t id_for_cie; - item_start = addr; - - dwarf_readu32 (unw_local_addr_space, a, &addr, &u32val, NULL); - - if (u32val == 0) - break; - else if (u32val != 0xffffffff) - { - uint32_t cie_id32 = 0; - item_end = addr + u32val; - dwarf_readu32 (unw_local_addr_space, a, &addr, &cie_id32, - NULL); - cie_id = cie_id32; - id_for_cie = 0xffffffff; - } - else - { - uint64_t u64val = 0; - /* Extended length. */ - dwarf_readu64 (unw_local_addr_space, a, &addr, &u64val, NULL); - item_end = addr + u64val; - - dwarf_readu64 (unw_local_addr_space, a, &addr, &cie_id, NULL); - id_for_cie = 0xffffffffffffffffull; - } - - /*Debug (1, "CIE/FDE id = %.8x\n", (int) cie_id);*/ - - if (cie_id == id_for_cie) - ; - /*Debug (1, "Found CIE at %.8x.\n", item_start);*/ - else - { - unw_word_t fde_addr = item_start; - unw_proc_info_t this_pi; - int err; - - /*Debug (1, "Found FDE at %.8x\n", item_start);*/ - - err = dwarf_extract_proc_info_from_fde (unw_local_addr_space, - a, &fde_addr, - &this_pi, 0, - (uintptr_t) buf, - NULL); - if (err == 0) - { - Debug (15, "start_ip = %lx, end_ip = %lx\n", - (long) this_pi.start_ip, (long) this_pi.end_ip); - debug_frame_tab_append (tab, - item_start - (unw_word_t) (uintptr_t) buf, - this_pi.start_ip); - } - /*else - Debug (1, "FDE parse failed\n");*/ - } - - addr = item_end; - } - - debug_frame_tab_shrink (tab); - qsort (tab->tab, tab->length, sizeof (struct table_entry), - debug_frame_tab_compare); - /* for (i = 0; i < tab->length; i++) - { - fprintf (stderr, "ip %x, fde offset %x\n", - (int) tab->tab[i].start_ip_offset, - (int) tab->tab[i].fde_offset); - }*/ - fdesc->index = tab->tab; - fdesc->index_size = tab->length; - free (tab); - } - - di->format = UNW_INFO_FORMAT_TABLE; - di->start_ip = fdesc->start; - di->end_ip = fdesc->end; - di->u.ti.name_ptr = (unw_word_t) (uintptr_t) info->dlpi_name; - di->u.ti.table_data = (unw_word_t *) fdesc; - di->u.ti.table_len = sizeof (*fdesc) / sizeof (unw_word_t); - di->u.ti.segbase = (unw_word_t) (uintptr_t) info->dlpi_addr; - - found = 1; - Debug (15, "found debug_frame table `%s': segbase=0x%lx, len=%lu, " - "gp=0x%lx, table_data=0x%lx\n", - (char *) (uintptr_t) di->u.ti.name_ptr, - (long) di->u.ti.segbase, (long) di->u.ti.table_len, - (long) di->gp, (long) di->u.ti.table_data); - } + found = dwarf_find_debug_frame (found, &cb_data->di_debug, info, ip); } #endif /* CONFIG_DEBUG_FRAME */ diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in index 343349f7..9c6b12dc 100644 --- a/tests/check-namespace.sh.in +++ b/tests/check-namespace.sh.in @@ -129,6 +129,11 @@ check_local_unw_abi () { match _UL${plat}_dwarf_search_unwind_table ;; esac + + if [ x@enable_debug_frame@ = xyes ]; then + match _UL${plat}_dwarf_find_debug_frame + fi + } check_generic_unw_abi () { @@ -187,6 +192,10 @@ check_generic_unw_abi () { match _U${plat}_dwarf_search_unwind_table ;; esac + + if [ x@enable_debug_frame@ = xyes ]; then + match _U${plat}_dwarf_find_debug_frame + fi } check_cxx_abi () { From 46e10c5abeeb93345367a70db2af3aba4440a49e Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 26 May 2010 19:25:41 -0700 Subject: [PATCH 157/162] Support .debug_frame based unwinding in _UPTi_find_unwind_table() Signed-off-by: Andris Zeila --- include/libunwind-common.h.in | 2 ++ src/dwarf/Gfind_proc_info-lsb.c | 13 ++++++------- src/dwarf/Gparser.c | 6 ++++++ src/ptrace/_UPT_find_proc_info.c | 26 +++++++++++++++++++++++++- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/include/libunwind-common.h.in b/include/libunwind-common.h.in index 228460a9..2fb78e8e 100644 --- a/include/libunwind-common.h.in +++ b/include/libunwind-common.h.in @@ -119,6 +119,8 @@ typedef struct unw_addr_space *unw_addr_space_t; /* Each target may define it's own set of flags, but bits 0-15 are reserved for general libunwind-use. */ #define UNW_PI_FLAG_FIRST_TDEP_BIT 16 +/* The information comes from a .debug_frame section. */ +#define UNW_PI_FLAG_DEBUG_FRAME 32 typedef struct unw_proc_info { diff --git a/src/dwarf/Gfind_proc_info-lsb.c b/src/dwarf/Gfind_proc_info-lsb.c index 9718260d..d65342c5 100644 --- a/src/dwarf/Gfind_proc_info-lsb.c +++ b/src/dwarf/Gfind_proc_info-lsb.c @@ -895,13 +895,11 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, #ifndef UNW_REMOTE_ONLY struct unw_debug_frame_list *fdesc = (void *) di->u.ti.table_data; - /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is currently only - supported for the local address space. Both the index and - the unwind tables live in local memory, but the address space - to check for properties like the address size and endianness - is the target one. When the ptrace code adds support for - .debug_frame something will have to change. */ - assert (as == unw_local_addr_space); + /* UNW_INFO_FORMAT_TABLE (i.e. .debug_frame) is read from local address + space. Both the index and the unwind tables live in local memory, but + the address space to check for properties like the address size and + endianness is the target one. */ + as = unw_local_addr_space; table = fdesc->index; table_len = fdesc->index_size * sizeof (struct table_entry); debug_frame_base = (uintptr_t) fdesc->debug_frame; @@ -958,6 +956,7 @@ dwarf_search_unwind_table (unw_addr_space_t as, unw_word_t ip, { pi->start_ip += segbase; pi->end_ip += segbase; + pi->flags = UNW_PI_FLAG_DEBUG_FRAME; } if (ip < pi->start_ip || ip >= pi->end_ip) diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 3b1a2b40..13bd9a27 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -73,6 +73,12 @@ run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr, as = c->as; arg = c->as_arg; + if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME) + { + /* .debug_frame CFI is stored in local address space. */ + as = unw_local_addr_space; + arg = NULL; + } a = unw_get_accessors (as); curr_ip = c->pi.start_ip; diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index a0bd52c4..97bf9e21 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -210,7 +210,31 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, } } if (!ptxt || !peh_hdr) - return NULL; + { + /* No .eh_frame found, try .debug_frame. */ + struct dl_phdr_info info; + + info.dlpi_name = path; + info.dlpi_phdr = phdr; + info.dlpi_phnum = ehdr->e_phnum; + + /* Fixup segbase to match correct base address. */ + for (i = 0; i < info.dlpi_phnum; i++) + { + if (info.dlpi_phdr[i].p_type == PT_LOAD && + info.dlpi_phdr[i].p_offset == 0) + { + segbase -= info.dlpi_phdr[i].p_vaddr; + break; + } + } + info.dlpi_addr = segbase; + + if (dwarf_find_debug_frame (0, &ui->di_cache, &info, ip)) + return &ui->di_cache; + else + return NULL; + } if (pdyn) { From 00aed9631b112d7aa7adc98054b62549cfc857da Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 26 May 2010 19:28:44 -0700 Subject: [PATCH 158/162] Add an experimental and optional frame chain unwinding for ARM The environment variable UNW_ARM_UNWIND_METHOD controls the unwind method. 1 - debug_frame unwinding 2 - frame chain unwinding, 3 - 1 & 2 (default)) Signed-off-by: Andris Zeila --- include/tdep-arm/libunwind_i.h | 10 +++++ src/arm/Gglobal.c | 10 +++++ src/arm/Gstep.c | 79 ++++++++++++++++++++++++++++++---- src/arm/getcontext.S | 4 ++ src/arm/siglongjmp.S | 4 ++ 5 files changed, 99 insertions(+), 8 deletions(-) diff --git a/include/tdep-arm/libunwind_i.h b/include/tdep-arm/libunwind_i.h index faa35fce..bae9c4de 100644 --- a/include/tdep-arm/libunwind_i.h +++ b/include/tdep-arm/libunwind_i.h @@ -255,4 +255,14 @@ extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, int write); +/* unwinding method selection support */ +#define UNW_ARM_METHOD_ALL 0xFF +#define UNW_ARM_METHOD_DWARF 0x01 +#define UNW_ARM_METHOD_FRAME 0x02 + +#define unwi_unwind_method UNWI_ARCH_OBJ(unwind_method) +extern int unwi_unwind_method; + +#define UNW_TRY_METHOD(x) (unwi_unwind_method & x) + #endif /* ARM_LIBUNWIND_I_H */ diff --git a/src/arm/Gglobal.c b/src/arm/Gglobal.c index a93c4ddb..473a0b85 100644 --- a/src/arm/Gglobal.c +++ b/src/arm/Gglobal.c @@ -29,6 +29,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ HIDDEN pthread_mutex_t arm_lock = PTHREAD_MUTEX_INITIALIZER; HIDDEN int tdep_needs_initialization = 1; +/* Unwinding methods to use. See UNW_METHOD_ enums */ +HIDDEN int unwi_unwind_method = UNW_ARM_METHOD_ALL; + /* FIXME: I'm pretty sure we don't need this at all for ARM, but "generic" code (include/dwarf_i.h) seems to expect it to be here at present. */ @@ -50,6 +53,13 @@ tdep_init (void) /* another thread else beat us to it... */ goto out; + /* read ARM unwind method setting */ + const char* str = getenv ("UNW_ARM_UNWIND_METHOD"); + if (str) + { + unwi_unwind_method = atoi (str); + } + mi_init (); dwarf_init (); diff --git a/src/arm/Gstep.c b/src/arm/Gstep.c index eff1fde3..5eac5f09 100644 --- a/src/arm/Gstep.c +++ b/src/arm/Gstep.c @@ -29,20 +29,83 @@ PROTECTED int unw_step (unw_cursor_t *cursor) { struct cursor *c = (struct cursor *) cursor; - int ret; + int ret = -UNW_EUNSPEC; Debug (1, "(cursor=%p)\n", c); /* Try DWARF-based unwinding... this is the only method likely to work for ARM. */ - ret = dwarf_step (&c->dwarf); + if (UNW_TRY_METHOD(UNW_ARM_METHOD_DWARF)) + { + ret = dwarf_step (&c->dwarf); + Debug(1, "dwarf_step()=%d\n", ret); - if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; + if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + if (ret < 0 && ret != -UNW_ENOINFO) + { + Debug (2, "returning %d\n", ret); + return ret; + } + } - /* Dwarf unwinding didn't work, stop. */ if (unlikely (ret < 0)) - return 0; - - return (c->dwarf.ip == 0) ? 0 : 1; + { + if (UNW_TRY_METHOD(UNW_ARM_METHOD_FRAME)) + { + ret = UNW_ESUCCESS; + /* DWARF unwinding failed, try to follow APCS/optimized APCS frame chain */ + unw_word_t instr, i; + Debug (13, "dwarf_step() failed (ret=%d), trying frame-chain\n", ret); + dwarf_loc_t ip_loc, fp_loc; + unw_word_t frame; + /* Mark all registers unsaved, since we don't know where + they are saved (if at all), except for the EBP and + EIP. */ + if (dwarf_get(&c->dwarf, c->dwarf.loc[UNW_ARM_R11], &frame) < 0) + { + return 0; + } + for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i) { + c->dwarf.loc[i] = DWARF_NULL_LOC; + } + if (frame) + { + if (dwarf_get(&c->dwarf, DWARF_LOC(frame, 0), &instr) < 0) + { + return 0; + } + instr -= 8; + if (dwarf_get(&c->dwarf, DWARF_LOC(instr, 0), &instr) < 0) + { + return 0; + } + if ((instr & 0xFFFFD800) == 0xE92DD800) + { + /* Standard APCS frame. */ + ip_loc = DWARF_LOC(frame - 4, 0); + fp_loc = DWARF_LOC(frame - 12, 0); + } + else + { + /* Codesourcery optimized normal frame. */ + ip_loc = DWARF_LOC(frame, 0); + fp_loc = DWARF_LOC(frame - 4, 0); + } + if (dwarf_get(&c->dwarf, ip_loc, &c->dwarf.ip) < 0) + { + return 0; + } + c->dwarf.loc[UNW_ARM_R12] = ip_loc; + c->dwarf.loc[UNW_ARM_R11] = fp_loc; + Debug(15, "ip=%lx\n", c->dwarf.ip); + } + else + { + ret = -UNW_ENOINFO; + } + } + } + return ret == -UNW_ENOINFO ? 0 : 1; } diff --git a/src/arm/getcontext.S b/src/arm/getcontext.S index 3b9abdae..c52992bf 100644 --- a/src/arm/getcontext.S +++ b/src/arm/getcontext.S @@ -50,3 +50,7 @@ _Uarm_getcontext: str r1, [r0, #15 * 4] ldmfd sp!, {r0, r1} bx lr +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/src/arm/siglongjmp.S b/src/arm/siglongjmp.S index 87f939e9..4df07366 100644 --- a/src/arm/siglongjmp.S +++ b/src/arm/siglongjmp.S @@ -6,3 +6,7 @@ _UI_siglongjmp_cont: _UI_longjmp_cont: bx lr +#ifdef __linux__ + /* We do not need executable stack. */ + .section .note.GNU-stack,"",%progbits +#endif From b3757e7792fdd92b49e2c8936e384009add4fee3 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 29 May 2010 01:07:40 +0300 Subject: [PATCH 159/162] Restore the linking when --enable-debug-frame is not specified --- src/ptrace/_UPT_find_proc_info.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ptrace/_UPT_find_proc_info.c b/src/ptrace/_UPT_find_proc_info.c index 97bf9e21..0c000392 100644 --- a/src/ptrace/_UPT_find_proc_info.c +++ b/src/ptrace/_UPT_find_proc_info.c @@ -210,6 +210,7 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, } } if (!ptxt || !peh_hdr) +#ifdef CONFIG_DEBUG_FRAME { /* No .eh_frame found, try .debug_frame. */ struct dl_phdr_info info; @@ -235,6 +236,9 @@ _UPTi_find_unwind_table (struct UPT_info *ui, unw_addr_space_t as, else return NULL; } +#else + return NULL; +#endif if (pdyn) { From 99e60be5a4c8bc9076d1b11e89a06f85d9da7b88 Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Tue, 8 Jun 2010 14:44:07 -0700 Subject: [PATCH 160/162] Fix the page boundary crossing bug. Signed-off-by: Jason Evans --- src/x86/Ginit.c | 12 +++++++++--- src/x86_64/Ginit.c | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/x86/Ginit.c b/src/x86/Ginit.c index 0af616a5..b8890a3c 100644 --- a/src/x86/Ginit.c +++ b/src/x86/Ginit.c @@ -88,8 +88,14 @@ validate_mem (unw_word_t addr) { int i, victim; #ifdef HAVE_MINCORE - char mvec[2]; /* Unaligned access may cross page boundary */ + unsigned char mvec[2]; /* Unaligned access may cross page boundary */ #endif + size_t len; + + if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) + len = PAGE_SIZE; + else + len = PAGE_SIZE * 2; addr = PAGE_START(addr); @@ -103,9 +109,9 @@ validate_mem (unw_word_t addr) } #ifdef HAVE_MINCORE - if (mincore ((void *) addr, sizeof (unw_word_t), mvec) == -1) + if (mincore ((void *) addr, len, mvec) == -1) #else - if (msync ((void *) addr, sizeof (unw_word_t), MS_ASYNC) == -1) + if (msync ((void *) addr, len, MS_ASYNC) == -1) #endif return -1; diff --git a/src/x86_64/Ginit.c b/src/x86_64/Ginit.c index 14614f13..8c69b841 100644 --- a/src/x86_64/Ginit.c +++ b/src/x86_64/Ginit.c @@ -91,8 +91,14 @@ validate_mem (unw_word_t addr) { int i, victim; #ifdef HAVE_MINCORE - char mvec[2]; /* Unaligned access may cross page boundary */ + unsigned char mvec[2]; /* Unaligned access may cross page boundary */ #endif + size_t len; + + if (PAGE_START(addr + sizeof (unw_word_t) - 1) == PAGE_START(addr)) + len = PAGE_SIZE; + else + len = PAGE_SIZE * 2; addr = PAGE_START(addr); @@ -106,9 +112,9 @@ validate_mem (unw_word_t addr) } #ifdef HAVE_MINCORE - if (mincore ((void *) addr, sizeof (unw_word_t), mvec) == -1) + if (mincore ((void *) addr, len, mvec) == -1) #else - if (msync ((void *) addr, sizeof (unw_word_t), MS_ASYNC) == -1) + if (msync ((void *) addr, len, MS_ASYNC) == -1) #endif return -1; From 7909c71e5d99d359c6246457adb2ac61cc43a878 Mon Sep 17 00:00:00 2001 From: Sven Neumann Date: Wed, 4 Aug 2010 14:25:33 -0700 Subject: [PATCH 161/162] [PATCH] Add files to EXTRA_DIST so that 'make dist' works again --- Makefile.am | 3 +++ src/Makefile.am | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 61f4fb96..a7de2fb4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,9 @@ EXTRA_DIST = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ include/libunwind_i.h include/mempool.h \ include/remote.h \ include/libunwind-common.h.in \ + include/tdep-arm/dwarf-config.h \ + include/tdep-arm/jmpbuf.h include/tdep-arm/libunwind_i.h \ + include/tdep-ia64/jmpbuf.h include/tdep-ia64/rse.h \ include/libunwind-ia64.h include/tdep-ia64/libunwind_i.h \ include/tdep-ia64/jmpbuf.h include/tdep-ia64/rse.h \ include/tdep-ia64/script.h \ diff --git a/src/Makefile.am b/src/Makefile.am index be547710..3107b00f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -108,11 +108,11 @@ dwarf_SOURCES_local = \ dwarf_SOURCES_generic = \ dwarf/Gexpr.c dwarf/Gfde.c dwarf/Gparser.c dwarf/Gpe.c dwarf/Gstep.c -# The list of files that go info libunwind and libunwind-arm: +# The list of files that go into libunwind and libunwind-arm: libunwind_la_SOURCES_arm_common = $(libunwind_la_SOURCES_common) \ $(dwarf_SOURCES_common) \ elf32.c elf32.h \ - arm/init.h arm/offsets.h arm/regs.h \ + arm/init.h arm/offsets.h arm/unwind_i.h \ arm/is_fpreg.c arm/regname.c # The list of files that go into libunwind: @@ -193,7 +193,7 @@ libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \ $(dwarf_SOURCES_common) \ elfxx.c \ - mips/init.h mips/offsets.h mips/regs.h \ + mips/init.h mips/offsets.h \ mips/is_fpreg.c mips/regname.c # The list of files that go into libunwind: From 982d590ddb778f0d301fe2e5647abd9135a2f9bc Mon Sep 17 00:00:00 2001 From: Arun Sharma Date: Wed, 4 Aug 2010 15:11:19 -0700 Subject: [PATCH 162/162] Add Gtest-nomalloc.c to EXTRA_DIST so we pass "make check" --- tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 8786923e..794f33fb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include EXTRA_DIST = run-ia64-test-dyn1 run-ptrace-mapper run-ptrace-misc \ - run-check-namespace check-namespace.sh.in + run-check-namespace check-namespace.sh.in Gtest-nomalloc.c noinst_PROGRAMS_common = check_PROGRAMS_common = test-proc-info test-static-link \