Index: gdb/ia64-linux-nat.c |
diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c |
index 5aaaed9fc57b9dd32fafd308c010599d0c2f37b0..9b5fbf3d8ae3471895d2aa4c560a6716968bbc05 100644 |
--- a/gdb/ia64-linux-nat.c |
+++ b/gdb/ia64-linux-nat.c |
@@ -272,7 +272,7 @@ static int u_offsets[] = |
-1, -1, -1, -1, -1, -1, -1, -1, -1, |
PT_AR_PFS, |
PT_AR_LC, |
- -1, /* Not available: EC, the Epilog Count register. */ |
+ PT_AR_EC, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
@@ -447,8 +447,20 @@ supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) |
{ |
int regi; |
const char *from; |
+ const gdb_byte f_zero[16] = { 0 }; |
+ const gdb_byte f_one[16] = |
+ { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; |
- for (regi = IA64_FR0_REGNUM; regi <= IA64_FR127_REGNUM; regi++) |
+ /* Kernel generated cores have fr1==0 instead of 1.0. Older GDBs |
+ did the same. So ignore whatever might be recorded in fpregset_t |
+ for fr0/fr1 and always supply their expected values. */ |
+ |
+ /* fr0 is always read as zero. */ |
+ regcache_raw_supply (regcache, IA64_FR0_REGNUM, f_zero); |
+ /* fr1 is always read as one (1.0). */ |
+ regcache_raw_supply (regcache, IA64_FR1_REGNUM, f_one); |
+ |
+ for (regi = IA64_FR2_REGNUM; regi <= IA64_FR127_REGNUM; regi++) |
{ |
from = (const char *) &((*fpregsetp)[regi - IA64_FR0_REGNUM]); |
regcache_raw_supply (regcache, regi, from); |
@@ -617,7 +629,7 @@ ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type, |
} |
static void |
-ia64_linux_new_thread (ptid_t ptid) |
+ia64_linux_new_thread (struct lwp_info *lp) |
{ |
int i, any; |
@@ -626,24 +638,25 @@ ia64_linux_new_thread (ptid_t ptid) |
{ |
if (debug_registers[i] != 0) |
any = 1; |
- store_debug_register (ptid, i, debug_registers[i]); |
+ store_debug_register (lp->ptid, i, debug_registers[i]); |
} |
if (any) |
- enable_watchpoints_in_psr (ptid); |
+ enable_watchpoints_in_psr (lp->ptid); |
} |
static int |
ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) |
{ |
CORE_ADDR psr; |
- struct siginfo *siginfo_p; |
+ siginfo_t siginfo; |
struct regcache *regcache = get_current_regcache (); |
- siginfo_p = linux_nat_get_siginfo (inferior_ptid); |
+ if (!linux_nat_get_siginfo (inferior_ptid, &siginfo)) |
+ return 0; |
- if (siginfo_p->si_signo != SIGTRAP |
- || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */) |
+ if (siginfo.si_signo != SIGTRAP |
+ || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */) |
return 0; |
regcache_cooked_read_unsigned (regcache, IA64_PSR_REGNUM, &psr); |
@@ -651,7 +664,7 @@ ia64_linux_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p) |
for the next instruction. */ |
regcache_cooked_write_unsigned (regcache, IA64_PSR_REGNUM, psr); |
- *addr_p = (CORE_ADDR)siginfo_p->si_addr; |
+ *addr_p = (CORE_ADDR) siginfo.si_addr; |
return 1; |
} |
@@ -680,6 +693,37 @@ ia64_linux_fetch_register (struct regcache *regcache, int regnum) |
PTRACE_TYPE_RET *buf; |
int pid, i; |
+ /* r0 cannot be fetched but is always zero. */ |
+ if (regnum == IA64_GR0_REGNUM) |
+ { |
+ const gdb_byte zero[8] = { 0 }; |
+ |
+ gdb_assert (sizeof (zero) == register_size (gdbarch, regnum)); |
+ regcache_raw_supply (regcache, regnum, zero); |
+ return; |
+ } |
+ |
+ /* fr0 cannot be fetched but is always zero. */ |
+ if (regnum == IA64_FR0_REGNUM) |
+ { |
+ const gdb_byte f_zero[16] = { 0 }; |
+ |
+ gdb_assert (sizeof (f_zero) == register_size (gdbarch, regnum)); |
+ regcache_raw_supply (regcache, regnum, f_zero); |
+ return; |
+ } |
+ |
+ /* fr1 cannot be fetched but is always one (1.0). */ |
+ if (regnum == IA64_FR1_REGNUM) |
+ { |
+ const gdb_byte f_one[16] = |
+ { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 }; |
+ |
+ gdb_assert (sizeof (f_one) == register_size (gdbarch, regnum)); |
+ regcache_raw_supply (regcache, regnum, f_one); |
+ return; |
+ } |
+ |
if (ia64_cannot_fetch_register (gdbarch, regnum)) |
{ |
regcache_raw_supply (regcache, regnum, NULL); |