2003-11-17 Jeff Johnston <jjohnstn@redhat.com>

David Mosberger  <davidm@hpl.hp.com>

        * ia64-tdep.c: Include elf.h.
        [HAVE_LIBUNWIND_IA64_H]: Include libunwind-frame.h and
        libunwind-ia64.h.
        (ia64_rse_slot_num, ia64_rse_skip_regs): New for libunwind support.
        (ia64_gdb2uw_regnum, ia64_uw2gdb_regnum): Ditto.
        (ia64_is_fpreg, ia64_access_reg): Ditto.
        (ia64_access_fpreg, ia64_access_mem): Ditto.
        (get_kernel_table): Ditto.
        (ia64_find_unwind_table): Ditto.
        (ia64_find_proc_info_x, ia64_put_unwind_info): Ditto.
        (ia64_get_dyn_info_list, ia64_libunwind_frame_this_id): Ditto.
        (ia64_libunwind_frame_prev_register): Ditto.
        (ia64_libunwind_frame_sniffer): Ditto.
        (ia64_gdbarch_init)[HAVE_LIBUNWIND_IA64_H]: Add libunwind frame
        sniffer.  Register libunwind functions needed by generic
        libunwind frame code using libunwind_frame_set_descr().
This commit is contained in:
Jeff Johnston 2003-11-17 21:38:36 +00:00
parent 3addb0a9e8
commit 968d1cb408
2 changed files with 639 additions and 0 deletions

View File

@ -1,3 +1,23 @@
2003-11-17 Jeff Johnston <jjohnstn@redhat.com>
David Mosberger <davidm@hpl.hp.com>
* ia64-tdep.c: Include elf.h.
[HAVE_LIBUNWIND_IA64_H]: Include libunwind-frame.h and
libunwind-ia64.h.
(ia64_rse_slot_num, ia64_rse_skip_regs): New for libunwind support.
(ia64_gdb2uw_regnum, ia64_uw2gdb_regnum): Ditto.
(ia64_is_fpreg, ia64_access_reg): Ditto.
(ia64_access_fpreg, ia64_access_mem): Ditto.
(get_kernel_table): Ditto.
(ia64_find_unwind_table): Ditto.
(ia64_find_proc_info_x, ia64_put_unwind_info): Ditto.
(ia64_get_dyn_info_list, ia64_libunwind_frame_this_id): Ditto.
(ia64_libunwind_frame_prev_register): Ditto.
(ia64_libunwind_frame_sniffer): Ditto.
(ia64_gdbarch_init)[HAVE_LIBUNWIND_IA64_H]: Add libunwind frame
sniffer. Register libunwind functions needed by generic
libunwind frame code using libunwind_frame_set_descr().
2003-11-16 Daniel Jacobowitz <drow@mvista.com>
* breakpoint.c (re_enable_breakpoints_in_shlibs): Only re-enable a

View File

