/* Frame unwinder for frames using the libunwind library.
- Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009
+ Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Written by Jeff Johnston, contributed by Red Hat Inc.
#include "complaints.h"
+/* The following two macros are normally defined in <endian.h>.
+ But systems such as ia64-hpux do not provide such header, so
+ we just define them here if not already defined. */
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN 4321
+#endif
+
static int libunwind_initialized;
static struct gdbarch_data *libunwind_descr_handle;
/* Required function pointers from libunwind. */
static int (*unw_get_reg_p) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
static int (*unw_get_fpreg_p) (unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
-static int (*unw_get_saveloc_p) (unw_cursor_t *, unw_regnum_t, unw_save_loc_t *);
+static int (*unw_get_saveloc_p) (unw_cursor_t *, unw_regnum_t,
+ unw_save_loc_t *);
static int (*unw_is_signal_frame_p) (unw_cursor_t *);
static int (*unw_step_p) (unw_cursor_t *);
static int (*unw_init_remote_p) (unw_cursor_t *, unw_addr_space_t, void *);
static unw_addr_space_t (*unw_create_addr_space_p) (unw_accessors_t *, int);
static void (*unw_destroy_addr_space_p) (unw_addr_space_t);
-static int (*unw_search_unwind_table_p) (unw_addr_space_t, unw_word_t, unw_dyn_info_t *,
+static int (*unw_search_unwind_table_p) (unw_addr_space_t, unw_word_t,
+ unw_dyn_info_t *,
unw_proc_info_t *, int, void *);
static unw_word_t (*unw_find_dyn_list_p) (unw_addr_space_t, unw_dyn_info_t *,
void *);
static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space));
static char *destroy_addr_space_name = STRINGIFY(UNW_OBJ(destroy_addr_space));
-static char *search_unwind_table_name = STRINGIFY(UNW_OBJ(search_unwind_table));
+static char *search_unwind_table_name
+ = STRINGIFY(UNW_OBJ(search_unwind_table));
static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
static struct libunwind_descr *
static void *
libunwind_descr_init (struct gdbarch *gdbarch)
{
- struct libunwind_descr *descr = GDBARCH_OBSTACK_ZALLOC (gdbarch,
- struct libunwind_descr);
+ struct libunwind_descr *descr
+ = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct libunwind_descr);
+
return descr;
}
void
-libunwind_frame_set_descr (struct gdbarch *gdbarch, struct libunwind_descr *descr)
+libunwind_frame_set_descr (struct gdbarch *gdbarch,
+ struct libunwind_descr *descr)
{
struct libunwind_descr *arch_descr;
{
/* First time here. Must initialize data area. */
arch_descr = libunwind_descr_init (gdbarch);
- deprecated_set_gdbarch_data (gdbarch, libunwind_descr_handle, arch_descr);
+ deprecated_set_gdbarch_data (gdbarch,
+ libunwind_descr_handle, arch_descr);
}
/* Copy new descriptor info into arch descriptor. */
/* Allocate a new cache. */
cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
- /* We can assume we are unwinding a normal frame. Even if this is
- for a signal trampoline, ia64 signal "trampolines" use a normal
- subroutine call to start the signal handler. */
cache->func_addr = get_frame_func (this_frame);
- if (cache->func_addr == 0
- && get_next_frame (this_frame)
- && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
- return NULL;
+ if (cache->func_addr == 0)
+ /* This can happen when the frame corresponds to a function for which
+ there is no debugging information nor any entry in the symbol table.
+ This is probably a static function for which an entry in the symbol
+ table was not created when the objfile got linked (observed in
+ libpthread.so on ia64-hpux).
+
+ The best we can do, in that case, is use the frame PC as the function
+ address. We don't need to give up since we still have the unwind
+ record to help us perform the unwinding. There is also another
+ compelling to continue, because abandonning now means stopping
+ the backtrace, which can never be helpful for the user. */
+ cache->func_addr = get_frame_pc (this_frame);
/* Get a libunwind cursor to the previous frame.
libunwind_frame_dealloc_cache (struct frame_info *self, void *this_cache)
{
struct libunwind_frame_cache *cache = this_cache;
+
if (cache->as)
unw_destroy_addr_space_p (cache->as);
}
return frame_unwind_got_constant (this_frame, regnum, 0);
val = frame_unwind_got_constant (this_frame, regnum, intval);
}
- set_value_optimized_out (val, 1);
break;
}
}
void
_initialize_libunwind_frame (void)
{
- libunwind_descr_handle = gdbarch_data_register_post_init (libunwind_descr_init);
+ libunwind_descr_handle
+ = gdbarch_data_register_post_init (libunwind_descr_init);
libunwind_initialized = libunwind_load ();
}