[V2,3/4] read_pieced_value do big endian processing only in case of valid gdb_regnum

Message ID 1413955589-5054-4-git-send-email-victor.kamensky@linaro.org
State New
Headers show

Commit Message

vkamensky Oct. 22, 2014, 5:26 a.m.
During armv7b testing gdb.base/store.exp test was failling with
'GDB internal error'. It turns out that compiler generated DWARF
with non-existent register numbers. The compiler issue is present
in both little endian (armv7) and big endian (armv7b) (it is
separate issue). In both case gdbarch_dwarf2_reg_to_regnum returns
-1 which is stored into gdb_regnum. But it cause severe problem
only in big endian case because in read_pieced_value and
write_pieced_value functions BFD_ENDIAN_BIG related processing
happen regardless of gdb_regnum value, and in case of gdb_regnum=-1,
it cause 'GDB internal error' and crash.

Solution is to move BFD_ENDIAN_BIG related processing under
(gdb_regnum != -1) branch of processing.

gdb/ChangeLog:

2014-10-21  Victor Kamensky  <victor.kamensky@linaro.org>

	* dwarf2loc.c (read_pieced_value): Do BE processing only if
	gdb_regnum is not -1.
	(write_pieced_value): Ditto.
---
 gdb/dwarf2loc.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

Patch

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index e347e59..fbe99bb 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1686,20 +1686,20 @@  read_pieced_value (struct value *v)
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno);
 	    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 (gdb_regnum != -1)
 	      {
 		int optim, unavail;
 
+		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))
@@ -1878,13 +1878,13 @@  write_pieced_value (struct value *to, struct value *from)
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno);
 	    int reg_offset = dest_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;
-
 	    if (gdb_regnum != -1)
 	      {
+		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;