S390: Fix for inadvertently setting 24-bit mode in fill_gregset
authorAndreas Arnez <arnez@linux.vnet.ibm.com>
Fri, 8 May 2015 10:50:47 +0000 (12:50 +0200)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 8 May 2015 10:50:47 +0000 (12:50 +0200)
On 64-bit S390 platforms, for programs compiled with -m31, it could
happen that GDB inadvertently cleared the inferior's 31-bit addressing
mode bit and left the inferior running in 24-bit addressing mode.  In
particular this occurred with checkpoint.exp, when the "restore"
command needed to create a new regcache copy: At the time when the
PSWM register was copied over, the addressing mode bit was taken from
the PSWA register, which was still zero since it had not been copied
yet.  And when the PSWA register was copied, the addressing mode was
not updated again.

The fix affects fill_gregset, where the bits "belonging" to each of
the PSWA and PSWM registers are now carefully separated.  The
addressing mode bit is no longer touched when writing PSWM, and --
more importantly -- it *is* written when writing PSWA.

gdb/ChangeLog:

* s390-linux-nat.c (fill_gregset): Avoid relying on the PSWA
register in the regcache when treating the PSWM register, and vice
versa.

gdb/ChangeLog
gdb/s390-linux-nat.c

index 44b6146790609ae5c2d15665b41072f4733597eb..c7e8c88d776b0c87e98a922e98aef76173177a46 100644 (file)
@@ -1,3 +1,9 @@
+2015-05-08  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+       * s390-linux-nat.c (fill_gregset): Avoid relying on the PSWA
+       register in the regcache when treating the PSWM register, and vice
+       versa.
+
 2015-05-07  Gary Benson <gbenson@redhat.com>
 
        * linux-thread-db.c (struct thread_db_info)
index 9298bccc305c9d6f124a1e11fe189ef629d9db60..4cd3192a42089e74beacfa7363c13cab791c6798 100644 (file)
@@ -156,19 +156,29 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
          enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
          ULONGEST pswa, pswm;
          gdb_byte buf[4];
+         gdb_byte *pswm_p = (gdb_byte *) regp + S390_PSWM_OFFSET;
+         gdb_byte *pswa_p = (gdb_byte *) regp + S390_PSWA_OFFSET;
 
-         regcache_raw_collect (regcache, S390_PSWM_REGNUM, buf);
-         pswm = extract_unsigned_integer (buf, 4, byte_order);
-         regcache_raw_collect (regcache, S390_PSWA_REGNUM, buf);
-         pswa = extract_unsigned_integer (buf, 4, byte_order);
+         pswm = extract_unsigned_integer (pswm_p, 8, byte_order);
 
          if (regno == -1 || regno == S390_PSWM_REGNUM)
-           store_unsigned_integer ((gdb_byte *) regp + S390_PSWM_OFFSET, 8,
-                                   byte_order, ((pswm & 0xfff7ffff) << 32) |
-                                   (pswa & 0x80000000));
+           {
+             pswm &= 0x80000000;
+             regcache_raw_collect (regcache, S390_PSWM_REGNUM, buf);
+             pswm |= (extract_unsigned_integer (buf, 4, byte_order)
+                      & 0xfff7ffff) << 32;
+           }
+
          if (regno == -1 || regno == S390_PSWA_REGNUM)
-           store_unsigned_integer ((gdb_byte *) regp + S390_PSWA_OFFSET, 8,
-                                   byte_order, pswa & 0x7fffffff);
+           {
+             regcache_raw_collect (regcache, S390_PSWA_REGNUM, buf);
+             pswa = extract_unsigned_integer (buf, 4, byte_order);
+             pswm ^= (pswm ^ pswa) & 0x80000000;
+             pswa &= 0x7fffffff;
+             store_unsigned_integer (pswa_p, 8, byte_order, pswa);
+           }
+
+         store_unsigned_integer (pswm_p, 8, byte_order, pswm);
        }
       return;
     }