+/* Verify if we are in a sigtramp frame and we can use libunwind to unwind. */
+int
+libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_cache)
+{
+ unw_cursor_t cursor;
+ unw_accessors_t *acc;
+ unw_addr_space_t as;
+ struct libunwind_descr *descr;
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ int i, ret;
+
+ /* To test for libunwind unwind support, initialize a cursor to the
+ current frame and try to back up. We use this same method when
+ setting up the frame cache (see libunwind_frame_cache()). If
+ libunwind returns success for this operation, it means that it
+ has found sufficient libunwind unwinding information to do
+ so. */
+
+ descr = libunwind_descr (gdbarch);
+ acc = descr->accessors;
+ as = unw_create_addr_space_p (acc,
+ gdbarch_byte_order (gdbarch)
+ == BFD_ENDIAN_BIG
+ ? __BIG_ENDIAN
+ : __LITTLE_ENDIAN);
+
+ ret = unw_init_remote_p (&cursor, as, this_frame);
+
+ if (ret < 0)
+ {
+ unw_destroy_addr_space_p (as);
+ return 0;
+ }
+
+ /* Check to see if we are in a signal frame. */
+ ret = unw_is_signal_frame_p (&cursor);
+ unw_destroy_addr_space_p (as);
+ if (ret > 0)
+ return 1;
+
+ return 0;
+}
+
+/* The following routine is for accessing special registers of the top frame.
+ A special set of accessors must be given that work without frame info.
+ This is used by ia64 to access the rse registers r32-r127. While they
+ are usually located at BOF, this is not always true and only the libunwind
+ info can decipher where they actually are. */
+int
+libunwind_get_reg_special (struct gdbarch *gdbarch, struct regcache *regcache,
+ int regnum, void *buf)
+{
+ unw_cursor_t cursor;
+ unw_accessors_t *acc;
+ unw_addr_space_t as;
+ struct libunwind_descr *descr;
+ int ret;
+ unw_regnum_t uw_regnum;
+ unw_word_t intval;
+ unw_fpreg_t fpval;
+ void *ptr;
+
+
+ descr = libunwind_descr (gdbarch);
+ acc = descr->special_accessors;
+ as = unw_create_addr_space_p (acc,
+ gdbarch_byte_order (gdbarch)
+ == BFD_ENDIAN_BIG
+ ? __BIG_ENDIAN
+ : __LITTLE_ENDIAN);
+
+ ret = unw_init_remote_p (&cursor, as, regcache);
+ if (ret < 0)
+ {
+ unw_destroy_addr_space_p (as);
+ return -1;
+ }
+
+ uw_regnum = descr->gdb2uw (regnum);
+
+ if (descr->is_fpreg (uw_regnum))
+ {
+ ret = unw_get_fpreg_p (&cursor, uw_regnum, &fpval);
+ ptr = &fpval;
+ }
+ else
+ {
+ ret = unw_get_reg_p (&cursor, uw_regnum, &intval);
+ ptr = &intval;
+ }
+
+ unw_destroy_addr_space_p (as);
+
+ if (ret < 0)
+ return -1;
+
+ if (buf)
+ memcpy (buf, ptr, register_size (gdbarch, regnum));
+
+ return 0;
+}
+