[PATCH 4/5] ARM: read_pieced_value do big endian processing only in case of valid gdb_regnum

Victor Kamensky
2014-10-21T00:57:31Z

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 | 6 ++++++
gdb/dwarf2loc.c | 30 +++++++++++++++---------------
2 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c32fb3f..6a735b8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2014-10-13 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.
+
+2014-10-13 Victor Kamensky <victor.kamensky@linaro.org>
+
* arm-tdep.c: (extract_arm_insn): use dbarch_byte_order_for_code
to read arm instruction.

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;
--
1.8.1.4