diff options
author | Mark Kettenis <kettenis@gnu.org> | 2002-11-09 21:31:12 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2002-11-09 21:31:12 +0000 |
commit | ce556f853977ba8b2df2321a48a7f29697b9c444 (patch) | |
tree | 20a31b56c20479a0475a10638d9b7ecca27667b6 /gdb/i386-linux-nat.c | |
parent | 932bb5249e2a85de849b8cf07b3b74a4816a4d21 (diff) | |
download | gdb-ce556f853977ba8b2df2321a48a7f29697b9c444.zip gdb-ce556f853977ba8b2df2321a48a7f29697b9c444.tar.gz gdb-ce556f853977ba8b2df2321a48a7f29697b9c444.tar.bz2 |
* 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.
Diffstat (limited to 'gdb/i386-linux-nat.c')
-rw-r--r-- | gdb/i386-linux-nat.c | 198 |
1 files changed, 61 insertions, 137 deletions
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"); |