diff options
-rw-r--r-- | gdb/ChangeLog | 23 | ||||
-rw-r--r-- | gdb/config/i386/nm-linux.h | 3 | ||||
-rw-r--r-- | gdb/i386-linux-nat.c | 198 |
3 files changed, 84 insertions, 140 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8b57e305..8753223 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2002-11-09 Mark Kettenis <kettenis@gnu.org> + + * i386-linux-nat.c (ORIG_EAX): Define to -1 if not already + defined. + (regmap): Extend to cover all registers. + (PT_READ_U, PT_WRITE_U, PTRACE_XFER_TYPE, + OLD_CANNOT_FETCH_REGISTERS, OLD_CANNOT_STORE_REGISTERS): Remove + definitions. + (fetch_register, sore_register): Simplify. + (old_fetch_inferior_registers, old_store_inferior_registers): + Remove functions. + (cannot_fetch_register, cannot_store_register): Change + implementation to use regmap array to decide which registers + cannot be fetched/stored. This removes $orig_eax from the + registers that cannot be fetched/stored. + (fetch_inferior_registers): Call fetch_register directly instead + of calling old_fetch_inferior_registers. + (store_inferior_registers): Call store_register directly instead + of calling old_store_inferior_registers. + (i386_linux_dr_get): Replace PT_READ_U with PTRACE_PEEKUSER. + (i386_linux_dr_set): Replace PT_WRITE_U with PTRACE_POKEUSER. + * config/i386/nm-linux.h (U_REGS_OFFSET): Remove definition. + 2002-11-09 Klee Dienes <kdienes@apple.com> * i387-tdep.c (i387_supply_register): When called with NULL as a diff --git a/gdb/config/i386/nm-linux.h b/gdb/config/i386/nm-linux.h index 073c3a3..ad57124 100644 --- a/gdb/config/i386/nm-linux.h +++ b/gdb/config/i386/nm-linux.h @@ -39,9 +39,6 @@ extern int kernel_u_size (void); the core file of the register values. */ #define KERNEL_U_ADDR 0 -/* Offset of the registers within the user area. */ -#define U_REGS_OFFSET 0 - extern CORE_ADDR register_u_addr (CORE_ADDR blockend, int regnum); #define REGISTER_U_ADDR(addr, blockend, regnum) \ (addr) = register_u_addr (blockend, regnum) diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c index 8458879..5ea7802 100644 --- a/gdb/i386-linux-nat.c +++ b/gdb/i386-linux-nat.c @@ -34,6 +34,10 @@ #include <sys/reg.h> #endif +#ifndef ORIG_EAX +#define ORIG_EAX -1 +#endif + #ifdef HAVE_SYS_DEBUGREG_H #include <sys/debugreg.h> #endif @@ -90,7 +94,15 @@ static int regmap[] = EAX, ECX, EDX, EBX, UESP, EBP, ESI, EDI, EIP, EFL, CS, SS, - DS, ES, FS, GS + DS, ES, FS, GS, + -1, -1, -1, -1, /* st0, st1, st2, st3 */ + -1, -1, -1, -1, /* st4, st5, st6, st7 */ + -1, -1, -1, -1, /* fctrl, fstat, ftag, fiseg */ + -1, -1, -1, -1, /* fioff, foseg, fooff, fop */ + -1, -1, -1, -1, /* xmm0, xmm1, xmm2, xmm3 */ + -1, -1, -1, -1, /* xmm4, xmm5, xmm6, xmm6 */ + -1, /* mxcsr */ + ORIG_EAX }; /* Which ptrace request retrieves which registers? @@ -148,155 +160,58 @@ kernel_u_size (void) } -/* Fetching registers directly from the U area, one at a time. */ - -/* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'. - The problem is that we define FETCH_INFERIOR_REGISTERS since we - want to use our own versions of {fetch,store}_inferior_registers - that use the GETREGS request. This means that the code in - `infptrace.c' is #ifdef'd out. But we need to fall back on that - code when GDB is running on top of a kernel that doesn't support - the GETREGS request. I want to avoid changing `infptrace.c' right - now. */ - -#ifndef PT_READ_U -#define PT_READ_U PTRACE_PEEKUSR -#endif -#ifndef PT_WRITE_U -#define PT_WRITE_U PTRACE_POKEUSR -#endif - -/* Default the type of the ptrace transfer to int. */ -#ifndef PTRACE_XFER_TYPE -#define PTRACE_XFER_TYPE int -#endif - -/* Registers we shouldn't try to fetch. */ -#define OLD_CANNOT_FETCH_REGISTER(regno) ((regno) >= I386_NUM_GREGS) +/* Accessing registers through the U area, one at a time. */ /* Fetch one register. */ static void fetch_register (int regno) { - /* This isn't really an address. But ptrace thinks of it as one. */ - CORE_ADDR regaddr; - char mess[128]; /* For messages */ - register int i; - unsigned int offset; /* Offset of registers within the u area. */ - char buf[MAX_REGISTER_RAW_SIZE]; int tid; + int val; - if (OLD_CANNOT_FETCH_REGISTER (regno)) + gdb_assert (!have_ptrace_getregs); + if (cannot_fetch_register (regno)) { - memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */ - supply_register (regno, buf); + supply_register (regno, NULL); return; } - /* Overload thread id onto process id */ + /* GNU/Linux LWP ID's are process ID's. */ if ((tid = TIDGET (inferior_ptid)) == 0) - tid = PIDGET (inferior_ptid); /* no thread id, just use process id */ - - offset = U_REGS_OFFSET; - - regaddr = register_addr (regno, offset); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) - { - errno = 0; - *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid, - (PTRACE_ARG3_TYPE) regaddr, 0); - regaddr += sizeof (PTRACE_XFER_TYPE); - if (errno != 0) - { - sprintf (mess, "reading register %s (#%d)", - REGISTER_NAME (regno), regno); - perror_with_name (mess); - } - } - supply_register (regno, buf); -} + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ -/* Fetch register values from the inferior. - If REGNO is negative, do this for all registers. - Otherwise, REGNO specifies which register (so we can save time). */ + errno = 0; + val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0); + if (errno != 0) + error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno), + regno, safe_strerror (errno)); -void -old_fetch_inferior_registers (int regno) -{ - if (regno >= 0) - { - fetch_register (regno); - } - else - { - for (regno = 0; regno < NUM_REGS; regno++) - { - fetch_register (regno); - } - } + supply_register (regno, &val); } -/* Registers we shouldn't try to store. */ -#define OLD_CANNOT_STORE_REGISTER(regno) ((regno) >= I386_NUM_GREGS) - /* Store one register. */ static void store_register (int regno) { - /* This isn't really an address. But ptrace thinks of it as one. */ - CORE_ADDR regaddr; - char mess[128]; /* For messages */ - register int i; - unsigned int offset; /* Offset of registers within the u area. */ int tid; + int val; - if (OLD_CANNOT_STORE_REGISTER (regno)) - { - return; - } + gdb_assert (!have_ptrace_getregs); + if (cannot_store_register (regno)) + return; - /* Overload thread id onto process id */ + /* GNU/Linux LWP ID's are process ID's. */ if ((tid = TIDGET (inferior_ptid)) == 0) - tid = PIDGET (inferior_ptid); /* no thread id, just use process id */ - - offset = U_REGS_OFFSET; - - regaddr = register_addr (regno, offset); - for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE)) - { - errno = 0; - ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr, - *(PTRACE_XFER_TYPE *) & registers[REGISTER_BYTE (regno) + i]); - regaddr += sizeof (PTRACE_XFER_TYPE); - if (errno != 0) - { - sprintf (mess, "writing register %s (#%d)", - REGISTER_NAME (regno), regno); - perror_with_name (mess); - } - } -} - -/* Store our register values back into the inferior. - If REGNO is negative, do this for all registers. - Otherwise, REGNO specifies which register (so we can save time). */ + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ -void -old_store_inferior_registers (int regno) -{ - if (regno >= 0) - { - store_register (regno); - } - else - { - for (regno = 0; regno < NUM_REGS; regno++) - { - store_register (regno); - } - } + errno = 0; + regcache_collect (regno, &val); + ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val); + if (errno != 0) + error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno), + regno, safe_strerror (errno)); } @@ -573,16 +488,15 @@ static void dummy_sse_values (void) {} int cannot_fetch_register (int regno) { - if (! have_ptrace_getregs) - return OLD_CANNOT_FETCH_REGISTER (regno); - return 0; + gdb_assert (regno >= 0 && regno < NUM_REGS); + return (!have_ptrace_getregs && regmap[regno] == -1); } + int cannot_store_register (int regno) { - if (! have_ptrace_getregs) - return OLD_CANNOT_STORE_REGISTER (regno); - return 0; + gdb_assert (regno >= 0 && regno < NUM_REGS); + return (!have_ptrace_getregs && regmap[regno] == -1); } /* Fetch register REGNO from the child process. If REGNO is -1, do @@ -596,9 +510,14 @@ fetch_inferior_registers (int regno) /* Use the old method of peeking around in `struct user' if the GETREGS request isn't available. */ - if (! have_ptrace_getregs) + if (!have_ptrace_getregs) { - old_fetch_inferior_registers (regno); + int i; + + for (i = 0; i < NUM_REGS; i++) + if (regno == -1 || regno == i) + fetch_register (i); + return; } @@ -615,9 +534,9 @@ fetch_inferior_registers (int regno) fetch_regs (tid); /* The call above might reset `have_ptrace_getregs'. */ - if (! have_ptrace_getregs) + if (!have_ptrace_getregs) { - old_fetch_inferior_registers (-1); + fetch_inferior_registers (regno); return; } @@ -662,9 +581,14 @@ store_inferior_registers (int regno) /* Use the old method of poking around in `struct user' if the SETREGS request isn't available. */ - if (! have_ptrace_getregs) + if (!have_ptrace_getregs) { - old_store_inferior_registers (regno); + int i; + + for (i = 0; i < NUM_REGS; i++) + if (regno == -1 || regno == i) + store_register (i); + return; } @@ -724,7 +648,7 @@ i386_linux_dr_get (int regnum) stuff to the target vectore. For now, just return zero if the ptrace call fails. */ errno = 0; - value = ptrace (PT_READ_U, tid, + value = ptrace (PTRACE_PEEKUSER, tid, offsetof (struct user, u_debugreg[regnum]), 0); if (errno != 0) #if 0 @@ -747,7 +671,7 @@ i386_linux_dr_set (int regnum, unsigned long value) tid = PIDGET (inferior_ptid); errno = 0; - ptrace (PT_WRITE_U, tid, + ptrace (PTRACE_POKEUSER, tid, offsetof (struct user, u_debugreg[regnum]), value); if (errno != 0) perror_with_name ("Couldn't write debug register"); |