@ -36,8 +36,14 @@
#include "objfiles.h"
#include "elf/common.h" /* for DT_PLTGOT value */
#include "elf-bfd.h"
#include "elf.h" /* for PT_IA64_UNWIND value */
#include "dis-asm.h"
#ifdef HAVE_LIBUNWIND_IA64_H
#include "libunwind-frame.h"
#include "libunwind-ia64.h"
#endif
/* Hook for determining the global pointer when calling functions in
the inferior under AIX. The initialization code in ia64-aix-nat.c
sets this hook to the address of a function which will find the
@ -87,6 +93,7 @@ typedef enum instruction_type
/* FIXME: These extern declarations should go in ia64-tdep.h. */
extern CORE_ADDR ia64_linux_sigcontext_register_address (CORE_ADDR, int);
extern CORE_ADDR ia64_aix_sigcontext_register_address (CORE_ADDR, int);
extern unsigned long ia64_linux_getunwind_table (void *, size_t);
static gdbarch_init_ftype ia64_gdbarch_init;
@ -2099,6 +2106,614 @@ static const struct frame_base ia64_frame_base =
ia64_frame_base_address
};
#ifdef HAVE_LIBUNWIND_IA64_H
struct ia64_unwind_table_entry
{
unw_word_t start_offset;
unw_word_t end_offset;
unw_word_t info_offset;
};
static __inline__ uint64_t
ia64_rse_slot_num (uint64_t addr)
{
return (addr >> 3) & 0x3f;
}
/* Skip over a designated number of registers in the backing
store, remembering every 64th position is for NAT. */
static __inline__ uint64_t
ia64_rse_skip_regs (uint64_t addr, long num_regs)
{
long delta = ia64_rse_slot_num(addr) + num_regs;
if (num_regs < 0)
delta -= 0x3e;
return addr + ((num_regs + delta/0x3f) << 3);
}
/* Gdb libunwind-frame callback function to convert from an ia64 gdb register
number to a libunwind register number. */
static int
ia64_gdb2uw_regnum (int regnum)
{
if (regnum == sp_regnum)
return UNW_IA64_SP;
else if (regnum == IA64_BSP_REGNUM)
return UNW_IA64_BSP;
else if ((unsigned) (regnum - IA64_GR0_REGNUM) < 128)
return UNW_IA64_GR + (regnum - IA64_GR0_REGNUM);
else if ((unsigned) (regnum - V32_REGNUM) < 95)
return UNW_IA64_GR + 32 + (regnum - V32_REGNUM);
else if ((unsigned) (regnum - IA64_FR0_REGNUM) < 128)
return UNW_IA64_FR + (regnum - IA64_FR0_REGNUM);
else if ((unsigned) (regnum - IA64_PR0_REGNUM) < 64)
return -1;
else if ((unsigned) (regnum - IA64_BR0_REGNUM) < 8)
return UNW_IA64_BR + (regnum - IA64_BR0_REGNUM);
else if (regnum == IA64_PR_REGNUM)
return UNW_IA64_PR;
else if (regnum == IA64_IP_REGNUM)
return UNW_REG_IP;
else if (regnum == IA64_CFM_REGNUM)
return UNW_IA64_CFM;
else if ((unsigned) (regnum - IA64_AR0_REGNUM) < 128)
return UNW_IA64_AR + (regnum - IA64_AR0_REGNUM);
else if ((unsigned) (regnum - IA64_NAT0_REGNUM) < 128)
return UNW_IA64_NAT + (regnum - IA64_NAT0_REGNUM);
else
return -1;
}
/* Gdb libunwind-frame callback function to convert from a libunwind register
number to a ia64 gdb register number. */
static int
ia64_uw2gdb_regnum (int uw_regnum)
{
if (uw_regnum == UNW_IA64_SP)
return sp_regnum;
else if (uw_regnum == UNW_IA64_BSP)
return IA64_BSP_REGNUM;
else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 32)
return IA64_GR0_REGNUM + (uw_regnum - UNW_IA64_GR);
else if ((unsigned) (uw_regnum - UNW_IA64_GR) < 128)
return V32_REGNUM + (uw_regnum - (IA64_GR0_REGNUM + 32));
else if ((unsigned) (uw_regnum - UNW_IA64_FR) < 128)
return IA64_FR0_REGNUM + (uw_regnum - UNW_IA64_FR);
else if ((unsigned) (uw_regnum - UNW_IA64_BR) < 8)
return IA64_BR0_REGNUM + (uw_regnum - UNW_IA64_BR);
else if (uw_regnum == UNW_IA64_PR)
return IA64_PR_REGNUM;
else if (uw_regnum == UNW_REG_IP)
return IA64_IP_REGNUM;
else if (uw_regnum == UNW_IA64_CFM)
return IA64_CFM_REGNUM;
else if ((unsigned) (uw_regnum - UNW_IA64_AR) < 128)
return IA64_AR0_REGNUM + (uw_regnum - UNW_IA64_AR);
else if ((unsigned) (uw_regnum - UNW_IA64_NAT) < 128)
return IA64_NAT0_REGNUM + (uw_regnum - UNW_IA64_NAT);
else
return -1;
}
/* Gdb libunwind-frame callback function to reveal if register is a float
register or not. */
static int
ia64_is_fpreg (int uw_regnum)
{
return unw_is_fpreg (uw_regnum);
}
/* Libunwind callback accessor function for general registers. */
static int
ia64_access_reg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_word_t *val,
int write, void *arg)
{
int regnum = ia64_uw2gdb_regnum (uw_regnum);
unw_word_t bsp, sof, sol, cfm, psr, ip;
struct frame_info *next_frame = arg;
long new_sof, old_sof;
char buf[MAX_REGISTER_SIZE];
if (write)
{
if (regnum < 0)
/* ignore writes to pseudo-registers such as UNW_IA64_PROC_STARTI. */
return 0;
switch (uw_regnum)
{
case UNW_REG_IP:
ia64_write_pc (*val, inferior_ptid);
break;
case UNW_IA64_AR_BSPSTORE:
write_register (IA64_BSP_REGNUM, *val);
break;
case UNW_IA64_AR_BSP:
case UNW_IA64_BSP:
/* Account for the fact that ptrace() expects bsp to point
after the current register frame. */
cfm = read_register (IA64_CFM_REGNUM);
sof = (cfm & 0x7f);
bsp = ia64_rse_skip_regs (*val, sof);
write_register (IA64_BSP_REGNUM, bsp);
break;
case UNW_IA64_CFM:
/* If we change CFM, we need to adjust ptrace's notion of
bsp accordingly, so that the real bsp remains
unchanged. */
bsp = read_register (IA64_BSP_REGNUM);
cfm = read_register (IA64_CFM_REGNUM);
old_sof = (cfm & 0x7f);
new_sof = (*val & 0x7f);
if (old_sof != new_sof)
{
bsp = ia64_rse_skip_regs (bsp, -old_sof + new_sof);
write_register (IA64_BSP_REGNUM, bsp);
}
write_register (IA64_CFM_REGNUM, *val);
break;
default:
write_register (regnum, *val);
break;
}
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog,
" access_reg: to cache: %4s=%016lx\n",
(((unsigned) regnum <= IA64_NAT127_REGNUM)
? ia64_register_names[regnum] : "r??"), *val);
}
else
{
switch (uw_regnum)
{
case UNW_REG_IP:
/* Libunwind expects to see the pc value which means the slot number
from the psr must be merged with the ip word address. */
frame_unwind_register (next_frame, IA64_IP_REGNUM, buf);
ip = extract_unsigned_integer (buf, 8);
frame_unwind_register (next_frame, IA64_PSR_REGNUM, buf);
psr = extract_unsigned_integer (buf, 8);
*val = ip | ((psr >> 41) & 0x3);
break;
case UNW_IA64_AR_BSP:
/* Libunwind expects to see the beginning of the current register
frame so we must account for the fact that ptrace() will return a value
for bsp that points *after* the current register frame. */
frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
bsp = extract_unsigned_integer (buf, 8);
frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
cfm = extract_unsigned_integer (buf, 8);
sof = (cfm & 0x7f);
*val = ia64_rse_skip_regs (bsp, -sof);
break;
case UNW_IA64_AR_BSPSTORE:
/* Libunwind wants bspstore to be after the current register frame.
This is what ptrace() and gdb treats as the regular bsp value. */
frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
*val = extract_unsigned_integer (buf, 8);
break;
default:
/* For all other registers, just unwind the value directly. */
frame_unwind_register (next_frame, regnum, buf);
*val = extract_unsigned_integer (buf, 8);
break;
}
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog,
" access_reg: from cache: %4s=%016lx\n",
(((unsigned) regnum <= IA64_NAT127_REGNUM)
? ia64_register_names[regnum] : "r??"), *val);
}
return 0;
}
/* Libunwind callback accessor function for floating-point registers. */
static int
ia64_access_fpreg (unw_addr_space_t as, unw_regnum_t uw_regnum, unw_fpreg_t *val,
int write, void *arg)
{
int regnum = ia64_uw2gdb_regnum (uw_regnum);
if (write)
regcache_cooked_write (current_regcache, regnum, (char *) val);
else
regcache_cooked_read (current_regcache, regnum, (char *) val);
return 0;
}
/* Libunwind callback accessor function for accessing memory. */
static int
ia64_access_mem (unw_addr_space_t as,
unw_word_t addr, unw_word_t *val,
int write, void *arg)
{
/* XXX do we need to normalize byte-order here? */
if (write)
return target_write_memory (addr, (char *) val, sizeof (unw_word_t));
else
return target_read_memory (addr, (char *) val, sizeof (unw_word_t));
}
/* Call low-level function to access the kernel unwind table. */
static int
getunwind_table (void *buf, size_t len)
{
LONGEST x;
x = target_read_partial (&current_target, TARGET_OBJECT_UNWIND_TABLE, NULL,
buf, 0, len);
return (int)x;
}
/* Get the kernel unwind table. */
static int
get_kernel_table (unw_word_t ip, unw_dyn_info_t *di)
{
size_t size;
struct ia64_table_entry
{
uint64_t start_offset;
uint64_t end_offset;
uint64_t info_offset;
};
static struct ia64_table_entry *ktab = NULL, *etab;
if (!ktab)
{
size = getunwind_table (NULL, 0);
if ((int)size < 0)
return -UNW_ENOINFO;
ktab = xmalloc (size);
getunwind_table (ktab, size);
/* Determine length of kernel's unwind table and relocate
it's entries. */
for (etab = ktab; etab->start_offset; ++etab)
etab->info_offset += (uint64_t) ktab;
}
if (ip < ktab[0].start_offset || ip >= etab[-1].end_offset)
return -UNW_ENOINFO;
di->format = UNW_INFO_FORMAT_TABLE;
di->gp = 0;
di->start_ip = ktab[0].start_offset;
di->end_ip = etab[-1].end_offset;
di->u.ti.name_ptr = (unw_word_t) "<kernel>";
di->u.ti.segbase = 0;
di->u.ti.table_len = ((char *) etab - (char *) ktab) / sizeof (unw_word_t);
di->u.ti.table_data = (unw_word_t *) ktab;
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog, "get_kernel_table: found table `%s': "
"segbase=%lx, length=%lu, gp=%lx\n",
(char *) di->u.ti.name_ptr, di->u.ti.segbase,
di->u.ti.table_len, di->gp);
return 0;
}
/* Find the unwind table entry for a specified address. */
static int
ia64_find_unwind_table (struct objfile *objfile, unw_word_t ip,
unw_dyn_info_t *dip, void **buf)
{
Elf_Internal_Phdr *phdr, *p_text = NULL, *p_unwind = NULL;
Elf_Internal_Ehdr *ehdr;
unw_word_t segbase = 0;
CORE_ADDR load_base;
bfd *bfd;
int i;
bfd = objfile->obfd;
ehdr = elf_tdata (bfd)->elf_header;
phdr = elf_tdata (bfd)->phdr;
load_base = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
for (i = 0; i < ehdr->e_phnum; ++i)
{
switch (phdr[i].p_type)
{
case PT_LOAD:
if ((unw_word_t) (ip - load_base - phdr[i].p_vaddr)
< phdr[i].p_memsz)
p_text = phdr + i;
break;
case PT_IA_64_UNWIND:
p_unwind = phdr + i;
break;
default:
break;
}
}
if (!p_text || !p_unwind
/* Verify that the segment that contains the IP also contains
the static unwind table. If not, we are dealing with
runtime-generated code, for which we have no info here. */
|| (p_unwind->p_vaddr - p_text->p_vaddr) >= p_text->p_memsz)
return -UNW_ENOINFO;
segbase = p_text->p_vaddr + load_base;
dip->start_ip = segbase;
dip->end_ip = dip->start_ip + p_text->p_memsz;
dip->gp = FIND_GLOBAL_POINTER (ip);
dip->format = UNW_INFO_FORMAT_TABLE;
dip->u.ti.name_ptr = (unw_word_t) bfd_get_filename (bfd);
dip->u.ti.segbase = segbase;
dip->u.ti.table_len = p_unwind->p_memsz / sizeof (unw_word_t);
/* The following can happen in corner cases where dynamically
generated code falls into the same page that contains the
data-segment and the page-offset of the code is within the first
page of the executable. */
if (ip < dip->start_ip || ip >= dip->end_ip)
return -UNW_ENOINFO;
/* Read in the libunwind table. */
*buf = xmalloc (p_unwind->p_memsz);
target_read_memory (p_unwind->p_vaddr + load_base, (char *)(*buf), p_unwind->p_memsz);
dip->u.ti.table_data = (unw_word_t *)(*buf);
return 0;
}
/* Libunwind callback accessor function to acquire procedure unwind-info. */
static int
ia64_find_proc_info_x (unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
int need_unwind_info, void *arg)
{
struct obj_section *sec = find_pc_section (ip);
unw_dyn_info_t di;
int ret;
void *buf = NULL;
if (!sec)
{
/* XXX This only works if the host and the target architecture are
both ia64 and if the have (more or less) the same kernel
version. */
if (get_kernel_table (ip, &di) < 0)
return -UNW_ENOINFO;
}
else
{
ret = ia64_find_unwind_table (sec->objfile, ip, &di, &buf);
if (ret < 0)
return ret;
}
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog, "acquire_unwind_info: %lx -> "
"(name=`%s',segbase=%lx,start=%lx,end=%lx,gp=%lx,"
"length=%lu,data=%p)\n", ip, (char *)di.u.ti.name_ptr,
di.u.ti.segbase, di.start_ip, di.end_ip,
di.gp, di.u.ti.table_len, di.u.ti.table_data);
ret = libunwind_search_unwind_table (&as, ip, &di, pi, need_unwind_info, arg);
/* We no longer need the dyn info storage so free it. */
xfree (buf);
return ret;
}
/* Libunwind callback accessor function for cleanup. */
static void
ia64_put_unwind_info (unw_addr_space_t as,
unw_proc_info_t *pip, void *arg)
{
/* Nothing required for now. */
}
/* Libunwind callback accessor function to get head of the dynamic
unwind-info registration list. */
static int
ia64_get_dyn_info_list (unw_addr_space_t as,
unw_word_t *dilap, void *arg)
{
struct obj_section *text_sec;
struct objfile *objfile;
unw_word_t ip, addr;
unw_dyn_info_t di;
int ret;
if (!libunwind_is_initialized ())
return -UNW_ENOINFO;
for (objfile = object_files; objfile; objfile = objfile->next)
{
void *buf = NULL;
text_sec = objfile->sections + SECT_OFF_TEXT (objfile);
ip = text_sec->addr;
ret = ia64_find_unwind_table (objfile, ip, &di, &buf);
if (ret >= 0)
{
addr = libunwind_find_dyn_list (as, di.u.ti.table_data,
(di.u.ti.table_len
* sizeof (di.u.ti.table_data[0])),
di.u.ti.segbase, di.gp, arg);
/* We no longer need the dyn info storage so free it. */
xfree (buf);
if (addr)
{
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog,
"dynamic unwind table in objfile %s "
"at %lx (gp=%lx)\n",
bfd_get_filename (objfile->obfd),
addr, di.gp);
*dilap = addr;
return 0;
}
}
}
return -UNW_ENOINFO;
}
/* Frame interface functions for libunwind. */
static void
ia64_libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
struct frame_id *this_id)
{
char buf[8];
CORE_ADDR bsp;
struct frame_id id;
libunwind_frame_this_id (next_frame, this_cache, &id);
/* We must add the bsp as the special address for frame comparison purposes. */
frame_unwind_register (next_frame, IA64_BSP_REGNUM, buf);
bsp = extract_unsigned_integer (buf, 8);
(*this_id) = frame_id_build_special (id.stack_addr, id.code_addr, bsp);
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog,
"libunwind frame id: code %lx, stack %lx, special %lx, next_frame %p\n",
id.code_addr, id.stack_addr, bsp, next_frame);
}
static void
ia64_libunwind_frame_prev_register (struct frame_info *next_frame,
void **this_cache,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *valuep)
{
int reg = regnum;
if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
reg = IA64_PR_REGNUM;
else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
reg = IA64_UNAT_REGNUM;
/* Let libunwind do most of the work. */
libunwind_frame_prev_register (next_frame, this_cache, reg,
optimizedp, lvalp, addrp, realnump, valuep);
if (VP0_REGNUM <= regnum && regnum <= VP63_REGNUM)
{
ULONGEST prN_val;
if (VP16_REGNUM <= regnum && regnum <= VP63_REGNUM)
{
int rrb_pr = 0;
ULONGEST cfm;
unsigned char buf[MAX_REGISTER_SIZE];
/* Fetch predicate register rename base from current frame
marker for this frame. */
frame_unwind_register (next_frame, IA64_CFM_REGNUM, buf);
cfm = extract_unsigned_integer (buf, 8);
rrb_pr = (cfm >> 32) & 0x3f;
/* Adjust the register number to account for register rotation. */
regnum = VP16_REGNUM
+ ((regnum - VP16_REGNUM) + rrb_pr) % 48;
}
prN_val = extract_bit_field ((unsigned char *) valuep,
regnum - VP0_REGNUM, 1);
store_unsigned_integer (valuep, register_size (current_gdbarch, regnum), prN_val);
}
else if (IA64_NAT0_REGNUM <= regnum && regnum <= IA64_NAT127_REGNUM)
{
ULONGEST unatN_val;
unatN_val = extract_bit_field ((unsigned char *) valuep,
regnum - IA64_NAT0_REGNUM, 1);
store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
unatN_val);
}
else if (regnum == IA64_BSP_REGNUM)
{
char cfm_valuep[MAX_REGISTER_SIZE];
int cfm_optim;
int cfm_realnum;
enum lval_type cfm_lval;
CORE_ADDR cfm_addr;
CORE_ADDR bsp, prev_cfm, prev_bsp;
/* We want to calculate the previous bsp as the end of the previous register stack frame.
This corresponds to what the hardware bsp register will be if we pop the frame
back which is why we might have been called. We know that libunwind will pass us back
the beginning of the current frame so we should just add sof to it. */
prev_bsp = extract_unsigned_integer (valuep, 8);
libunwind_frame_prev_register (next_frame, this_cache, IA64_CFM_REGNUM,
&cfm_optim, &cfm_lval, &cfm_addr, &cfm_realnum, cfm_valuep);
prev_cfm = extract_unsigned_integer (cfm_valuep, 8);
prev_bsp = rse_address_add (prev_bsp, (prev_cfm & 0x7f));
store_unsigned_integer (valuep, register_size (current_gdbarch, regnum),
prev_bsp);
}
if (gdbarch_debug >= 1)
fprintf_unfiltered (gdb_stdlog,
"libunwind prev register <%s> is %lx\n",
(((unsigned) regnum <= IA64_NAT127_REGNUM)
? ia64_register_names[regnum] : "r??"), extract_unsigned_integer (valuep, 8));
}
static const struct frame_unwind ia64_libunwind_frame_unwind =
{
NORMAL_FRAME,
ia64_libunwind_frame_this_id,
ia64_libunwind_frame_prev_register
};
static const struct frame_unwind *
ia64_libunwind_frame_sniffer (struct frame_info *next_frame)
{
if (libunwind_is_initialized () && libunwind_frame_sniffer (next_frame))
return &ia64_libunwind_frame_unwind;
return NULL;
}
/* Set of libunwind callback acccessor functions. */
static unw_accessors_t ia64_unw_accessors =
{
ia64_find_proc_info_x,
ia64_put_unwind_info,
ia64_get_dyn_info_list,
ia64_access_mem,
ia64_access_reg,
ia64_access_fpreg,
/* resume */
/* get_proc_name */
};
/* Set of ia64 gdb libunwind-frame callbacks and data for generic libunwind-frame code to use. */
static struct libunwind_descr ia64_libunwind_descr =
{
ia64_gdb2uw_regnum,
ia64_uw2gdb_regnum,
ia64_is_fpreg,
&ia64_unw_accessors,
};
#endif /* HAVE_LIBUNWIND_IA64_H */
/* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of
EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc
and TYPE is the type (which is known to be struct, union or array). */
@ -2795,6 +3410,10 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_unwind_pc (gdbarch, ia64_unwind_pc);
frame_unwind_append_sniffer (gdbarch, ia64_sigtramp_frame_sniffer);
#ifdef HAVE_LIBUNWIND_IA64_H
frame_unwind_append_sniffer (gdbarch, ia64_libunwind_frame_sniffer);
libunwind_frame_set_descr (gdbarch, &ia64_libunwind_descr);
#endif
frame_unwind_append_sniffer (gdbarch, ia64_frame_sniffer);
frame_base_set_default (gdbarch, &ia64_frame_base);