This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH v2] [PR symtab/17391] gdb internal error: assertion fails in regcache.c:178
- From: Doug Evans <dje at google dot com>
- To: Doug Evans <dje at google dot com>
- Cc: Pedro Alves <palves at redhat dot com>, gdb-patches at sourceware dot org
- Date: Tue, 18 Aug 2015 00:26:07 +0000
- Subject: Re: [PATCH v2] [PR symtab/17391] gdb internal error: assertion fails in regcache.c:178
- Authentication-results: sourceware.org; auth=none
Doug Evans writes:
> Pedro Alves writes:
> > On 08/13/2015 02:21 AM, Doug Evans wrote:
> > > Doug Evans writes:
> > > > Hi.
> > > >
> > > > This patch, I hope, addresses PR 17391.
> > > > I couldn't recreate 17391 but there is clearly a lack of
> robustness here:
> > > > gdbarch_dwarf2_reg_to_regnum can return -1 but not all callers
> > > > watch for that. Some callers do watch for it but call error
> themselves.
> > > > There is already dwarf2_reg_to_regnum_or_error so this patch
just
> > > > changes appropriate callers of gdbarch_dwarf2_reg_to_regnum to
use
> it.
> > > > Sometimes a register number is stored as a ULONGEST, so I
changed
> > > > dwarf2_reg_to_regnum_or_error to take one.
> > > >
> > > > Regression tested on amd64-linux.
> > > >
> > > > 2015-08-10 Doug Evans <dje@google.com>
> > > >
> > > > PR symtab/17391
> > > > * dwarf2-frame.c (read_addr_from_reg): Call
> > > > dwarf2_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 (dwarf_expr_read_addr_from_reg): Ditto.
> > > > (dwarf_expr_get_reg_value): Ditto.
> > > > (read_pieced_value): Ditto.
> > > > (write_pieced_value): Ditto.
> > > > (dwarf2_evaluate_loc_desc_full): Ditto.
> > > > (dwarf2_reg_to_regnum_or_error): Change to take a ULONGEST
regnum.
> > > > (locexpr_regname): Improve text of bad register number.
> > > > * dwarf2loc.h (dwarf2_reg_to_regnum_or_error): Update
prototype.
> > > >
> > > > testsuite/
> > > > * lib/gdb.exp (_location): Add support for DW_OP_regx.
> > > > * gdb.dwarf2/bad-regnum.c: New file.
> > > > * gdb.dwarf2/bad-regnum.exp: New file.
> > >
> > > Hi.
> > >
> > > This is a revised version.
> > > Digging deeper I found several broken targets.
> > > I'm not prepared to fix all of them,
> >
> > OOC, was that because the fix looked complicated, or because
> > you wanted to avoid breaking them? If the latter, I'd be more
inclined
> > to avoiding leaving a wart in place that is probably going to take
> > a long while to address, even if that meant the fix goes in untested.
> > Is there an easy way to tell which targets still need fixing? Or
what
> > to look for?
>
> More like for those I left it wasn't clear to me how to fix them.
> e.g., rs6000-tdep.c:rs6000_dwarf2_reg_to_regnum.
> I'm certainly not making things worse by leaving them alone.
>
> > > but this fixes a lot of them and adds documentation
> > > to actually specify what the rules are
> > > (as opposed to targets just cut-n-pasting
> > > and hoping it was right).
> >
> > Otherwise the patch looked fine to me.
I missed a few obvious cases.
The main remaining cases that I can think of are rs6000 and spu.
Plus this supplemental patch makes stabs and ecoff more robust.
Stabs was using num_arch + num_pseudo to denote "bad reg",
but some targets use the same reg_to_regnum function for both
stabs and dwarf, so that's asking for trouble (since dwarf uses -1).
This patch makes stabs handle negative regnos too.
If it's too hard to review this apart from the original patch
I can resubmit the entire thing.
2015-08-17 Doug Evans <dje@google.com>
* 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.
diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c
index d7347b6..5a3ed95 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 3a81615..90f1f51 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 d2831db..7ab4928 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/mips-tdep.c b/gdb/mips-tdep.c
index e0706db..4bf0d99 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -8020,9 +8020,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;
}
@@ -8045,9 +8043,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 985821c..83a3e48 100644
--- a/gdb/mn10300-tdep.c
+++ b/gdb/mn10300-tdep.c
@@ -1383,10 +1383,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/stabsread.c b/gdb/stabsread.c
index 03c9eb1..f6d8343 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);
}
@@ -598,8 +598,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/xtensa-tdep.c b/gdb/xtensa-tdep.c
index 55e7d98..6c60070 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -354,9 +354,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;
}