* [rfc] dwarf2 unwinder and MIPS n32
@ 2007-04-28 20:42 Daniel Jacobowitz
2007-04-28 22:52 ` Ulrich Weigand
2007-04-30 13:00 ` Maciej W. Rozycki
0 siblings, 2 replies; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-04-28 20:42 UTC (permalink / raw)
To: gdb-patches
The DWARF-2 unwinder uses store_typed_address to store the value of
the CFA or RA into a register-sized buffer. The type of the register
might be a pointer or integer type, so it passes
builtin_type_void_data_ptr and builtin_type_void_func_ptr as
appropriate. But for MIPS N32, sizeof (void *) == 4 and the stack
pointer is 64-bit. So it unwinds writes four bytes into the first
four of the eight byte slot; since I'm testing big-endian, the failure
is quickly obvious.
So what do we do about it? The patch below works for MIPS, but I'm
reasonably sure it's wrong; it avoids the architecture's
ADDRESS_TO_POINTER method entirely. If we pass the register's type to
store_typed_address we'll get various failures if the architecture
doesn't define the relevant register as a pointer. And MIPS doesn't,
partly because the register is 64-bit and the pointer would only be
32-bit.
Maybe if the size of the register != the size of a void * we should
store it as an unsigned integer. But that seems hackish to me.
I'd love comments; I don't want to commit this patch, but I can't turn
on CFI for MIPS without it.
--
Daniel Jacobowitz
CodeSourcery
2007-04-28 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2-frame.c (dwarf2_frame_prev_register): Use
store_unsigned_integer instead of store_typed_address.
---
dwarf2-frame.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
Index: gdb/dwarf2-frame.c
===================================================================
--- gdb.orig/dwarf2-frame.c 2007-04-27 17:03:21.000000000 -0400
+++ gdb/dwarf2-frame.c 2007-04-27 17:42:37.000000000 -0400
@@ -1137,10 +1137,8 @@ dwarf2_frame_prev_register (struct frame
*addrp = 0;
*realnump = -1;
if (valuep)
- {
- /* Store the value. */
- store_typed_address (valuep, builtin_type_void_data_ptr, cache->cfa);
- }
+ store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+ cache->cfa);
break;
case DWARF2_FRAME_REG_CFA_OFFSET:
@@ -1149,11 +1147,8 @@ dwarf2_frame_prev_register (struct frame
*addrp = 0;
*realnump = -1;
if (valuep)
- {
- /* Store the value. */
- store_typed_address (valuep, builtin_type_void_data_ptr,
- cache->cfa + cache->reg[regnum].loc.offset);
- }
+ store_unsigned_integer (valuep, register_size (gdbarch, regnum),
+ cache->cfa + cache->reg[regnum].loc.offset);
break;
case DWARF2_FRAME_REG_RA_OFFSET:
@@ -1167,7 +1162,7 @@ dwarf2_frame_prev_register (struct frame
regnum = DWARF2_REG_TO_REGNUM (cache->retaddr_reg.loc.reg);
pc += frame_unwind_register_unsigned (next_frame, regnum);
- store_typed_address (valuep, builtin_type_void_func_ptr, pc);
+ store_unsigned_integer (valuep, register_size (gdbarch, regnum), pc);
}
break;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-28 20:42 [rfc] dwarf2 unwinder and MIPS n32 Daniel Jacobowitz
@ 2007-04-28 22:52 ` Ulrich Weigand
2007-04-30 13:28 ` Daniel Jacobowitz
2007-04-30 13:00 ` Maciej W. Rozycki
1 sibling, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2007-04-28 22:52 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Daniel Jacobowitz wrote:
> So what do we do about it? The patch below works for MIPS, but I'm
> reasonably sure it's wrong; it avoids the architecture's
> ADDRESS_TO_POINTER method entirely. If we pass the register's type to
> store_typed_address we'll get various failures if the architecture
> doesn't define the relevant register as a pointer. And MIPS doesn't,
> partly because the register is 64-bit and the pointer would only be
> 32-bit.
Well, when we *read* a register in order to get (or compute) the CFA,
read_reg does
unpack_long (register_type (gdbarch, regnum), buf)
which in turn uses either extract_type_address, extract_signed_integer,
or extract_unsigned_integer, depending on the type.
It may make sense to perform the analogous operation when *writing*
the CFA to (an unwound copy of the contents of) a register. There
is no "pack_long", but something like
memcpy (buf, value_contents
(value_from_longest (register_type (gdbarch, regnum), cfa)),
register_size (gdbarch, regnum));
should have that effect.
Not sure if that is the right thing to do in all cases, but at least
it would be consistent ...
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-28 20:42 [rfc] dwarf2 unwinder and MIPS n32 Daniel Jacobowitz
2007-04-28 22:52 ` Ulrich Weigand
@ 2007-04-30 13:00 ` Maciej W. Rozycki
2007-04-30 13:26 ` Daniel Jacobowitz
1 sibling, 1 reply; 8+ messages in thread
From: Maciej W. Rozycki @ 2007-04-30 13:00 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches, Maciej W. Rozycki
On Sat, 28 Apr 2007, Daniel Jacobowitz wrote:
> Maybe if the size of the register != the size of a void * we should
> store it as an unsigned integer. But that seems hackish to me.
Of course MIPS addresses are signed, so if you have a stack pointer in
KSEG0 (e.g. 0x8fff0000), you want to store it as a signed integer, don't
you?
Anyway, I have the following patch waiting in the queue for submission --
perhaps it is less hackish. ;-)
2007-04-30 Maciej W. Rozycki <macro@mips.com>
* dwarf2-frame.c (read_reg): Extract an address using the width
of the register to be used to hold it as the size.
(dwarf2_frame_prev_register): Store an address using the width
of the holding register as the size.
It can certainly jump the queue if you find it useful. ;-)
Maciej
13118.diff
Index: gdb/src/gdb/dwarf2-frame.c
===================================================================
--- gdb.orig/src/gdb/dwarf2-frame.c 2007-02-13 13:51:55.000000000 +0000
+++ gdb/src/gdb/dwarf2-frame.c 2007-02-13 13:51:56.000000000 +0000
@@ -229,6 +229,7 @@
static CORE_ADDR
read_reg (void *baton, int reg)
{
+ struct type reg_void_data_ptr = *builtin_type_void_data_ptr;
struct frame_info *next_frame = (struct frame_info *) baton;
struct gdbarch *gdbarch = get_frame_arch (next_frame);
int regnum;
@@ -236,6 +237,8 @@
regnum = DWARF2_REG_TO_REGNUM (reg);
+ TYPE_LENGTH(®_void_data_ptr) = register_size (gdbarch, regnum);
+
buf = alloca (register_size (gdbarch, regnum));
frame_unwind_register (next_frame, regnum, buf);
@@ -244,7 +247,7 @@
under the covers, and this makes more sense for non-pointer
registers. Maybe read_reg and the associated interfaces should
deal with "struct value" instead of CORE_ADDR. */
- return unpack_long (register_type (gdbarch, regnum), buf);
+ return extract_typed_address (buf, ®_void_data_ptr);
}
static void
@@ -1020,10 +1023,13 @@
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, gdb_byte *valuep)
{
+ struct type reg_void_data_ptr = *builtin_type_void_data_ptr;
struct gdbarch *gdbarch = get_frame_arch (next_frame);
struct dwarf2_frame_cache *cache =
dwarf2_frame_cache (next_frame, this_cache);
+ TYPE_LENGTH(®_void_data_ptr) = register_size (gdbarch, regnum);
+
switch (cache->reg[regnum].how)
{
case DWARF2_FRAME_REG_UNDEFINED:
@@ -1132,7 +1138,7 @@
if (valuep)
{
/* Store the value. */
- store_typed_address (valuep, builtin_type_void_data_ptr, cache->cfa);
+ store_typed_address (valuep, ®_void_data_ptr, cache->cfa);
}
break;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-30 13:00 ` Maciej W. Rozycki
@ 2007-04-30 13:26 ` Daniel Jacobowitz
2007-04-30 13:44 ` Maciej W. Rozycki
0 siblings, 1 reply; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-04-30 13:26 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: gdb-patches, Maciej W. Rozycki
On Mon, Apr 30, 2007 at 01:40:54PM +0100, Maciej W. Rozycki wrote:
> On Sat, 28 Apr 2007, Daniel Jacobowitz wrote:
>
> > Maybe if the size of the register != the size of a void * we should
> > store it as an unsigned integer. But that seems hackish to me.
>
> Of course MIPS addresses are signed, so if you have a stack pointer in
> KSEG0 (e.g. 0x8fff0000), you want to store it as a signed integer, don't
> you?
It should already be sign extended at this point; CORE_ADDR will be a
64-bit type and it should be set to 0xffffffff_8fff0000 by read_reg.
That's the only reason we can get away with it.
> Anyway, I have the following patch waiting in the queue for submission --
> perhaps it is less hackish. ;-)
Ewww. Sorry, this one's even worse than mine :-) Let's not abuse our
types that way. I have a nicer patch now based on Ulrich's
suggestion. I'll post it in a few minutes when testing finishes (or a
little later if I can figure out where to get that board file you
mentioned).
> 2007-04-30 Maciej W. Rozycki <macro@mips.com>
>
> * dwarf2-frame.c (read_reg): Extract an address using the width
> of the register to be used to hold it as the size.
I see the read_reg part of this patch has been updated to apply to
HEAD, but do you know if it is older than this change? If so, it's
probably not necessary anymore.
2006-05-17 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2-frame.c: Include "value.h".
(read_reg): Use unpack_long and register_type.
* Makefile.in (dwarf2-frame.o): Update.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-28 22:52 ` Ulrich Weigand
@ 2007-04-30 13:28 ` Daniel Jacobowitz
2007-04-30 20:19 ` Ulrich Weigand
0 siblings, 1 reply; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-04-30 13:28 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches
On Sun, Apr 29, 2007 at 12:40:41AM +0200, Ulrich Weigand wrote:
> Well, when we *read* a register in order to get (or compute) the CFA,
> read_reg does
>
> unpack_long (register_type (gdbarch, regnum), buf)
>
> which in turn uses either extract_type_address, extract_signed_integer,
> or extract_unsigned_integer, depending on the type.
>
> It may make sense to perform the analogous operation when *writing*
> the CFA to (an unwound copy of the contents of) a register. There
> is no "pack_long", [...]
Well then, how about we add one? Your mention of symmetry is I think
very important; we have a lot of different ways to manipulate longs /
addresses, and I'd rather reduce than increase the number, but the
first step is to make the interfaces we have consistent.
Tested on mips64-linux N32, where it still fixes the problem; unlike
the previous patch, this one should not break segmented architectures
that need to adjust pointers and addresses.
--
Daniel Jacobowitz
CodeSourcery
2007-04-30 Daniel Jacobowitz <dan@codesourcery.com>
* dwarf2-frame.c (dwarf2_frame_prev_register): Use pack_long
instead of store_typed_address.
* value.c (pack_long): New.
(value_from_longest): Use it.
* value.h (pack_long): New prototype.
---
dwarf2-frame.c | 14 ++++----------
value.c | 36 ++++++++++++++++++++++--------------
value.h | 2 ++
3 files changed, 28 insertions(+), 24 deletions(-)
Index: gdb/dwarf2-frame.c
===================================================================
--- gdb.orig/dwarf2-frame.c 2007-04-30 08:29:26.000000000 -0400
+++ gdb/dwarf2-frame.c 2007-04-30 08:34:48.000000000 -0400
@@ -1137,10 +1137,7 @@ dwarf2_frame_prev_register (struct frame
*addrp = 0;
*realnump = -1;
if (valuep)
- {
- /* Store the value. */
- store_typed_address (valuep, builtin_type_void_data_ptr, cache->cfa);
- }
+ pack_long (valuep, register_type (gdbarch, regnum), cache->cfa);
break;
case DWARF2_FRAME_REG_CFA_OFFSET:
@@ -1149,11 +1146,8 @@ dwarf2_frame_prev_register (struct frame
*addrp = 0;
*realnump = -1;
if (valuep)
- {
- /* Store the value. */
- store_typed_address (valuep, builtin_type_void_data_ptr,
- cache->cfa + cache->reg[regnum].loc.offset);
- }
+ pack_long (valuep, register_type (gdbarch, regnum),
+ cache->cfa + cache->reg[regnum].loc.offset);
break;
case DWARF2_FRAME_REG_RA_OFFSET:
@@ -1167,7 +1161,7 @@ dwarf2_frame_prev_register (struct frame
regnum = DWARF2_REG_TO_REGNUM (cache->retaddr_reg.loc.reg);
pc += frame_unwind_register_unsigned (next_frame, regnum);
- store_typed_address (valuep, builtin_type_void_func_ptr, pc);
+ pack_long (valuep, register_type (gdbarch, regnum), pc);
}
break;
Index: gdb/value.c
===================================================================
--- gdb.orig/value.c 2007-04-30 08:29:26.000000000 -0400
+++ gdb/value.c 2007-04-30 08:35:14.000000000 -0400
@@ -1505,23 +1505,18 @@ modify_field (gdb_byte *addr, LONGEST fi
store_unsigned_integer (addr, sizeof oword, oword);
}
\f
-/* Convert C numbers into newly allocated values */
+/* Pack NUM into BUF using a target format of TYPE. */
-struct value *
-value_from_longest (struct type *type, LONGEST num)
+void
+pack_long (gdb_byte *buf, struct type *type, LONGEST num)
{
- struct value *val = allocate_value (type);
- enum type_code code;
int len;
-retry:
- code = TYPE_CODE (type);
+
+ type = check_typedef (type);
len = TYPE_LENGTH (type);
- switch (code)
+ switch (TYPE_CODE (type))
{
- case TYPE_CODE_TYPEDEF:
- type = check_typedef (type);
- goto retry;
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
case TYPE_CODE_ENUM:
@@ -1529,17 +1524,30 @@ retry:
case TYPE_CODE_BOOL:
case TYPE_CODE_RANGE:
case TYPE_CODE_MEMBERPTR:
- store_signed_integer (value_contents_raw (val), len, num);
+ store_signed_integer (buf, len, num);
break;
case TYPE_CODE_REF:
case TYPE_CODE_PTR:
- store_typed_address (value_contents_raw (val), type, (CORE_ADDR) num);
+ store_typed_address (buf, type, (CORE_ADDR) num);
break;
default:
- error (_("Unexpected type (%d) encountered for integer constant."), code);
+ error (_("Unexpected type (%d) encountered for integer constant."),
+ TYPE_CODE (type));
}
+}
+
+
+/* Convert C numbers into newly allocated values. */
+
+struct value *
+value_from_longest (struct type *type, LONGEST num)
+{
+ struct value *val = allocate_value (type);
+
+ pack_long (value_contents_raw (val), type, num);
+
return val;
}
Index: gdb/value.h
===================================================================
--- gdb.orig/value.h 2007-04-30 08:29:26.000000000 -0400
+++ gdb/value.h 2007-04-30 08:29:57.000000000 -0400
@@ -271,6 +271,8 @@ extern LONGEST unpack_field_as_long (str
const gdb_byte *valaddr,
int fieldno);
+extern void pack_long (gdb_byte *buf, struct type *type, LONGEST num);
+
extern struct value *value_from_longest (struct type *type, LONGEST num);
extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr);
extern struct value *value_from_double (struct type *type, DOUBLEST num);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-30 13:26 ` Daniel Jacobowitz
@ 2007-04-30 13:44 ` Maciej W. Rozycki
0 siblings, 0 replies; 8+ messages in thread
From: Maciej W. Rozycki @ 2007-04-30 13:44 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches, Maciej W. Rozycki
On Mon, 30 Apr 2007, Daniel Jacobowitz wrote:
> I see the read_reg part of this patch has been updated to apply to
> HEAD, but do you know if it is older than this change? If so, it's
> probably not necessary anymore.
Well, 2005-01-22 is the original date, so it is somewhat older indeed.
I have not tried to check whether any of the changes have become redundant
since that change -- the patch builds and causes no regressions as far as
I can tell. I would normally check the usefulness of these changes before
submission.
Maciej
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-30 13:28 ` Daniel Jacobowitz
@ 2007-04-30 20:19 ` Ulrich Weigand
2007-05-14 17:22 ` Daniel Jacobowitz
0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2007-04-30 20:19 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Daniel Jacobowitz wrote:
> Well then, how about we add one? Your mention of symmetry is I think
> very important; we have a lot of different ways to manipulate longs /
> addresses, and I'd rather reduce than increase the number, but the
> first step is to make the interfaces we have consistent.
>
> Tested on mips64-linux N32, where it still fixes the problem; unlike
> the previous patch, this one should not break segmented architectures
> that need to adjust pointers and addresses.
Looks good to me ...
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [rfc] dwarf2 unwinder and MIPS n32
2007-04-30 20:19 ` Ulrich Weigand
@ 2007-05-14 17:22 ` Daniel Jacobowitz
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Jacobowitz @ 2007-05-14 17:22 UTC (permalink / raw)
To: gdb-patches
On Mon, Apr 30, 2007 at 08:43:52PM +0200, Ulrich Weigand wrote:
> Daniel Jacobowitz wrote:
>
> > Well then, how about we add one? Your mention of symmetry is I think
> > very important; we have a lot of different ways to manipulate longs /
> > addresses, and I'd rather reduce than increase the number, but the
> > first step is to make the interfaces we have consistent.
> >
> > Tested on mips64-linux N32, where it still fixes the problem; unlike
> > the previous patch, this one should not break segmented architectures
> > that need to adjust pointers and addresses.
>
> Looks good to me ...
Thanks! I checked it in.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-05-14 17:22 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-04-28 20:42 [rfc] dwarf2 unwinder and MIPS n32 Daniel Jacobowitz
2007-04-28 22:52 ` Ulrich Weigand
2007-04-30 13:28 ` Daniel Jacobowitz
2007-04-30 20:19 ` Ulrich Weigand
2007-05-14 17:22 ` Daniel Jacobowitz
2007-04-30 13:00 ` Maciej W. Rozycki
2007-04-30 13:26 ` Daniel Jacobowitz
2007-04-30 13:44 ` Maciej W. Rozycki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox