diff options
author | Mark Kettenis <kettenis@gnu.org> | 2000-05-24 22:32:58 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2000-05-24 22:32:58 +0000 |
commit | e6031aeb52be6c31dc1c7cbd7c74de76a114ad02 (patch) | |
tree | 46402436df156851b4971bbebc557affc930db84 /gdb/i386bsd-nat.c | |
parent | dd167cc82ff5da37e3de8630e2c86c907cc810b2 (diff) | |
download | gdb-e6031aeb52be6c31dc1c7cbd7c74de76a114ad02.zip gdb-e6031aeb52be6c31dc1c7cbd7c74de76a114ad02.tar.gz gdb-e6031aeb52be6c31dc1c7cbd7c74de76a114ad02.tar.bz2 |
Add support for FreeBSD/i386 ELF.
* i386bsd-nat.c: New file.
* config/i386/tm-fbsd.h (HAVE_I387_REGS): Define.
Include "i386/tm-i386.h" instead of "i386/tm-i386b.h".
(NUM_REGS): Remove redefinition.
(USE_STRUCT_CONVENTION): Define.
(i386_float_info): Remove prototype.
(FLOAT_INFO): Remove define.
(JB_ELEMENT_SIZE): Define to 4.
(JB_PC): Define to 0.
(GET_LONGJMP_TARGET): Define.
(SIGTRAMP_START, SIGTRAMP_END): Define.
(SIGCONTEXT_PC_OFFSET): Define.
(IN_SOLIB_CALL_TRAMPOLINE): Only define if !SVR4_SHARED_LIBS
* config/i386/nm-fbsd.h (PTRACE_ARG3_TYPE): Define to caddr_t.
(FETCH_INFERIOR_REGISTERS): Define.
(ATTACH_DETACH): Define.
(kernel_u_size): Remove PARAMS.
(register_u_addr): Use CORE_ADDR in prototype where appropriate.
Remove PARAMS.
(SVR4_SHARED_LIBS) [FREEBSD_ELF || __ELF__ && !FREEBSD_AOUT]:
Define.
[SVR4_SHARED_LIBS]: Include "elf/common.h".
Only define aliases for struct members from <link.h> if
!SVR4_SHARED_LIBS.
* config/i386/xm-fbsd.h: New file.
* config/i386/fbsd.mt (TDEPFILES): Remove solib.o.
* config/i386/fbsd.mh (NATDEPFILES): Remove i386b-nat.o. Add
core-regset.o i387-nat.o i386bsd-nat.o.
Diffstat (limited to 'gdb/i386bsd-nat.c')
-rw-r--r-- | gdb/i386bsd-nat.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c new file mode 100644 index 0000000..c4def7e --- /dev/null +++ b/gdb/i386bsd-nat.c @@ -0,0 +1,238 @@ +/* Native-dependent code for modern i386 BSD's. + Copyright (C) 2000 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <machine/reg.h> +#include <machine/frame.h> + +#ifdef HAVE_SYS_PROCFS_H +#include <sys/procfs.h> +#endif + +#ifndef HAVE_GREGSET_T +typedef struct reg gregset_t; +#endif + +#ifndef HAVE_FPREGSET_T +typedef struct fpreg fpregset_t; +#endif + +/* In older BSD versions we cannot get at some of the segment + registers. FreeBSD for example didn't support the %fs and %gs + registers until the 3.0 release. We have autoconf checks for their + presence, and deal gracefully with their absence. */ + +/* Registers we shouldn't try to fetch. */ +#if !defined (CANNOT_FETCH_REGISTER) +#define CANNOT_FETCH_REGISTER(regno) cannot_fetch_register (regno) +#endif + +/* Registers we shouldn't try to store. */ +#if !defined (CANNOT_STORE_REGISTER) +#define CANNOT_STORE_REGISTER(regno) CANNOT_FETCH_REGISTER (regno) +#endif + +/* Offset to the gregset_t location where REG is stored. */ +#define REG_OFFSET(reg) offsetof (gregset_t, reg) + +/* At reg_offset[REGNO] you'll find the offset to the gregset_t + location where the GDB register REGNO is stored. Unsupported + registers are marked with `-1'. */ +static int reg_offset[] = +{ + REG_OFFSET (r_eax), + REG_OFFSET (r_ecx), + REG_OFFSET (r_edx), + REG_OFFSET (r_edx), + REG_OFFSET (r_esp), + REG_OFFSET (r_ebp), + REG_OFFSET (r_esi), + REG_OFFSET (r_edi), + REG_OFFSET (r_eip), + REG_OFFSET (r_eflags), + REG_OFFSET (r_cs), + REG_OFFSET (r_ss), + REG_OFFSET (r_ds), + REG_OFFSET (r_es), +#ifdef HAVE_R_FS + REG_OFFSET (r_fs), +#else + -1, +#endif +#ifdef HAVE_R_GS + REG_OFFSET (r_gs) +#else + -1 +#endif +}; + +#define REG_ADDR(regset, regno) ((char *) (regset) + reg_offset[regno]) + +/* Return nonzero if we shouldn't try to fetch register REGNO. */ + +static int +cannot_fetch_register (int regno) +{ + return (reg_offset[regno] == -1); +} + + +/* Transfering the registers between GDB, inferiors and core files. */ + +/* Fill GDB's register array with the genereal-purpose register values + in *GREGSETP. */ + +void +supply_gregset (gregset_t *gregsetp) +{ + char buf[MAX_REGISTER_RAW_SIZE]; + int i; + + for (i = 0; i < NUM_GREGS; i++) + { + if (CANNOT_FETCH_REGISTER (i)) + { + memset (buf, 0, REGISTER_RAW_SIZE (i)); + supply_register (i, buf); + } + else + supply_register (i, REG_ADDR (gregsetp, i)); + } +} + +/* Fill register REGNO (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_gregset (gregset_t *gregsetp, int regno) +{ + int i; + + for (i = 0; i < NUM_GREGS; i++) + if ((regno == -1 || regno == i) && ! CANNOT_STORE_REGISTER (i)) + memcpy (REG_ADDR (gregsetp, i), ®isters[REGISTER_BYTE (regno)], + REGISTER_RAW_SIZE (i)); +} + +#include "i387-nat.h" + +/* Fill GDB's register array with the floating-point register values + in *FPREGSETP. */ + +void +supply_fpregset (fpregset_t *fpregsetp) +{ + i387_supply_fsave ((char *) fpregsetp); +} + +/* Fill register REGNO (if it is a floating-point register) in + *FPREGSETP with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_fpregset (fpregset_t *fpregsetp, int regno) +{ + i387_fill_fsave ((char *) fpregsetp, regno); +} + +/* Fetch register REGNO from the inferior. If REGNO is -1, do this + for all registers (including the floating point registers). */ + +void +fetch_inferior_registers (int regno) +{ + gregset_t gregs; + + if (ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &gregs, 0) == -1) + perror_with_name ("Couldn't get registers"); + + supply_gregset (&gregs); + + if (regno == -1 || regno >= FP0_REGNUM) + { + fpregset_t fpregs; + + if (ptrace (PT_GETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &fpregs, 0) == -1) + perror_with_name ("Couldn't get floating point status"); + + supply_fpregset (&fpregs); + } +} + +/* Store register REGNO back into the inferior. If REGNO is -1, do + this for all registers (including the floating point registers). */ + +void +store_inferior_registers (int regno) +{ + gregset_t gregs; + + if (ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &gregs, 0) == -1) + perror_with_name ("Couldn't get registers"); + + fill_gregset (&gregs, regno); + + if (ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &gregs, 0) == -1) + perror_with_name ("Couldn't write registers"); + + if (regno == -1 || regno >= FP0_REGNUM) + { + fpregset_t fpregs; + + if (ptrace (PT_GETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &fpregs, 0) == -1) + perror_with_name ("Couldn't get floating point status"); + + fill_fpregset (&fpregs, regno); + + if (ptrace (PT_SETFPREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &fpregs, 0) == -1) + perror_with_name ("Couldn't write floating point status"); + } +} + + +/* Support for the user struct. */ + +/* Return the address register REGNO. BLOCKEND is the value of + u.u_ar0, which should point to the registers. */ + +CORE_ADDR +register_u_addr (CORE_ADDR blockend, int regno) +{ + return (CORE_ADDR) REG_ADDR (blockend, regno); +} + +#include <sys/param.h> +#include <sys/user.h> + +/* Return the size of the user struct. */ + +int +kernel_u_size (void) +{ + return (sizeof (struct user)); +} |