diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/i387-tdep.c | 87 |
2 files changed, 62 insertions, 33 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c204b94..4a33075 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2012-03-06 Pedro Alves <palves@redhat.com> + + PR gdb/13766 + + * i387-tdep.c (i387_supply_xsave): If we have an xsave buffer, and + the register state is clear, supply explicit zero, instead of + marking the register unavailable. + 2011-10-20 Aleksandar Ristovski <aristovski@qnx.com> * cp-namespace.c (cp_scan_for_anonymous_namespaces): Changed function diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 9eece41..cfb27ac 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -726,6 +726,7 @@ i387_supply_xsave (struct regcache *regcache, int regnum, const gdb_byte *regs = xsave; int i; unsigned int clear_bv; + static const gdb_byte zero[MAX_REGISTER_SIZE] = { 0 }; const gdb_byte *p; enum { @@ -765,6 +766,19 @@ i387_supply_xsave (struct regcache *regcache, int regnum, else clear_bv = I386_XSTATE_AVX_MASK; + /* With the delayed xsave mechanism, in between the program + starting, and the program accessing the vector registers for the + first time, the register's values are invalid. The kernel + initializes register states to zero when they are set the first + time in a program. This means that from the user-space programs' + perspective, it's the same as if the registers have always been + zero from the start of the program. Therefore, the debugger + should provide the same illusion to the user. + + Note however, the case when REGS is NULL is a different case. + That case means we do not have access to the x87 states, so we + should mark the registers as unavailable (by supplying NULL). */ + switch (regclass) { case none: @@ -772,26 +786,26 @@ i387_supply_xsave (struct regcache *regcache, int regnum, case avxh: if ((clear_bv & I386_XSTATE_AVX)) - p = NULL; + regcache_raw_supply (regcache, regnum, regs == NULL ? NULL : zero); else - p = XSAVE_AVXH_ADDR (tdep, regs, regnum); - regcache_raw_supply (regcache, regnum, p); + regcache_raw_supply (regcache, regnum, + XSAVE_AVXH_ADDR (tdep, regs, regnum)); return; case sse: if ((clear_bv & I386_XSTATE_SSE)) - p = NULL; + regcache_raw_supply (regcache, regnum, regs == NULL ? NULL : zero); else - p = FXSAVE_ADDR (tdep, regs, regnum); - regcache_raw_supply (regcache, regnum, p); + regcache_raw_supply (regcache, regnum, + FXSAVE_ADDR (tdep, regs, regnum)); return; case x87: if ((clear_bv & I386_XSTATE_X87)) - p = NULL; + regcache_raw_supply (regcache, regnum, regs == NULL ? NULL : zero); else - p = FXSAVE_ADDR (tdep, regs, regnum); - regcache_raw_supply (regcache, regnum, p); + regcache_raw_supply (regcache, regnum, + FXSAVE_ADDR (tdep, regs, regnum)); return; case all: @@ -799,16 +813,19 @@ i387_supply_xsave (struct regcache *regcache, int regnum, if ((tdep->xcr0 & I386_XSTATE_AVX)) { if ((clear_bv & I386_XSTATE_AVX)) - p = NULL; + { + for (i = I387_YMM0H_REGNUM (tdep); + i < I387_YMMENDH_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, regs == NULL ? NULL : zero); + } else - p = regs; - - for (i = I387_YMM0H_REGNUM (tdep); - i < I387_YMMENDH_REGNUM (tdep); i++) { - if (p != NULL) - p = XSAVE_AVXH_ADDR (tdep, regs, i); - regcache_raw_supply (regcache, i, p); + for (i = I387_YMM0H_REGNUM (tdep); + i < I387_YMMENDH_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, + XSAVE_AVXH_ADDR (tdep, regs, i)); } } @@ -816,16 +833,18 @@ i387_supply_xsave (struct regcache *regcache, int regnum, if ((tdep->xcr0 & I386_XSTATE_SSE)) { if ((clear_bv & I386_XSTATE_SSE)) - p = NULL; + { + for (i = I387_XMM0_REGNUM (tdep); + i < I387_MXCSR_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, regs == NULL ? NULL : zero); + } else - p = regs; - - for (i = I387_XMM0_REGNUM (tdep); - i < I387_MXCSR_REGNUM (tdep); i++) { - if (p != NULL) - p = FXSAVE_ADDR (tdep, regs, i); - regcache_raw_supply (regcache, i, p); + for (i = I387_XMM0_REGNUM (tdep); + i < I387_MXCSR_REGNUM (tdep); i++) + regcache_raw_supply (regcache, i, + FXSAVE_ADDR (tdep, regs, i)); } } @@ -833,16 +852,18 @@ i387_supply_xsave (struct regcache *regcache, int regnum, if ((tdep->xcr0 & I386_XSTATE_X87)) { if ((clear_bv & I386_XSTATE_X87)) - p = NULL; + { + for (i = I387_ST0_REGNUM (tdep); + i < I387_FCTRL_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, regs == NULL ? NULL : zero); + } else - p = regs; - - for (i = I387_ST0_REGNUM (tdep); - i < I387_FCTRL_REGNUM (tdep); i++) { - if (p != NULL) - p = FXSAVE_ADDR (tdep, regs, i); - regcache_raw_supply (regcache, i, p); + for (i = I387_ST0_REGNUM (tdep); + i < I387_FCTRL_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i)); } } break; |