From 0fde2c536bc483baa4baa2990ebebfb3a7c00415 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Mon, 26 Oct 2015 16:05:21 -0700 Subject: [PATCH] PR symtab/17391 gdb internal error: assertion fails in regcache.c:178 gdb/ChangeLog: * dwarf2-frame.c (dwarf2_restore_rule): Call dwarf_reg_to_regnum instead of gdbarch_dwarf2_reg_to_regnum. (dwarf2_frame_cache): Ditto. (read_addr_from_reg): Call dwarf_reg_to_regnum_or_error instead of gdbarch_dwarf2_reg_to_regnum. (get_reg_value): Ditto. (dwarf2_fetch_cfa_info): Ditto. (dwarf2_frame_prev_register): Ditto. * dwarf2loc.c: #include "complaints.h". (dwarf_expr_read_addr_from_reg): Call dwarf_reg_to_regnum_or_error instead of gdbarch_dwarf2_reg_to_regnum. (dwarf_expr_get_reg_value): Ditto. (read_pieced_value): Ditto. (write_pieced_value): Ditto. (dwarf2_evaluate_loc_desc_full): Ditto. (dwarf_reg_to_regnum): New function. (throw_bad_regnum_error): New function. (dwarf_reg_to_regnum_or_error): Renamed from dwarf2_reg_to_regnum_or_errorChange to take a ULONGEST regnum. All callers updated. Call throw_bad_regnum_error. (locexpr_regname): Improve text of bad register number. * dwarf2loc.h (dwarf_reg_to_regnum): Declare. (dwarf_reg_to_regnum_or_error): Update prototype. * dwarf2expr.c: #include "dwarf2loc.h". (dwarf_block_to_sp_offset): Call dwarf_reg_to_regnum instead of gdbarch_dwarf2_reg_to_regnum. * gdbarch.sh (dwarf2_reg_to_regnum): Add comment. * gdbarch.h: Regenerate. * amd64-tdep.c (amd64_dwarf_reg_to_regnum): Remove warning for bad register. * avr-tdep.c (avr_dwarf_reg_to_regnum): Ditto. * cris-tdep.c (cris_dwarf2_reg_to_regnum): Ditto. * bfin-tdep.c (bfin_reg_to_regnum): Fix error checking. * hppa-linux-tdep.c (hppa_dwarf_reg_to_regnum): Improve error checking. Remove warning for bad register. * hppa-tdep.c (hppa64_dwarf_reg_to_regnum): Ditto. * i386-tdep.c (i386_svr4_dwarf_reg_to_regnum): Renamed from i386_svr4_reg_to_regnum. Return -1 for bad registers. (i386_svr4_reg_to_regnum): New function. (i386_gdbarch_init): Update call to set_gdbarch_dwarf2_reg_to_regnum. * microblaze-tdep.c (microblaze_dwarf2_reg_to_regnum): Don't assert on bad registers, return -1. * msp430-tdep.c (msp430_dwarf2_reg_to_regnum): Improve error checking. Remove warning for bad register. * nios2-tdep.c: Add static assert for NIOS2_NUM_REGS. (nios2_dwarf_reg_to_regnum): Fix off-by-one error. Remove warning for bad register. Return -1 for bad register. * rl78-tdep.c (rl78_dwarf_reg_to_regnum): Don't flag an internal error for bad register, return -1. * rx-tdep.c (rx_dwarf_reg_to_regnum): Ditto. * m68k-tdep.c (m68k_dwarf_reg_to_regnum): Fix error result. * mep-tdep.c (mep_debug_reg_to_regnum): Ditto. * mips-tdep.c (mips_stab_reg_to_regnum): Ditto. (mips_dwarf_dwarf2_ecoff_reg_to_regnum): Ditto. * mn10300-tdep.c (mn10300_dwarf2_reg_to_regnum): Remove warning for bad regs. * xtensa-tdep.c (xtensa_reg_to_regnum): Remove internal error for bad regs. Fix error result. * stabsread.c (stab_reg_to_regnum): Watch for negative regno. (reg_value_complaint): Update complaint text. * mdebugread.c (reg_value_complaint): New function. (mdebug_reg_to_regnum): Rewrite to watch for bad reg numbers. gdb/testsuite/ChangeLog: * lib/dwarf.exp (_location): Add support for DW_OP_regx. * gdb.dwarf2/bad-regnum.c: New file. * gdb.dwarf2/bad-regnum.exp: New file. --- gdb/ChangeLog | 66 +++++++ gdb/amd64-tdep.c | 4 +- gdb/avr-tdep.c | 3 - gdb/bfin-tdep.c | 4 +- gdb/compile/compile-loc2c.c | 12 +- gdb/cris-tdep.c | 3 - gdb/dwarf2-frame.c | 39 ++-- gdb/dwarf2expr.c | 3 +- gdb/dwarf2loc.c | 229 +++++++++++++----------- gdb/dwarf2loc.h | 15 +- gdb/gdbarch.h | 3 +- gdb/gdbarch.sh | 1 + gdb/hppa-linux-tdep.c | 3 +- gdb/hppa-tdep.c | 3 +- gdb/i386-tdep.c | 22 ++- gdb/m68k-tdep.c | 2 +- gdb/mdebugread.c | 24 ++- gdb/mep-tdep.c | 4 +- gdb/microblaze-tdep.c | 5 +- gdb/mips-tdep.c | 8 +- gdb/mn10300-tdep.c | 5 +- gdb/msp430-tdep.c | 8 +- gdb/nios2-tdep.c | 8 +- gdb/rl78-tdep.c | 4 +- gdb/rx-tdep.c | 4 +- gdb/stabsread.c | 7 +- gdb/testsuite/ChangeLog | 7 + gdb/testsuite/gdb.dwarf2/bad-regnum.c | 22 +++ gdb/testsuite/gdb.dwarf2/bad-regnum.exp | 76 ++++++++ gdb/testsuite/lib/dwarf.exp | 4 + gdb/xtensa-tdep.c | 4 +- 31 files changed, 411 insertions(+), 191 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/bad-regnum.c create mode 100644 gdb/testsuite/gdb.dwarf2/bad-regnum.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 337ff05846f..a481f099741 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,69 @@ +2015-10-26 Doug Evans + + PR symtab/17391 + * dwarf2-frame.c (dwarf2_restore_rule): Call dwarf_reg_to_regnum + instead of gdbarch_dwarf2_reg_to_regnum. + (dwarf2_frame_cache): Ditto. + (read_addr_from_reg): Call dwarf_reg_to_regnum_or_error instead of + gdbarch_dwarf2_reg_to_regnum. + (get_reg_value): Ditto. + (dwarf2_fetch_cfa_info): Ditto. + (dwarf2_frame_prev_register): Ditto. + * dwarf2loc.c: #include "complaints.h". + (dwarf_expr_read_addr_from_reg): Call dwarf_reg_to_regnum_or_error + instead of gdbarch_dwarf2_reg_to_regnum. + (dwarf_expr_get_reg_value): Ditto. + (read_pieced_value): Ditto. + (write_pieced_value): Ditto. + (dwarf2_evaluate_loc_desc_full): Ditto. + (dwarf_reg_to_regnum): New function. + (throw_bad_regnum_error): New function. + (dwarf_reg_to_regnum_or_error): Renamed from + dwarf2_reg_to_regnum_or_errorChange to take a ULONGEST regnum. + All callers updated. Call throw_bad_regnum_error. + (locexpr_regname): Improve text of bad register number. + * dwarf2loc.h (dwarf_reg_to_regnum): Declare. + (dwarf_reg_to_regnum_or_error): Update prototype. + * dwarf2expr.c: #include "dwarf2loc.h". + (dwarf_block_to_sp_offset): Call dwarf_reg_to_regnum instead of + gdbarch_dwarf2_reg_to_regnum. + * gdbarch.sh (dwarf2_reg_to_regnum): Add comment. + * gdbarch.h: Regenerate. + * amd64-tdep.c (amd64_dwarf_reg_to_regnum): Remove warning for bad + register. + * avr-tdep.c (avr_dwarf_reg_to_regnum): Ditto. + * cris-tdep.c (cris_dwarf2_reg_to_regnum): Ditto. + * bfin-tdep.c (bfin_reg_to_regnum): Fix error checking. + * hppa-linux-tdep.c (hppa_dwarf_reg_to_regnum): Improve error checking. + Remove warning for bad register. + * hppa-tdep.c (hppa64_dwarf_reg_to_regnum): Ditto. + * i386-tdep.c (i386_svr4_dwarf_reg_to_regnum): Renamed from + i386_svr4_reg_to_regnum. Return -1 for bad registers. + (i386_svr4_reg_to_regnum): New function. + (i386_gdbarch_init): Update call to set_gdbarch_dwarf2_reg_to_regnum. + * microblaze-tdep.c (microblaze_dwarf2_reg_to_regnum): Don't assert + on bad registers, return -1. + * msp430-tdep.c (msp430_dwarf2_reg_to_regnum): Improve error checking. + Remove warning for bad register. + * nios2-tdep.c: Add static assert for NIOS2_NUM_REGS. + (nios2_dwarf_reg_to_regnum): Fix off-by-one error. + Remove warning for bad register. Return -1 for bad register. + * rl78-tdep.c (rl78_dwarf_reg_to_regnum): Don't flag an internal error + for bad register, return -1. + * rx-tdep.c (rx_dwarf_reg_to_regnum): Ditto. + * m68k-tdep.c (m68k_dwarf_reg_to_regnum): Fix error result. + * mep-tdep.c (mep_debug_reg_to_regnum): Ditto. + * mips-tdep.c (mips_stab_reg_to_regnum): Ditto. + (mips_dwarf_dwarf2_ecoff_reg_to_regnum): Ditto. + * mn10300-tdep.c (mn10300_dwarf2_reg_to_regnum): Remove warning + for bad regs. + * xtensa-tdep.c (xtensa_reg_to_regnum): Remove internal error for + bad regs. Fix error result. + * stabsread.c (stab_reg_to_regnum): Watch for negative regno. + (reg_value_complaint): Update complaint text. + * mdebugread.c (reg_value_complaint): New function. + (mdebug_reg_to_regnum): Rewrite to watch for bad reg numbers. + 2015-10-26 Doug Evans PR python/18938 diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index f0720c8c249..6096ce9fa95 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -252,9 +252,7 @@ amd64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) if (reg >= 0 && reg < amd64_dwarf_regmap_len) regnum = amd64_dwarf_regmap[reg]; - if (regnum == -1) - warning (_("Unmapped DWARF Register #%d encountered."), reg); - else if (ymm0_regnum >= 0 + if (ymm0_regnum >= 0 && i386_xmm_regnum_p (gdbarch, regnum)) regnum += ymm0_regnum - I387_XMM0_REGNUM (tdep); diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 1108eb4681e..9c54b2d4b05 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -1364,9 +1364,6 @@ avr_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) return reg; if (reg == 32) return AVR_SP_REGNUM; - - warning (_("Unmapped DWARF Register #%d encountered."), reg); - return -1; } diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c index 3afa7bc63da..1d48225b420 100644 --- a/gdb/bfin-tdep.c +++ b/gdb/bfin-tdep.c @@ -566,8 +566,8 @@ bfin_push_dummy_call (struct gdbarch *gdbarch, static int bfin_reg_to_regnum (struct gdbarch *gdbarch, int reg) { - if (reg > ARRAY_SIZE (map_gcc_gdb)) - return 0; + if (reg < 0 || reg >= ARRAY_SIZE (map_gcc_gdb)) + return -1; return map_gcc_gdb[reg]; } diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c index 8058cbd74fb..dac904e17c8 100644 --- a/gdb/compile/compile-loc2c.c +++ b/gdb/compile/compile-loc2c.c @@ -817,15 +817,15 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream, case DW_OP_reg31: dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx"); pushf_register_address (indent, stream, registers_used, arch, - dwarf2_reg_to_regnum_or_error (arch, - op - DW_OP_reg0)); + dwarf_reg_to_regnum_or_error + (arch, op - DW_OP_reg0)); break; case DW_OP_regx: op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx"); pushf_register_address (indent, stream, registers_used, arch, - dwarf2_reg_to_regnum_or_error (arch, reg)); + dwarf_reg_to_regnum_or_error (arch, reg)); break; case DW_OP_breg0: @@ -862,8 +862,8 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream, case DW_OP_breg31: op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); pushf_register (indent, stream, registers_used, arch, - dwarf2_reg_to_regnum_or_error (arch, - op - DW_OP_breg0), + dwarf_reg_to_regnum_or_error (arch, + op - DW_OP_breg0), offset); break; case DW_OP_bregx: @@ -871,7 +871,7 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream, op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); pushf_register (indent, stream, registers_used, arch, - dwarf2_reg_to_regnum_or_error (arch, reg), offset); + dwarf_reg_to_regnum_or_error (arch, reg), offset); } break; case DW_OP_fbreg: diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index 3d53aef449c..46afc1f1e05 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -1790,9 +1790,6 @@ cris_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg) if (reg >= 0 && reg < ARRAY_SIZE (cris_dwarf_regmap)) regnum = cris_dwarf_regmap[reg]; - if (regnum == -1) - warning (_("Unmapped DWARF Register #%d encountered."), reg); - return regnum; } diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 200b04469a4..a640c2614ea 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -292,7 +292,7 @@ read_addr_from_reg (void *baton, int reg) { struct frame_info *this_frame = (struct frame_info *) baton; struct gdbarch *gdbarch = get_frame_arch (this_frame); - int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg); return address_from_register (regnum, this_frame); } @@ -304,7 +304,7 @@ get_reg_value (void *baton, struct type *type, int reg) { struct frame_info *this_frame = (struct frame_info *) baton; struct gdbarch *gdbarch = get_frame_arch (this_frame); - int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg); return value_from_register (type, regnum, this_frame); } @@ -336,13 +336,15 @@ dwarf2_restore_rule (struct gdbarch *gdbarch, ULONGEST reg_num, fs->regs.reg[reg].how = DWARF2_FRAME_REG_UNSPECIFIED; if (fs->regs.reg[reg].how == DWARF2_FRAME_REG_UNSPECIFIED) - complaint (&symfile_complaints, _("\ + { + int regnum = dwarf_reg_to_regnum (gdbarch, reg); + + complaint (&symfile_complaints, _("\ incomplete CFI data; DW_CFA_restore unspecified\n\ register %s (#%d) at %s"), - gdbarch_register_name - (gdbarch, gdbarch_dwarf2_reg_to_regnum (gdbarch, reg)), - gdbarch_dwarf2_reg_to_regnum (gdbarch, reg), - paddress (gdbarch, fs->pc)); + gdbarch_register_name (gdbarch, regnum), regnum, + paddress (gdbarch, fs->pc)); + } } /* Virtual method table for execute_stack_op below. */ @@ -942,11 +944,7 @@ dwarf2_fetch_cfa_info (struct gdbarch *gdbarch, CORE_ADDR pc, { case CFA_REG_OFFSET: { - int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, fs.regs.cfa_reg); - - if (regnum == -1) - error (_("Unable to access DWARF register number %d"), - (int) fs.regs.cfa_reg); /* FIXME */ + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, fs.regs.cfa_reg); *regnum_out = regnum; if (fs.armcc_cfa_offsets_reversed) @@ -1093,7 +1091,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) entry_pc, fs); if (fs->regs.cfa_how == CFA_REG_OFFSET - && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg) + && (dwarf_reg_to_regnum (gdbarch, fs->regs.cfa_reg) == gdbarch_sp_regnum (gdbarch))) { cache->entry_cfa_sp_offset = fs->regs.cfa_offset; @@ -1156,19 +1154,16 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) /* Go through the DWARF2 CFI generated table and save its register location information in the cache. Note that we don't skip the return address column; it's perfectly all right for it to - correspond to a real register. If it doesn't correspond to a - real register, or if we shouldn't treat it as such, - gdbarch_dwarf2_reg_to_regnum should be defined to return a number outside - the range [0, gdbarch_num_regs). */ + correspond to a real register. */ { int column; /* CFI speak for "register number". */ for (column = 0; column < fs->regs.num_regs; column++) { /* Use the GDB register number as the destination index. */ - int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, column); + int regnum = dwarf_reg_to_regnum (gdbarch, column); - /* If there's no corresponding GDB register, ignore it. */ + /* Protect against a target returning a bad register. */ if (regnum < 0 || regnum >= num_regs) continue; @@ -1330,8 +1325,8 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, return frame_unwind_got_memory (this_frame, regnum, addr); case DWARF2_FRAME_REG_SAVED_REG: - realnum - = gdbarch_dwarf2_reg_to_regnum (gdbarch, cache->reg[regnum].loc.reg); + realnum = dwarf_reg_to_regnum_or_error + (gdbarch, cache->reg[regnum].loc.reg); return frame_unwind_got_register (this_frame, regnum, realnum); case DWARF2_FRAME_REG_SAVED_EXP: @@ -1374,7 +1369,7 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, case DWARF2_FRAME_REG_RA_OFFSET: addr = cache->reg[regnum].loc.offset; - regnum = gdbarch_dwarf2_reg_to_regnum + regnum = dwarf_reg_to_regnum_or_error (gdbarch, cache->retaddr_reg.loc.reg); addr += get_frame_register_unsigned (this_frame, regnum); return frame_unwind_got_address (this_frame, regnum, addr); diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c index 2ac60b7e50e..2e500e94baa 100644 --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -26,6 +26,7 @@ #include "gdbcore.h" #include "dwarf2.h" #include "dwarf2expr.h" +#include "dwarf2loc.h" /* Local prototypes. */ @@ -611,7 +612,7 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf, return 0; } - if (gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg) + if (dwarf_reg_to_regnum (gdbarch, dwarf_reg) != gdbarch_sp_regnum (gdbarch)) return 0; diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 3e652f97ac1..a8f5c91289c 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -32,7 +32,7 @@ #include "objfiles.h" #include "block.h" #include "gdbcmd.h" - +#include "complaints.h" #include "dwarf2.h" #include "dwarf2expr.h" #include "dwarf2loc.h" @@ -312,7 +312,7 @@ dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum) { struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; struct gdbarch *gdbarch = get_frame_arch (debaton->frame); - int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum); return address_from_register (regnum, debaton->frame); } @@ -324,7 +324,7 @@ dwarf_expr_get_reg_value (void *baton, struct type *type, int dwarf_regnum) { struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; struct gdbarch *gdbarch = get_frame_arch (debaton->frame); - int regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum); + int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum); return value_from_register (type, regnum, debaton->frame); } @@ -1757,40 +1757,31 @@ read_pieced_value (struct value *v) case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno); + int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno); + int optim, unavail; + int reg_offset = source_offset; - if (gdb_regnum != -1) + if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG + && this_size < register_size (arch, gdb_regnum)) { - int optim, unavail; - int reg_offset = source_offset; - - if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG - && this_size < register_size (arch, gdb_regnum)) - { - /* Big-endian, and we want less than full size. */ - reg_offset = register_size (arch, gdb_regnum) - this_size; - /* We want the lower-order THIS_SIZE_BITS of the bytes - we extract from the register. */ - source_offset_bits += 8 * this_size - this_size_bits; - } - - if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, - this_size, buffer, - &optim, &unavail)) - { - /* Just so garbage doesn't ever shine through. */ - memset (buffer, 0, this_size); - - if (optim) - mark_value_bits_optimized_out (v, offset, this_size_bits); - if (unavail) - mark_value_bits_unavailable (v, offset, this_size_bits); - } + /* Big-endian, and we want less than full size. */ + reg_offset = register_size (arch, gdb_regnum) - this_size; + /* We want the lower-order THIS_SIZE_BITS of the bytes + we extract from the register. */ + source_offset_bits += 8 * this_size - this_size_bits; } - else + + if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, + this_size, buffer, + &optim, &unavail)) { - error (_("Unable to access DWARF register number %s"), - paddress (arch, p->v.regno)); + /* Just so garbage doesn't ever shine through. */ + memset (buffer, 0, this_size); + + if (optim) + mark_value_bits_optimized_out (v, offset, this_size_bits); + if (unavail) + mark_value_bits_unavailable (v, offset, this_size_bits); } } break; @@ -1949,52 +1940,43 @@ write_pieced_value (struct value *to, struct value *from) case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno); + int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, p->v.regno); + int reg_offset = dest_offset; - if (gdb_regnum != -1) + if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG + && this_size <= register_size (arch, gdb_regnum)) { - int reg_offset = dest_offset; + /* Big-endian, and we want less than full size. */ + reg_offset = register_size (arch, gdb_regnum) - this_size; + } - if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG - && this_size <= register_size (arch, gdb_regnum)) - { - /* Big-endian, and we want less than full size. */ - reg_offset = register_size (arch, gdb_regnum) - this_size; - } + if (need_bitwise) + { + int optim, unavail; - if (need_bitwise) + if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, + this_size, buffer, + &optim, &unavail)) { - int optim, unavail; - - if (!get_frame_register_bytes (frame, gdb_regnum, reg_offset, - this_size, buffer, - &optim, &unavail)) - { - if (optim) - throw_error (OPTIMIZED_OUT_ERROR, - _("Can't do read-modify-write to " - "update bitfield; containing word " - "has been optimized out")); - if (unavail) - throw_error (NOT_AVAILABLE_ERROR, - _("Can't do read-modify-write to update " - "bitfield; containing word " - "is unavailable")); - } - copy_bitwise (buffer, dest_offset_bits, - contents, source_offset_bits, - this_size_bits, - bits_big_endian); + if (optim) + throw_error (OPTIMIZED_OUT_ERROR, + _("Can't do read-modify-write to " + "update bitfield; containing word " + "has been optimized out")); + if (unavail) + throw_error (NOT_AVAILABLE_ERROR, + _("Can't do read-modify-write to update " + "bitfield; containing word " + "is unavailable")); } - - put_frame_register_bytes (frame, gdb_regnum, reg_offset, - this_size, source_buffer); - } - else - { - error (_("Unable to write to DWARF register number %s"), - paddress (arch, p->v.regno)); + copy_bitwise (buffer, dest_offset_bits, + contents, source_offset_bits, + this_size_bits, + bits_big_endian); } + + put_frame_register_bytes (frame, gdb_regnum, reg_offset, + this_size, source_buffer); } break; case DWARF_VALUE_MEMORY: @@ -2335,30 +2317,27 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, struct gdbarch *arch = get_frame_arch (frame); int dwarf_regnum = longest_to_int (value_as_long (dwarf_expr_fetch (ctx, 0))); - int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum); + int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, dwarf_regnum); if (byte_offset != 0) error (_("cannot use offset on synthetic pointer to register")); do_cleanups (value_chain); - if (gdb_regnum == -1) - error (_("Unable to access DWARF register number %d"), - dwarf_regnum); - retval = value_from_register (type, gdb_regnum, frame); - if (value_optimized_out (retval)) - { - struct value *tmp; - - /* This means the register has undefined value / was - not saved. As we're computing the location of some - variable etc. in the program, not a value for - inspecting a register ($pc, $sp, etc.), return a - generic optimized out value instead, so that we show - instead of . */ - do_cleanups (value_chain); - tmp = allocate_value (type); - value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type)); - retval = tmp; - } + retval = value_from_register (type, gdb_regnum, frame); + if (value_optimized_out (retval)) + { + struct value *tmp; + + /* This means the register has undefined value / was + not saved. As we're computing the location of some + variable etc. in the program, not a value for + inspecting a register ($pc, $sp, etc.), return a + generic optimized out value instead, so that we show + instead of . */ + do_cleanups (value_chain); + tmp = allocate_value (type); + value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type)); + retval = tmp; + } } break; @@ -2858,14 +2837,54 @@ unimplemented (unsigned int op) op); } -/* See dwarf2loc.h. */ +/* See dwarf2loc.h. + + This is basically a wrapper on gdbarch_dwarf2_reg_to_regnum so that we + can issue a complaint, which is better than having every target's + implementation of dwarf2_reg_to_regnum do it. */ int -dwarf2_reg_to_regnum_or_error (struct gdbarch *arch, int dwarf_reg) +dwarf_reg_to_regnum (struct gdbarch *arch, int dwarf_reg) { int reg = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_reg); + if (reg == -1) - error (_("Unable to access DWARF register number %d"), dwarf_reg); + { + complaint (&symfile_complaints, + _("bad DWARF register number %d"), dwarf_reg); + } + return reg; +} + +/* Subroutine of dwarf_reg_to_regnum_or_error to simplify it. + Throw an error because DWARF_REG is bad. */ + +static void +throw_bad_regnum_error (ULONGEST dwarf_reg) +{ + /* Still want to print -1 as "-1". + We *could* have int and ULONGEST versions of dwarf2_reg_to_regnum_or_error + but that's overkill for now. */ + if ((int) dwarf_reg == dwarf_reg) + error (_("Unable to access DWARF register number %d"), (int) dwarf_reg); + error (_("Unable to access DWARF register number %s"), + pulongest (dwarf_reg)); +} + +/* See dwarf2loc.h. */ + +int +dwarf_reg_to_regnum_or_error (struct gdbarch *arch, ULONGEST dwarf_reg) +{ + int reg; + + if (dwarf_reg > INT_MAX) + throw_bad_regnum_error (dwarf_reg); + /* Yes, we will end up issuing a complaint and an error if DWARF_REG is + bad, but that's ok. */ + reg = dwarf_reg_to_regnum (arch, (int) dwarf_reg); + if (reg == -1) + throw_bad_regnum_error (dwarf_reg); return reg; } @@ -3112,14 +3131,14 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc, case DW_OP_reg30: case DW_OP_reg31: dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx"); - loc->u.reg = dwarf2_reg_to_regnum_or_error (arch, op - DW_OP_reg0); + loc->u.reg = dwarf_reg_to_regnum_or_error (arch, op - DW_OP_reg0); loc->kind = axs_lvalue_register; break; case DW_OP_regx: op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx"); - loc->u.reg = dwarf2_reg_to_regnum_or_error (arch, reg); + loc->u.reg = dwarf_reg_to_regnum_or_error (arch, reg); loc->kind = axs_lvalue_register; break; @@ -3182,7 +3201,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc, case DW_OP_breg30: case DW_OP_breg31: op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); - i = dwarf2_reg_to_regnum_or_error (arch, op - DW_OP_breg0); + i = dwarf_reg_to_regnum_or_error (arch, op - DW_OP_breg0); ax_reg (expr, i); if (offset != 0) { @@ -3194,7 +3213,7 @@ dwarf2_compile_expr_to_ax (struct agent_expr *expr, struct axs_value *loc, { op_ptr = safe_read_uleb128 (op_ptr, op_end, ®); op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset); - i = dwarf2_reg_to_regnum_or_error (arch, reg); + i = dwarf_reg_to_regnum_or_error (arch, reg); ax_reg (expr, i); if (offset != 0) { @@ -3659,7 +3678,17 @@ locexpr_regname (struct gdbarch *gdbarch, int dwarf_regnum) { int regnum; - regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum); + /* This doesn't use dwarf_reg_to_regnum_or_error on purpose. + We'd rather print *something* here than throw an error. */ + regnum = dwarf_reg_to_regnum (gdbarch, dwarf_regnum); + /* gdbarch_register_name may just return "", return something more + descriptive for bad register numbers. */ + if (regnum == -1) + { + /* The text is output as "$bad_register_number". + That is why we use the underscores. */ + return _("bad_register_number"); + } return gdbarch_register_name (gdbarch, regnum); } diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index 2415656589c..aac983a0513 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -293,9 +293,18 @@ extern struct call_site_chain *call_site_find_chain (struct gdbarch *gdbarch, /* A helper function to convert a DWARF register to an arch register. ARCH is the architecture. DWARF_REG is the register. - This will throw an exception if the DWARF register cannot be - translated to an architecture register. */ + If DWARF_REG is bad then a complaint is issued and -1 is returned. + Note: Some targets get this wrong. */ -extern int dwarf2_reg_to_regnum_or_error (struct gdbarch *arch, int dwarf_reg); +extern int dwarf_reg_to_regnum (struct gdbarch *arch, int dwarf_reg); + +/* A wrapper on dwarf_reg_to_regnum to throw an exception if the + DWARF register cannot be translated to an architecture register. + This takes a ULONGEST instead of an int because some callers actually have + a ULONGEST. Negative values passed as ints will still be flagged as + invalid. */ + +extern int dwarf_reg_to_regnum_or_error (struct gdbarch *arch, + ULONGEST dwarf_reg); #endif /* dwarf2loc.h */ diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 3eb81c152c3..b9b2290c4c6 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -334,7 +334,8 @@ typedef int (gdbarch_sdb_reg_to_regnum_ftype) (struct gdbarch *gdbarch, int sdb_ extern int gdbarch_sdb_reg_to_regnum (struct gdbarch *gdbarch, int sdb_regnr); extern void set_gdbarch_sdb_reg_to_regnum (struct gdbarch *gdbarch, gdbarch_sdb_reg_to_regnum_ftype *sdb_reg_to_regnum); -/* Provide a default mapping from a DWARF2 register number to a gdb REGNUM. */ +/* Provide a default mapping from a DWARF2 register number to a gdb REGNUM. + Return -1 for bad REGNUM. Note: Several targets get this wrong. */ typedef int (gdbarch_dwarf2_reg_to_regnum_ftype) (struct gdbarch *gdbarch, int dwarf2_regnr); extern int gdbarch_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int dwarf2_regnr); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index ce9d71d19be..236ce41b473 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -461,6 +461,7 @@ m:int:ecoff_reg_to_regnum:int ecoff_regnr:ecoff_regnr::no_op_reg_to_regnum::0 # Convert from an sdb register number to an internal gdb register number. m:int:sdb_reg_to_regnum:int sdb_regnr:sdb_regnr::no_op_reg_to_regnum::0 # Provide a default mapping from a DWARF2 register number to a gdb REGNUM. +# Return -1 for bad REGNUM. Note: Several targets get this wrong. m:int:dwarf2_reg_to_regnum:int dwarf2_regnr:dwarf2_regnr::no_op_reg_to_regnum::0 m:const char *:register_name:int regnr:regnr::0 diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c index 0b05c372927..eb7203a0547 100644 --- a/gdb/hppa-linux-tdep.c +++ b/gdb/hppa-linux-tdep.c @@ -39,14 +39,13 @@ static int hppa_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { /* The general registers and the sar are the same in both sets. */ - if (reg <= 32) + if (reg >= 0 && reg <= 32) return reg; /* fr4-fr31 (left and right halves) are mapped from 72. */ if (reg >= 72 && reg <= 72 + 28 * 2) return HPPA_FP4_REGNUM + (reg - 72); - warning (_("Unmapped DWARF DBX Register #%d encountered."), reg); return -1; } diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 78462d3fe0c..ba7f9461591 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -696,14 +696,13 @@ static int hppa64_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { /* The general registers and the sar are the same in both sets. */ - if (reg <= 32) + if (reg >= 0 && reg <= 32) return reg; /* fr4-fr31 are mapped from 72 in steps of 2. */ if (reg >= 72 && reg < 72 + 28 * 2 && !(reg & 1)) return HPPA64_FP4_REGNUM + (reg - 72) / 2; - warning (_("Unmapped DWARF DBX Register #%d encountered."), reg); return -1; } diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 92f60fd8731..e83f49fc337 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -502,11 +502,11 @@ i386_dbx_reg_to_regnum (struct gdbarch *gdbarch, int reg) return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); } -/* Convert SVR4 register number REG to the appropriate register number +/* Convert SVR4 DWARF register number REG to the appropriate register number used by GDB. */ static int -i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg) +i386_svr4_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -544,8 +544,20 @@ i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg) case 45: return I386_GS_REGNUM; } - /* This will hopefully provoke a warning. */ - return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + return -1; +} + +/* Wrapper on i386_svr4_dwarf_reg_to_regnum to return + num_regs + num_pseudo_regs for other debug formats. */ + +static int +i386_svr4_reg_to_regnum (struct gdbarch *gdbarch, int reg) +{ + int regnum = i386_svr4_dwarf_reg_to_regnum (gdbarch, reg); + + if (regnum == -1) + return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + return regnum; } @@ -8349,7 +8361,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_sdb_reg_to_regnum (gdbarch, i386_dbx_reg_to_regnum); /* Use the SVR4 register numbering scheme for DWARF 2. */ - set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum); + set_gdbarch_dwarf2_reg_to_regnum (gdbarch, i386_svr4_dwarf_reg_to_regnum); /* We don't set gdbarch_stab_reg_to_regnum, since ECOFF doesn't seem to be in use on any of the supported i386 targets. */ diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index 01e67b9a51c..1a18d36eb9a 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -573,7 +573,7 @@ m68k_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int num) /* pc */ return M68K_PC_REGNUM; else - return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + return -1; } diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c index 8109ee3a867..03c1ff893e4 100644 --- a/gdb/mdebugread.c +++ b/gdb/mdebugread.c @@ -521,6 +521,14 @@ add_pending (FDR *fh, char *sh, struct type *t) /* Parsing Routines proper. */ +static void +reg_value_complaint (int regnum, int num_regs, const char *sym) +{ + complaint (&symfile_complaints, + _("bad register number %d (max %d) in symbol %s"), + regnum, num_regs - 1, sym); +} + /* Parse a single symbol. Mostly just make up a GDB symbol for it. For blocks, procedures and types we open a new lexical context. This is basically just a big switch on the symbol's type. Argument @@ -533,7 +541,21 @@ add_pending (FDR *fh, char *sh, struct type *t) static int mdebug_reg_to_regnum (struct symbol *sym, struct gdbarch *gdbarch) { - return gdbarch_ecoff_reg_to_regnum (gdbarch, SYMBOL_VALUE (sym)); + int regno = gdbarch_ecoff_reg_to_regnum (gdbarch, SYMBOL_VALUE (sym)); + + if (regno < 0 + || regno >= (gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch))) + { + reg_value_complaint (regno, + gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch), + SYMBOL_PRINT_NAME (sym)); + + regno = gdbarch_sp_regnum (gdbarch); /* Known safe, though useless. */ + } + + return regno; } static const struct symbol_register_ops mdebug_register_funcs = { diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c index f7d33ca92c7..81243b7efd6 100644 --- a/gdb/mep-tdep.c +++ b/gdb/mep-tdep.c @@ -784,7 +784,9 @@ static int mep_debug_reg_to_regnum (struct gdbarch *gdbarch, int debug_reg) { /* The debug info uses the raw register numbers. */ - return mep_raw_to_pseudo[debug_reg]; + if (debug_reg >= 0 && debug_reg < ARRAY_SIZE (mep_raw_to_pseudo)) + return mep_raw_to_pseudo[debug_reg]; + return -1; } diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c index 02dfd2d7932..4bcd88d12b5 100644 --- a/gdb/microblaze-tdep.c +++ b/gdb/microblaze-tdep.c @@ -638,8 +638,9 @@ static int dwarf2_to_reg_map[78] = static int microblaze_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg) { - gdb_assert ((size_t) reg < sizeof (dwarf2_to_reg_map)); - return dwarf2_to_reg_map[reg]; + if (reg >= 0 && reg < sizeof (dwarf2_to_reg_map)) + return dwarf2_to_reg_map[reg]; + return -1; } static void diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 2275138001c..7cea8321a4f 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -8024,9 +8024,7 @@ mips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 72 && num < 78) regnum = num + mips_regnum (gdbarch)->dspacc - 72; else - /* This will hopefully (eventually) provoke a warning. Should - we be calling complaint() here? */ - return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + return -1; return gdbarch_num_regs (gdbarch) + regnum; } @@ -8049,9 +8047,7 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num) else if (mips_regnum (gdbarch)->dspacc != -1 && num >= 66 && num < 72) regnum = num + mips_regnum (gdbarch)->dspacc - 66; else - /* This will hopefully (eventually) provoke a warning. Should we - be calling complaint() here? */ - return gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch); + return -1; return gdbarch_num_regs (gdbarch) + regnum; } diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index c6d018f9784..5603333263b 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -1385,10 +1385,7 @@ mn10300_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int dwarf2) if (dwarf2 < 0 || dwarf2 >= ARRAY_SIZE (dwarf2_to_gdb)) - { - warning (_("Bogus register number in debug info: %d"), dwarf2); - return -1; - } + return -1; return dwarf2_to_gdb[dwarf2]; } diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c index 4c22ee429c5..5368025561b 100644 --- a/gdb/msp430-tdep.c +++ b/gdb/msp430-tdep.c @@ -583,13 +583,9 @@ static const struct frame_unwind msp430_unwind = { static int msp430_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg) { - if (reg < MSP430_NUM_REGS) + if (reg >= 0 && reg < MSP430_NUM_REGS) return reg + MSP430_NUM_REGS; - else - { - warning (_("Unmapped DWARF Register #%d encountered."), reg); - return -1; - } + return -1; } /* Implement the "return_value" gdbarch method. */ diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c index 3b66dbaae97..8ffe84d9675 100644 --- a/gdb/nios2-tdep.c +++ b/gdb/nios2-tdep.c @@ -138,17 +138,15 @@ static int nios2_dwarf2gdb_regno_map[] = NIOS2_MPUACC_REGNUM /* 48 */ }; +gdb_static_assert (ARRAY_SIZE (nios2_dwarf2gdb_regno_map) == NIOS2_NUM_REGS); /* Implement the dwarf2_reg_to_regnum gdbarch method. */ static int nios2_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int dw_reg) { - if (dw_reg < 0 || dw_reg > NIOS2_NUM_REGS) - { - warning (_("Dwarf-2 uses unmapped register #%d"), dw_reg); - return dw_reg; - } + if (dw_reg < 0 || dw_reg >= NIOS2_NUM_REGS) + return -1; return nios2_dwarf2gdb_regno_map[dw_reg]; } diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c index c97e7c87d3a..bbe61c10298 100644 --- a/gdb/rl78-tdep.c +++ b/gdb/rl78-tdep.c @@ -1217,9 +1217,7 @@ rl78_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) else if (reg == 37) return RL78_PC_REGNUM; else - internal_error (__FILE__, __LINE__, - _("Undefined dwarf2 register mapping of reg %d"), - reg); + return -1; } /* Implement the `register_sim_regno' gdbarch method. */ diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c index a95c6d33e19..5a9d729b69b 100644 --- a/gdb/rx-tdep.c +++ b/gdb/rx-tdep.c @@ -1011,9 +1011,7 @@ rx_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg) else if (reg == 17) return RX_PC_REGNUM; else - internal_error (__FILE__, __LINE__, - _("Undefined dwarf2 register mapping of reg %d"), - reg); + return -1; } /* Allocate and initialize a gdbarch object. */ diff --git a/gdb/stabsread.c b/gdb/stabsread.c index e6eacd3797b..bc435660699 100644 --- a/gdb/stabsread.c +++ b/gdb/stabsread.c @@ -169,7 +169,7 @@ static void reg_value_complaint (int regnum, int num_regs, const char *sym) { complaint (&symfile_complaints, - _("register number %d too large (max %d) in symbol %s"), + _("bad register number %d (max %d) in symbol %s"), regnum, num_regs - 1, sym); } @@ -597,8 +597,9 @@ stab_reg_to_regnum (struct symbol *sym, struct gdbarch *gdbarch) { int regno = gdbarch_stab_reg_to_regnum (gdbarch, SYMBOL_VALUE (sym)); - if (regno >= gdbarch_num_regs (gdbarch) - + gdbarch_num_pseudo_regs (gdbarch)) + if (regno < 0 + || regno >= (gdbarch_num_regs (gdbarch) + + gdbarch_num_pseudo_regs (gdbarch))) { reg_value_complaint (regno, gdbarch_num_regs (gdbarch) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 0543617ab0a..89c453c5b7b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-10-26 Doug Evans + + PR symtab/17391 + * lib/dwarf.exp (_location): Add support for DW_OP_regx. + * gdb.dwarf2/bad-regnum.c: New file. + * gdb.dwarf2/bad-regnum.exp: New file. + 2015-10-26 Doug Evans PR python/18938 diff --git a/gdb/testsuite/gdb.dwarf2/bad-regnum.c b/gdb/testsuite/gdb.dwarf2/bad-regnum.c new file mode 100644 index 00000000000..35230f26e5f --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/bad-regnum.c @@ -0,0 +1,22 @@ +/* Copyright 2015 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +int +main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/bad-regnum.exp b/gdb/testsuite/gdb.dwarf2/bad-regnum.exp new file mode 100644 index 00000000000..749d72148d7 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/bad-regnum.exp @@ -0,0 +1,76 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile bad-regnum.c bad-regnum-dw.S + +# Make some DWARF for the test. +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + cu {} { + DW_TAG_compile_unit { + {DW_AT_language @DW_LANG_C} + {DW_AT_name bad-regnum-dw.c} + {DW_AT_comp_dir /tmp} + } { + declare_labels integer_label + + integer_label: DW_TAG_base_type { + {DW_AT_byte_size 4 DW_FORM_sdata} + {DW_AT_encoding @DW_ATE_signed} + {DW_AT_name integer} + } + + DW_TAG_variable { + {DW_AT_name foo1} + {DW_AT_type :$integer_label} + {DW_AT_location { + DW_OP_regx 2147483647 + } SPECIAL_expr} + {external 1 flag} + } + + DW_TAG_variable { + {DW_AT_name foo2} + {DW_AT_type :$integer_label} + {DW_AT_location { + DW_OP_regx -1 + } SPECIAL_expr} + {external 1 flag} + } + } + } +} + +if { [prepare_for_testing ${testfile}.exp ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +gdb_test "info addr foo1" \ + "Symbol \"foo1\" is a variable in \\\$bad_register_number." + +gdb_test "info addr foo2" \ + "Symbol \"foo2\" is a variable in \\\$bad_register_number." diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 888ba94f4c1..5dc7ea89afe 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -836,6 +836,10 @@ namespace eval Dwarf { _op .${_cu_addr_size}byte [lindex $line 1] } + DW_OP_regx { + _op .uleb128 [lindex $line 1] + } + DW_OP_pick - DW_OP_const1u - DW_OP_const1s { diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c index a24fb2596f2..cd70d933137 100644 --- a/gdb/xtensa-tdep.c +++ b/gdb/xtensa-tdep.c @@ -356,9 +356,7 @@ xtensa_reg_to_regnum (struct gdbarch *gdbarch, int regnum) if (regnum == gdbarch_tdep (gdbarch)->regmap[i].target_number) return i; - internal_error (__FILE__, __LINE__, - _("invalid dwarf/stabs register number %d"), regnum); - return 0; + return -1; } -- 2.30.2