This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[rfc] Handle DWARF-2 value pieces residing in *parts* of a register


Hello,

when implementing support for 64-bit register set on s390-linux, I ran
into a problem with handling of DWARF-2 "piece" values.  Specifically,
handling of value pieces that reside in a register, but do not occupy
the *whole* register.

For example, when a 64-bit value is passed as argument on s390-linux,
it is passed in a register pair, with a 32-bit piece in each register.
However, when using the 64-bit register set, this means that we have
pieces of size 4 bytes in registers of size 8 bytes.

The current code would simply always use the initial 4 bytes of the
register value in this case; in the case of a big-endian machine,
this is the most-significant part.  That's wrong for the s390 case
described above; the value pieces are passed in the *least*-significant
parts of the register.

Now, according to the DWARF-2 standard, the location of register pieces
of smaller than full register size is defined by the platform ABI.
For the placement of a small value in a *single* register we have a
gdbarch callback (gdbarch_value_from_register); maybe we need something
like that for value pieces as well.  At the very least, we ought to
you the same default as default_value_from_register does: assume
partial register use implies the least-significant part of the register.

The patch below implements this.

Tested on s390(x)-linux in conjunction with the "32-bit application
with 64-bit register set" patch.

Any comments?  I'm planning to apply this next week.

Bye,
Ulrich


ChangeLog:

	* dwarf2loc.c (read_pieced_value): If a piece occupies part of
	a register, assume the least-signficant part is used.
	(write_pieced_value): Likewise.


diff -urNp gdb-orig/gdb/dwarf2loc.c gdb-head/gdb/dwarf2loc.c
--- gdb-orig/gdb/dwarf2loc.c	2009-12-18 17:27:13.000000000 +0100
+++ gdb-head/gdb/dwarf2loc.c	2009-12-18 17:42:44.000000000 +0100
@@ -263,11 +263,17 @@ read_pieced_value (struct value *v)
 	case DWARF_VALUE_REGISTER:
 	  {
 	    struct gdbarch *arch = get_frame_arch (frame);
-	    bfd_byte regval[MAX_REGISTER_SIZE];
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch,
 							   p->v.expr.value);
-	    get_frame_register (frame, gdb_regnum, regval);
-	    memcpy (contents + offset, regval, p->size);
+	    int reg_offset = 0;
+
+	    if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
+		&& p->size < register_size (arch, gdb_regnum))
+	      /* Big-endian, and we want less than full size.  */
+	      reg_offset = register_size (arch, gdb_regnum) - p->size;
+
+	    get_frame_register_bytes (frame, gdb_regnum, reg_offset, p->size,
+				      contents + offset);
 	  }
 	  break;
 
@@ -334,7 +340,15 @@ write_pieced_value (struct value *to, st
 	  {
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.expr.value);
-	    put_frame_register (frame, gdb_regnum, contents + offset);
+	    int reg_offset = 0;
+
+	    if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG
+		&& p->size < register_size (arch, gdb_regnum))
+	      /* Big-endian, and we want less than full size.  */
+	      reg_offset = register_size (arch, gdb_regnum) - p->size;
+
+	    put_frame_register_bytes (frame, gdb_regnum, reg_offset, p->size,
+				      contents + offset);
 	  }
 	  break;
 	case DWARF_VALUE_MEMORY:
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]