diff options
Diffstat (limited to 'gdb/hppah-nat.c')
-rw-r--r-- | gdb/hppah-nat.c | 81 |
1 files changed, 64 insertions, 17 deletions
diff --git a/gdb/hppah-nat.c b/gdb/hppah-nat.c index 4ade6f2..627760d 100644 --- a/gdb/hppah-nat.c +++ b/gdb/hppah-nat.c @@ -104,45 +104,92 @@ store_inferior_registers (regno) store_inferior_registers (regno); } -/* Fetch one register. */ +/* Our own version of the offsetof macro, since we can't assume ANSI C. */ +#define HPPAH_OFFSETOF(type, member) ((int) (&((type *) 0)->member)) + +/* Fetch a register's value from the process's U area. */ static void fetch_register (regno) int regno; { - register unsigned int regaddr; char buf[MAX_REGISTER_RAW_SIZE]; - register int i; + unsigned int addr, len, offset; + int i; + + offset = 0; + len = REGISTER_RAW_SIZE (regno); + + /* Requests for register zero actually want the save_state's + ss_flags member. As RM says: "Oh, what a hack!" */ + if (regno == 0) + { + save_state_t ss; + addr = HPPAH_OFFSETOF (save_state_t, ss_flags); + len = sizeof (ss.ss_flags); + + /* Note that ss_flags is always an int, no matter what + REGISTER_RAW_SIZE(0) says. Assuming all HP-UX PA machines + are big-endian, put it at the least significant end of the + value, and zap the rest of the buffer. */ + offset = REGISTER_RAW_SIZE (0) - len; + memset (buf, 0, sizeof (buf)); + } - /* Offset of registers within the u area. */ - unsigned int offset; + /* Floating-point registers come from the ss_fpblock area. */ + else if (regno >= FP0_REGNUM) + addr = (HPPAH_OFFSETOF (save_state_t, ss_fpblock) + + (REGISTER_BYTE (regno) - REGISTER_BYTE (FP0_REGNUM))); + + /* Wide registers come from the ss_wide area. + I think it's more PC to test (ss_flags & SS_WIDEREGS) to select + between ss_wide and ss_narrow than to use the raw register size. + But checking ss_flags would require an extra ptrace call for + every register reference. Bleah. */ + else if (len == 8) + addr = (HPPAH_OFFSETOF (save_state_t, ss_wide) + + REGISTER_BYTE (regno)); + + /* Narrow registers come from the ss_narrow area. Note that + ss_narrow starts with gr1, not gr0. */ + else if (len == 4) + addr = (HPPAH_OFFSETOF (save_state_t, ss_narrow) + + (REGISTER_BYTE (regno) - REGISTER_BYTE (1))); - offset = U_REGS_OFFSET; + else + fatal ("hppa-nat.c (fetch_register): unexpected register size"); - regaddr = register_addr (regno, offset); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) + for (i = 0; i < len; i += sizeof (int)) { errno = 0; - *(int *) &buf[i] = call_ptrace (PT_RUREGS, inferior_pid, - (PTRACE_ARG3_TYPE) regaddr, 0); - regaddr += sizeof (int); + /* Copy an int from the U area to buf. Fill the least + significant end if len != raw_size. */ + * (int *) &buf[offset + i] = + call_ptrace (PT_RUREGS, inferior_pid, + (PTRACE_ARG3_TYPE) addr + i, 0); if (errno != 0) { - /* Warning, not error, in case we are attached; sometimes the - kernel doesn't let us at the registers. */ + /* Warning, not error, in case we are attached; sometimes + the kernel doesn't let us at the registers. */ char *err = safe_strerror (errno); char *msg = alloca (strlen (err) + 128); - sprintf (msg, "reading register %s: %s", REGISTER_NAME (regno), err); + sprintf (msg, "reading `%s' register: %s", + REGISTER_NAME (regno), err); warning (msg); - goto error_exit; + return; } } + + /* If we're reading an address from the instruction address queue, + mask out the bottom two bits --- they contain the privilege + level. */ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM) - buf[3] &= ~0x3; + buf[len - 1] &= ~0x3; + supply_register (regno, buf); -error_exit:; } + /* Copy LEN bytes to or from inferior's memory starting at MEMADDR to debugger memory starting at MYADDR. Copy to inferior if WRITE is nonzero. |