diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 1999-05-02 19:50:19 +0000 |
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 1999-05-02 19:50:19 +0000 |
| commit | 9845cb14aa768f3f327ce16c1951e523b544bc8b (patch) | |
| tree | 9d0f059f3e75503fa5ffec11da47c4c153cc3cdf /gnu/usr.bin/binutils | |
| parent | be65909220f0ca54bfe78ac30763bffbfbd4e826 (diff) | |
Notes
Diffstat (limited to 'gnu/usr.bin/binutils')
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/Makefile.alpha | 7 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/Makefile.i386 | 7 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/alpha/nm.h | 71 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/alpha/tm.h | 33 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/alpha/version.c | 3 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/alpha/xm.h | 30 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/config.h | 326 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c | 440 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c | 974 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/i386/nm.h | 135 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/i386/tm.h | 58 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdb/i386/version.c | 3 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdbreplay/Makefile | 20 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdbserver/Makefile | 20 | ||||
| -rw-r--r-- | gnu/usr.bin/binutils/gdbserver/low-fbsd.c | 339 |
15 files changed, 2466 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/gdb/Makefile.alpha b/gnu/usr.bin/binutils/gdb/Makefile.alpha new file mode 100644 index 000000000000..54a09eeea753 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/Makefile.alpha @@ -0,0 +1,7 @@ +# +# $Id$ +# + +XSRCS+= freebsd-nat.c alpha-tdep.c + +.PATH: ${.CURDIR}/alpha diff --git a/gnu/usr.bin/binutils/gdb/Makefile.i386 b/gnu/usr.bin/binutils/gdb/Makefile.i386 new file mode 100644 index 000000000000..364b5258e2bc --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/Makefile.i386 @@ -0,0 +1,7 @@ +# +# $Id$ +# + +XSRCS+= freebsd-nat.c i386-tdep.c i387-tdep.c kvm-fbsd.c + +.PATH: ${.CURDIR}/i386 diff --git a/gnu/usr.bin/binutils/gdb/alpha/nm.h b/gnu/usr.bin/binutils/gdb/alpha/nm.h new file mode 100644 index 000000000000..b5a8b65df6c6 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/alpha/nm.h @@ -0,0 +1,71 @@ +/* Native definitions for alpha running FreeBSD. + Copyright (C) 1993, 1994 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Figure out where the longjmp will land. We expect that we have just entered + longjmp and haven't yet setup the stack frame, so the args are still in the + argument regs. A0_REGNUM points at the jmp_buf structure from which we + extract the pc (JB_PC) that we will land at. The pc is copied into ADDR. + This routine returns true on success */ + +#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR) +extern int +get_longjmp_target PARAMS ((CORE_ADDR *)); + +/* Tell gdb that we can attach and detach other processes */ +#define ATTACH_DETACH + +/* We define our own fetch/store methods */ +#define FETCH_INFERIOR_REGISTERS + +extern CORE_ADDR alpha_u_regs_offset(); +#define U_REGS_OFFSET alpha_u_regs_offset() + +#define PTRACE_ARG3_TYPE char* + +/* ptrace transfers longs, the ptrace man page is lying. */ + +#define PTRACE_XFER_TYPE int + +/* The alpha does not step over a breakpoint, the manpage is lying again. */ + +#define CANNOT_STEP_BREAKPOINT + +/* Linux has shared libraries. */ + +#define GDB_TARGET_HAS_SHARED_LIBS + +/* Support for shared libraries. */ + +#include "solib.h" + +#ifdef __ELF__ +#define SVR4_SHARED_LIBS +#define TARGET_ELF64 +#endif + +/* This is a lie. It's actually in stdio.h. */ + +#define PSIGNAL_IN_SIGNAL_H + +/* Given a pointer to either a gregset_t or fpregset_t, return a + pointer to the first register. */ +#define ALPHA_REGSET_BASE(regsetp) ((long *) (regsetp)) + +extern int kernel_debugging; +extern int kernel_writablecore; diff --git a/gnu/usr.bin/binutils/gdb/alpha/tm.h b/gnu/usr.bin/binutils/gdb/alpha/tm.h new file mode 100644 index 000000000000..a0667a56263c --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/alpha/tm.h @@ -0,0 +1,33 @@ +/* Definitions to make GDB run on an Alpha box under FreeBSD. The + definitions here are used when the _target_ system is running Linux. + Copyright 1996 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. */ + +#ifndef TM_FREEBSDALPHA_H +#define TM_FREEBSDALPHA_H + +#include "alpha/tm-alpha.h" + +/* Number of traps that happen between exec'ing the shell to run an + inferior, and when we finally get to the inferior code. This is 2 + on FreeBSD and most implementations. */ + +#undef START_INFERIOR_TRAPS_EXPECTED +#define START_INFERIOR_TRAPS_EXPECTED 2 + +#endif /* TM_FREEBSDALPHA_H */ diff --git a/gnu/usr.bin/binutils/gdb/alpha/version.c b/gnu/usr.bin/binutils/gdb/alpha/version.c new file mode 100644 index 000000000000..b55c0d1a46de --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/alpha/version.c @@ -0,0 +1,3 @@ +char *version = "4.18"; +char *host_name = "alpha-unknown-freebsd"; +char *target_name = "alpha-unknown-freebsd"; diff --git a/gnu/usr.bin/binutils/gdb/alpha/xm.h b/gnu/usr.bin/binutils/gdb/alpha/xm.h new file mode 100644 index 000000000000..9d340a3cb762 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/alpha/xm.h @@ -0,0 +1,30 @@ +/* Host definitions for GDB running on an Alpha under FreeBSD + Copyright (C) 1996 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#if !defined (HOST_BYTE_ORDER) +#define HOST_BYTE_ORDER LITTLE_ENDIAN +#endif + +/* The alpha has no siginterrupt routine. */ +#define NO_SIGINTERRUPT + +#define HAVE_TERMIOS +#define HAVE_SIGSETMASK 1 + +#include <limits.h> diff --git a/gnu/usr.bin/binutils/gdb/config.h b/gnu/usr.bin/binutils/gdb/config.h new file mode 100644 index 000000000000..f24a6aceb7b3 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/config.h @@ -0,0 +1,326 @@ +/* config.h. Generated automatically by configure. */ +/* config.in. Generated automatically from configure.in by autoheader. */ + +/* Whether malloc must be declared even if <stdlib.h> is included. */ +/* #undef NEED_DECLARATION_MALLOC */ + +/* Whether realloc must be declared even if <stdlib.h> is included. */ +/* #undef NEED_DECLARATION_REALLOC */ + +/* Whether free must be declared even if <stdlib.h> is included. */ +/* #undef NEED_DECLARATION_FREE */ + +/* Whether strerror must be declared even if <string.h> is included. */ +/* #undef NEED_DECLARATION_STRERROR */ + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* #undef _ALL_SOURCE */ +#endif + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define to empty if the keyword does not work. */ +/* #undef const */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +/* #undef HAVE_ALLOCA_H */ + +/* Define if the `long double' type works. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define as __inline if that's what the C compiler calls it. */ +/* #undef inline */ + +/* Define to `long' if <sys/types.h> doesn't define. */ +/* #undef off_t */ + +/* Define if you need to in order for stat and other things to work. */ +/* #undef _POSIX_SOURCE */ + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define to `unsigned' if <sys/types.h> doesn't define. */ +/* #undef size_t */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ + +/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */ +/* #undef STAT_MACROS_BROKEN */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if ioctl argument PIOCSET is available. */ +/* #undef HAVE_PROCFS_PIOCSET */ + +/* /proc PID entries are directories containing the files + ctl as map status */ +/* #undef HAVE_MULTIPLE_PROC_FDS */ + +/* Define if the `long long' type works. */ +#define CC_HAS_LONG_LONG 1 + +/* Define if the "ll" format works to print long long ints. */ +#define PRINTF_HAS_LONG_LONG 1 + +/* Define if the "%Lg" format works to print long doubles. */ +#define PRINTF_HAS_LONG_DOUBLE 1 + +/* Define if the "%Lg" format works to scan long doubles. */ +#define SCANF_HAS_LONG_DOUBLE 1 + +/* Define if using Solaris thread debugging. */ +/* #undef HAVE_THREAD_DB_LIB */ + +/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */ +/* #undef START_INFERIOR_TRAPS_EXPECTED */ +/* #undef sys_quotactl */ + +/* Define if you have HPUX threads */ +/* #undef HAVE_HPUX_THREAD_SUPPORT */ + +/* Define if you want to use the memory mapped malloc package (mmalloc). */ +/* #undef USE_MMALLOC */ + +/* Define if the runtime uses a routine from mmalloc before gdb has a chance + to initialize mmalloc, and we want to force checking to be used anyway. + This may cause spurious memory corruption messages if the runtime tries + to explicitly deallocate that memory when gdb calls exit. */ +/* #undef MMCHECK_FORCE */ + +/* Define if you want to use the full-screen terminal user interface. */ +/* #undef TUI */ + +/* Define if <proc_service.h> on solaris uses int instead of + size_t, and assorted other type changes. */ +/* #undef PROC_SERVICE_IS_OLD */ + +/* Set to true if the save_state_t structure is present */ +#define HAVE_STRUCT_SAVE_STATE_T 0 + +/* Set to true if the save_state_t structure has the ss_wide member */ +#define HAVE_STRUCT_MEMBER_SS_WIDE 0 + +/* Define if you have the __argz_count function. */ +/* #undef HAVE___ARGZ_COUNT */ + +/* Define if you have the __argz_next function. */ +/* #undef HAVE___ARGZ_NEXT */ + +/* Define if you have the __argz_stringify function. */ +/* #undef HAVE___ARGZ_STRINGIFY */ + +/* Define if you have the bcopy function. */ +#define HAVE_BCOPY 1 + +/* Define if you have the btowc function. */ +/* #undef HAVE_BTOWC */ + +/* Define if you have the bzero function. */ +#define HAVE_BZERO 1 + +/* Define if you have the dcgettext function. */ +/* #undef HAVE_DCGETTEXT */ + +/* Define if you have the getcwd function. */ +#define HAVE_GETCWD 1 + +/* Define if you have the getpagesize function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if you have the isascii function. */ +#define HAVE_ISASCII 1 + +/* Define if you have the munmap function. */ +#define HAVE_MUNMAP 1 + +/* Define if you have the putenv function. */ +#define HAVE_PUTENV 1 + +/* Define if you have the sbrk function. */ +#define HAVE_SBRK 1 + +/* Define if you have the setenv function. */ +#define HAVE_SETENV 1 + +/* Define if you have the setlocale function. */ +#define HAVE_SETLOCALE 1 + +/* Define if you have the setpgid function. */ +#define HAVE_SETPGID 1 + +/* Define if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define if you have the stpcpy function. */ +/* #undef HAVE_STPCPY */ + +/* Define if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define if you have the strchr function. */ +#define HAVE_STRCHR 1 + +/* Define if you have the <argz.h> header file. */ +/* #undef HAVE_ARGZ_H */ + +/* Define if you have the <asm/debugreg.h> header file. */ +/* #undef HAVE_ASM_DEBUGREG_H */ + +/* Define if you have the <ctype.h> header file. */ +#define HAVE_CTYPE_H 1 + +/* Define if you have the <curses.h> header file. */ +#define HAVE_CURSES_H 1 + +/* Define if you have the <endian.h> header file. */ +/* #undef HAVE_ENDIAN_H */ + +/* Define if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the <link.h> header file. */ +#define HAVE_LINK_H 1 + +/* Define if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you have the <malloc.h> header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define if you have the <nl_types.h> header file. */ +#define HAVE_NL_TYPES_H 1 + +/* Define if you have the <objlist.h> header file. */ +/* #undef HAVE_OBJLIST_H */ + +/* Define if you have the <ptrace.h> header file. */ +/* #undef HAVE_PTRACE_H */ + +/* Define if you have the <sgtty.h> header file. */ +#define HAVE_SGTTY_H 1 + +/* Define if you have the <stddef.h> header file. */ +#define HAVE_STDDEF_H 1 + +/* Define if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the <sys/debugreg.h> header file. */ +/* #undef HAVE_SYS_DEBUGREG_H */ + +/* Define if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define if you have the <sys/procfs.h> header file. */ +#define HAVE_SYS_PROCFS_H 1 + +/* Define if you have the <sys/ptrace.h> header file. */ +#define HAVE_SYS_PTRACE_H 1 + +/* Define if you have the <sys/reg.h> header file. */ +/* #undef HAVE_SYS_REG_H */ + +/* Define if you have the <sys/wait.h> header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define if you have the <term.h> header file. */ +#define HAVE_TERM_H 1 + +/* Define if you have the <termio.h> header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define if you have the <termios.h> header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if you have the <values.h> header file. */ +/* #undef HAVE_VALUES_H */ + +/* Define if you have the <wait.h> header file. */ +/* #undef HAVE_WAIT_H */ + +/* Define if you have the <wchar.h> header file. */ +/* #undef HAVE_WCHAR_H */ + +/* Define if you have the <wctype.h> header file. */ +/* #undef HAVE_WCTYPE_H */ + +/* Define if you have the dl library (-ldl). */ +/* #undef HAVE_LIBDL */ + +/* Define if you have the m library (-lm). */ +#define HAVE_LIBM 1 + +/* Define if you have the w library (-lw). */ +/* #undef HAVE_LIBW */ + +/* Define if you have the stpcpy function */ +/* #undef HAVE_STPCPY */ + +/* Define if your locale.h file contains LC_MESSAGES. */ +#define HAVE_LC_MESSAGES 1 + +/* Define to 1 if NLS is requested */ +#define ENABLE_NLS 1 + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +/* #undef HAVE_GETTEXT */ + +/* Define if malloc is not declared in system header files. */ +/* #undef NEED_DECLARATION_MALLOC */ + +/* Define if realloc is not declared in system header files. */ +/* #undef NEED_DECLARATION_REALLOC */ + +/* Define if free is not declared in system header files. */ +/* #undef NEED_DECLARATION_FREE */ + +/* Define if strerror is not declared in system header files. */ +/* #undef NEED_DECLARATION_STRERROR */ + +/* Define if strdup is not declared in system header files. */ +/* #undef NEED_DECLARATION_STRDUP */ + +/* Define if <sys/procfs.h> has pstatus_t. */ +/* #undef HAVE_PSTATUS_T */ + +/* Define if <sys/procfs.h> has prrun_t. */ +/* #undef HAVE_PRRUN_T */ + +/* Define if <sys/procfs.h> has gregset_t. */ +#define HAVE_GREGSET_T 1 + +/* Define if <sys/procfs.h> has fpregset_t. */ +#define HAVE_FPREGSET_T 1 + diff --git a/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c b/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c new file mode 100644 index 000000000000..84c121d8e50f --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/i386/freebsd-nat.c @@ -0,0 +1,440 @@ +/* Native-dependent code for BSD Unix running on i386's, for GDB. + Copyright 1988, 1989, 1991, 1992, 1994, 1996 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 <sys/types.h> +#include <sys/ptrace.h> +#include <machine/reg.h> +#include <machine/frame.h> +#include <sys/param.h> +#include <sys/user.h> +#include "gdbcore.h" +#include "value.h" +#include "inferior.h" + +#if defined(HAVE_GREGSET_T) || defined(HAVE_FPREGSET_T) +#include <sys/procfs.h> +#endif + +/* this table must line up with REGISTER_NAMES in tm-i386v.h */ +/* symbols like 'tEAX' come from <machine/reg.h> */ +static int tregmap[] = +{ + tEAX, tECX, tEDX, tEBX, + tESP, tEBP, tESI, tEDI, + tEIP, tEFLAGS, tCS, tSS, + tDS, tES, tFS, tGS, +}; + +static struct save87 pcb_savefpu; + +void +fetch_inferior_registers (regno) + int regno; +{ + struct reg inferior_registers; /* ptrace order, not gcc/gdb order */ + int r; + + ptrace (PT_GETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); + + for (r = 0; r < NUM_REGS; r++) + memcpy (®isters[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4); + + registers_fetched (); +} + +void +store_inferior_registers (regno) + int regno; +{ + struct reg inferior_registers; /* ptrace order, not gcc/gdb order */ + int r; + + for (r = 0; r < NUM_REGS; r++) + memcpy (((int *)&inferior_registers) + tregmap[r], ®isters[REGISTER_BYTE (r)], 4); + + ptrace (PT_SETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); +} + +/* Extract the register values out of the core file and store + them where `read_register' will find them. + Extract the floating point state out of the core file and store + it where `float_info' will find it. + + CORE_REG_SECT points to the register values themselves, read into memory. + CORE_REG_SIZE is the size of that area. + WHICH says which set of registers we are handling (0 = int, 2 = float + on machines where they are discontiguous). + REG_ADDR is the offset from u.u_ar0 to the register values relative to + core_reg_sect. This is used with old-fashioned core files to + locate the registers in a large upage-plus-stack ".reg" section. + Original upage address X is at location core_reg_sect+x+reg_addr. + */ + +static void +fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) + char *core_reg_sect; + unsigned core_reg_size; + int which; + CORE_ADDR reg_addr; +{ + register int regno; + register int cregno; + register int addr; + int bad_reg = -1; + int offset; + struct user *tmp_uaddr; + + /* + * First get virtual address of user structure. Then calculate offset. + */ + memcpy(&tmp_uaddr, + &((struct user *) core_reg_sect)->u_kproc.kp_proc.p_addr, + sizeof(tmp_uaddr)); + offset = -reg_addr - (int) tmp_uaddr; + + for (regno = 0; regno < NUM_REGS; regno++) + { + cregno = tregmap[regno]; + if (cregno == tGS) + addr = offsetof (struct user, u_pcb) + offsetof (struct pcb, pcb_gs); + else + addr = offset + 4 * cregno; + if (addr < 0 || addr >= core_reg_size) + { + if (bad_reg < 0) + bad_reg = regno; + } + else + { + supply_register (regno, core_reg_sect + addr); + } + } + if (bad_reg >= 0) + { + error ("Register %s not found in core file.", gdb_register_names[bad_reg]); + } + + addr = offsetof (struct user, u_pcb) + offsetof (struct pcb, pcb_savefpu); + memcpy (&pcb_savefpu, core_reg_sect + addr, sizeof pcb_savefpu); +} + +#ifdef FLOAT_INFO +#include "expression.h" +#include "language.h" /* for local_hex_string */ +#include "floatformat.h" + +#include <sys/param.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <fcntl.h> + +#include <a.out.h> + +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/uio.h> +#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */ +#include <sys/user.h> +#undef curpcb +#include <sys/file.h> +#include "gdb_stat.h" +#include <sys/ptrace.h> + +extern void print_387_control_word (); /* i387-tdep.h */ +extern void print_387_status_word (); + +#define fpstate save87 +#define U_FPSTATE(u) u.u_pcb.pcb_savefpu + +static void +i387_to_double (from, to) + char *from; + char *to; +{ + long *lp; + /* push extended mode on 387 stack, then pop in double mode + * + * first, set exception masks so no error is generated - + * number will be rounded to inf or 0, if necessary + */ + asm ("pushl %eax"); /* grab a stack slot */ + asm ("fstcw (%esp)"); /* get 387 control word */ + asm ("movl (%esp),%eax"); /* save old value */ + asm ("orl $0x3f,%eax"); /* mask all exceptions */ + asm ("pushl %eax"); + asm ("fldcw (%esp)"); /* load new value into 387 */ + + asm ("movl 8(%ebp),%eax"); + asm ("fldt (%eax)"); /* push extended number on 387 stack */ + asm ("fwait"); + asm ("movl 12(%ebp),%eax"); + asm ("fstpl (%eax)"); /* pop double */ + asm ("fwait"); + + asm ("popl %eax"); /* flush modified control word */ + asm ("fnclex"); /* clear exceptions */ + asm ("fldcw (%esp)"); /* restore original control word */ + asm ("popl %eax"); /* flush saved copy */ +} + +struct env387 +{ + unsigned short control; + unsigned short r0; + unsigned short status; + unsigned short r1; + unsigned short tag; + unsigned short r2; + unsigned long eip; + unsigned short code_seg; + unsigned short opcode; + unsigned long operand; + unsigned short operand_seg; + unsigned short r3; + unsigned char regs[8][10]; +}; + +static void +print_387_status (status, ep) + unsigned short status; + struct env387 *ep; +{ + int i; + int bothstatus; + int top; + int fpreg; + + bothstatus = ((status != 0) && (ep->status != 0)); + if (status != 0) + { + if (bothstatus) + printf_unfiltered ("u: "); + print_387_status_word ((unsigned int)status); + } + + if (ep->status != 0) + { + if (bothstatus) + printf_unfiltered ("e: "); + print_387_status_word ((unsigned int)ep->status); + } + + print_387_control_word ((unsigned int)ep->control); + printf_unfiltered ("last instruction: "); + printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode)); + printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg)); + printf_unfiltered ("%s; ", local_hex_string(ep->eip)); + printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg)); + printf_unfiltered (":%s\n", local_hex_string(ep->operand)); + + top = (ep->status >> 11) & 7; + + printf_unfiltered (" regno tag msb lsb value\n"); + for (fpreg = 7; fpreg >= 0; fpreg--) + { + int exp; + int mantissa_or; + int normal; + char *sign; + int st_regno; + unsigned short *usregs; + double val; + + /* The physical regno `fpreg' is only relevant as an index into the + * tag word. Logical `%st' numbers are required for indexing ep->regs. + */ + st_regno = (fpreg + 8 - top) & 7; + + printf_unfiltered ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : " "); + + switch ((ep->tag >> (fpreg * 2)) & 3) + { + case 0: printf_unfiltered ("valid "); break; + case 1: printf_unfiltered ("zero "); break; + case 2: printf_unfiltered ("trap "); break; + case 3: printf_unfiltered ("empty "); break; + } + for (i = 9; i >= 0; i--) + printf_unfiltered ("%02x", ep->regs[st_regno][i]); + + printf_unfiltered (" "); + + /* + * Handle weird cases better than floatformat_to_double () and + * printf (). + */ + usregs = (unsigned short *) ep->regs[st_regno]; + sign = usregs[4] & 0x8000 ? "-" : ""; + exp = usregs[4] & 0x7fff; + normal = usregs[3] & 0x8000; + mantissa_or = usregs[0] | usregs[1] | usregs[2] | (usregs[3] & 0x7fff); + if (exp == 0) + { + if (normal) + printf_unfiltered ("Pseudo Denormal (0 as a double)"); + else if (mantissa_or == 0) + printf_unfiltered ("%s0", sign); + else + printf_unfiltered ("Denormal (0 as a double)"); + } + else if (exp == 0x7fff) + { + if (!normal) + printf_unfiltered ("Pseudo "); + if (mantissa_or == 0) + printf_unfiltered ("%sInf", sign); + else + printf_unfiltered ("%s NaN", + usregs[3] & 0x4000 ? "Quiet" : "Signaling"); + if (!normal) + printf_unfiltered (" (NaN)"); + } + else if (!normal) + printf_unfiltered ("Unnormal (NaN)"); + else + { +#if 0 + /* Use this we stop trapping on overflow. */ + floatformat_to_double(&floatformat_i387_ext, + (char *) ep->regs[st_regno], &val); +#else + i387_to_double((char *) ep->regs[st_regno], (char *) &val); +#endif + printf_unfiltered ("%g", val); + } + printf_unfiltered ("\n"); + } +} + +void +i386_float_info () +{ + struct user u; /* just for address computations */ + int i; + /* fpstate defined in <sys/user.h> */ + struct fpstate *fpstatep; + char buf[sizeof (struct fpstate) + 2 * sizeof (int)]; + unsigned int uaddr; + char fpvalid; + unsigned int rounded_addr; + unsigned int rounded_size; + /*extern int corechan;*/ + int skip; + extern int inferior_pid; + + uaddr = (char *)&U_FPSTATE(u) - (char *)&u; + if (inferior_pid != 0 && core_bfd == NULL) + { + int *ip; + + rounded_addr = uaddr & -sizeof (int); + rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) + + sizeof (int) - 1) / sizeof (int); + skip = uaddr - rounded_addr; + + ip = (int *)buf; + for (i = 0; i < rounded_size; i++) + { + *ip++ = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0); + rounded_addr += sizeof (int); + } + fpstatep = (struct fpstate *)(buf + skip); + } + else + fpstatep = &pcb_savefpu; + + print_387_status (fpstatep->sv_ex_sw, (struct env387 *)fpstatep); +} +#endif /* FLOAT_INFO */ + +int +kernel_u_size () +{ + return (sizeof (struct user)); +} + +#ifdef SETUP_ARBITRARY_FRAME +#include "frame.h" +struct frame_info * +setup_arbitrary_frame (argc, argv) + int argc; + CORE_ADDR *argv; +{ + if (argc != 2) + error ("i386 frame specifications require two arguments: sp and pc"); + + return create_new_frame (argv[0], argv[1]); +} +#endif /* SETUP_ARBITRARY_FRAME */ + +#ifdef HAVE_GREGSET_T +void +supply_gregset (gp) + gregset_t *gp; +{ + int regno = 0; + + /* These must be ordered the same as REGISTER_NAMES in + config/i386/tm-i386.h. */ + supply_register (regno++, (char *)&gp->r_eax); + supply_register (regno++, (char *)&gp->r_ecx); + supply_register (regno++, (char *)&gp->r_edx); + supply_register (regno++, (char *)&gp->r_ebx); + supply_register (regno++, (char *)&gp->r_esp); + supply_register (regno++, (char *)&gp->r_ebp); + supply_register (regno++, (char *)&gp->r_esi); + supply_register (regno++, (char *)&gp->r_edi); + supply_register (regno++, (char *)&gp->r_eip); + supply_register (regno++, (char *)&gp->r_eflags); + supply_register (regno++, (char *)&gp->r_cs); + supply_register (regno++, (char *)&gp->r_ss); + supply_register (regno++, (char *)&gp->r_ds); + supply_register (regno++, (char *)&gp->r_es); + supply_register (regno++, (char *)&gp->r_fs); + supply_register (regno++, (char *)&gp->r_gs); +} +#endif /* HAVE_GREGSET_T */ + +#ifdef HAVE_FPREGSET_T +void +supply_fpregset (fp) + fpregset_t *fp; +{ + memcpy (&pcb_savefpu, fp, sizeof pcb_savefpu); +} +#endif /* HAVE_FPREGSET_T */ + +/* Register that we are able to handle aout (trad-core) file formats. */ + +static struct core_fns aout_core_fns = +{ + bfd_target_unknown_flavour, + fetch_core_registers, + NULL +}; + +void +_initialize_core_aout () +{ + add_core_fns (&aout_core_fns); +} diff --git a/gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c new file mode 100644 index 000000000000..2608e3c9b335 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/i386/kvm-fbsd.c @@ -0,0 +1,974 @@ +/* Live and postmortem kernel debugging functions for FreeBSD. + Copyright 1996 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 <errno.h> +#include <signal.h> +#include <fcntl.h> +#include <sys/sysctl.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/user.h> +#include "frame.h" /* required by inferior.h */ +#include "inferior.h" +#include "symtab.h" +#include "symfile.h" +#include "objfiles.h" +#include "command.h" +#include "bfd.h" +#include "target.h" +#include "gdbcore.h" +#include <sys/stat.h> +#include <unistd.h> +#include <vm/vm.h> +#include <vm/vm_param.h> + +#include <machine/vmparam.h> +#include <machine/pcb.h> +#include <machine/tss.h> +#include <machine/frame.h> + +static void kcore_files_info PARAMS ((struct target_ops *)); + +static void kcore_close PARAMS ((int)); + +static void get_kcore_registers PARAMS ((int)); + +static int kcore_xfer_kmem PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); + +static int xfer_umem PARAMS ((CORE_ADDR, char *, int, int)); + +static CORE_ADDR ksym_lookup PARAMS ((const char *)); + +static int read_pcb PARAMS ((int, CORE_ADDR)); + +static struct proc * curProc PARAMS ((void)); + +static int set_proc_context PARAMS ((CORE_ADDR paddr)); + +static void kcore_open PARAMS ((char *filename, int from_tty)); + +static void kcore_detach PARAMS ((char *args, int from_tty)); + +static void set_proc_cmd PARAMS ((char *arg, int from_tty)); + +static void set_cpu_cmd PARAMS ((char *arg, int from_tty)); + +static CORE_ADDR kvtophys PARAMS ((int, CORE_ADDR)); + +static int physrd PARAMS ((int, u_int, char*, int)); + +static int kvm_open PARAMS ((const char *efile, char *cfile, char *sfile, + int perm, char *errout)); + +static int kvm_close PARAMS ((int fd)); + +static int kvm_write PARAMS ((int core_kd, CORE_ADDR memaddr, + char *myaddr, int len)); + +static int kvm_read PARAMS ((int core_kd, CORE_ADDR memaddr, + char *myaddr, int len)); + +static int kvm_uread PARAMS ((int core_kd, struct proc *p, + CORE_ADDR memaddr, char *myaddr, + int len)); + +static int kernel_core_file_hook PARAMS ((int fd, CORE_ADDR addr, + char *buf, int len)); + +static struct kinfo_proc * kvm_getprocs PARAMS ((int cfd, int op, + CORE_ADDR proc, int *cnt)); + +extern struct target_ops kcore_ops; /* Forward decl */ + +/* Non-zero means we are debugging a kernel core file */ +int kernel_debugging = 0; +int kernel_writablecore = 0; + +static char *core_file; +static int core_kd = -1; +static struct proc *cur_proc; +static CORE_ADDR kernel_start; + +static int ncpus; +static int cpuid; +static CORE_ADDR prv_space; /* per-cpu private space */ +static int prv_space_size; +#define prv_start (prv_space + cpuid * prv_space_size) + +/* + * Read the "thing" at kernel address 'addr' into the space pointed to + * by point. The length of the "thing" is determined by the type of p. + * Result is non-zero if transfer fails. + */ +#define kvread(addr, p) \ + (target_read_memory ((CORE_ADDR)(addr), (char *)(p), sizeof(*(p)))) + + + +/* + * The following is FreeBSD-specific hackery to decode special frames + * and elide the assembly-language stub. This could be made faster by + * defining a frame_type field in the machine-dependent frame information, + * but we don't think that's too important right now. + */ +enum frametype { tf_normal, tf_trap, tf_interrupt, tf_syscall }; + +CORE_ADDR +fbsd_kern_frame_saved_pc (fr) +struct frame_info *fr; +{ + struct minimal_symbol *sym; + CORE_ADDR this_saved_pc; + enum frametype frametype; + + this_saved_pc = read_memory_integer (fr->frame + 4, 4); + sym = lookup_minimal_symbol_by_pc (this_saved_pc); + frametype = tf_normal; + if (sym != NULL) { + if (strcmp (SYMBOL_NAME(sym), "calltrap") == 0) + frametype = tf_trap; + else if (strncmp (SYMBOL_NAME(sym), "Xresume", 7) == 0) + frametype = tf_interrupt; + else if (strcmp (SYMBOL_NAME(sym), "Xsyscall") == 0) + frametype = tf_syscall; + } + + switch (frametype) { + case tf_normal: + return (this_saved_pc); + +#define oEIP offsetof(struct trapframe, tf_eip) + + case tf_trap: + return (read_memory_integer (fr->frame + 8 + oEIP, 4)); + + case tf_interrupt: + return (read_memory_integer (fr->frame + 16 + oEIP, 4)); + + case tf_syscall: + return (read_memory_integer (fr->frame + 8 + oEIP, 4)); +#undef oEIP + } +} + +static CORE_ADDR +ksym_lookup (name) +const char *name; +{ + struct minimal_symbol *sym; + + sym = lookup_minimal_symbol (name, NULL, NULL); + if (sym == NULL) + error ("kernel symbol `%s' not found.", name); + + return SYMBOL_VALUE_ADDRESS (sym); +} + +static struct proc * +curProc () +{ + struct proc *p; + CORE_ADDR addr = ksym_lookup ("gd_curproc") + prv_start; + + if (kvread (addr, &p)) + error ("cannot read proc pointer at %x\n", addr); + return p; +} + +/* + * Set the process context to that of the proc structure at + * system address paddr. + */ +static int +set_proc_context (paddr) + CORE_ADDR paddr; +{ + struct proc p; + + if (paddr < kernel_start) + return (1); + + cur_proc = (struct proc *)paddr; +#ifdef notyet + set_kernel_boundaries (cur_proc); +#endif + + /* Fetch all registers from core file */ + target_fetch_registers (-1); + + /* Now, set up the frame cache, and print the top of stack */ + flush_cached_frames (); + set_current_frame (create_new_frame (read_fp (), read_pc ())); + select_frame (get_current_frame (), 0); + return (0); +} + +/* Discard all vestiges of any previous core file + and mark data and stack spaces as empty. */ + +/* ARGSUSED */ +static void +kcore_close (quitting) + int quitting; +{ + inferior_pid = 0; /* Avoid confusion from thread stuff */ + + if (core_kd) + { + kvm_close (core_kd); + free (core_file); + core_file = NULL; + core_kd = -1; + } +} + +/* This routine opens and sets up the core file bfd */ + +static void +kcore_open (filename, from_tty) + char *filename; + int from_tty; +{ + const char *p; + struct cleanup *old_chain; + char buf[256], *cp; + int ontop; + CORE_ADDR addr; + struct pcb pcb; + + target_preopen (from_tty); + + unpush_target (&kcore_ops); + + if (!filename) + { + /*error (core_kd?*/ + error ( (core_kd >= 0)? + "No core file specified. (Use `detach' to stop debugging a core file.)" + : "No core file specified."); + } + + filename = tilde_expand (filename); + if (filename[0] != '/') + { + cp = concat (current_directory, "/", filename, NULL); + free (filename); + filename = cp; + } + + old_chain = make_cleanup (free, filename); + + /* + * gdb doesn't really do anything if the exec-file couldn't + * be opened (in that case exec_bfd is NULL). Usually that's + * no big deal, but kvm_open needs the exec-file's name, + * which results in dereferencing a NULL pointer, a real NO-NO ! + * So, check here if the open of the exec-file succeeded. + */ + if (exec_bfd == NULL) /* the open failed */ + error ("kgdb could not open the exec-file, please check the name you used !"); + + core_kd = kvm_open (exec_bfd->filename, filename, NULL, + kernel_writablecore? O_RDWR : O_RDONLY, "kgdb: "); + if (core_kd < 0) + perror_with_name (filename); + + /* Looks semi-reasonable. Toss the old core file and work on the new. */ + + discard_cleanups (old_chain); /* Don't free filename any more */ + core_file = filename; + ontop = !push_target (&kcore_ops); + + kernel_start = bfd_get_start_address (exec_bfd); /* XXX */ + + /* print out the panic string if there is one */ + if (kvread (ksym_lookup ("panicstr"), &addr) == 0 + && addr != 0 + && target_read_memory (addr, buf, sizeof (buf)) == 0) + { + for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++) + if (!isascii (*cp) || (!isprint (*cp) && !isspace (*cp))) + *cp = '?'; + *cp = '\0'; + if (buf[0] != '\0') + printf ("panicstr: %s\n", buf); + } + + /* Print all the panic messages if possible. */ + if (symfile_objfile != NULL) + { + printf ("panic messages:\n---\n"); + snprintf (buf, sizeof buf, + "/sbin/dmesg -N %s -M %s | \ + /usr/bin/awk '/^(panic:|Fatal trap) / { printing = 1 } \ + { if (printing) print $0 }'", + symfile_objfile->name, filename); + fflush(stdout); + system (buf); + printf ("---\n"); + } + + if (!ontop) + { + warning ("you won't be able to access this core file until you terminate\n\ +your %s; do ``info files''", target_longname); + return; + } + + /* we may need this later */ + cur_proc = (struct proc *)curProc (); + /* Now, set up the frame cache, and print the top of stack */ + flush_cached_frames (); + set_current_frame (create_new_frame (read_fp (), read_pc ())); + select_frame (get_current_frame (), 0); + print_stack_frame (selected_frame, selected_frame_level, 1); +} + +static void +kcore_detach (args, from_tty) + char *args; + int from_tty; +{ + if (args) + error ("Too many arguments"); + unpush_target (&kcore_ops); + reinit_frame_cache (); + if (from_tty) + printf_filtered ("No kernel core file now.\n"); +} + +/* Get the registers out of a core file. This is the machine- + independent part. Fetch_core_registers is the machine-dependent + part, typically implemented in the xm-file for each architecture. */ + +/* We just get all the registers, so we don't use regno. */ +/* ARGSUSED */ +static void +get_kcore_registers (regno) + int regno; +{ + struct user *uaddr; + + /* find the pcb for the current process */ + if (cur_proc == NULL || kvread (&cur_proc->p_addr, &uaddr)) + error ("cannot read u area ptr for proc at %#x", cur_proc); + if (read_pcb (core_kd, (CORE_ADDR)&uaddr->u_pcb) < 0) + error ("cannot read pcb at %#x", &uaddr->u_pcb); +} + +static void +kcore_files_info (t) + struct target_ops *t; +{ + printf ("\t`%s'\n", core_file); +} + +static int +kcore_xfer_kmem (memaddr, myaddr, len, write, target) + CORE_ADDR memaddr; + char *myaddr; + int len; + int write; + struct target_ops *target; +{ + int ns; + int nu; + + if (memaddr >= (CORE_ADDR)VM_MAXUSER_ADDRESS) + nu = 0; + else + { + nu = xfer_umem (memaddr, myaddr, len, write); + if (nu <= 0) + return (0); + if (nu == len) + return (nu); + memaddr += nu; + if (memaddr != (CORE_ADDR)VM_MAXUSER_ADDRESS) + return (nu); + myaddr += nu; + len -= nu; + } + + ns = (write ? kvm_write : kvm_read) (core_kd, memaddr, myaddr, len); + if (ns < 0) + ns = 0; + + return (nu + ns); +} + +static int +xfer_umem (memaddr, myaddr, len, write) + CORE_ADDR memaddr; + char *myaddr; + int len; + int write; /* ignored */ +{ + int n; + struct proc proc; + + if (cur_proc == NULL || kvread (cur_proc, &proc)) + error ("cannot read proc at %#x", cur_proc); + n = kvm_uread (core_kd, &proc, memaddr, myaddr, len) ; + + if (n < 0) + return 0; + return n; +} + +#define KERNOFF ((unsigned)KERNBASE) +#define INKERNEL(x) ((x) >= KERNOFF) + +static CORE_ADDR sbr; +static CORE_ADDR curpcb; +static int found_pcb; +static int devmem; +static int kfd; +static struct pcb pcb; + +static void +set_proc_cmd (arg, from_tty) + char *arg; + int from_tty; +{ + CORE_ADDR paddr; + struct kinfo_proc *kp; + int cnt = 0; + + if (!arg) + error_no_arg ("proc address for new current process"); + if (!kernel_debugging) + error ("not debugging kernel"); + + paddr = (CORE_ADDR)parse_and_eval_address (arg); + /* assume it's a proc pointer if it's in the kernel */ + if (paddr >= kernel_start) { + if (set_proc_context(paddr)) + error("invalid proc address"); + } else { + kp = kvm_getprocs(core_kd, KERN_PROC_PID, paddr, &cnt); + if (!cnt) + error("invalid pid"); + if (set_proc_context((CORE_ADDR)kp->kp_eproc.e_paddr)) + error("invalid proc address"); + } +} + +static void +set_cpu_cmd (arg, from_tty) + char *arg; + int from_tty; +{ + CORE_ADDR paddr; + struct kinfo_proc *kp; + int cpu, cfd; + + if (!arg) + error_no_arg ("cpu number"); + if (!kernel_debugging) + error ("not debugging kernel"); + if (!ncpus) + error ("not debugging SMP kernel"); + + cpu = (int)parse_and_eval_address (arg); + if (cpu < 0 || cpu > ncpus) + error ("cpu number out of range"); + cpuid = cpu; + + cfd = core_kd; + curpcb = kvtophys(cfd, ksym_lookup ("gd_curpcb") + prv_start); + physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb); + + if (!devmem) + paddr = ksym_lookup ("dumppcb") - KERNOFF; + else + paddr = kvtophys (cfd, curpcb); + read_pcb (cfd, paddr); + printf ("initial pcb at %lx\n", (unsigned long)paddr); + + if ((cur_proc = curProc())) + target_fetch_registers (-1); + + /* Now, set up the frame cache, and print the top of stack */ + flush_cached_frames (); + set_current_frame (create_new_frame (read_fp (), read_pc ())); + select_frame (get_current_frame (), 0); + print_stack_frame (selected_frame, selected_frame_level, 1); +} + +/* substitutes for the stuff in libkvm which doesn't work */ +/* most of this was taken from the old kgdb */ + +/* we don't need all this stuff, but the call should look the same */ + +static int +kvm_open (efile, cfile, sfile, perm, errout) + const char *efile; + char *cfile; + char *sfile; /* makes this kvm_open more compatible to the one in libkvm */ + int perm; + char *errout; /* makes this kvm_open more compatible to the one in libkvm */ +{ + struct stat stb; + int cfd; + CORE_ADDR paddr; + + if ((cfd = open (cfile, perm, 0)) < 0) + return (cfd); + + fstat (cfd, &stb); + if ((stb.st_mode & S_IFMT) == S_IFCHR + && stb.st_rdev == makedev (2, 0)) + { + devmem = 1; + kfd = open ("/dev/kmem", perm, 0); + } + + if (lookup_minimal_symbol("mp_ncpus", NULL, NULL)) { + physrd(cfd, ksym_lookup("mp_ncpus") - KERNOFF, + (char*)&ncpus, sizeof(ncpus)); + prv_space = ksym_lookup("SMP_prvspace"); + prv_space_size = (int)ksym_lookup("gd_idlestack_top"); + printf ("SMP %d cpus\n", ncpus); + } else { + ncpus = 0; + prv_space = 0; + prv_space_size = 0; + } + cpuid = 0; + + physrd (cfd, ksym_lookup ("IdlePTD") - KERNOFF, (char*)&sbr, sizeof sbr); + printf ("IdlePTD %lu\n", (unsigned long)sbr); + curpcb = kvtophys(cfd, ksym_lookup ("gd_curpcb") + prv_start); + physrd (cfd, curpcb, (char*)&curpcb, sizeof curpcb); + + found_pcb = 1; /* for vtophys */ + if (!devmem) + paddr = ksym_lookup ("dumppcb") - KERNOFF; + else + paddr = kvtophys (cfd, curpcb); + read_pcb (cfd, paddr); + printf ("initial pcb at %lx\n", (unsigned long)paddr); + + return (cfd); +} + +static int +kvm_close (fd) + int fd; +{ + return (close (fd)); +} + +static int +kvm_write (core_kd, memaddr, myaddr, len) + int core_kd; + CORE_ADDR memaddr; + char *myaddr; +{ + int cc; + + if (devmem) + { + if (kfd > 0) + { + /* + * Just like kvm_read, only we write. + */ + errno = 0; + if (lseek (kfd, (off_t)memaddr, 0) < 0 + && errno != 0) + { + error ("kvm_write:invalid address (%x)", memaddr); + return (0); + } + cc = write (kfd, myaddr, len); + if (cc < 0) + { + error ("kvm_write:write failed"); + return (0); + } + else if (cc < len) + error ("kvm_write:short write"); + return (cc); + } + else + return (0); + } + else + { + printf ("kvm_write not implemented for dead kernels\n"); + return (0); + } + /* NOTREACHED */ +} + +static int +kvm_read (core_kd, memaddr, myaddr, len) + int core_kd; + CORE_ADDR memaddr; + char *myaddr; +{ + return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); +} + +static int +kvm_uread (core_kd, p, memaddr, myaddr, len) + int core_kd; + register struct proc *p; + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + register char *cp; + char procfile[MAXPATHLEN]; + ssize_t amount; + int fd; + + if (devmem) + { + sprintf (procfile, "/proc/%d/mem", p->p_pid); + fd = open (procfile, O_RDONLY, 0); + if (fd < 0) + { + error ("cannot open %s", procfile); + close (fd); + return (0); + } + + cp = myaddr; + while (len > 0) + { + errno = 0; + if (lseek (fd, (off_t)memaddr, 0) == -1 && errno != 0) + { + error ("invalid address (%x) in %s", memaddr, procfile); + break; + } + amount = read (fd, cp, len); + if (amount < 0) + { + error ("error reading %s", procfile); + break; + } + if (amount == 0) + { + error ("EOF reading %s", procfile); + break; + } + cp += amount; + memaddr += amount; + len -= amount; + } + + close (fd); + return ((ssize_t) (cp - myaddr)); + } + else + return (kernel_core_file_hook (core_kd, memaddr, myaddr, len)); +} + +static struct kinfo_proc kp; + +/* + * try to do what kvm_proclist in libkvm would do + */ +static int +kvm_proclist (cfd, pid, p, cnt) +int cfd, pid, *cnt; +struct proc *p; +{ + struct proc lp; + + for (; p != NULL; p = lp.p_list.le_next) { + if (!kvm_read(cfd, (CORE_ADDR)p, (char *)&lp, sizeof (lp))) + return (0); + if (lp.p_pid != pid) + continue; + kp.kp_eproc.e_paddr = p; + *cnt = 1; + return (1); + } + *cnt = 0; + return (0); +} + +/* + * try to do what kvm_deadprocs in libkvm would do + */ +static struct kinfo_proc * +kvm_deadprocs (cfd, pid, cnt) +int cfd, pid, *cnt; +{ + CORE_ADDR allproc, zombproc; + struct proc *p; + + allproc = ksym_lookup("allproc"); + if (kvm_read(cfd, allproc, (char *)&p, sizeof (p)) == 0) + return (NULL); + kvm_proclist (cfd, pid, p, cnt); + if (!*cnt) { + zombproc = ksym_lookup("zombproc"); + if (kvm_read(cfd, zombproc, (char *)&p, sizeof (p)) == 0) + return (NULL); + kvm_proclist (cfd, pid, p, cnt); + } + return (&kp); +} + +/* + * try to do what kvm_getprocs in libkvm would do + */ +static struct kinfo_proc * +kvm_getprocs (cfd, op, proc, cnt) +int cfd, op, *cnt; +CORE_ADDR proc; +{ + int mib[4], size; + + *cnt = 0; + /* assume it's a pid */ + if (devmem) { /* "live" kernel, use sysctl */ + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = (int)proc; + size = sizeof (kp); + if (sysctl (mib, 4, &kp, &size, NULL, 0) < 0) { + perror("sysctl"); + *cnt = 0; + return (NULL); + } + if (!size) + *cnt = 0; + else + *cnt = 1; + return (&kp); + } else + return (kvm_deadprocs (cfd, (int)proc, cnt)); +} + +static int +physrd (cfd, addr, dat, len) + int cfd; + u_int addr; + char *dat; + int len; +{ + if (lseek (cfd, (off_t)addr, L_SET) == -1) + return (-1); + return (read (cfd, dat, len)); +} + +static CORE_ADDR +kvtophys (fd, addr) + int fd; + CORE_ADDR addr; +{ + CORE_ADDR v; + unsigned int pte; + static CORE_ADDR PTD = -1; + CORE_ADDR current_ptd; + + /* + * We may no longer have a linear system page table... + * + * Here's the scoop. IdlePTD contains the physical address + * of a page table directory that always maps the kernel. + * IdlePTD is in memory that is mapped 1-to-1, so we can + * find it easily given its 'virtual' address from ksym_lookup(). + * For hysterical reasons, the value of IdlePTD is stored in sbr. + * + * To look up a kernel address, we first convert it to a 1st-level + * address and look it up in IdlePTD. This gives us the physical + * address of a page table page; we extract the 2nd-level part of + * VA and read the 2nd-level pte. Finally, we add the offset part + * of the VA into the physical address from the pte and return it. + * + * User addresses are a little more complicated. If we don't have + * a current PCB from read_pcb(), we use PTD, which is the (fixed) + * virtual address of the current ptd. Since it's NOT in 1-to-1 + * kernel space, we must look it up using IdlePTD. If we do have + * a pcb, we get the ptd from pcb_ptd. + */ + + if (INKERNEL (addr)) + current_ptd = sbr; + else if (found_pcb == 0) + { + if (PTD == -1) + PTD = kvtophys (fd, ksym_lookup ("PTD")); + current_ptd = PTD; + } + else + current_ptd = pcb.pcb_cr3; + + /* + * Read the first-level page table (ptd). + */ + v = current_ptd + ( (unsigned)addr >> PDRSHIFT) * sizeof pte; + if (physrd (fd, v, (char *)&pte, sizeof pte) < 0 || (pte&PG_V) == 0) + return (~0); + + if (pte & PG_PS) + { + /* + * No second-level page table; ptd describes one 4MB page. + * (We assume that the kernel wouldn't set PG_PS without enabling + * it cr0, and that the kernel doesn't support 36-bit physical + * addresses). + */ +#define PAGE4M_MASK (NBPDR - 1) +#define PG_FRAME4M (~PAGE4M_MASK) + addr = (pte & PG_FRAME4M) + (addr & PAGE4M_MASK); + } + else + { + /* + * Read the second-level page table. + */ + v = (pte&PG_FRAME) + ((addr >> PAGE_SHIFT)&(NPTEPG-1)) * sizeof pte; + if (physrd (fd, v, (char *) &pte, sizeof (pte)) < 0 || (pte&PG_V) == 0) + return (~0); + + addr = (pte & PG_FRAME) + (addr & PAGE_MASK); + } +#if 0 + printf ("vtophys (%x) -> %x\n", oldaddr, addr); +#endif + return (addr); +} + +static int +read_pcb (fd, uaddr) + int fd; + CORE_ADDR uaddr; +{ + int i; + int noreg; + CORE_ADDR nuaddr = uaddr; + + /* need this for the `proc' command to work */ + if (INKERNEL(uaddr)) + nuaddr = kvtophys(fd, uaddr); + + if (physrd (fd, nuaddr, (char *)&pcb, sizeof pcb) < 0) + { + error ("cannot read pcb at %x\n", uaddr); + return (-1); + } + + /* + * get the register values out of the sys pcb and + * store them where `read_register' will find them. + */ + /* + * XXX many registers aren't available. + * XXX for the non-core case, the registers are stale - they are for + * the last context switch to the debugger. + * XXX gcc's register numbers aren't all #defined in tm-i386.h. + */ + noreg = 0; + for (i = 0; i < 3; ++i) /* eax,ecx,edx */ + supply_register (i, (char *)&noreg); + supply_register (3, (char *)&pcb.pcb_ebx); + supply_register (SP_REGNUM, (char *)&pcb.pcb_esp); + supply_register (FP_REGNUM, (char *)&pcb.pcb_ebp); + supply_register (6, (char *)&pcb.pcb_esi); + supply_register (7, (char *)&pcb.pcb_edi); + supply_register (PC_REGNUM, (char *)&pcb.pcb_eip); + for (i = 9; i < 14; ++i) /* eflags, cs, ss, ds, es, fs */ + supply_register (i, (char *)&noreg); + supply_register (15, (char *)&pcb.pcb_gs); + + /* XXX 80387 registers? */ +} + +/* + * read len bytes from kernel virtual address 'addr' into local + * buffer 'buf'. Return numbert of bytes if read ok, 0 otherwise. On read + * errors, portion of buffer not read is zeroed. + */ + +static int +kernel_core_file_hook (fd, addr, buf, len) + int fd; + CORE_ADDR addr; + char *buf; + int len; +{ + int i; + CORE_ADDR paddr; + register char *cp; + int cc; + + cp = buf; + + while (len > 0) + { + paddr = kvtophys (fd, addr); + if (paddr == ~0) + { + memset (buf, '\000', len); + break; + } + /* we can't read across a page boundary */ + i = min (len, PAGE_SIZE - (addr & PAGE_MASK)); + if ( (cc = physrd (fd, paddr, cp, i)) <= 0) + { + memset (cp, '\000', len); + return (cp - buf); + } + cp += cc; + addr += cc; + len -= cc; + } + return (cp - buf); +} + +static struct target_ops kcore_ops; + +void +_initialize_kcorelow() +{ + kcore_ops.to_shortname = "kcore"; + kcore_ops.to_longname = "Kernel core dump file"; + kcore_ops.to_doc = + "Use a core file as a target. Specify the filename of the core file."; + kcore_ops.to_open = kcore_open; + kcore_ops.to_close = kcore_close; + kcore_ops.to_attach = find_default_attach; + kcore_ops.to_detach = kcore_detach; + kcore_ops.to_fetch_registers = get_kcore_registers; + kcore_ops.to_xfer_memory = kcore_xfer_kmem; + kcore_ops.to_files_info = kcore_files_info; + kcore_ops.to_create_inferior = find_default_create_inferior; + kcore_ops.to_stratum = kcore_stratum; + kcore_ops.to_has_memory = 1; + kcore_ops.to_has_stack = 1; + kcore_ops.to_has_registers = 1; + kcore_ops.to_magic = OPS_MAGIC; + + add_target (&kcore_ops); + add_com ("proc", class_obscure, set_proc_cmd, "Set current process context"); + add_com ("cpu", class_obscure, set_cpu_cmd, "Set current cpu"); +} diff --git a/gnu/usr.bin/binutils/gdb/i386/nm.h b/gnu/usr.bin/binutils/gdb/i386/nm.h new file mode 100644 index 000000000000..786abc94b648 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/i386/nm.h @@ -0,0 +1,135 @@ +/* Native-dependent definitions for Intel 386 running BSD Unix, for GDB. + Copyright 1986, 1987, 1989, 1992, 1996 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. */ + +#ifndef NM_FREEBSD_H +#define NM_FREEBSD_H + +#define ATTACH_DETACH + +/* Be shared lib aware */ +#include "solib.h" +#ifdef FREEBSD_ELF +#define SVR4_SHARED_LIBS +#endif + +/* This is the amount to subtract from u.u_ar0 + to get the offset in the core file of the register values. */ + +#include <machine/vmparam.h> +#define KERNEL_U_ADDR USRSTACK + +#define REGISTER_U_ADDR(addr, blockend, regno) \ + (addr) = i386_register_u_addr ((blockend),(regno)); + +/* We define our own fetch/store methods */ +#define FETCH_INFERIOR_REGISTERS + +extern int +i386_register_u_addr PARAMS ((int, int)); + +#define PTRACE_ARG3_TYPE char* + +#ifndef FREEBSD_ELF + +/* make structure definitions match up with those expected in solib.c */ +#define link_object sod +#define lo_name sod_name +#define lo_library sod_library +#define lo_unused sod_reserved +#define lo_major sod_major +#define lo_minor sod_minor +#define lo_next sod_next + +#define link_map so_map +#define lm_addr som_addr +#define lm_name som_path +#define lm_next som_next +#define lm_lop som_sod +#define lm_lob som_sodbase +#define lm_rwt som_write +#define lm_ld som_dynamic +#define lm_lpd som_spd + +#define link_dynamic_2 section_dispatch_table +#define ld_loaded sdt_loaded +#define ld_need sdt_sods +#define ld_rules sdt_filler1 +#define ld_got sdt_got +#define ld_plt sdt_plt +#define ld_rel sdt_rel +#define ld_hash sdt_hash +#define ld_stab sdt_nzlist +#define ld_stab_hash sdt_filler2 +#define ld_buckets sdt_buckets +#define ld_symbols sdt_strings +#define ld_symb_size sdt_str_sz +#define ld_text sdt_text_sz +#define ld_plt_sz sdt_plt_sz + +#define rtc_symb rt_symbol +#define rtc_sp rt_sp +#define rtc_next rt_next + +#define ld_debug so_debug +#define ldd_version dd_version +#define ldd_in_debugger dd_in_debugger +#define ldd_sym_loaded dd_sym_loaded +#define ldd_bp_addr dd_bpt_addr +#define ldd_bp_inst dd_bpt_shadow +#define ldd_cp dd_cc + +#define link_dynamic _dynamic +#define ld_version d_version +#define ldd d_debug +#define ld_un d_un +#define ld_2 d_sdt + +#endif + +/* Return sizeof user struct to callers in less machine dependent routines */ + +#define KERNEL_U_SIZE kernel_u_size() +extern int kernel_u_size PARAMS ((void)); + +#define ADDITIONAL_OPTIONS \ + {"kernel", no_argument, &kernel_debugging, 1}, \ + {"k", no_argument, &kernel_debugging, 1}, \ + {"wcore", no_argument, &kernel_writablecore, 1}, \ + {"w", no_argument, &kernel_writablecore, 1}, + +#define ADDITIONAL_OPTION_HELP \ + "\ + --kernel Enable kernel debugging.\n\ + --wcore Make core file writable (only works for /dev/mem).\n\ + This option only works while debugging a kernel !!\n\ +" + +extern int kernel_debugging; +extern int kernel_writablecore; + +#define DEFAULT_PROMPT kernel_debugging?"(kgdb) ":"(gdb) " + +/* misuse START_PROGRESS to test whether we're running as kgdb */ +/* START_PROGRESS is called at the top of main */ +#undef START_PROGRESS +#define START_PROGRESS(STR,N) \ + if (!strcmp(STR, "kgdb")) \ + kernel_debugging = 1; + +#endif /* NM_FREEBSD_H */ diff --git a/gnu/usr.bin/binutils/gdb/i386/tm.h b/gnu/usr.bin/binutils/gdb/i386/tm.h new file mode 100644 index 000000000000..2afa02b9a642 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/i386/tm.h @@ -0,0 +1,58 @@ +/* Target macro definitions for i386 running FreeBSD + Copyright (C) 1997 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef TM_FBSD_H +#define TM_FBSD_H 1 + +#include "i386/tm-i386bsd.h" + +#undef NUM_REGS +#define NUM_REGS 16 + +extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *)); + +#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv) + +extern void i386_float_info PARAMS ((void)); + +#define FLOAT_INFO i386_float_info () + +#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) STREQ (name, "_DYNAMIC") + +/* Saved Pc. Get it from sigcontext if within sigtramp. */ + +extern CORE_ADDR fbsd_kern_frame_saved_pc (struct frame_info *); +#undef FRAME_SAVED_PC +#define FRAME_SAVED_PC(FRAME) \ + (kernel_debugging ? fbsd_kern_frame_saved_pc(FRAME) : \ + (((FRAME)->signal_handler_caller \ + ? sigtramp_saved_pc (FRAME) \ + : read_memory_integer ((FRAME)->frame + 4, 4)) \ + )) + +/* On FreeBSD, sigtramp has size 0x18 and is immediately below the + ps_strings struct which has size 0x10 and is at the top of the + user stack. */ + +#undef SIGTRAMP_START +#undef SIGTRAMP_END +#define SIGTRAMP_START(pc) 0xcfbfdfd8 +#define SIGTRAMP_END(pc) 0xcfbfdff0 + +#endif /* ifndef TM_FBSD_H */ diff --git a/gnu/usr.bin/binutils/gdb/i386/version.c b/gnu/usr.bin/binutils/gdb/i386/version.c new file mode 100644 index 000000000000..45b9acd41413 --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/i386/version.c @@ -0,0 +1,3 @@ +char *version = "4.18"; +char *host_name = "i386-unknown-freebsd"; +char *target_name = "i386-unknown-freebsd"; diff --git a/gnu/usr.bin/binutils/gdbreplay/Makefile b/gnu/usr.bin/binutils/gdbreplay/Makefile new file mode 100644 index 000000000000..a0809d82e8cc --- /dev/null +++ b/gnu/usr.bin/binutils/gdbreplay/Makefile @@ -0,0 +1,20 @@ +# $Id: Makefile,v 1.3 1998/05/01 14:48:04 bde Exp $ + +.include "../Makefile.inc0" + +GDBDIR= ${.CURDIR}/../../../../contrib/gdb +.PATH: ${GDBDIR}/gdb/gdbserver +.PATH: ${GDBDIR}/gdb + +PROG= gdbreplay +NOMAN= yes + +SRCS= gdbreplay.c + +CFLAGS+= -I${.CURDIR}/../gdb/${MACHINE_ARCH} +CFLAGS+= -I${GDBDIR}/gdb +CFLAGS+= -I${GDBDIR}/gdb/config +CFLAGS+= -I${GDBDIR}/gdb/gdbserver +CFLAGS+= -DNO_MMALLOC + +.include <bsd.prog.mk> diff --git a/gnu/usr.bin/binutils/gdbserver/Makefile b/gnu/usr.bin/binutils/gdbserver/Makefile new file mode 100644 index 000000000000..c20ca0511733 --- /dev/null +++ b/gnu/usr.bin/binutils/gdbserver/Makefile @@ -0,0 +1,20 @@ +# $Id: Makefile,v 1.3 1998/05/01 14:48:06 bde Exp $ + +.include "../Makefile.inc0" + +GDBDIR= ${.CURDIR}/../../../../contrib/gdb +.PATH: ${GDBDIR}/gdb/gdbserver +.PATH: ${GDBDIR}/gdb + +PROG= gdbserver + +SRCS= remote-utils.c utils.c server.c +SRCS+= low-fbsd.c + +CFLAGS+= -I${.CURDIR}/../gdb/${MACHINE_ARCH} +CFLAGS+= -I${GDBDIR}/gdb +CFLAGS+= -I${GDBDIR}/gdb/config +CFLAGS+= -I${GDBDIR}/gdb/gdbserver +CFLAGS+= -DNO_MMALLOC + +.include <bsd.prog.mk> diff --git a/gnu/usr.bin/binutils/gdbserver/low-fbsd.c b/gnu/usr.bin/binutils/gdbserver/low-fbsd.c new file mode 100644 index 000000000000..090628e7da00 --- /dev/null +++ b/gnu/usr.bin/binutils/gdbserver/low-fbsd.c @@ -0,0 +1,339 @@ +/* Low level interface to ptrace, for the remote server for GDB. + Copyright (C) 1995 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 <sys/wait.h> +#include "frame.h" +#include "inferior.h" + +#include <stdio.h> +#include <sys/param.h> +#include <dirent.h> +#include <sys/user.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <sgtty.h> +#include <fcntl.h> +#include <string.h> + +/***************Begin MY defs*********************/ +int quit_flag = 0; +char registers[REGISTER_BYTES]; + +/* Index within `registers' of the first byte of the space for + register N. */ + + +char buf2[MAX_REGISTER_RAW_SIZE]; +/***************End MY defs*********************/ + +#include <sys/ptrace.h> +#include <machine/reg.h> + +extern char **environ; +extern int inferior_pid; +void quit (), perror_with_name (); +int query (); + +/* Start an inferior process and returns its pid. + ALLARGS is a vector of program-name and args. + ENV is the environment vector to pass. */ + +int +create_inferior (program, allargs) + char *program; + char **allargs; +{ + int pid; + + pid = fork (); + if (pid < 0) + perror_with_name ("fork"); + + if (pid == 0) + { + ptrace (PT_TRACE_ME, 0, 0, 0); + + execv (program, allargs); + + fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror(errno)); + fflush (stderr); + _exit (0177); + } + + return pid; +} + +/* Kill the inferior process. Make us have no inferior. */ + +void +kill_inferior () +{ + if (inferior_pid == 0) + return; + ptrace (PT_KILL, inferior_pid, 0, 0); + wait (0); + /*************inferior_died ();****VK**************/ +} + +/* Return nonzero if the given thread is still alive. */ +int +mythread_alive (pid) + int pid; +{ + return 1; +} + +/* Wait for process, returns status */ + +unsigned char +mywait (status) + char *status; +{ + int pid; + int w; + + pid = wait (&w); + if (pid != inferior_pid) + perror_with_name ("wait"); + + if (WIFEXITED (w)) + { + fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w)); + *status = 'W'; + return ((unsigned char) WEXITSTATUS (w)); + } + else if (!WIFSTOPPED (w)) + { + fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w)); + *status = 'X'; + return ((unsigned char) WTERMSIG (w)); + } + + fetch_inferior_registers (0); + + *status = 'T'; + return ((unsigned char) WSTOPSIG (w)); +} + +/* Resume execution of the inferior process. + If STEP is nonzero, single-step it. + If SIGNAL is nonzero, give it that signal. */ + +void +myresume (step, signal) + int step; + int signal; +{ + errno = 0; + ptrace (step ? PT_STEP : PT_CONTINUE, inferior_pid, + (PTRACE_ARG3_TYPE) 1, signal); + if (errno) + perror_with_name ("ptrace"); +} + +#if defined(__i386__) + +/* this table must line up with REGISTER_NAMES in tm-i386v.h */ +/* symbols like 'tEAX' come from <machine/reg.h> */ +static int tregmap[] = +{ + tEAX, tECX, tEDX, tEBX, + tESP, tEBP, tESI, tEDI, + tEIP, tEFLAGS, tCS, tSS, + tDS, tES, tFS, tGS, +}; + +static struct save87 pcb_savefpu; + +void +fetch_inferior_registers (regno) + int regno; +{ + struct reg inferior_registers; /* ptrace order, not gcc/gdb order */ + int r; + + ptrace (PT_GETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); + + for (r = 0; r < NUM_REGS; r++) + memcpy (®isters[REGISTER_BYTE (r)], ((int *)&inferior_registers) + tregmap[r], 4); +} + +void +store_inferior_registers (regno) + int regno; +{ + struct reg inferior_registers; /* ptrace order, not gcc/gdb order */ + int r; + + ptrace (PT_GETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); + + for (r = 0; r < NUM_REGS; r++) + memcpy (((int *)&inferior_registers) + tregmap[r], ®isters[REGISTER_BYTE (r)], 4); + + ptrace (PT_SETREGS, inferior_pid, + (PTRACE_ARG3_TYPE) &inferior_registers, 0); +} + +#elif defined(__alpha__) + +void +fetch_inferior_registers (regno) + int regno; +{ + struct reg regs; /* ptrace order, not gcc/gdb order */ + struct fpreg fpregs; + int r; + + ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) ®s, 0); + ptrace (PT_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0); + + for (r = 0; r < 31; r++) + memcpy (®isters[REGISTER_BYTE (r)], + ®s.r_regs[r], sizeof(u_int64_t)); + for (r = 0; r < 32; r++) + memcpy (®isters[REGISTER_BYTE (r + FP0_REGNUM)], + &fpregs.fpr_regs[r], sizeof(u_int64_t)); + memcpy (®isters[REGISTER_BYTE (PC_REGNUM)], + ®s.r_regs[31], sizeof(u_int64_t)); + + memset (®isters[REGISTER_BYTE (ZERO_REGNUM)], 0, sizeof(u_int64_t)); + memset (®isters[REGISTER_BYTE (FP_REGNUM)], 0, sizeof(u_int64_t)); +} + +void +store_inferior_registers (regno) + int regno; +{ + struct reg regs; /* ptrace order, not gcc/gdb order */ + struct fpreg fpregs; + int r; + + for (r = 0; r < 31; r++) + memcpy (®s.r_regs[r], + ®isters[REGISTER_BYTE (r)], sizeof(u_int64_t)); + for (r = 0; r < 32; r++) + memcpy (&fpregs.fpr_regs[r], + ®isters[REGISTER_BYTE (r + FP0_REGNUM)], sizeof(u_int64_t)); + memcpy (®s.r_regs[31], + ®isters[REGISTER_BYTE (PC_REGNUM)], sizeof(u_int64_t)); + + ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) ®s, 0); + ptrace (PT_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fpregs, 0); +} + +#endif + + +/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory + in the NEW_SUN_PTRACE case. + It ought to be straightforward. But it appears that writing did + not write the data that I specified. I cannot understand where + it got the data that it actually did write. */ + +/* Copy LEN bytes from inferior's memory starting at MEMADDR + to debugger memory starting at MYADDR. */ + +read_inferior_memory (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + register int i; + /* Round starting address down to longword boundary. */ + register CORE_ADDR addr = memaddr & -sizeof (int); + /* Round ending address up; get number of longwords that makes. */ + register int count + = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); + /* Allocate buffer of that many longwords. */ + register int *buffer = (int *) alloca (count * sizeof (int)); + + /* Read all the longwords */ + for (i = 0; i < count; i++, addr += sizeof (int)) + { + buffer[i] = ptrace (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0); + } + + /* Copy appropriate bytes out of the buffer. */ + memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); +} + +/* Copy LEN bytes of data from debugger memory at MYADDR + to inferior's memory at MEMADDR. + On failure (cannot write the inferior) + returns the value of errno. */ + +int +write_inferior_memory (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + register int i; + /* Round starting address down to longword boundary. */ + register CORE_ADDR addr = memaddr & -sizeof (int); + /* Round ending address up; get number of longwords that makes. */ + register int count + = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); + /* Allocate buffer of that many longwords. */ + register int *buffer = (int *) alloca (count * sizeof (int)); + extern int errno; + + /* Fill start and end extra bytes of buffer with existing memory data. */ + + buffer[0] = ptrace (PT_READ_I, inferior_pid, + (PTRACE_ARG3_TYPE) addr, 0); + + if (count > 1) + { + buffer[count - 1] + = ptrace (PT_READ_I, inferior_pid, + (PTRACE_ARG3_TYPE) addr + (count - 1) * sizeof (int), 0); + } + + /* Copy data to be written over corresponding part of buffer */ + + memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); + + /* Write the entire buffer. */ + + for (i = 0; i < count; i++, addr += sizeof (int)) + { + errno = 0; + ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]); + if (errno) + return errno; + } + + return 0; +} + +void +initialize () +{ + inferior_pid = 0; +} + +int +have_inferior_p () +{ + return inferior_pid != 0; +} |
