diff options
author | edwin <edwin@FreeBSD.org> | 2003-09-27 15:38:23 +0800 |
---|---|---|
committer | edwin <edwin@FreeBSD.org> | 2003-09-27 15:38:23 +0800 |
commit | e3425a233f65462922bec75d8e11dc0c89d4a09f (patch) | |
tree | 2ace3703872cb3998f7ae290ba16bf8463011f7f /devel | |
parent | 14fb75cb258f29133887fd28e1892a4ab11ad154 (diff) | |
download | freebsd-ports-gnome-e3425a233f65462922bec75d8e11dc0c89d4a09f.tar.gz freebsd-ports-gnome-e3425a233f65462922bec75d8e11dc0c89d4a09f.tar.zst freebsd-ports-gnome-e3425a233f65462922bec75d8e11dc0c89d4a09f.zip |
new port - ACT modified gdb53, a gdb that understands the Ada programming language
Ada programming knowledgeable version of gdb53
PR: ports/56371
Submitted by: John R. Shannon <john@johnrshannon.com>
Diffstat (limited to 'devel')
25 files changed, 2132 insertions, 0 deletions
diff --git a/devel/Makefile b/devel/Makefile index 94aa1d24eb52..d19fbd915d1c 100644 --- a/devel/Makefile +++ b/devel/Makefile @@ -216,6 +216,7 @@ SUBDIR += gcvs SUBDIR += gdb52 SUBDIR += gdb53 + SUBDIR += gdb53-act SUBDIR += gdbmods SUBDIR += gengameng SUBDIR += gengetopt diff --git a/devel/gdb53-act/Makefile b/devel/gdb53-act/Makefile new file mode 100644 index 000000000000..e7f3ce745129 --- /dev/null +++ b/devel/gdb53-act/Makefile @@ -0,0 +1,71 @@ +# Ports collection makefile for: GDB 5.3-act +# Date created: 8 August 2003 +# Whom: John R. Shannon <john@johnrshannon.com> +# +# $FreeBSD$ + +PORTNAME= gdb +PORTVERSION= 5.3-act +CATEGORIES= devel + +MAINTAINER= john@johnrshannon.com +COMMENT= GDB 5.3 modified by ACT for Ada programming language + +USE_GMAKE= yes +GNU_CONFIGURE= yes +CONFIGURE_ARGS= --program-suffix=ada +CONFIGURE_ARGS+= --disable-nls + +SNAPDATE= 2003-09-03 +CVS_DATE= ${SNAPDATE} 12:44:04 GMT +.if defined(CVS_DATE) +NO_CHECKSUM= yes +DIST_SUBDIR= ${PKGNAME} +CVS_CMD?= cvs -z3 -qR +CVSROOT= :pserver:anoncvs@libre.act-europe.fr:/anoncvs +STAMPFILE= ${DISTDIR}/${DIST_SUBDIR}/.timestamp +do-fetch: + @if [ ! -e ${WRKDIR}/.extract_done ] ; then \ + if [ ! -e ${STAMPFILE} ] ; then \ + ${MKDIR} ${DISTDIR}/${DIST_SUBDIR} && \ + cd ${DISTDIR}/${DIST_SUBDIR} ; \ + unset CVS_RSH CVS_SERVER || ${TRUE} ; \ + ${ECHO_MSG} ">> Attempting to CVS checkout from ${CVSROOT}." ;\ + if ${CVS_CMD} -d ${CVSROOT} co -P gdb-5.3 ; \ + then \ + ( ${ECHO} -n "${CVS_DATE}" > ${STAMPFILE} ) ; \ + exit ; \ + fi ; \ + ${ECHO_MSG} ">> Couldn't CVS checkout ${PKGNAME}." ; \ + ${ECHO_MSG} ">> Please try again later."; \ + exit 1; \ + else \ + if [ "X${CVS_DATE}" != "X$$(${CAT} ${STAMPFILE})" ]; then \ + cd ${DISTDIR}/${DIST_SUBDIR} ; \ + unset CVS_RSH CVS_SERVER || ${TRUE} ; \ + ${ECHO_MSG} ">> Attempting to CVS update from ${CVSROOT}." ;\ + if ${CVS_CMD} -d ${CVSROOT} up -Pd gdb-5.3 ; \ + then \ + ( ${ECHO} -n "${CVS_DATE}" > ${STAMPFILE} ) ; \ + exit ; \ + fi ; \ + ${ECHO_MSG} ">> Couldn't CVS checkout ${PKGNAME}." ; \ + ${ECHO_MSG} ">> Please try again later."; \ + exit 1; \ + fi; \ + fi; \ + fi; + + +do-extract: + ${MKDIR} ${WRKSRC} + cd ${DISTDIR}/${DIST_SUBDIR}/gdb-5.3 ; pax -pe -rwt . ${WRKSRC} +.endif # CVS_DATE + +pre-configure: + cd ${WRKSRC} ; ${RM} -rf dejagnu expect sim tcl texinfo + +do-install: + ${INSTALL_PROGRAM} ${WRKSRC}/gdb/gdb ${PREFIX}/bin/gdbada + +.include <bsd.port.mk> diff --git a/devel/gdb53-act/distinfo b/devel/gdb53-act/distinfo new file mode 100644 index 000000000000..259f8a418902 --- /dev/null +++ b/devel/gdb53-act/distinfo @@ -0,0 +1 @@ +MD5 (gdb-5.3-act.tar.gz) = 1d3f8aaef1c4fcc25704ba4257c6970f diff --git a/devel/gdb53-act/files/patch-gdb_config_alpha_fbsd.mh b/devel/gdb53-act/files/patch-gdb_config_alpha_fbsd.mh new file mode 100644 index 000000000000..5d5df6b89105 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_alpha_fbsd.mh @@ -0,0 +1,10 @@ +--- gdb/config/alpha/fbsd.mh Sat Jan 19 17:12:50 2002 ++++ gdb/config/alpha/fbsd.mh Sun Oct 13 12:22:36 2002 +@@ -1,5 +1,6 @@ + # Host: FreeBSD/Alpha + NATDEPFILES= fork-child.o infptrace.o inftarg.o \ + solib.o solib-svr4.o solib-legacy.o \ +- corelow.o core-regset.o alphabsd-nat.o ++ corelow.o core-regset.o alphabsd-nat.o freebsd-uthread.o kvm-fbsd.o + NAT_FILE= nm-fbsd.h ++NAT_CLIBS= -lkvm diff --git a/devel/gdb53-act/files/patch-gdb_config_alpha_nm-fbsd.h b/devel/gdb53-act/files/patch-gdb_config_alpha_nm-fbsd.h new file mode 100644 index 000000000000..d364e03cd2ec --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_alpha_nm-fbsd.h @@ -0,0 +1,11 @@ +--- gdb/config/alpha/nm-fbsd.h Tue Mar 6 00:21:21 2001 ++++ gdb/config/alpha/nm-fbsd.h Sun Oct 13 12:23:51 2002 +@@ -22,6 +22,8 @@ + #ifndef NM_FBSD_H + #define NM_FBSD_H + ++#include "config/nm-fbsd.h" ++ + /* Type of the third argument to the `ptrace' system call. */ + #define PTRACE_ARG3_TYPE caddr_t + diff --git a/devel/gdb53-act/files/patch-gdb_config_i386_fbsd.mh b/devel/gdb53-act/files/patch-gdb_config_i386_fbsd.mh new file mode 100644 index 000000000000..b9645a9b1765 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_i386_fbsd.mh @@ -0,0 +1,10 @@ +--- gdb/config/i386/fbsd.mh Sat May 11 10:22:27 2002 ++++ gdb/config/i386/fbsd.mh Sun Oct 13 11:50:47 2002 +@@ -4,4 +4,6 @@ + + NAT_FILE= nm-fbsd.h + # NOTE: Do not spread NATDEPFILES over several lines - it hurts BSD make. +-NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o solib-svr4.o solib-legacy.o corelow.o core-aout.o core-regset.o i386-nat.o i386bsd-nat.o i386fbsd-nat.o gcore.o fbsd-proc.o ++NATDEPFILES= fork-child.o infptrace.o inftarg.o solib.o solib-svr4.o solib-legacy.o corelow.o core-aout.o core-regset.o i386-nat.o i386bsd-nat.o i386fbsd-nat.o gcore.o fbsd-proc.o kvm-fbsd.o freebsd-uthread.o ++ ++NAT_CLIBS= -lkvm diff --git a/devel/gdb53-act/files/patch-gdb_config_i386_nm-fbsd.h b/devel/gdb53-act/files/patch-gdb_config_i386_nm-fbsd.h new file mode 100644 index 000000000000..efd2ce270e6f --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_i386_nm-fbsd.h @@ -0,0 +1,10 @@ +--- gdb/config/i386/nm-fbsd.h Fri Jun 28 11:44:49 2002 ++++ gdb/config/i386/nm-fbsd.h Sun Oct 13 10:53:27 2002 +@@ -26,6 +26,7 @@ + #define I386_USE_GENERIC_WATCHPOINTS + #endif + ++#include "config/nm-fbsd.h" + #include "i386/nm-i386.h" + + #ifdef HAVE_SYS_PARAM_H diff --git a/devel/gdb53-act/files/patch-gdb_config_nm-fbsd.h b/devel/gdb53-act/files/patch-gdb_config_nm-fbsd.h new file mode 100644 index 000000000000..9b6c033446c5 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_nm-fbsd.h @@ -0,0 +1,39 @@ +--- gdb/config/nm-fbsd.h Fri Jan 3 09:33:00 2003 ++++ gdb/config/nm-fbsd.h Fri Jan 3 09:36:00 2003 +@@ -0,0 +1,36 @@ ++#ifndef CONFIG_NM_FBSD_H ++#define CONFIG_NM_FBSD_H ++ ++#ifdef HAVE_SYS_PARAM_H ++#include <sys/param.h> ++#endif ++ ++extern int kernel_debugging; ++extern int kernel_writablecore; ++ ++CORE_ADDR fbsd_kern_frame_saved_pc(struct frame_info *frame); ++ ++#if __FreeBSD_version >= 500032 ++#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\ ++" ++ ++#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 ++#endif /* CONFIG_NM_FBSD_H */ diff --git a/devel/gdb53-act/files/patch-gdb_config_sparc_fbsd.mh b/devel/gdb53-act/files/patch-gdb_config_sparc_fbsd.mh new file mode 100644 index 000000000000..1a23ca92d26f --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_sparc_fbsd.mh @@ -0,0 +1,13 @@ +--- gdb/config/sparc/fbsd.mh.orig Wed Mar 13 03:20:24 2002 ++++ gdb/config/sparc/fbsd.mh Thu Oct 17 05:59:25 2002 +@@ -19,7 +19,7 @@ + # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + # Host: FreeBSD/sparc64 +-NATDEPFILES= sparc-nat.o \ +- corelow.o fork-child.o infptrace.o inftarg.o \ +- solib.o solib-svr4.o solib-legacy.o ++NATDEPFILES= fork-child.o infptrace.o inftarg.o sparc64nbsd-nat.o \ ++ solib.o solib-svr4.o solib-legacy.o kvm-fbsd.o + NAT_FILE= nm-fbsd.h ++NAT_CLIBS= -lkvm diff --git a/devel/gdb53-act/files/patch-gdb_config_sparc_fbsd.mt b/devel/gdb53-act/files/patch-gdb_config_sparc_fbsd.mt new file mode 100644 index 000000000000..3147c4ef30e2 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_sparc_fbsd.mt @@ -0,0 +1,10 @@ +--- gdb/config/sparc/fbsd.mt.orig Wed Mar 13 03:20:24 2002 ++++ gdb/config/sparc/fbsd.mt Thu Oct 17 05:59:59 2002 +@@ -19,5 +19,6 @@ + # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + # Target: FreeBSD/sparc64 +-TDEPFILES= sparc-tdep.o solib.o solib-svr4.o solib-legacy.o ++TDEPFILES= sparc-tdep.o sparcnbsd-tdep.o nbsd-tdep.o corelow.o solib.o \ ++ solib-svr4.o solib-legacy.o + TM_FILE= tm-fbsd.h diff --git a/devel/gdb53-act/files/patch-gdb_config_sparc_nm-fbsd.h b/devel/gdb53-act/files/patch-gdb_config_sparc_nm-fbsd.h new file mode 100644 index 000000000000..4ab0b5ada57d --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_sparc_nm-fbsd.h @@ -0,0 +1,72 @@ +--- gdb/config/sparc/nm-fbsd.h.orig Fri Mar 1 18:35:24 2002 ++++ gdb/config/sparc/nm-fbsd.h Tue Oct 22 16:33:14 2002 +@@ -32,36 +32,45 @@ + #define ATTACH_DETACH + + +-/* Shared library support. */ ++#include "regcache.h" ++ ++/* Get generic FreeBSD native definitions. */ ++ ++#include "config/nm-fbsd.h" ++ ++/* Shared library support. */ + + #define SVR4_SHARED_LIBS + + #include "solib.h" /* Support for shared libraries. */ + #include "elf/common.h" /* Additional ELF shared library info. */ + +-/* Make things match up with what is expected in sparc-nat.c. */ ++/* Before storing, we need to read all the registers. */ ++ ++#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES) ++ ++#define REG32_OFFSET_GLOBAL (0) ++#define REG32_OFFSET_OUT (32) ++#define REG32_OFFSET_NPC (96) ++#define REG32_OFFSET_PC (100) ++#define REG32_OFFSET_PSR (104) ++#define REG32_OFFSET_Y (112) ++#define REG32_SIZE (128) ++#define FPREG32_SIZE (136) ++ ++#define REG64_OFFSET_GLOBAL (0) ++#define REG64_OFFSET_OUT (64) ++#define REG64_OFFSET_NPC (192) ++#define REG64_OFFSET_PC (200) ++#define REG64_OFFSET_TSTATE (208) ++#define REG64_OFFSET_Y (224) ++#define REG64_SIZE (256) ++#define FPREG64_SIZE (272) ++ ++#define JB32_OFFSET_PC REG32_OFFSET_PC ++#define JB64_OFFSET_PC REG64_OFFSET_PC + +-#define PTRACE_GETREGS PT_GETREGS +-#define PTRACE_SETREGS PT_SETREGS +-#define PTRACE_GETFPREGS PT_GETFPREGS +-#define PTRACE_SETFPREGS PT_SETFPREGS +- +-#define GDB_GREGSET_T struct reg +-#define GDB_FPREGSET_T struct fpreg +- +-#define regs trapframe +-#define r_g1 tf_global[1] +-#define r_ps tf_tstate +-#define r_pc tf_tpc +-#define r_npc tf_tnpc +-#define r_y tf_y +- +-#define FPU_FSR_TYPE unsigned long +-#define fp_status fpreg /* our reg.h */ +-#define fpu fpreg /* our reg.h */ +-#define fpu_regs fr_regs /* one field of fpu_fr on Solaris */ +-#define fpu_fr fr_regs /* a union w/in struct fpu on Solaris */ +-#define fpu_fsr fr_fsr +-#define Fpu_fsr fr_fsr ++#define reg64 reg ++#define fpreg64 fpreg + + #endif /* NM_FBSD_H */ diff --git a/devel/gdb53-act/files/patch-gdb_config_sparc_tm-fbsd.h b/devel/gdb53-act/files/patch-gdb_config_sparc_tm-fbsd.h new file mode 100644 index 000000000000..4e15435b3505 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_config_sparc_tm-fbsd.h @@ -0,0 +1,17 @@ +--- gdb/config/sparc/tm-fbsd.h.orig Fri Mar 1 18:35:24 2002 ++++ gdb/config/sparc/tm-fbsd.h Thu Oct 17 06:01:10 2002 +@@ -22,13 +22,7 @@ + #define TM_FBSD_H + + #define SVR4_SHARED_LIBS ++#include "sparc/tm-sp64.h" /* sets GDB_MULTI_ARCH */ + #include "solib.h" /* Support for shared libraries. */ +-#include "sparc/tm-sp64.h" +- +-/* Number of traps that happen between exec'ing the shell to run an +- inferior, and when we finally get to the inferior code. The +- default is right for FreeBSD. */ +- +-#undef START_INFERIOR_TRAPS_EXPECTED + + #endif /* TM_FBSD_H */ diff --git a/devel/gdb53-act/files/patch-gdb_defs.h b/devel/gdb53-act/files/patch-gdb_defs.h new file mode 100644 index 000000000000..be60dcfc7217 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_defs.h @@ -0,0 +1,20 @@ +--- gdb/defs.h Thu Aug 1 10:18:32 2002 ++++ gdb/defs.h Sun Oct 13 10:44:10 2002 +@@ -39,8 +39,6 @@ + #include <unistd.h> + #endif + +-#include "gdb_locale.h" +- + /* For ``enum target_signal''. */ + #include "gdb/signals.h" + +@@ -57,6 +55,8 @@ + here and in all subsequent file inclusions. */ + + #include "ansidecl.h" ++ ++#include "gdb_locale.h" + + #include <stdarg.h> /* for va_list */ + diff --git a/devel/gdb53-act/files/patch-gdb_freebsd-uthread.c b/devel/gdb53-act/files/patch-gdb_freebsd-uthread.c new file mode 100644 index 000000000000..8027063a6355 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_freebsd-uthread.c @@ -0,0 +1,937 @@ +--- gdb/freebsd-uthread.c Wed Dec 31 16:00:00 1969 ++++ gdb/freebsd-uthread.c Sun Oct 13 13:10:51 2002 +@@ -0,0 +1,934 @@ ++/* $FreeBSD: /tmp/pcvs/ports/devel/gdb53-act/files/Attic/patch-gdb_freebsd-uthread.c,v 1.1 2003-09-27 07:38:23 edwin Exp $ */ ++/* Low level interface for debugging FreeBSD user threads for GDB, the GNU debugger. ++ Copyright 1996, 1999 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. */ ++ ++/* This module implements a sort of half target that sits between the ++ machine-independent parts of GDB and the ptrace interface (infptrace.c) to ++ provide access to the FreeBSD user-mode thread implementation. ++ ++ FreeBSD threads are true user-mode threads, which are invoked via ++ the pthread_* interfaces. These are mostly implemented in ++ user-space, with all thread context kept in various structures that ++ live in the user's heap. For the most part, the kernel has no ++ knowlege of these threads. ++ ++ Based largely on hpux-thread.c ++ ++ */ ++ ++ ++#include "defs.h" ++#include <sys/queue.h> ++#include <signal.h> ++#include <setjmp.h> ++#include <string.h> ++#include "gdbthread.h" ++#include "target.h" ++#include "inferior.h" ++#include <fcntl.h> ++#include <ucontext.h> ++#include <unistd.h> ++#include <sys/stat.h> ++#include "gdbcore.h" ++#include "regcache.h" ++ ++extern int child_suppress_run; ++extern struct target_ops child_ops; /* target vector for inftarg.c */ ++ ++extern void _initialize_freebsd_uthread PARAMS ((void)); ++ ++/* Set to true while we are part-way through attaching */ ++static int freebsd_uthread_attaching; ++ ++static int freebsd_uthread_active = 0; ++static CORE_ADDR P_thread_list; ++static CORE_ADDR P_thread_run; ++ ++/* Pointer to the next function on the objfile event chain. */ ++static void (*target_new_objfile_chain) (struct objfile *objfile); ++ ++static void freebsd_uthread_resume PARAMS ((ptid_t pid, int step, ++ enum target_signal signo)); ++ ++static void init_freebsd_uthread_ops PARAMS ((void)); ++ ++static struct target_ops freebsd_uthread_ops; ++ ++static ptid_t find_active_ptid PARAMS ((void)); ++ ++struct cached_pthread { ++ u_int64_t uniqueid; ++ int state; ++ CORE_ADDR name; ++ union { ++ ucontext_t uc; ++ jmp_buf jb; ++ } ctx; ++}; ++ ++static ptid_t cached_ptid; ++static struct cached_pthread cached_pthread; ++static CORE_ADDR cached_pthread_addr; ++ ++LIST_HEAD(idmaplist, idmap); ++ ++struct idmap { ++ LIST_ENTRY(idmap) link; ++ u_int64_t uniqueid; ++ int tid; ++}; ++ ++#define MAPHASH_SIZE 257 ++#define TID_MIN 1 ++#define TID_MAX 16383 ++ ++static int tid_to_hash[TID_MAX + 1]; /* set to map_hash index */ ++static struct idmaplist map_hash[MAPHASH_SIZE]; ++static int next_free_tid = TID_MIN; /* first available tid */ ++static int last_free_tid = TID_MIN; /* first unavailable */ ++ ++static CORE_ADDR P_thread_next_offset; ++static CORE_ADDR P_thread_uniqueid_offset; ++static CORE_ADDR P_thread_state_offset; ++static CORE_ADDR P_thread_name_offset; ++static CORE_ADDR P_thread_ctx_offset; ++static CORE_ADDR P_thread_PS_RUNNING_value; ++static CORE_ADDR P_thread_PS_DEAD_value; ++ ++static int next_offset; ++static int uniqueid_offset; ++static int state_offset; ++static int name_offset; ++static int ctx_offset; ++static int PS_RUNNING_value; ++static int PS_DEAD_value; ++ ++#define UNIQUEID_HASH(id) (id % MAPHASH_SIZE) ++#define TID_ADD1(tid) (((tid) + 1) == TID_MAX + 1 \ ++ ? TID_MIN : (tid) + 1) ++#define IS_TID_FREE(tid) (tid_to_hash[tid] == -1) ++ ++static int ++get_new_tid(int h) ++{ ++ int tid = next_free_tid; ++ ++ tid_to_hash[tid] = h; ++ next_free_tid = TID_ADD1(next_free_tid); ++ if (next_free_tid == last_free_tid) ++ { ++ int i; ++ ++ for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i)) ++ if (IS_TID_FREE(i)) ++ break; ++ if (TID_ADD1(i) == last_free_tid) ++ { ++ error("too many threads"); ++ return 0; ++ } ++ next_free_tid = i; ++ for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i)) ++ ; ++ last_free_tid = i; ++ } ++ ++ return tid; ++} ++ ++static ptid_t ++find_ptid(u_int64_t uniqueid) ++{ ++ int h = UNIQUEID_HASH(uniqueid); ++ struct idmap *im; ++ ++ LIST_FOREACH(im, &map_hash[h], link) ++ if (im->uniqueid == uniqueid) ++ return MERGEPID(PIDGET(inferior_ptid), im->tid); ++ ++ im = xmalloc(sizeof(struct idmap)); ++ im->uniqueid = uniqueid; ++ im->tid = get_new_tid(h); ++ LIST_INSERT_HEAD(&map_hash[h], im, link); ++ ++ return MERGEPID(PIDGET(inferior_ptid), im->tid); ++} ++ ++static void ++free_ptid(ptid_t ptid) ++{ ++ int tid = TIDGET(ptid); ++ int h = tid_to_hash[tid]; ++ struct idmap *im; ++ ++ if (!tid) return; ++ ++ LIST_FOREACH(im, &map_hash[h], link) ++ if (im->tid == tid) ++ break; ++ ++ if (!im) return; ++ ++ LIST_REMOVE(im, link); ++ tid_to_hash[tid] = -1; ++ free(im); ++} ++ ++#define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \ ++ (char *) &field##_offset, \ ++ sizeof(field##_offset)) ++ ++#define READ_VALUE(name) read_memory(P_thread_##name##_value, \ ++ (char *) &name##_value, \ ++ sizeof(name##_value)) ++ ++static void ++read_thread_offsets (void) ++{ ++ READ_OFFSET(next); ++ READ_OFFSET(uniqueid); ++ READ_OFFSET(state); ++ READ_OFFSET(name); ++ READ_OFFSET(ctx); ++ ++ READ_VALUE(PS_RUNNING); ++ READ_VALUE(PS_DEAD); ++} ++ ++#define READ_FIELD(ptr, T, field, result) \ ++ read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result) ++ ++static u_int64_t ++read_pthread_uniqueid (CORE_ADDR ptr) ++{ ++ u_int64_t uniqueid; ++ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid); ++ return uniqueid; ++} ++ ++static CORE_ADDR ++read_pthread_next (CORE_ADDR ptr) ++{ ++ CORE_ADDR next; ++ READ_FIELD(ptr, CORE_ADDR, next, next); ++ return next; ++} ++ ++static void ++read_cached_pthread (CORE_ADDR ptr, struct cached_pthread *cache) ++{ ++ READ_FIELD(ptr, u_int64_t, uniqueid, cache->uniqueid); ++ READ_FIELD(ptr, int, state, cache->state); ++ READ_FIELD(ptr, CORE_ADDR, name, cache->name); ++ READ_FIELD(ptr, ucontext_t, ctx, cache->ctx); ++} ++ ++static ptid_t ++find_active_ptid (void) ++{ ++ CORE_ADDR ptr; ++ ++ read_memory ((CORE_ADDR)P_thread_run, ++ (char *)&ptr, ++ sizeof ptr); ++ ++ return find_ptid(read_pthread_uniqueid(ptr)); ++} ++ ++static CORE_ADDR find_pthread_addr PARAMS ((ptid_t ptid)); ++static struct cached_pthread * find_pthread PARAMS ((ptid_t ptid)); ++ ++static CORE_ADDR ++find_pthread_addr (ptid_t ptid) ++{ ++ CORE_ADDR ptr; ++ ++ if (ptid_equal(ptid, cached_ptid)) ++ return cached_pthread_addr; ++ ++ read_memory ((CORE_ADDR)P_thread_list, ++ (char *)&ptr, ++ sizeof ptr); ++ ++ while (ptr != 0) ++ { ++ if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid)) ++ { ++ cached_ptid = ptid; ++ cached_pthread_addr = ptr; ++ read_cached_pthread(ptr, &cached_pthread); ++ return ptr; ++ } ++ ptr = read_pthread_next(ptr); ++ } ++ ++ return NULL; ++} ++ ++static struct cached_pthread * ++find_pthread (ptid_t ptid) ++{ ++ CORE_ADDR ptr; ++ ++ if (ptid_equal(ptid, cached_ptid)) ++ return &cached_pthread; ++ ++ read_memory ((CORE_ADDR)P_thread_list, ++ (char *)&ptr, ++ sizeof ptr); ++ ++ while (ptr != 0) ++ { ++ if (ptid_equal(find_ptid(read_pthread_uniqueid(ptr)), ptid)) ++ { ++ cached_ptid = ptid; ++ cached_pthread_addr = ptr; ++ read_cached_pthread(ptr, &cached_pthread); ++ return &cached_pthread; ++ } ++ ptr = read_pthread_next(ptr); ++ } ++ ++#if 0 ++ error ("Can't find pthread %d,%d", PIDGET(ptid), TIDGET(ptid)); ++#endif ++ return NULL; ++} ++ ++ ++/* Most target vector functions from here on actually just pass through to ++ inftarg.c, as they don't need to do anything specific for threads. */ ++ ++/* ARGSUSED */ ++static void ++freebsd_uthread_open (char *arg, int from_tty) ++{ ++ child_ops.to_open (arg, from_tty); ++} ++ ++/* Attach to process PID, then initialize for debugging it ++ and wait for the trace-trap that results from attaching. */ ++ ++static void ++freebsd_uthread_attach (char *args, int from_tty) ++{ ++ child_ops.to_attach (args, from_tty); ++ push_target (&freebsd_uthread_ops); ++ freebsd_uthread_attaching = 1; ++} ++ ++/* After an attach, see if the target is threaded */ ++ ++static void ++freebsd_uthread_post_attach (int pid) ++{ ++ if (freebsd_uthread_active) ++ { ++ read_thread_offsets (); ++ inferior_ptid = find_active_ptid (); ++ add_thread (inferior_ptid); ++ } ++ else ++ { ++ unpush_target (&freebsd_uthread_ops); ++ push_target (&child_ops); ++ } ++ ++ freebsd_uthread_attaching = 0; ++} ++ ++/* Take a program previously attached to and detaches it. ++ The program resumes execution and will no longer stop ++ on signals, etc. We'd better not have left any breakpoints ++ in the program or it'll die when it hits one. For this ++ to work, it may be necessary for the process to have been ++ previously attached. It *might* work if the program was ++ started via the normal ptrace (PTRACE_TRACEME). */ ++ ++static void ++freebsd_uthread_detach (char *args, int from_tty) ++{ ++ child_ops.to_detach (args, from_tty); ++} ++ ++/* Resume execution of process PID. If STEP is nozero, then ++ just single step it. If SIGNAL is nonzero, restart it with that ++ signal activated. We may have to convert pid from a thread-id to an LWP id ++ for procfs. */ ++ ++static void ++freebsd_uthread_resume (ptid_t ptid, int step, enum target_signal signo) ++{ ++ if (freebsd_uthread_attaching) ++ { ++ child_ops.to_resume (ptid, step, signo); ++ return; ++ } ++ ++ child_ops.to_resume (ptid, step, signo); ++ cached_ptid = MERGEPID(0, 0); ++} ++ ++/* Wait for any threads to stop. We may have to convert PID from a thread id ++ to a LWP id, and vice versa on the way out. */ ++ ++static ptid_t ++freebsd_uthread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) ++{ ++ ptid_t rtnval; ++ ++ if (freebsd_uthread_attaching) ++ { ++ return child_ops.to_wait (ptid, ourstatus); ++ } ++ ++ rtnval = child_ops.to_wait (ptid, ourstatus); ++ ++ if (PIDGET(rtnval) >= 0) ++ { ++ rtnval = find_active_ptid (); ++ if (!in_thread_list (rtnval)) ++ add_thread (rtnval); ++ } ++ ++ return rtnval; ++} ++ ++/* XXX: this needs to be selected by target, not [build] host */ ++#ifdef __i386__ ++ ++#include "i386-tdep.h" ++ ++static char sigmap[I386_SSE_NUM_REGS] = /* map reg to sigcontext */ ++{ ++ 12, /* eax */ ++ 11, /* ecx */ ++ 10, /* edx */ ++ 9, /* ebx */ ++ 8, /* esp */ ++ 7, /* ebp */ ++ 6, /* esi */ ++ 5, /* edi */ ++ 15, /* eip */ ++ 17, /* eflags */ ++ 16, /* cs */ ++ 19, /* ss */ ++ 4, /* ds */ ++ 3, /* es */ ++ 2, /* fs */ ++ 1, /* gs */ ++ -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */ ++ -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */ ++ -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */ ++ -1, /* mxcsr */ ++}; ++ ++static char jmpmap[I386_SSE_NUM_REGS] = /* map reg to jmp_buf */ ++{ ++ 6, /* eax */ ++ -1, /* ecx */ ++ -1, /* edx */ ++ 1, /* ebx */ ++ 2, /* esp */ ++ 3, /* ebp */ ++ 4, /* esi */ ++ 5, /* edi */ ++ 0, /* eip */ ++ -1, /* eflags */ ++ -1, /* cs */ ++ -1, /* ss */ ++ -1, /* ds */ ++ -1, /* es */ ++ -1, /* fs */ ++ -1, /* gs */ ++ -1, -1, -1, -1, -1, -1, -1, /* st0-st7 */ ++ -1, -1, -1, -1, -1, -1, -1, /* fctrl-fop */ ++ -1, -1, -1, -1, -1, -1, -1, /* xmm0-xmm7 */ ++ -1, /* mxcsr */ ++}; ++ ++#endif ++ ++#ifdef __alpha__ ++ ++#include "alpha-tdep.h" ++ ++static char sigmap[ALPHA_NUM_REGS] = /* map reg to sigcontext */ ++{ ++ 1, 2, 3, 4, 5, 6, 7, 8, /* v0 - t6 */ ++ 9, 10, 11, 12, 13, 14, 15, 16, /* t7 - fp */ ++ 17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */ ++ 25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */ ++ 38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */ ++ 46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */ ++ 54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */ ++ 62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */ ++ 33, -1 /* pc, vfp */ ++}; ++static char jmpmap[ALPHA_NUM_REGS] = { ++ 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */ ++ 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */ ++ 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */ ++ 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */ ++ 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */ ++ 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */ ++ 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */ ++ 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */ ++ 2, -1, /* pc, vfp */ ++}; ++ ++#endif ++ ++#ifdef __sparc64__ ++ ++static char sigmap[125] = /* map reg to sigcontext */ ++{ ++ -1 ++}; ++static char jmpmap[125] = { ++ -1 ++}; ++ ++#endif ++ ++static void ++freebsd_uthread_fetch_registers (int regno) ++{ ++ struct cached_pthread *thread; ++ int active; ++ int first_regno, last_regno; ++ register_t *regbase; ++ char *regmap; ++ ++ if (freebsd_uthread_attaching || TIDGET(inferior_ptid) == 0) ++ { ++ child_ops.to_fetch_registers (regno); ++ return; ++ } ++ ++ thread = find_pthread (inferior_ptid); ++ active = (ptid_equal(inferior_ptid, find_active_ptid())); ++ ++ if (active) ++ { ++ child_ops.to_fetch_registers (regno); ++ return; ++ } ++ ++ if (regno == -1) ++ { ++ first_regno = 0; ++ last_regno = NUM_REGS - 1; ++ } ++ else ++ { ++ first_regno = regno; ++ last_regno = regno; ++ } ++ ++ regbase = (register_t*) &thread->ctx.jb[0]; ++ regmap = jmpmap; ++ ++ for (regno = first_regno; regno <= last_regno; regno++) ++ { ++ if (regmap[regno] == -1) ++ child_ops.to_fetch_registers (regno); ++ else ++ if (thread) ++ supply_register (regno, (char*) ®base[regmap[regno]]); ++ else ++ supply_register (regno, NULL); ++ } ++} ++ ++static void ++freebsd_uthread_store_registers (int regno) ++{ ++ struct cached_pthread *thread; ++ CORE_ADDR ptr; ++ int first_regno, last_regno; ++ u_int32_t *regbase; ++ char *regmap; ++ ++ if (freebsd_uthread_attaching) ++ { ++ child_ops.to_store_registers (regno); ++ return; ++ } ++ ++ thread = find_pthread (inferior_ptid); ++ ++ if (thread->state == PS_RUNNING_value) ++ { ++ child_ops.to_store_registers (regno); ++ return; ++ } ++ ++ if (regno == -1) ++ { ++ first_regno = 0; ++ last_regno = NUM_REGS - 1; ++ } ++ else ++ { ++ first_regno = regno; ++ last_regno = regno; ++ } ++ ++ regbase = (u_int32_t*) &thread->ctx.jb[0]; ++ regmap = jmpmap; ++ ++ ptr = find_pthread_addr (inferior_ptid); ++ for (regno = first_regno; regno <= last_regno; regno++) ++ { ++ if (regmap[regno] == -1) ++ child_ops.to_store_registers (regno); ++ else ++ { ++ u_int32_t *reg = ®base[regmap[regno]]; ++ int off; ++ ++ /* Hang onto cached value */ ++ memcpy(reg, registers + REGISTER_BYTE (regno), ++ REGISTER_RAW_SIZE (regno)); ++ ++ /* And push out to inferior */ ++ off = (char *) reg - (char *) thread; ++ write_memory (ptr + off, ++ registers + REGISTER_BYTE (regno), ++ REGISTER_RAW_SIZE (regno)); ++ } ++ } ++} ++ ++/* Get ready to modify the registers array. On machines which store ++ individual registers, this doesn't need to do anything. On machines ++ which store all the registers in one fell swoop, this makes sure ++ that registers contains all the registers from the program being ++ debugged. */ ++ ++static void ++freebsd_uthread_prepare_to_store (void) ++{ ++ child_ops.to_prepare_to_store (); ++} ++ ++static int ++freebsd_uthread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, ++ int dowrite, struct mem_attrib *attrib, ++ struct target_ops *target) ++{ ++ return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, ++ attrib, target); ++} ++ ++/* Print status information about what we're accessing. */ ++ ++static void ++freebsd_uthread_files_info (struct target_ops *ignore) ++{ ++ child_ops.to_files_info (ignore); ++} ++ ++static void ++freebsd_uthread_kill_inferior (void) ++{ ++ child_ops.to_kill (); ++} ++ ++static void ++freebsd_uthread_notice_signals (ptid_t ptid) ++{ ++ child_ops.to_notice_signals (ptid); ++} ++ ++/* Fork an inferior process, and start debugging it with /proc. */ ++ ++static void ++freebsd_uthread_create_inferior (char *exec_file, char *allargs, char **env) ++{ ++ child_ops.to_create_inferior (exec_file, allargs, env); ++ ++ if (PIDGET(inferior_ptid) && freebsd_uthread_active) ++ { ++ read_thread_offsets (); ++ push_target (&freebsd_uthread_ops); ++ inferior_ptid = find_active_ptid (); ++ add_thread (inferior_ptid); ++ } ++} ++ ++/* This routine is called to find out if the inferior is using threads. ++ We check for the _thread_run and _thread_list globals. */ ++ ++void ++freebsd_uthread_new_objfile (struct objfile *objfile) ++{ ++ struct minimal_symbol *ms; ++ ++ if (!objfile) ++ { ++ freebsd_uthread_active = 0; ++ return; ++ } ++ ++ ms = lookup_minimal_symbol ("_thread_run", NULL, objfile); ++ ++ if (!ms) ++ return; ++ ++ P_thread_run = SYMBOL_VALUE_ADDRESS (ms); ++ ++ ms = lookup_minimal_symbol ("_thread_list", NULL, objfile); ++ ++ if (!ms) ++ return; ++ ++ P_thread_list = SYMBOL_VALUE_ADDRESS (ms); ++ ++#define OFFSET_SYM(field) "_thread_" #field "_offset" ++#define LOOKUP_OFFSET(field) \ ++ do { \ ++ ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \ ++ if (!ms) \ ++ return; \ ++ P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \ ++ } while (0); ++ ++#define VALUE_SYM(name) "_thread_" #name "_value" ++#define LOOKUP_VALUE(name) \ ++ do { \ ++ ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \ ++ if (!ms) \ ++ return; \ ++ P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \ ++ } while (0); ++ ++ LOOKUP_OFFSET(next); ++ LOOKUP_OFFSET(uniqueid); ++ LOOKUP_OFFSET(state); ++ LOOKUP_OFFSET(name); ++ LOOKUP_OFFSET(ctx); ++ ++ LOOKUP_VALUE(PS_RUNNING); ++ LOOKUP_VALUE(PS_DEAD); ++ ++ freebsd_uthread_active = 1; ++} ++ ++/* Clean up after the inferior dies. */ ++ ++static void ++freebsd_uthread_mourn_inferior () ++{ ++ child_ops.to_mourn_inferior (); ++ unpush_target (&freebsd_uthread_ops); ++} ++ ++/* Mark our target-struct as eligible for stray "run" and "attach" commands. */ ++ ++static int ++freebsd_uthread_can_run () ++{ ++ return child_suppress_run; ++} ++ ++static int ++freebsd_uthread_thread_alive (ptid_t ptid) ++{ ++ struct cached_pthread *thread; ++ int ret = 0; ++ ++ if (freebsd_uthread_attaching) ++ return 1; ++ ++ /* ++ * We can get called from child_ops.to_wait() which passes the underlying ++ * pid (without a thread number). ++ */ ++ if (TIDGET(ptid) == 0) ++ return 1; ++ ++ if (find_pthread_addr (ptid) != 0) ++ { ++ thread = find_pthread (ptid); ++ ret = (thread->state != PS_DEAD_value); ++ } ++ ++ if (!ret) ++ free_ptid(ptid); ++ ++ return ret; ++} ++ ++static void ++freebsd_uthread_stop (void) ++{ ++ child_ops.to_stop (); ++} ++ ++static void ++freebsd_uthread_find_new_threads (void) ++{ ++ CORE_ADDR ptr; ++ int state; ++ u_int64_t uniqueid; ++ ++ read_memory ((CORE_ADDR)P_thread_list, ++ (char *)&ptr, ++ sizeof ptr); ++ ++ while (ptr != 0) ++ { ++ READ_FIELD(ptr, int, state, state); ++ READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid); ++ if (state != PS_DEAD_value && ++ !in_thread_list (find_ptid(uniqueid))) ++ add_thread (find_ptid(uniqueid)); ++ ptr = read_pthread_next(ptr); ++ } ++} ++ ++/* MUST MATCH enum pthread_state */ ++static const char *statenames[] = { ++ "RUNNING", ++ "SIGTHREAD", ++ "MUTEX_WAIT", ++ "COND_WAIT", ++ "FDLR_WAIT", ++ "FDLW_WAIT", ++ "FDR_WAIT", ++ "FDW_WAIT", ++ "POLL_WAIT", ++ "FILE_WAIT", ++ "SELECT_WAIT", ++ "SLEEP_WAIT", ++ "WAIT_WAIT", ++ "SIGSUSPEND", ++ "SIGWAIT", ++ "SPINBLOCK", ++ "JOIN", ++ "SUSPENDED", ++ "DEAD", ++ "DEADLOCK", ++}; ++ ++#if 0 ++ ++static int ++freebsd_uthread_get_thread_info (ref, selection, info) ++ gdb_threadref *ref; ++ int selection; ++ struct gdb_ext_thread_info *info; ++{ ++ int pid = *ref; ++ struct cached_pthread *thread = find_pthread (pid); ++ struct cleanup *old_chain; ++ ++ old_chain = save_inferior_pid (); ++ inferior_pid = main_pid; ++ ++ memset(&info->threadid, 0, OPAQUETHREADBYTES); ++ ++ memcpy(&info->threadid, ref, sizeof *ref); ++ info->active = thread->state == PS_RUNNING_value; ++ strcpy(info->display, statenames[thread->state]); ++ if (thread->name) ++ read_memory ((CORE_ADDR) thread->name, info->shortname, 32); ++ else ++ strcpy(info->shortname, ""); ++ ++ do_cleanups (old_chain); ++ return (0); ++} ++ ++#endif ++ ++char * ++freebsd_uthread_pid_to_str (ptid_t ptid) ++{ ++ static char buf[30]; ++ ++ if (STREQ (current_target.to_shortname, "freebsd-uthreads")) ++ sprintf (buf, "Process %d, Thread %ld", ++ PIDGET(ptid), TIDGET(ptid)); ++ else ++ sprintf (buf, "Process %d", PIDGET(ptid)); ++ ++ return buf; ++} ++ ++ ++static void ++init_freebsd_uthread_ops () ++{ ++ freebsd_uthread_ops.to_shortname = "freebsd-uthreads"; ++ freebsd_uthread_ops.to_longname = "FreeBSD uthreads"; ++ freebsd_uthread_ops.to_doc = "FreeBSD user threads support."; ++ freebsd_uthread_ops.to_open = freebsd_uthread_open; ++ freebsd_uthread_ops.to_attach = freebsd_uthread_attach; ++ freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach; ++ freebsd_uthread_ops.to_detach = freebsd_uthread_detach; ++ freebsd_uthread_ops.to_resume = freebsd_uthread_resume; ++ freebsd_uthread_ops.to_wait = freebsd_uthread_wait; ++ freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers; ++ freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers; ++ freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store; ++ freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory; ++ freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info; ++ freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint; ++ freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint; ++ freebsd_uthread_ops.to_terminal_init = terminal_init_inferior; ++ freebsd_uthread_ops.to_terminal_inferior = terminal_inferior; ++ freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output; ++ freebsd_uthread_ops.to_terminal_ours = terminal_ours; ++ freebsd_uthread_ops.to_terminal_info = child_terminal_info; ++ freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior; ++ freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior; ++ freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior; ++ freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run; ++ freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals; ++ freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive; ++ freebsd_uthread_ops.to_stop = freebsd_uthread_stop; ++ freebsd_uthread_ops.to_stratum = process_stratum; ++ freebsd_uthread_ops.to_has_all_memory = 1; ++ freebsd_uthread_ops.to_has_memory = 1; ++ freebsd_uthread_ops.to_has_stack = 1; ++ freebsd_uthread_ops.to_has_registers = 1; ++ freebsd_uthread_ops.to_has_execution = 1; ++ freebsd_uthread_ops.to_has_thread_control = 0; ++ freebsd_uthread_ops.to_magic = OPS_MAGIC; ++ freebsd_uthread_ops.to_find_new_threads = freebsd_uthread_find_new_threads; ++ freebsd_uthread_ops.to_pid_to_str = freebsd_uthread_pid_to_str; ++#if 0 ++ freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info; ++#endif ++} ++ ++void ++_initialize_freebsd_uthread () ++{ ++ init_freebsd_uthread_ops (); ++ add_target (&freebsd_uthread_ops); ++ ++ target_new_objfile_chain = target_new_objfile_hook; ++ target_new_objfile_hook = freebsd_uthread_new_objfile; ++ ++ child_suppress_run = 1; ++} diff --git a/devel/gdb53-act/files/patch-gdb_i386-tdep.c b/devel/gdb53-act/files/patch-gdb_i386-tdep.c new file mode 100644 index 000000000000..f91663ccfa40 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_i386-tdep.c @@ -0,0 +1,12 @@ +--- gdb/i386-tdep.c Mon Aug 26 11:35:25 2002 ++++ gdb/i386-tdep.c Sun Oct 13 14:15:58 2002 +@@ -534,6 +534,9 @@ + static CORE_ADDR + i386_frame_saved_pc (struct frame_info *frame) + { ++ if (kernel_debugging) ++ return fbsd_kern_frame_saved_pc(frame); ++ + if (PC_IN_CALL_DUMMY (frame->pc, 0, 0)) + return generic_read_register_dummy (frame->pc, frame->frame, + PC_REGNUM); diff --git a/devel/gdb53-act/files/patch-gdb_i386bsd-nat.c b/devel/gdb53-act/files/patch-gdb_i386bsd-nat.c new file mode 100644 index 000000000000..a28ce60b09e2 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_i386bsd-nat.c @@ -0,0 +1,20 @@ +--- gdb/i386bsd-nat.c 2003/01/02 20:22:00 1.1 ++++ gdb/i386bsd-nat.c 2003/01/02 20:22:35 +@@ -306,7 +306,7 @@ + /* For some mysterious reason, some of the reserved bits in the + debug control register get set. Mask these off, otherwise the + ptrace call below will fail. */ +- dbregs.dr7 &= ~(0x0000fc00); ++ DBREG_DRX ((&dbregs), 7) = ~(0x0000fc00); + + DBREG_DRX ((&dbregs), regnum) = value; + +@@ -355,7 +355,7 @@ + return 0; + #endif + +- return dbregs.dr6; ++ return DBREG_DRX ((&dbregs), 6); + } + + #endif /* PT_GETDBREGS */ diff --git a/devel/gdb53-act/files/patch-gdb_kvm-fbsd.c b/devel/gdb53-act/files/patch-gdb_kvm-fbsd.c new file mode 100644 index 000000000000..c708b2ef9f5b --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_kvm-fbsd.c @@ -0,0 +1,759 @@ +--- gdb/kvm-fbsd.c Fri Jan 3 08:57:23 2003 ++++ gdb/kvm-fbsd.c Fri Jan 3 08:57:20 2003 +@@ -0,0 +1,756 @@ ++/* Kernel core dump functions below target vector, for GDB. ++ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 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. ++*/ ++ ++/* $FreeBSD: /tmp/pcvs/ports/devel/gdb53-act/files/Attic/patch-gdb_kvm-fbsd.c,v 1.1 2003-09-27 07:38:23 edwin Exp $ */ ++ ++/* ++ * This works like "remote" but, you use it like this: ++ * target kcore /dev/mem ++ * or ++ * target kcore /var/crash/host/core.0 ++ * ++ * This way makes it easy to short-circut the whole bfd monster, ++ * and direct the inferior stuff to our libkvm implementation. ++ * ++ */ ++ ++#include <sys/param.h> ++#include <sys/time.h> ++#include <sys/proc.h> ++#include <sys/user.h> ++#include <ctype.h> ++#include <errno.h> ++#include <signal.h> ++#include <fcntl.h> ++#include <kvm.h> ++#include <sys/sysctl.h> ++#include <paths.h> ++#include <readline/tilde.h> ++#include <machine/frame.h> ++ ++#include "defs.h" ++#include "gdb_string.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 "regcache.h" ++ ++#if __FreeBSD_version >= 500032 ++static void ++kcore_files_info (struct target_ops *); ++ ++static void ++kcore_close (int); ++ ++static void ++get_kcore_registers (int); ++ ++static int ++xfer_mem (CORE_ADDR, char *, int, int, struct mem_attrib *, ++ struct target_ops *); ++ ++static int ++xfer_umem (CORE_ADDR, char *, int, int); ++ ++static char *core_file; ++static kvm_t *core_kd; ++static struct pcb cur_pcb; ++static struct kinfo_proc *cur_proc; ++ ++static struct target_ops kcore_ops; ++ ++int kernel_debugging; ++int kernel_writablecore; ++ ++/* 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)))) ++ ++static CORE_ADDR ++ksym_kernbase (void) ++{ ++ static CORE_ADDR kernbase; ++ struct minimal_symbol *sym; ++ ++ if (kernbase == 0) ++ { ++ sym = lookup_minimal_symbol ("kernbase", NULL, NULL); ++ if (sym == NULL) { ++ kernbase = KERNBASE; ++ } else { ++ kernbase = SYMBOL_VALUE_ADDRESS (sym); ++ } ++ } ++ return kernbase; ++} ++ ++#define KERNOFF (ksym_kernbase ()) ++#define INKERNEL(x) ((x) >= KERNOFF) ++ ++CORE_ADDR ++ksym_lookup(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); ++} ++ ++/* Provide the address of an initial PCB to use. ++ If this is a crash dump, try for "dumppcb". ++ If no "dumppcb" or it's /dev/mem, use proc0. ++ Return the core address of the PCB we found. */ ++ ++static CORE_ADDR ++initial_pcb (void) ++{ ++ struct minimal_symbol *sym; ++ CORE_ADDR addr; ++ void *val; ++ ++ /* Make sure things are open... */ ++ if (!core_kd || !core_file) ++ return (0); ++ ++ /* If this is NOT /dev/mem try for dumppcb. */ ++ if (strncmp (core_file, _PATH_DEV, sizeof _PATH_DEV - 1)) ++ { ++ sym = lookup_minimal_symbol ("dumppcb", NULL, NULL); ++ if (sym != NULL) ++ { ++ addr = SYMBOL_VALUE_ADDRESS (sym); ++ return (addr); ++ } ++ } ++ ++ /* OK, just use thread0's pcb. Note that curproc might ++ not exist, and if it does, it will point to gdb. ++ Therefore, just use proc0 and let the user set ++ some other context if they care about it. */ ++ ++ addr = ksym_lookup ("thread0"); ++ if (kvread (addr, &val)) ++ { ++ error ("cannot read thread0 pointer at %x\n", addr); ++ val = 0; ++ } ++ else ++ { ++ /* Read the PCB address in thread structure. */ ++ addr += offsetof (struct thread, td_pcb); ++ if (kvread (addr, &val)) ++ { ++ error ("cannot read thread0->td_pcb pointer at %x\n", addr); ++ val = 0; ++ } ++ } ++ ++ /* thread0 is wholly in the kernel and cur_proc is only used for ++ reading user mem, so no point in setting this up. */ ++ cur_proc = 0; ++ ++ return ((CORE_ADDR)val); ++} ++ ++/* Set the current context to that of the PCB struct at the system address ++ passed. */ ++ ++static int ++set_context (CORE_ADDR addr) ++{ ++ CORE_ADDR procaddr = 0; ++ ++ if (kvread (addr, &cur_pcb)) ++ error ("cannot read pcb at %#x", addr); ++ ++ /* 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 ()); ++ return (0); ++} ++ ++/* Discard all vestiges of any previous core file and mark data and stack ++ spaces as empty. */ ++ ++/* ARGSUSED */ ++static void ++kcore_close (int quitting) ++{ ++ ++ inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */ ++ ++ if (core_kd) ++ { ++ kvm_close (core_kd); ++ free (core_file); ++ core_file = NULL; ++ core_kd = NULL; ++ } ++} ++ ++/* This routine opens and sets up the core file bfd. */ ++ ++static void ++kcore_open (char *filename /* the core file */, int from_tty) ++{ ++ kvm_t *kd; ++ const char *p; ++ struct cleanup *old_chain; ++ char buf[256], *cp; ++ int ontop; ++ CORE_ADDR addr; ++ ++ target_preopen (from_tty); ++ ++ /* The exec file is required for symbols. */ ++ if (exec_bfd == NULL) ++ error ("No kernel exec file specified"); ++ ++ if (core_kd) ++ { ++ error ("No core file specified." ++ " (Use `detach' to stop debugging a core file.)"); ++ return; ++ } ++ ++ if (!filename) ++ { ++ error ("No core file specified."); ++ return; ++ } ++ ++ filename = tilde_expand (filename); ++ if (filename[0] != '/') ++ { ++ cp = concat (current_directory, "/", filename, NULL); ++ free (filename); ++ filename = cp; ++ } ++ ++ old_chain = make_cleanup (free, filename); ++ ++ kd = kvm_open (bfd_get_filename(exec_bfd), filename, NULL, ++ kernel_writablecore ? O_RDWR: O_RDONLY, 0); ++ if (kd == NULL) ++ { ++ perror_with_name (filename); ++ return; ++ } ++ ++ /* 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; ++ unpush_target (&kcore_ops); ++ ontop = !push_target (&kcore_ops); ++ ++ /* Note unpush_target (above) calls kcore_close. */ ++ core_kd = kd; ++ ++ /* 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_filtered ("panic: %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; ++ } ++ ++ /* Now, set up process context, and print the top of stack. */ ++ (void)set_context (initial_pcb()); ++ print_stack_frame (selected_frame, frame_relative_level(selected_frame), 1); ++} ++ ++static void ++kcore_detach (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"); ++} ++ ++#ifdef __alpha__ ++ ++#include "alpha/tm-alpha.h" ++#include "alpha-tdep.h" ++ ++#ifndef S0_REGNUM ++#define S0_REGNUM (ALPHA_T7_REGNUM+1) ++#endif ++ ++fetch_kcore_registers (struct pcb *pcbp) ++{ ++ ++ /* First clear out any garbage. */ ++ memset (registers, '\0', REGISTER_BYTES); ++ ++ /* SP */ ++ *(long *) ®isters[REGISTER_BYTE (SP_REGNUM)] = ++ pcbp->pcb_hw.apcb_ksp; ++ ++ /* S0 through S6 */ ++ memcpy (®isters[REGISTER_BYTE (S0_REGNUM)], ++ &pcbp->pcb_context[0], 7 * sizeof (long)); ++ ++ /* PC */ ++ *(long *) ®isters[REGISTER_BYTE (PC_REGNUM)] = ++ pcbp->pcb_context[7]; ++ ++ registers_fetched (); ++} ++ ++ ++CORE_ADDR ++fbsd_kern_frame_saved_pc (struct frame_info *fi) ++{ ++ struct minimal_symbol *sym; ++ CORE_ADDR this_saved_pc; ++ ++ this_saved_pc = FRAME_SAVED_PC(fi); ++ ++ sym = lookup_minimal_symbol_by_pc (this_saved_pc); ++ ++ if (sym != NULL && ++ (strcmp (SYMBOL_NAME (sym), "XentArith") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentIF") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentInt") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentMM") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentSys") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentUna") == 0 || ++ strcmp (SYMBOL_NAME (sym), "XentRestart") == 0)) ++ { ++ return (read_memory_integer (fi->frame + 32 * 8, 8)); ++ } ++ else ++ { ++ return (this_saved_pc); ++ } ++} ++ ++#endif /* __alpha__ */ ++ ++#ifdef __i386__ ++ ++static CORE_ADDR ++ksym_maxuseraddr (void) ++{ ++ static CORE_ADDR maxuseraddr; ++ struct minimal_symbol *sym; ++ ++ if (maxuseraddr == 0) ++ { ++ sym = lookup_minimal_symbol ("PTmap", NULL, NULL); ++ if (sym == NULL) { ++ maxuseraddr = VM_MAXUSER_ADDRESS; ++ } else { ++ maxuseraddr = SYMBOL_VALUE_ADDRESS (sym); ++ } ++ } ++ return maxuseraddr; ++} ++ ++ ++/* Symbol names of kernel entry points. Use special frames. */ ++#define KSYM_TRAP "calltrap" ++#define KSYM_INTR "Xintr" ++#define KSYM_FASTINTR "Xfastintr" ++#define KSYM_OLDSYSCALL "Xlcall_syscall" ++#define KSYM_SYSCALL "Xint0x80_syscall" ++ ++/* 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 (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), KSYM_TRAP) == 0) ++ frametype = tf_trap; ++ else ++ if (strncmp (SYMBOL_NAME (sym), KSYM_INTR, ++ strlen (KSYM_INTR)) == 0 || strncmp (SYMBOL_NAME(sym), ++ KSYM_FASTINTR, strlen (KSYM_FASTINTR)) == 0) ++ frametype = tf_interrupt; ++ else ++ if (strcmp (SYMBOL_NAME (sym), KSYM_SYSCALL) == 0 || ++ strcmp (SYMBOL_NAME (sym), KSYM_OLDSYSCALL) == 0) ++ frametype = tf_syscall; ++ } ++ ++ switch (frametype) ++ { ++ default: ++ 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 + 12 + oEIP, 4)); ++ ++ case tf_syscall: ++ return (read_memory_integer (fr->frame + 8 + oEIP, 4)); ++#undef oEIP ++ } ++} ++ ++static void ++fetch_kcore_registers (struct pcb *pcb) ++{ ++ int i; ++ int noreg; ++ ++ /* 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? */ ++} ++ ++#endif /* __i386__ */ ++ ++#ifdef __sparc64__ ++ ++#define SPARC_INTREG_SIZE 8 ++ ++static void ++fetch_kcore_registers (struct pcb *pcbp) ++{ ++ static struct frame top; ++ CORE_ADDR f_addr; ++ int i; ++ ++ /* 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 do something with the floating-point registers? ++ */ ++ supply_register (SP_REGNUM, &pcbp->pcb_fp); ++ supply_register (PC_REGNUM, &pcbp->pcb_pc); ++ f_addr = extract_address (&pcbp->pcb_fp, SPARC_INTREG_SIZE); ++ /* Load the previous frame by hand (XXX) and supply it. */ ++ read_memory (f_addr + SPOFF, (char *)&top, sizeof (top)); ++ for (i = 0; i < 8; i++) ++ supply_register (i + L0_REGNUM, &top.fr_local[i]); ++ for (i = 0; i < 8; i++) ++ supply_register (i + I0_REGNUM, &top.fr_in[i]); ++} ++ ++CORE_ADDR ++fbsd_kern_frame_saved_pc (struct frame_info *fi) ++{ ++ struct minimal_symbol *sym; ++ CORE_ADDR frame, pc_addr, pc; ++ char *buf; ++ ++ buf = alloca (MAX_REGISTER_RAW_SIZE); ++ /* XXX: duplicates fi->extra_info->bottom. */ ++ frame = (fi->next != NULL) ? fi->next->frame : read_sp (); ++ pc_addr = frame + offsetof (struct frame, fr_in[7]); ++ ++#define READ_PC(pc, a, b) do { \ ++ read_memory (a, b, SPARC_INTREG_SIZE); \ ++ pc = extract_address (b, SPARC_INTREG_SIZE); \ ++} while (0) ++ ++ READ_PC (pc, pc_addr, buf); ++ ++ sym = lookup_minimal_symbol_by_pc (pc); ++ if (sym != NULL) ++ { ++ if (strncmp (SYMBOL_NAME (sym), "tl0_", 4) == 0 || ++ strcmp (SYMBOL_NAME (sym), "btext") == 0 || ++ strcmp (SYMBOL_NAME (sym), "mp_startup") == 0 || ++ strcmp (SYMBOL_NAME (sym), "fork_trampoline") == 0) ++ { ++ /* ++ * Ugly kluge: user space addresses aren't separated from kernel ++ * ones by range; if encountering a trap from user space, just ++ * return a 0 to stop the trace. ++ * Do the same for entry points of kernel processes to avoid ++ * printing garbage. ++ */ ++ pc = 0; ++ } ++ if (strncmp (SYMBOL_NAME (sym), "tl1_", 4) == 0) ++ { ++ pc_addr = fi->frame + sizeof (struct frame) + ++ offsetof (struct trapframe, tf_tpc); ++ READ_PC (pc, pc_addr, buf); ++ } ++ } ++ return (pc); ++} ++ ++#endif /* __sparc64__ */ ++ ++/* 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 (int regno) ++{ ++ ++ /* XXX - Only read the pcb when set_context() is called. ++ When looking at a live kernel this may be a problem, ++ but the user can do another "proc" or "pcb" command to ++ grab a new copy of the pcb... */ ++ ++ /* Zero out register set then fill in the ones we know about. */ ++ fetch_kcore_registers (&cur_pcb); ++} ++ ++static void ++kcore_files_info (t) ++ struct target_ops *t; ++{ ++ printf_filtered ("\t`%s'\n", core_file); ++} ++ ++/* If mourn is being called in all the right places, this could be say ++ `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */ ++ ++static int ++ignore (CORE_ADDR addr, char *contents) ++{ ++ return 0; ++} ++ ++static int ++xfer_kmem (CORE_ADDR memaddr, char *myaddr, int len, int write, ++ struct mem_attrib *attrib, struct target_ops *target) ++{ ++ int n; ++ ++ ++ if (!INKERNEL (memaddr)) ++ return xfer_umem (memaddr, myaddr, len, write); ++ ++ if (core_kd == NULL) ++ return 0; ++ ++ if (write) ++ n = kvm_write (core_kd, memaddr, myaddr, len); ++ else ++ n = kvm_read (core_kd, memaddr, myaddr, len) ; ++ if (n < 0) { ++ fprintf_unfiltered (gdb_stderr, "can not access 0x%x, %s\n", ++ memaddr, kvm_geterr (core_kd)); ++ n = 0; ++ } ++ ++ return n; ++} ++ ++ ++static int ++xfer_umem (CORE_ADDR memaddr, char *myaddr, int len, int write /* ignored */) ++{ ++ int n = 0; ++ ++ if (cur_proc == 0) ++ { ++ error ("---Can't read userspace from dump, or kernel process---\n"); ++ return 0; ++ } ++ ++ if (write) ++ error ("kvm_uwrite unimplemented\n"); ++ else ++ n = kvm_uread (core_kd, cur_proc, memaddr, myaddr, len) ; ++ ++ if (n < 0) ++ return 0; ++ ++ return n; ++} ++ ++static void ++set_proc_cmd (char *arg, int from_tty) ++{ ++ CORE_ADDR addr, pid_addr, first_td; ++ void *val; ++ struct kinfo_proc *kp; ++ int cnt; ++ pid_t pid; ++ ++ if (!arg) ++ error_no_arg ("proc address for the new context"); ++ ++ if (core_kd == NULL) ++ error ("no kernel core file"); ++ ++ addr = (CORE_ADDR) parse_and_eval_address (arg); ++ ++ if (!INKERNEL (addr)) ++ { ++ kp = kvm_getprocs (core_kd, KERN_PROC_PID, addr, &cnt); ++ if (!cnt) ++ error ("invalid pid"); ++ addr = (CORE_ADDR)kp->ki_paddr; ++ cur_proc = kp; ++ } ++ else ++ { ++ /* Update cur_proc. */ ++ pid_addr = addr + offsetof (struct proc, p_pid); ++ if (kvread (pid_addr, &pid)) ++ error ("cannot read pid ptr"); ++ cur_proc = kvm_getprocs (core_kd, KERN_PROC_PID, pid, &cnt); ++ if (!cnt) ++ error("invalid pid"); ++ } ++ ++ /* Find the first thread in the process. XXXKSE */ ++ addr += offsetof (struct proc, p_threads.tqh_first); ++ if (kvread (addr, &first_td)) ++ error ("cannot read thread ptr"); ++ ++ /* Read the PCB address in thread structure. */ ++ addr = first_td + offsetof (struct thread, td_pcb); ++ if (kvread (addr, &val)) ++ error("cannot read pcb ptr"); ++ ++ /* Read the PCB address in proc structure. */ ++ if (set_context ((CORE_ADDR) val)) ++ error ("invalid proc address"); ++} ++#else ++int kernel_debugging = 0; ++int kernel_writablecore = 0; ++ ++CORE_ADDR ++fbsd_kern_frame_saved_pc (struct frame_info *fi) ++{ ++ return 0; ++} ++#endif ++ ++void ++_initialize_kcorelow (void) ++{ ++#if __FreeBSD_version >= 500032 ++ 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 = 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"); ++#endif ++} diff --git a/devel/gdb53-act/files/patch-gdb_sparc-tdep.c b/devel/gdb53-act/files/patch-gdb_sparc-tdep.c new file mode 100644 index 000000000000..950276ea2089 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_sparc-tdep.c @@ -0,0 +1,13 @@ +--- gdb/sparc-tdep.c.orig Sun Oct 20 18:21:09 2002 ++++ gdb/sparc-tdep.c Sun Oct 20 18:16:53 2002 +@@ -450,6 +450,9 @@ + char *buf; + CORE_ADDR addr; + ++ if (kernel_debugging) ++ return fbsd_kern_frame_saved_pc(frame); ++ + buf = alloca (MAX_REGISTER_RAW_SIZE); + if (frame->signal_handler_caller) + { + diff --git a/devel/gdb53-act/files/patch-gdb_sparcnbsd-tdep.c b/devel/gdb53-act/files/patch-gdb_sparcnbsd-tdep.c new file mode 100644 index 000000000000..13ba396dd6b7 --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_sparcnbsd-tdep.c @@ -0,0 +1,63 @@ +diff -urN gdb/sparcnbsd-tdep.c.orig gdb/sparcnbsd-tdep.c +--- gdb/sparcnbsd-tdep.c.orig Sat Oct 19 17:19:17 2002 ++++ gdb/sparcnbsd-tdep.c Sat Oct 19 17:44:47 2002 +@@ -31,20 +31,6 @@ + + #include "solib-svr4.h" + +-#define REG32_OFFSET_PSR (0 * 4) +-#define REG32_OFFSET_PC (1 * 4) +-#define REG32_OFFSET_NPC (2 * 4) +-#define REG32_OFFSET_Y (3 * 4) +-#define REG32_OFFSET_GLOBAL (4 * 4) +-#define REG32_OFFSET_OUT (12 * 4) +- +-#define REG64_OFFSET_TSTATE (0 * 8) +-#define REG64_OFFSET_PC (1 * 8) +-#define REG64_OFFSET_NPC (2 * 8) +-#define REG64_OFFSET_Y (3 * 8) +-#define REG64_OFFSET_GLOBAL (4 * 8) +-#define REG64_OFFSET_OUT (12 * 8) +- + void + sparcnbsd_supply_reg32 (char *regs, int regno) + { +@@ -375,16 +361,13 @@ + + if (gdbarch_ptr_bit (current_gdbarch) == 32) + { +- reg_size = (20 * 4); +- fpreg_size = (33 * 4); ++ reg_size = REG32_SIZE; ++ fpreg_size = FPREG32_SIZE; + } + else + { +- reg_size = (20 * 8); +- fpreg_size = (64 * 4) +- + 8 /* fsr */ +- + 4 /* gsr */ +- + 4; /* pad */ ++ reg_size = REG64_SIZE; ++ fpreg_size = FPREG64_SIZE; + } + + switch (which) +@@ -442,7 +425,7 @@ + + jb_addr = read_register (O0_REGNUM); + +- if (target_read_memory (jb_addr + 12, buf, sizeof (buf))) ++ if (target_read_memory (jb_addr + JB32_OFFSET_PC, buf, sizeof (buf))) + return 0; + + *pc = extract_address (buf, sizeof (buf)); +@@ -458,7 +441,7 @@ + + jb_addr = read_register (O0_REGNUM); + +- if (target_read_memory (jb_addr + 16, buf, sizeof (buf))) ++ if (target_read_memory (jb_addr + JB64_OFFSET_PC, buf, sizeof (buf))) + return 0; + + *pc = extract_address (buf, sizeof (buf)); diff --git a/devel/gdb53-act/files/patch-gdb_symfile.c b/devel/gdb53-act/files/patch-gdb_symfile.c new file mode 100644 index 000000000000..99c75ffe04bf --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_symfile.c @@ -0,0 +1,15 @@ +--- gdb/symfile.c Tue Feb 26 17:40:36 2002 ++++ gdb/symfile.c Wed May 29 11:10:17 2002 +@@ -1546,11 +1546,7 @@ + char *val = sect_opts[i].value; + char *sec = sect_opts[i].name; + +- val = sect_opts[i].value; +- if (val[0] == '0' && val[1] == 'x') +- addr = strtoul (val+2, NULL, 16); +- else +- addr = strtoul (val, NULL, 10); ++ addr = parse_and_eval_address(val); + + /* Here we store the section offsets in the order they were + entered on the command line. */ diff --git a/devel/gdb53-act/files/patch-gdb_target.c b/devel/gdb53-act/files/patch-gdb_target.c new file mode 100644 index 000000000000..3bd25996c60a --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_target.c @@ -0,0 +1,11 @@ +--- gdb/target.c Mon Aug 26 12:18:33 2002 ++++ gdb/target.c Sun Oct 13 10:51:32 2002 +@@ -1429,7 +1429,7 @@ + for (t = target_structs; t < target_structs + target_struct_size; + ++t) + { +- if ((*t)->to_stratum == core_stratum) ++ if ((*t)->to_stratum == (kernel_debugging ? kcore_stratum : core_stratum)) + { + runable = *t; + ++count; diff --git a/devel/gdb53-act/files/patch-gdb_target.h b/devel/gdb53-act/files/patch-gdb_target.h new file mode 100644 index 000000000000..147cfe49620f --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_target.h @@ -0,0 +1,10 @@ +--- gdb/target.h Sat Feb 9 20:08:42 2002 ++++ gdb/target.h Fri May 24 08:38:31 2002 +@@ -52,6 +52,7 @@ + dummy_stratum, /* The lowest of the low */ + file_stratum, /* Executable files, etc */ + core_stratum, /* Core dump files */ ++ kcore_stratum, /* Kernel core files */ + download_stratum, /* Downloading of remote targets */ + process_stratum, /* Executing processes */ + thread_stratum /* Executing threads */ diff --git a/devel/gdb53-act/files/patch-gdb_version.in b/devel/gdb53-act/files/patch-gdb_version.in new file mode 100644 index 000000000000..4496ebfb1f3e --- /dev/null +++ b/devel/gdb53-act/files/patch-gdb_version.in @@ -0,0 +1,5 @@ +--- gdb/version.in Fri Apr 26 18:04:22 2002 ++++ gdb/version.in Mon Jun 3 08:14:54 2002 +@@ -1 +1 @@ +-5.2.90 ++5.3 (FreeBSD) diff --git a/devel/gdb53-act/pkg-descr b/devel/gdb53-act/pkg-descr new file mode 100644 index 000000000000..be3a1138a100 --- /dev/null +++ b/devel/gdb53-act/pkg-descr @@ -0,0 +1 @@ +GNU GDB 5.3 developmental snapshot. diff --git a/devel/gdb53-act/pkg-plist b/devel/gdb53-act/pkg-plist new file mode 100644 index 000000000000..ff0a320f5e68 --- /dev/null +++ b/devel/gdb53-act/pkg-plist @@ -0,0 +1 @@ +bin/gdbada |