X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fia64-linux-tdep.c;h=2696f14b2cb023761d6da7ca9a5217fb8f7d207d;hb=8948cc6971fb82feffc49e2d21747111466ad642;hp=49d5b721ad59f0ceab16c82d3277bf9f3e041748;hpb=0fb0cc7590113e9b459dfcc48dc71c9d419d9580;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c index 49d5b721ad..2696f14b2c 100644 --- a/gdb/ia64-linux-tdep.c +++ b/gdb/ia64-linux-tdep.c @@ -1,7 +1,6 @@ /* Target-dependent code for the IA-64 for GDB, the GNU debugger. - Copyright (C) 2000, 2004, 2005, 2007, 2008, 2009 - Free Software Foundation, Inc. + Copyright (C) 2000-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -26,16 +25,20 @@ #include "osabi.h" #include "solib-svr4.h" #include "symtab.h" +#include "linux-tdep.h" +#include "regset.h" + +#include /* The sigtramp code is in a non-readable (executable-only) region of memory called the ``gate page''. The addresses in question were determined by examining the system headers. They are - overly generous to allow for different pages sizes. */ + overly generous to allow for different pages sizes. */ #define GATE_AREA_START 0xa000000000000100LL #define GATE_AREA_END 0xa000000000020000LL -/* Offset to sigcontext structure from frame of handler */ +/* Offset to sigcontext structure from frame of handler. */ #define IA64_LINUX_SIGCONTEXT_OFFSET 192 static int @@ -46,18 +49,21 @@ ia64_linux_pc_in_sigtramp (CORE_ADDR pc) /* IA-64 GNU/Linux specific function which, given a frame address and a register number, returns the address at which that register may be - found. 0 is returned for registers which aren't stored in the the - sigcontext structure. */ + found. 0 is returned for registers which aren't stored in the + sigcontext structure. */ static CORE_ADDR -ia64_linux_sigcontext_register_address (CORE_ADDR sp, int regno) +ia64_linux_sigcontext_register_address (struct gdbarch *gdbarch, + CORE_ADDR sp, int regno) { - char buf[8]; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + gdb_byte buf[8]; CORE_ADDR sigcontext_addr = 0; - /* The address of the sigcontext area is found at offset 16 in the sigframe. */ + /* The address of the sigcontext area is found at offset 16 in the + sigframe. */ read_memory (sp + 16, buf, 8); - sigcontext_addr = extract_unsigned_integer (buf, 8); + sigcontext_addr = extract_unsigned_integer (buf, 8, byte_order); if (IA64_GR0_REGNUM <= regno && regno <= IA64_GR31_REGNUM) return sigcontext_addr + 200 + 8 * (regno - IA64_GR0_REGNUM); @@ -76,7 +82,7 @@ ia64_linux_sigcontext_register_address (CORE_ADDR sp, int regno) return sigcontext_addr + 56; /* user mask only */ /* sc_ar_rsc is provided, from which we could compute bspstore, but I don't think it's worth it. Anyway, if we want it, it's at offset - 64 */ + 64. */ case IA64_BSP_REGNUM : return sigcontext_addr + 72; case IA64_RNAT_REGNUM : @@ -115,10 +121,109 @@ ia64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc) regcache_cooked_write_unsigned (regcache, IA64_GR10_REGNUM, 0); } +/* Implementation of `gdbarch_stap_is_single_operand', as defined in + gdbarch.h. */ + +static int +ia64_linux_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) +{ + return ((isdigit (*s) && s[1] == '[' && s[2] == 'r') /* Displacement. */ + || *s == 'r' /* Register value. */ + || isdigit (*s)); /* Literal number. */ +} + +/* Core file support. */ + +static const struct regcache_map_entry ia64_linux_gregmap[] = + { + { 32, IA64_GR0_REGNUM, 8 }, /* r0 ... r31 */ + { 1, REGCACHE_MAP_SKIP, 8 }, /* FIXME: NAT collection bits? */ + { 1, IA64_PR_REGNUM, 8 }, + { 8, IA64_BR0_REGNUM, 8 }, /* b0 ... b7 */ + { 1, IA64_IP_REGNUM, 8 }, + { 1, IA64_CFM_REGNUM, 8 }, + { 1, IA64_PSR_REGNUM, 8 }, + { 1, IA64_RSC_REGNUM, 8 }, + { 1, IA64_BSP_REGNUM, 8 }, + { 1, IA64_BSPSTORE_REGNUM, 8 }, + { 1, IA64_RNAT_REGNUM, 8 }, + { 1, IA64_CCV_REGNUM, 8 }, + { 1, IA64_UNAT_REGNUM, 8 }, + { 1, IA64_FPSR_REGNUM, 8 }, + { 1, IA64_PFS_REGNUM, 8 }, + { 1, IA64_LC_REGNUM, 8 }, + { 1, IA64_EC_REGNUM, 8 }, + { 0 } + }; + +/* Size of 'gregset_t', as defined by the Linux kernel. Note that + this is more than actually mapped in the regmap above. */ + +#define IA64_LINUX_GREGS_SIZE (128 * 8) + +static const struct regcache_map_entry ia64_linux_fpregmap[] = + { + { 128, IA64_FR0_REGNUM, 16 }, /* f0 ... f127 */ + { 0 } + }; + +#define IA64_LINUX_FPREGS_SIZE (128 * 16) + +static void +ia64_linux_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *regs, size_t len) +{ + const gdb_byte f_zero[16] = { 0 }; + const gdb_byte f_one[16] = + { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; + + regcache_supply_regset (regset, regcache, regnum, regs, len); + + /* Kernel generated cores have fr1==0 instead of 1.0. Older GDBs + did the same. So ignore whatever might be recorded in fpregset_t + for fr0/fr1 and always supply their expected values. */ + if (regnum == -1 || regnum == IA64_FR0_REGNUM) + regcache->raw_supply (IA64_FR0_REGNUM, f_zero); + if (regnum == -1 || regnum == IA64_FR1_REGNUM) + regcache->raw_supply (IA64_FR1_REGNUM, f_one); +} + +static const struct regset ia64_linux_gregset = + { + ia64_linux_gregmap, + regcache_supply_regset, regcache_collect_regset + }; + +static const struct regset ia64_linux_fpregset = + { + ia64_linux_fpregmap, + ia64_linux_supply_fpregset, regcache_collect_regset + }; + +static void +ia64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", IA64_LINUX_GREGS_SIZE, IA64_LINUX_GREGS_SIZE, &ia64_linux_gregset, + NULL, cb_data); + cb (".reg2", IA64_LINUX_FPREGS_SIZE, IA64_LINUX_FPREGS_SIZE, + &ia64_linux_fpregset, NULL, cb_data); +} + static void ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + static const char *const stap_register_prefixes[] = { "r", NULL }; + static const char *const stap_register_indirection_prefixes[] = { "[", + NULL }; + static const char *const stap_register_indirection_suffixes[] = { "]", + NULL }; + + linux_init_abi (info, gdbarch); /* Set the method of obtaining the sigcontext addresses at which registers are saved. */ @@ -137,6 +242,20 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Enable TLS support. */ set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); + + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, ia64_linux_iterate_over_regset_sections); + + /* SystemTap related. */ + set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes); + set_gdbarch_stap_register_indirection_prefixes (gdbarch, + stap_register_indirection_prefixes); + set_gdbarch_stap_register_indirection_suffixes (gdbarch, + stap_register_indirection_suffixes); + set_gdbarch_stap_gdb_register_prefix (gdbarch, "r"); + set_gdbarch_stap_is_single_operand (gdbarch, + ia64_linux_stap_is_single_operand); } void