PR gdb/10565
authorDaniel Jacobowitz <drow@false.org>
Fri, 28 Aug 2009 18:50:49 +0000 (18:50 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 28 Aug 2009 18:50:49 +0000 (18:50 +0000)
* value.c (value_primitive_field): Do not save value_offset for
bitfields.
(unpack_bits_as_long): Do not read an entire ULONGEST.

testsuite/
PR gdb/10565

* gdb.base/bitfields.c (struct container, container): New.
(main): Initialize it and call break5.
* gdb.base/bitfields.exp (bitfield_at_offset): New test.

gdb/ChangeLog
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/bitfields.c
gdb/testsuite/gdb.base/bitfields.exp
gdb/value.c

index 8f534a7032d8b3d4d76d7a2ca38917a387ee230e..4cd1e538ba720a80e95966cf042992c0f3d6fc8e 100644 (file)
@@ -1,3 +1,11 @@
+2009-08-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       PR gdb/10565
+
+       * value.c (value_primitive_field): Do not save value_offset for
+       bitfields.
+       (unpack_bits_as_long): Do not read an entire ULONGEST.
+
 2009-08-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        Support constant DW_AT_data_member_location by GCC PR debug/40659.
index a07ed2a3cd6da0fa30636428b22f44a3578acef1..0d10281441474b6333a0192a2bb63ae73f3ae8fe 100644 (file)
@@ -1,3 +1,11 @@
+2009-08-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       PR gdb/10565
+
+       * gdb.base/bitfields.c (struct container, container): New.
+       (main): Initialize it and call break5.
+       * gdb.base/bitfields.exp (bitfield_at_offset): New test.
+
 2009-08-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        Support constant DW_AT_data_member_location by GCC PR debug/40659.
index bd411f7b647c67820fe6eb7ea0750e9edc3a01ee..3b5e42c629906d410197ed25c31af25072d0da71 100644 (file)
@@ -63,6 +63,12 @@ void break10 ()
 {
 }
 
+struct container
+{
+  struct fields one;
+  struct fields two;
+} container;
+
 /* This is used by bitfields.exp to determine if the target understands
    signed bitfields.  */
 int i;
@@ -190,5 +196,10 @@ int main ()
   flags.s3 = 0;
   flags.s9 = 0;
 
+  /* Bitfields at a non-zero offset in a containing structure.  */
+  container.one.u3 = 5;
+  container.two.u3 = 3;
+  break5 ();
+
   return 0;
 }
index 31e8b0151c5e905479032b5cbf06700591e5b93e..659785e69b603b4a19e98fec64a3b8cc95910504 100644 (file)
@@ -233,6 +233,26 @@ proc bitfield_signedness {} {
     gdb_stop_suppressing_tests;
 }
 
+# Test bitfields at non-zero offsets in a struct.
+
+proc bitfield_at_offset {} {
+    global decimal
+    global hex
+    global gdb_prompt
+    global srcfile
+
+    gdb_breakpoint break5
+    if [gdb_test "cont" "Break.*break5 \\(\\) at .*$srcfile:$decimal.*" "continuing to break5"] {
+       return
+    }
+
+    set one ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 5, s9 = 0, u9 = 0, sc = 0.*"
+    set two ".*uc = 0 .*, s1 = 0, u1 = 0, s2 = 0, u2 = 0, s3 = 0, u3 = 3, s9 = 0, u9 = 0, sc = 0.*"
+    gdb_test "print container" "$one$two" "distinct bitfields in container"
+    gdb_test "print container.one.u3" ".* = 5"
+    gdb_test "print container.two.u3" ".* = 3"
+}
+
 gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 gdb_load ${binfile}
@@ -264,3 +284,5 @@ if [istarget "mips-idt-*"] then {
     gdb_load ${binfile}
 }
 bitfield_signedness
+
+bitfield_at_offset
index 330ab156956e90b744a801286f764a4f0e4d86f2..f26e16c7d626012f17a8a58b3b70b503dd7616b9 100644 (file)
@@ -1878,7 +1878,7 @@ value_primitive_field (struct value *arg1, int offset,
        v->bitpos = bitpos % container_bitsize;
       else
        v->bitpos = bitpos % 8;
-      v->offset = value_offset (arg1) + value_embedded_offset (arg1)
+      v->offset = value_embedded_offset (arg1)
        + (bitpos - v->bitpos) / 8;
       v->parent = arg1;
       value_incref (v->parent);
@@ -2031,15 +2031,23 @@ unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr,
   ULONGEST val;
   ULONGEST valmask;
   int lsbcount;
+  int bytes_read;
 
-  val = extract_unsigned_integer (valaddr + bitpos / 8,
-                                 sizeof (val), byte_order);
+  /* Read the minimum number of bytes required; there may not be
+     enough bytes to read an entire ULONGEST.  */
   CHECK_TYPEDEF (field_type);
+  if (bitsize)
+    bytes_read = ((bitpos % 8) + bitsize + 7) / 8;
+  else
+    bytes_read = TYPE_LENGTH (field_type);
+
+  val = extract_unsigned_integer (valaddr + bitpos / 8,
+                                 bytes_read, byte_order);
 
   /* Extract bits.  See comment above. */
 
   if (gdbarch_bits_big_endian (get_type_arch (field_type)))
-    lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
+    lsbcount = (bytes_read * 8 - bitpos % 8 - bitsize);
   else
     lsbcount = (bitpos % 8);
   val >>= lsbcount;