X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fhppa-tdep.c;h=6a3ae47ba85285313f02408a8dc0981e41051be5;hb=806e23c026a7eee3db787352ff97cc4a1a41e357;hp=8deacc389e497dc0d33bc28656e94254fc81832b;hpb=38ca4e0c24a0e3d7b70b141c913d7e2998eb28e4;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 8deacc389e..6a3ae47ba8 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1,8 +1,8 @@ -/* Target-dependent code for the HP PA architecture, for GDB. +/* Target-dependent code for the HP PA-RISC architecture. - Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software - Foundation, Inc. + Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, + 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Contributed by the Center for Software Science at the University of Utah (pa-gdb-bugs@cs.utah.edu). @@ -21,8 +21,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ #include "defs.h" #include "bfd.h" @@ -72,102 +72,6 @@ const struct objfile_data *hppa_objfile_priv_data = NULL; following functions static, once we hppa is partially multiarched. */ int hppa_pc_requires_run_before_use (CORE_ADDR pc); -/* Handle 32/64-bit struct return conventions. */ - -static enum return_value_convention -hppa32_return_value (struct gdbarch *gdbarch, - struct type *type, struct regcache *regcache, - void *readbuf, const void *writebuf) -{ - if (TYPE_LENGTH (type) <= 2 * 4) - { - /* The value always lives in the right hand end of the register - (or register pair)? */ - int b; - int reg = TYPE_CODE (type) == TYPE_CODE_FLT ? HPPA_FP4_REGNUM : 28; - int part = TYPE_LENGTH (type) % 4; - /* The left hand register contains only part of the value, - transfer that first so that the rest can be xfered as entire - 4-byte registers. */ - if (part > 0) - { - if (readbuf != NULL) - regcache_cooked_read_part (regcache, reg, 4 - part, - part, readbuf); - if (writebuf != NULL) - regcache_cooked_write_part (regcache, reg, 4 - part, - part, writebuf); - reg++; - } - /* Now transfer the remaining register values. */ - for (b = part; b < TYPE_LENGTH (type); b += 4) - { - if (readbuf != NULL) - regcache_cooked_read (regcache, reg, (char *) readbuf + b); - if (writebuf != NULL) - regcache_cooked_write (regcache, reg, (const char *) writebuf + b); - reg++; - } - return RETURN_VALUE_REGISTER_CONVENTION; - } - else - return RETURN_VALUE_STRUCT_CONVENTION; -} - -static enum return_value_convention -hppa64_return_value (struct gdbarch *gdbarch, - struct type *type, struct regcache *regcache, - void *readbuf, const void *writebuf) -{ - /* RM: Floats are returned in FR4R, doubles in FR4. Integral values - are in r28, padded on the left. Aggregates less that 65 bits are - in r28, right padded. Aggregates upto 128 bits are in r28 and - r29, right padded. */ - if (TYPE_CODE (type) == TYPE_CODE_FLT - && TYPE_LENGTH (type) <= 8) - { - /* Floats are right aligned? */ - int offset = register_size (gdbarch, HPPA_FP4_REGNUM) - TYPE_LENGTH (type); - if (readbuf != NULL) - regcache_cooked_read_part (regcache, HPPA_FP4_REGNUM, offset, - TYPE_LENGTH (type), readbuf); - if (writebuf != NULL) - regcache_cooked_write_part (regcache, HPPA_FP4_REGNUM, offset, - TYPE_LENGTH (type), writebuf); - return RETURN_VALUE_REGISTER_CONVENTION; - } - else if (TYPE_LENGTH (type) <= 8 && is_integral_type (type)) - { - /* Integrals are right aligned. */ - int offset = register_size (gdbarch, HPPA_FP4_REGNUM) - TYPE_LENGTH (type); - if (readbuf != NULL) - regcache_cooked_read_part (regcache, 28, offset, - TYPE_LENGTH (type), readbuf); - if (writebuf != NULL) - regcache_cooked_write_part (regcache, 28, offset, - TYPE_LENGTH (type), writebuf); - return RETURN_VALUE_REGISTER_CONVENTION; - } - else if (TYPE_LENGTH (type) <= 2 * 8) - { - /* Composite values are left aligned. */ - int b; - for (b = 0; b < TYPE_LENGTH (type); b += 8) - { - int part = min (8, TYPE_LENGTH (type) - b); - if (readbuf != NULL) - regcache_cooked_read_part (regcache, 28 + b / 8, 0, part, - (char *) readbuf + b); - if (writebuf != NULL) - regcache_cooked_write_part (regcache, 28 + b / 8, 0, part, - (const char *) writebuf + b); - } - return RETURN_VALUE_REGISTER_CONVENTION; - } - else - return RETURN_VALUE_STRUCT_CONVENTION; -} - /* Routines to extract various sized constants out of hppa instructions. */ @@ -460,7 +364,7 @@ read_unwind_info (struct objfile *objfile) } /* Now compute the size of the stub unwinds. Note the ELF tools do not - use stub unwinds at the curren time. */ + use stub unwinds at the current time. */ stub_unwind_sec = bfd_get_section_by_name (objfile->obfd, "$UNWIND_END$"); if (stub_unwind_sec) @@ -585,7 +489,7 @@ find_unwind_entry (CORE_ADDR pc) read_unwind_info (objfile); priv = objfile_data (objfile, hppa_objfile_priv_data); if (priv == NULL) - error ("Internal error reading unwind information."); + error (_("Internal error reading unwind information.")); ui = ((struct hppa_objfile_private *) priv)->unwind_info; } @@ -758,6 +662,21 @@ hppa64_register_name (int i) return names[i]; } +static int +hppa64_dwarf_reg_to_regnum (int reg) +{ + /* r0-r31 and sar map one-to-one. */ + if (reg <= 32) + return reg; + + /* fr4-fr31 are mapped from 72 in steps of 2. */ + if (reg >= 72 || reg < 72 + 28 * 2) + return HPPA64_FP4_REGNUM + (reg - 72) / 2; + + error ("Invalid DWARF register num %d.", reg); + return -1; +} + /* This function pushes a stack frame with arguments as part of the inferior function calling mechanism. @@ -819,7 +738,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, param_len = 4; struct_ptr += align_up (TYPE_LENGTH (type), 8); if (write_pass) - write_memory (struct_end - struct_ptr, VALUE_CONTENTS (arg), + write_memory (struct_end - struct_ptr, value_contents (arg), TYPE_LENGTH (type)); store_unsigned_integer (param_val, 4, struct_end - struct_ptr); } @@ -831,13 +750,13 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, param_len = align_up (TYPE_LENGTH (type), 4); store_unsigned_integer (param_val, param_len, unpack_long (type, - VALUE_CONTENTS (arg))); + value_contents (arg))); } else if (TYPE_CODE (type) == TYPE_CODE_FLT) { /* Floating point value store, right aligned. */ param_len = align_up (TYPE_LENGTH (type), 4); - memcpy (param_val, VALUE_CONTENTS (arg), param_len); + memcpy (param_val, value_contents (arg), param_len); } else { @@ -845,7 +764,7 @@ hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Small struct value are stored right-aligned. */ memcpy (param_val + param_len - TYPE_LENGTH (type), - VALUE_CONTENTS (arg), TYPE_LENGTH (type)); + value_contents (arg), TYPE_LENGTH (type)); /* Structures of size 5, 6 and 7 bytes are special in that the higher-ordered word is stored in the lower-ordered @@ -978,6 +897,50 @@ hppa64_floating_p (const struct type *type) return 0; } +/* If CODE points to a function entry address, try to look up the corresponding + function descriptor and return its address instead. If CODE is not a + function entry address, then just return it unchanged. */ +static CORE_ADDR +hppa64_convert_code_addr_to_fptr (CORE_ADDR code) +{ + struct obj_section *sec, *opd; + + sec = find_pc_section (code); + + if (!sec) + return code; + + /* If CODE is in a data section, assume it's already a fptr. */ + if (!(sec->the_bfd_section->flags & SEC_CODE)) + return code; + + ALL_OBJFILE_OSECTIONS (sec->objfile, opd) + { + if (strcmp (opd->the_bfd_section->name, ".opd") == 0) + break; + } + + if (opd < sec->objfile->sections_end) + { + CORE_ADDR addr; + + for (addr = opd->addr; addr < opd->endaddr; addr += 2 * 8) + { + ULONGEST opdaddr; + char tmp[8]; + + if (target_read_memory (addr, tmp, sizeof (tmp))) + break; + opdaddr = extract_unsigned_integer (tmp, sizeof (tmp)); + + if (opdaddr == code) + return addr - 16; + } + } + + return code; +} + static CORE_ADDR hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct regcache *regcache, CORE_ADDR bp_addr, @@ -997,7 +960,8 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct value *arg = args[i]; struct type *type = value_type (arg); int len = TYPE_LENGTH (type); - char *valbuf; + const bfd_byte *valbuf; + bfd_byte fptrbuf[8]; int regnum; /* "Each parameter begins on a 64-bit (8-byte) boundary." */ @@ -1056,7 +1020,7 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, the right halves of the floating point registers; the left halves are unused." */ regcache_cooked_write_part (regcache, regnum, offset % 8, - len, VALUE_CONTENTS (arg)); + len, value_contents (arg)); } } } @@ -1073,10 +1037,26 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } } + /* If we are passing a function pointer, make sure we pass a function + descriptor instead of the function entry address. */ + if (TYPE_CODE (type) == TYPE_CODE_PTR + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC) + { + ULONGEST codeptr, fptr; + + codeptr = unpack_long (type, value_contents (arg)); + fptr = hppa64_convert_code_addr_to_fptr (codeptr); + store_unsigned_integer (fptrbuf, TYPE_LENGTH (type), fptr); + valbuf = fptrbuf; + } + else + { + valbuf = value_contents (arg); + } + /* Always store the argument in memory. */ - write_memory (sp + offset, VALUE_CONTENTS (arg), len); + write_memory (sp + offset, valbuf, len); - valbuf = VALUE_CONTENTS (arg); regnum = HPPA_ARG0_REGNUM - offset / 8; while (regnum > HPPA_ARG0_REGNUM - 8 && len > 0) { @@ -1126,17 +1106,149 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } +/* Handle 32/64-bit struct return conventions. */ + +static enum return_value_convention +hppa32_return_value (struct gdbarch *gdbarch, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + if (TYPE_LENGTH (type) <= 2 * 4) + { + /* The value always lives in the right hand end of the register + (or register pair)? */ + int b; + int reg = TYPE_CODE (type) == TYPE_CODE_FLT ? HPPA_FP4_REGNUM : 28; + int part = TYPE_LENGTH (type) % 4; + /* The left hand register contains only part of the value, + transfer that first so that the rest can be xfered as entire + 4-byte registers. */ + if (part > 0) + { + if (readbuf != NULL) + regcache_cooked_read_part (regcache, reg, 4 - part, + part, readbuf); + if (writebuf != NULL) + regcache_cooked_write_part (regcache, reg, 4 - part, + part, writebuf); + reg++; + } + /* Now transfer the remaining register values. */ + for (b = part; b < TYPE_LENGTH (type); b += 4) + { + if (readbuf != NULL) + regcache_cooked_read (regcache, reg, readbuf + b); + if (writebuf != NULL) + regcache_cooked_write (regcache, reg, writebuf + b); + reg++; + } + return RETURN_VALUE_REGISTER_CONVENTION; + } + else + return RETURN_VALUE_STRUCT_CONVENTION; +} + +static enum return_value_convention +hppa64_return_value (struct gdbarch *gdbarch, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + int len = TYPE_LENGTH (type); + int regnum, offset; + + if (len > 16) + { + /* All return values larget than 128 bits must be aggregate + return values. */ + gdb_assert (!hppa64_integral_or_pointer_p (type)); + gdb_assert (!hppa64_floating_p (type)); + + /* "Aggregate return values larger than 128 bits are returned in + a buffer allocated by the caller. The address of the buffer + must be passed in GR 28." */ + return RETURN_VALUE_STRUCT_CONVENTION; + } + + if (hppa64_integral_or_pointer_p (type)) + { + /* "Integral return values are returned in GR 28. Values + smaller than 64 bits are padded on the left (with garbage)." */ + regnum = HPPA_RET0_REGNUM; + offset = 8 - len; + } + else if (hppa64_floating_p (type)) + { + if (len > 8) + { + /* "Double-extended- and quad-precision floating-point + values are returned in GRs 28 and 29. The sign, + exponent, and most-significant bits of the mantissa are + returned in GR 28; the least-significant bits of the + mantissa are passed in GR 29. For double-extended + precision values, GR 29 is padded on the right with 48 + bits of garbage." */ + regnum = HPPA_RET0_REGNUM; + offset = 0; + } + else + { + /* "Single-precision and double-precision floating-point + return values are returned in FR 4R (single precision) or + FR 4 (double-precision)." */ + regnum = HPPA64_FP4_REGNUM; + offset = 8 - len; + } + } + else + { + /* "Aggregate return values up to 64 bits in size are returned + in GR 28. Aggregates smaller than 64 bits are left aligned + in the register; the pad bits on the right are undefined." + + "Aggregate return values between 65 and 128 bits are returned + in GRs 28 and 29. The first 64 bits are placed in GR 28, and + the remaining bits are placed, left aligned, in GR 29. The + pad bits on the right of GR 29 (if any) are undefined." */ + regnum = HPPA_RET0_REGNUM; + offset = 0; + } + + if (readbuf) + { + while (len > 0) + { + regcache_cooked_read_part (regcache, regnum, offset, + min (len, 8), readbuf); + readbuf += min (len, 8); + len -= min (len, 8); + regnum++; + } + } + + if (writebuf) + { + while (len > 0) + { + regcache_cooked_write_part (regcache, regnum, offset, + min (len, 8), writebuf); + writebuf += min (len, 8); + len -= min (len, 8); + regnum++; + } + } + + return RETURN_VALUE_REGISTER_CONVENTION; +} + + static CORE_ADDR -hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch, - CORE_ADDR addr, +hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, struct target_ops *targ) { if (addr & 2) { - CORE_ADDR plabel; - - plabel = addr & ~3; - target_read_memory(plabel, (char *)&addr, 4); + CORE_ADDR plabel = addr & ~3; + return read_memory_typed_address (plabel, builtin_type_void_func_ptr); } return addr; @@ -1244,9 +1356,9 @@ prologue_inst_adjust_sp (unsigned long inst) if ((inst & 0xffe00008) == 0x73c00008) return (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3); - /* addil high21,%r1; ldo low11,(%r1),%r30) + /* addil high21,%r30; ldo low11,(%r1),%r30) save high bits in save_high21 for later use. */ - if ((inst & 0xffe00000) == 0x28200000) + if ((inst & 0xffe00000) == 0x2bc00000) { save_high21 = hppa_extract_21 (inst); return 0; @@ -1455,7 +1567,7 @@ restart: /* There are limited ways to store the return pointer into the stack. */ - if (inst == 0x6bc23fd9 || inst == 0x0fc212c1) + if (inst == 0x6bc23fd9 || inst == 0x0fc212c1 || inst == 0x73c23fe1) save_rp = 0; /* These are the only ways we save SP into the stack. At this time @@ -1789,7 +1901,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache) if (!safe_frame_unwind_memory (next_frame, pc, buf4, sizeof buf4)) { - error ("Cannot read instruction at 0x%s\n", paddr_nz (pc)); + error (_("Cannot read instruction at 0x%s."), paddr_nz (pc)); return (*this_cache); } @@ -1810,7 +1922,8 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache) looking_for_rp = 0; cache->saved_regs[HPPA_RP_REGNUM].addr = -24; } - else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */ + else if (inst == 0x0fc212c1 + || inst == 0x73c23fe1) /* std rp,-0x10(sr0,sp) */ { looking_for_rp = 0; cache->saved_regs[HPPA_RP_REGNUM].addr = -16; @@ -1948,7 +2061,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache) cache->base = fp; if (hppa_debug) - fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer] }", + fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer]", paddr_nz (cache->base)); } else if (u->Save_SP @@ -1960,7 +2073,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache) cache->base = read_memory_integer (this_sp, TARGET_PTR_BIT / 8); if (hppa_debug) - fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved] }", + fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved]", paddr_nz (cache->base)); } else @@ -1969,7 +2082,7 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache) the SP back. */ cache->base = this_sp - frame_size; if (hppa_debug) - fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ", + fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust]", paddr_nz (cache->base)); } @@ -1981,21 +2094,34 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache) if (u->Millicode) { if (trad_frame_addr_p (cache->saved_regs, 31)) - cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31]; + { + cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31]; + if (hppa_debug) + fprintf_unfiltered (gdb_stdlog, " (pc=r31) [stack] } "); + } else { ULONGEST r31 = frame_unwind_register_unsigned (next_frame, 31); trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, r31); + if (hppa_debug) + fprintf_unfiltered (gdb_stdlog, " (pc=r31) [frame] } "); } } else { if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM)) - cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM]; + { + cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = + cache->saved_regs[HPPA_RP_REGNUM]; + if (hppa_debug) + fprintf_unfiltered (gdb_stdlog, " (pc=rp) [stack] } "); + } else { ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM); trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp); + if (hppa_debug) + fprintf_unfiltered (gdb_stdlog, " (pc=rp) [frame] } "); } } @@ -2068,7 +2194,7 @@ hppa_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 *realnump, gdb_byte *valuep) { struct hppa_frame_cache *info = hppa_frame_cache (next_frame, this_cache); hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum, @@ -2105,72 +2231,66 @@ static struct hppa_frame_cache * hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache) { struct hppa_frame_cache *cache; - unsigned int frame_size; - int found_rp; - CORE_ADDR pc, start_pc, end_pc, cur_pc; + unsigned int frame_size = 0; + int found_rp = 0; + CORE_ADDR start_pc; if (hppa_debug) - fprintf_unfiltered (gdb_stdlog, "{ hppa_fallback_frame_cache (frame=%d)-> ", - frame_relative_level(next_frame)); + fprintf_unfiltered (gdb_stdlog, + "{ hppa_fallback_frame_cache (frame=%d) -> ", + frame_relative_level (next_frame)); cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache); (*this_cache) = cache; cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); - pc = frame_func_unwind (next_frame); - cur_pc = frame_pc_unwind (next_frame); - frame_size = 0; - found_rp = 0; - - find_pc_partial_function (pc, NULL, &start_pc, &end_pc); - - if (start_pc == 0 || end_pc == 0) + start_pc = frame_func_unwind (next_frame); + if (start_pc) { - error ("Cannot find bounds of current function (@0x%s), unwinding will " - "fail.", paddr_nz (pc)); - return cache; - } - - if (end_pc > cur_pc) - end_pc = cur_pc; + CORE_ADDR cur_pc = frame_pc_unwind (next_frame); + CORE_ADDR pc; - for (pc = start_pc; pc < end_pc; pc += 4) - { - unsigned int insn; - - insn = read_memory_unsigned_integer (pc, 4); + for (pc = start_pc; pc < cur_pc; pc += 4) + { + unsigned int insn; - frame_size += prologue_inst_adjust_sp (insn); + insn = read_memory_unsigned_integer (pc, 4); + frame_size += prologue_inst_adjust_sp (insn); - /* There are limited ways to store the return pointer into the - stack. */ - if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */ - { - cache->saved_regs[HPPA_RP_REGNUM].addr = -20; - found_rp = 1; - } - else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */ - { - cache->saved_regs[HPPA_RP_REGNUM].addr = -16; - found_rp = 1; - } + /* There are limited ways to store the return pointer into the + stack. */ + if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */ + { + cache->saved_regs[HPPA_RP_REGNUM].addr = -20; + found_rp = 1; + } + else if (insn == 0x0fc212c1 + || insn == 0x73c23fe1) /* std rp,-0x10(sr0,sp) */ + { + cache->saved_regs[HPPA_RP_REGNUM].addr = -16; + found_rp = 1; + } + } } if (hppa_debug) - fprintf_unfiltered (gdb_stdlog, " frame_size = %d, found_rp = %d }\n", - frame_size, found_rp); + fprintf_unfiltered (gdb_stdlog, " frame_size=%d, found_rp=%d }\n", + frame_size, found_rp); - cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM) - frame_size; + cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM); + cache->base -= frame_size; trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base); if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM)) { cache->saved_regs[HPPA_RP_REGNUM].addr += cache->base; - cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[HPPA_RP_REGNUM]; + cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = + cache->saved_regs[HPPA_RP_REGNUM]; } else { - ULONGEST rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM); + ULONGEST rp; + rp = frame_unwind_register_unsigned (next_frame, HPPA_RP_REGNUM); trad_frame_set_value (cache->saved_regs, HPPA_PCOQ_HEAD_REGNUM, rp); } @@ -2191,7 +2311,7 @@ hppa_fallback_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 *realnump, gdb_byte *valuep) { struct hppa_frame_cache *info = hppa_fallback_frame_cache (next_frame, this_cache); @@ -2276,7 +2396,7 @@ hppa_stub_frame_prev_register (struct frame_info *next_frame, void **this_prologue_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *valuep) + int *realnump, gdb_byte *valuep) { struct hppa_stub_unwind_cache *info = hppa_stub_frame_unwind_cache (next_frame, this_prologue_cache); @@ -2286,7 +2406,7 @@ hppa_stub_frame_prev_register (struct frame_info *next_frame, optimizedp, lvalp, addrp, realnump, valuep); else - error ("Requesting registers from null frame.\n"); + error (_("Requesting registers from null frame.")); } static const struct frame_unwind hppa_stub_frame_unwind = { @@ -2363,16 +2483,6 @@ hppa_lookup_stub_minimal_symbol (const char *name, return NULL; } -/* Instead of this nasty cast, add a method pvoid() that prints out a - host VOID data type (remember %p isn't portable). */ - -static CORE_ADDR -hppa_pointer_to_address_hack (void *ptr) -{ - gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr)); - return POINTER_TO_ADDRESS (builtin_type_void_data_ptr, &ptr); -} - static void unwind_command (char *exp, int from_tty) { @@ -2394,8 +2504,7 @@ unwind_command (char *exp, int from_tty) return; } - printf_unfiltered ("unwind_table_entry (0x%s):\n", - paddr_nz (hppa_pointer_to_address_hack (u))); + printf_unfiltered ("unwind_table_entry (0x%lx):\n", (unsigned long)u); printf_unfiltered ("\tregion_start = "); print_address (u->region_start, gdb_stdout); @@ -2488,7 +2597,7 @@ hppa_pc_requires_run_before_use (CORE_ADDR pc) minimal symbols, I'm resorting to the gross hack of checking the top byte of the address for all 1's. Sigh. */ - return (!target_has_stack && (pc & 0xFF000000)); + return (!target_has_stack && (pc & 0xFF000000) == 0xFF000000); } /* Return the GDB type object for the "standard" data type of data in @@ -2546,26 +2655,25 @@ hppa_smash_text_address (CORE_ADDR addr) return (addr &= ~0x3); } -/* Get the ith function argument for the current function. */ +/* Get the ARGIth function argument for the current function. */ + static CORE_ADDR hppa_fetch_pointer_argument (struct frame_info *frame, int argi, struct type *type) { - CORE_ADDR addr; - get_frame_register (frame, HPPA_R0_REGNUM + 26 - argi, &addr); - return addr; + return get_frame_register_unsigned (frame, HPPA_R0_REGNUM + 26 - argi); } static void hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, - int regnum, void *buf) + int regnum, gdb_byte *buf) { ULONGEST tmp; regcache_raw_read_unsigned (regcache, regnum, &tmp); if (regnum == HPPA_PCOQ_HEAD_REGNUM || regnum == HPPA_PCOQ_TAIL_REGNUM) tmp &= ~0x3; - store_unsigned_integer (buf, sizeof(tmp), tmp); + store_unsigned_integer (buf, sizeof tmp, tmp); } static CORE_ADDR @@ -2579,20 +2687,23 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame, struct trad_frame_saved_reg saved_regs[], int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *valuep) + int *realnump, gdb_byte *valuep) { + struct gdbarch *arch = get_frame_arch (next_frame); + if (regnum == HPPA_PCOQ_TAIL_REGNUM) { if (valuep) { + int size = register_size (arch, HPPA_PCOQ_HEAD_REGNUM); CORE_ADDR pc; trad_frame_get_prev_register (next_frame, saved_regs, HPPA_PCOQ_HEAD_REGNUM, optimizedp, lvalp, addrp, realnump, valuep); - pc = extract_unsigned_integer (valuep, 4); - store_unsigned_integer (valuep, 4, pc + 4); + pc = extract_unsigned_integer (valuep, size); + store_unsigned_integer (valuep, size, pc + 4); } /* It's a computed value. */ @@ -2611,10 +2722,7 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame, if (regnum == HPPA_FLAGS_REGNUM) { if (valuep) - store_unsigned_integer (valuep, - register_size (get_frame_arch (next_frame), - regnum), - 0); + store_unsigned_integer (valuep, register_size (arch, regnum), 0); /* It's a computed value. */ *optimizedp = 0; @@ -2629,6 +2737,223 @@ hppa_frame_prev_register_helper (struct frame_info *next_frame, } +/* An instruction to match. */ +struct insn_pattern +{ + unsigned int data; /* See if it matches this.... */ + unsigned int mask; /* ... with this mask. */ +}; + +/* See bfd/elf32-hppa.c */ +static struct insn_pattern hppa_long_branch_stub[] = { + /* ldil LR'xxx,%r1 */ + { 0x20200000, 0xffe00000 }, + /* be,n RR'xxx(%sr4,%r1) */ + { 0xe0202002, 0xffe02002 }, + { 0, 0 } +}; + +static struct insn_pattern hppa_long_branch_pic_stub[] = { + /* b,l .+8, %r1 */ + { 0xe8200000, 0xffe00000 }, + /* addil LR'xxx - ($PIC_pcrel$0 - 4), %r1 */ + { 0x28200000, 0xffe00000 }, + /* be,n RR'xxxx - ($PIC_pcrel$0 - 8)(%sr4, %r1) */ + { 0xe0202002, 0xffe02002 }, + { 0, 0 } +}; + +static struct insn_pattern hppa_import_stub[] = { + /* addil LR'xxx, %dp */ + { 0x2b600000, 0xffe00000 }, + /* ldw RR'xxx(%r1), %r21 */ + { 0x48350000, 0xffffb000 }, + /* bv %r0(%r21) */ + { 0xeaa0c000, 0xffffffff }, + /* ldw RR'xxx+4(%r1), %r19 */ + { 0x48330000, 0xffffb000 }, + { 0, 0 } +}; + +static struct insn_pattern hppa_import_pic_stub[] = { + /* addil LR'xxx,%r19 */ + { 0x2a600000, 0xffe00000 }, + /* ldw RR'xxx(%r1),%r21 */ + { 0x48350000, 0xffffb000 }, + /* bv %r0(%r21) */ + { 0xeaa0c000, 0xffffffff }, + /* ldw RR'xxx+4(%r1),%r19 */ + { 0x48330000, 0xffffb000 }, + { 0, 0 }, +}; + +static struct insn_pattern hppa_plt_stub[] = { + /* b,l 1b, %r20 - 1b is 3 insns before here */ + { 0xea9f1fdd, 0xffffffff }, + /* depi 0,31,2,%r20 */ + { 0xd6801c1e, 0xffffffff }, + { 0, 0 } +}; + +static struct insn_pattern hppa_sigtramp[] = { + /* ldi 0, %r25 or ldi 1, %r25 */ + { 0x34190000, 0xfffffffd }, + /* ldi __NR_rt_sigreturn, %r20 */ + { 0x3414015a, 0xffffffff }, + /* be,l 0x100(%sr2, %r0), %sr0, %r31 */ + { 0xe4008200, 0xffffffff }, + /* nop */ + { 0x08000240, 0xffffffff }, + { 0, 0 } +}; + +/* Maximum number of instructions on the patterns above. */ +#define HPPA_MAX_INSN_PATTERN_LEN 4 + +/* Return non-zero if the instructions at PC match the series + described in PATTERN, or zero otherwise. PATTERN is an array of + 'struct insn_pattern' objects, terminated by an entry whose mask is + zero. + + When the match is successful, fill INSN[i] with what PATTERN[i] + matched. */ + +static int +hppa_match_insns (CORE_ADDR pc, struct insn_pattern *pattern, + unsigned int *insn) +{ + CORE_ADDR npc = pc; + int i; + + for (i = 0; pattern[i].mask; i++) + { + gdb_byte buf[HPPA_INSN_SIZE]; + + deprecated_read_memory_nobpt (npc, buf, HPPA_INSN_SIZE); + insn[i] = extract_unsigned_integer (buf, HPPA_INSN_SIZE); + if ((insn[i] & pattern[i].mask) == pattern[i].data) + npc += 4; + else + return 0; + } + + return 1; +} + +/* This relaxed version of the insstruction matcher allows us to match + from somewhere inside the pattern, by looking backwards in the + instruction scheme. */ + +static int +hppa_match_insns_relaxed (CORE_ADDR pc, struct insn_pattern *pattern, + unsigned int *insn) +{ + int offset, len = 0; + + while (pattern[len].mask) + len++; + + for (offset = 0; offset < len; offset++) + if (hppa_match_insns (pc - offset * HPPA_INSN_SIZE, pattern, insn)) + return 1; + + return 0; +} + +static int +hppa_in_dyncall (CORE_ADDR pc) +{ + struct unwind_table_entry *u; + + u = find_unwind_entry (hppa_symbol_address ("$$dyncall")); + if (!u) + return 0; + + return (pc >= u->region_start && pc <= u->region_end); +} + +int +hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name) +{ + unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN]; + struct unwind_table_entry *u; + + if (in_plt_section (pc, name) || hppa_in_dyncall (pc)) + return 1; + + /* The GNU toolchain produces linker stubs without unwind + information. Since the pattern matching for linker stubs can be + quite slow, so bail out if we do have an unwind entry. */ + + u = find_unwind_entry (pc); + if (u != NULL) + return 0; + + return (hppa_match_insns_relaxed (pc, hppa_import_stub, insn) + || hppa_match_insns_relaxed (pc, hppa_import_pic_stub, insn) + || hppa_match_insns_relaxed (pc, hppa_long_branch_stub, insn) + || hppa_match_insns_relaxed (pc, hppa_long_branch_pic_stub, insn)); +} + +/* This code skips several kind of "trampolines" used on PA-RISC + systems: $$dyncall, import stubs and PLT stubs. */ + +CORE_ADDR +hppa_skip_trampoline_code (CORE_ADDR pc) +{ + unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN]; + int dp_rel; + + /* $$dyncall handles both PLABELs and direct addresses. */ + if (hppa_in_dyncall (pc)) + { + pc = read_register (HPPA_R0_REGNUM + 22); + + /* PLABELs have bit 30 set; if it's a PLABEL, then dereference it. */ + if (pc & 0x2) + pc = read_memory_typed_address (pc & ~0x3, builtin_type_void_func_ptr); + + return pc; + } + + dp_rel = hppa_match_insns (pc, hppa_import_stub, insn); + if (dp_rel || hppa_match_insns (pc, hppa_import_pic_stub, insn)) + { + /* Extract the target address from the addil/ldw sequence. */ + pc = hppa_extract_21 (insn[0]) + hppa_extract_14 (insn[1]); + + if (dp_rel) + pc += read_register (HPPA_DP_REGNUM); + else + pc += read_register (HPPA_R0_REGNUM + 19); + + /* fallthrough */ + } + + if (in_plt_section (pc, NULL)) + { + pc = read_memory_typed_address (pc, builtin_type_void_func_ptr); + + /* If the PLT slot has not yet been resolved, the target will be + the PLT stub. */ + if (in_plt_section (pc, NULL)) + { + /* Sanity check: are we pointing to the PLT stub? */ + if (!hppa_match_insns (pc, hppa_plt_stub, insn)) + { + warning (_("Cannot resolve PLT stub at 0x%s."), paddr_nz (pc)); + return 0; + } + + /* This should point to the fixup routine. */ + pc = read_memory_typed_address (pc + 8, builtin_type_void_func_ptr); + } + } + + return pc; +} + + /* Here is a table of C type sizes on hppa with various compiles and options. I measured this on PA 9000/800 with HP-UX 11.11 and these compilers: @@ -2715,13 +3040,15 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_num_regs (gdbarch, hppa64_num_regs); set_gdbarch_register_name (gdbarch, hppa64_register_name); set_gdbarch_register_type (gdbarch, hppa64_register_type); + set_gdbarch_dwarf_reg_to_regnum (gdbarch, hppa64_dwarf_reg_to_regnum); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, hppa64_dwarf_reg_to_regnum); set_gdbarch_cannot_store_register (gdbarch, hppa64_cannot_store_register); set_gdbarch_cannot_fetch_register (gdbarch, hppa64_cannot_store_register); break; default: - internal_error (__FILE__, __LINE__, "Unsupported address size: %d", + internal_error (__FILE__, __LINE__, _("Unsupported address size: %d"), tdep->bytes_per_address); } @@ -2773,7 +3100,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_frame_align (gdbarch, hppa64_frame_align); break; default: - internal_error (__FILE__, __LINE__, "bad switch"); + internal_error (__FILE__, __LINE__, _("bad switch")); } /* Struct return methods. */ @@ -2786,7 +3113,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_return_value (gdbarch, hppa64_return_value); break; default: - internal_error (__FILE__, __LINE__, "bad switch"); + internal_error (__FILE__, __LINE__, _("bad switch")); } set_gdbarch_breakpoint_from_pc (gdbarch, hppa_breakpoint_from_pc); @@ -2827,15 +3154,18 @@ _initialize_hppa_tdep (void) hppa_objfile_priv_data = register_objfile_data (); add_cmd ("unwind", class_maintenance, unwind_command, - "Print unwind table entry at given address.", + _("Print unwind table entry at given address."), &maintenanceprintlist); /* Debug this files internals. */ - add_setshow_boolean_cmd ("hppa", class_maintenance, &hppa_debug, "\ -Set whether hppa target specific debugging information should be displayed.", "\ -Show whether hppa target specific debugging information is displayed.", "\ + add_setshow_boolean_cmd ("hppa", class_maintenance, &hppa_debug, _("\ +Set whether hppa target specific debugging information should be displayed."), + _("\ +Show whether hppa target specific debugging information is displayed."), _("\ This flag controls whether hppa target specific debugging information is\n\ displayed. This information is particularly useful for debugging frame\n\ -unwinding problems.", "hppa debug flag is %s.", - NULL, NULL, &setdebuglist, &showdebuglist); +unwinding problems."), + NULL, + NULL, /* FIXME: i18n: hppa debug flag is %s. */ + &setdebuglist, &showdebuglist); }