Index: head/devel/gdb/Makefile =================================================================== --- head/devel/gdb/Makefile (revision 384977) +++ head/devel/gdb/Makefile (revision 384978) @@ -1,118 +1,122 @@ # Created by: Steven Kreuzer # $FreeBSD$ PORTNAME= gdb -PORTVERSION= 7.8.2 -PORTREVISION= 2 +PORTVERSION= 7.9 CATEGORIES= devel MASTER_SITES= GNU MAINTAINER= luca.pizzamiglio@gmail.com COMMENT= GNU GDB of newer version than comes with the system LICENSE= GPLv3 USES= cpe iconv gmake libtool tar:xz USE_CSTD= gnu89 CPE_VENDOR= gnu GNU_CONFIGURE= yes CONFIGURE_ENV= CONFIGURED_M4=m4 CONFIGURED_BISON=byacc CONFIGURE_ARGS= --program-suffix=${PORTVERSION:S/.//g} \ --enable-targets=all \ --with-gdb-datadir=${PREFIX}/share/gdb${PORTVERSION:S/.//g} \ --with-separate-debug-dir=/usr/lib/debug \ ${ICONV_CONFIGURE_ARG} \ --without-libunwind-ia64 CFLAGS:= ${CFLAGS:C/ +$//} # blanks at EOL creep in sometimes CFLAGS+= -DRL_NO_COMPAT -Wno-unused-function -Wno-unused-variable EXCLUDE= dejagnu expect sim texinfo intl EXTRACT_AFTER_ARGS= ${EXCLUDE:S/^/--exclude /} +EXTRA_PATCHES= ${FILESDIR}/commit-c5cb74e \ + ${FILESDIR}/commit-cf424ae \ + ${FILESDIR}/commit-773eacf \ + ${FILESDIR}/commit-2526815 \ + ${FILESDIR}/commit-3ce5b6e \ + ${FILESDIR}/commit-97de354 VER= ${PORTVERSION:S/.//g} PLIST_SUB= VER=${VER} ONLY_FOR_ARCHS= i386 amd64 powerpc powerpc64 # untested elsewhere, might work OPTIONS_DEFINE= DEBUG EXPAT GDB_LINK GUILE PYTHON THREADS TUI OPTIONS_DEFAULT= GDB_LINK THREADS TUI PORT_READLINE OPTIONS_SINGLE= READLINE OPTIONS_SINGLE_READLINE= BASE_READLINE BUNDLED_READLINE PORT_READLINE GDB_LINK_DESC= Create ${PREFIX}/bin/gdb symlink BASE_READLINE_DESC= from base system (experimental) BUNDLED_READLINE_DESC= from gdb distfile PORT_READLINE_DESC= from devel/readline port TUI_DESC= Text User Interface enabled OPTIONS_SUB= yes BASE_READLINE_USES= readline BASE_READLINE_CFLAGS= -D_rl_echoing_p=readline_echoing_p BUNDLED_READLINE_CONFIGURE_OFF= --with-system-readline DEBUG_CFLAGS= -g EXPAT_CONFIGURE_ON= --with-expat=yes EXPAT_CONFIGURE_OFF= --without-expat EXPAT_LIB_DEPENDS= libexpat.so:${PORTSDIR}/textproc/expat2 GUILE_CONFIGURE_ON= --with-guile GUILE_USES= pkgconfig GUILE_LIB_DEPENDS= libguile-2.0.so:${PORTSDIR}/lang/guile2 PYTHON_CONFIGURE_ON= --with-python=${PYTHON_CMD} PYTHON_CONFIGURE_OFF= --without-python PYTHON_USES= python:2 -PORT_READLINE_EXTRA_PATCHES= ${FILESDIR}/extrapatch-gdb-tui-tui-io.c PORT_READLINE_USES= readline:port TUI_CONFIGURE_ENABLE= tui .include .if ! ${PORT_OPTIONS:MBUNDLED_READLINE} EXCLUDE+= readline .endif .if ${ARCH} == "amd64" CONFIGURE_TARGET= x86_64-portbld-freebsd${OSREL} .endif post-patch: @${REINPLACE_CMD} -e 's|$$| [GDB v${PORTVERSION} for FreeBSD]|' \ ${WRKSRC}/gdb/version.in .if ${PORT_OPTIONS:MTHREADS} @${CP} ${FILESDIR}/fbsd-threads.c ${WRKSRC}/gdb/ @${PATCH} ${PATCH_ARGS} < ${FILESDIR}/extrapatch-threads .endif do-install: ${INSTALL_PROGRAM} ${WRKSRC}/gdb/gdb \ ${STAGEDIR}${PREFIX}/bin/gdb${VER} ${INSTALL_MAN} ${WRKSRC}/gdb/doc/gdb.1 \ ${STAGEDIR}${MAN1PREFIX}/man/man1/gdb${VER}.1 .if ${PORT_OPTIONS:MTUI} ${LN} -sf gdb${VER} ${STAGEDIR}${PREFIX}/bin/gdbtui${VER} .endif .if ${PORT_OPTIONS:MGDB_LINK} ${LN} -sf gdb${VER} ${STAGEDIR}${PREFIX}/bin/gdb .endif .if ${PORT_OPTIONS:MPYTHON} (cd ${WRKSRC}/gdb; ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-python ) (cd ${WRKSRC}/gdb/data-directory ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-python ) .endif .if ${PORT_OPTIONS:MGUILE} (cd ${WRKSRC}/gdb; ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-guile ) (cd ${WRKSRC}/gdb/data-directory ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-guile ) .endif .if ${PORT_OPTIONS:MPYTHON} . for f in gdb gdb/command gdb/function @(cd ${STAGEDIR}${PREFIX}/share/gdb${VER}/python/${f} ; ${CHMOD} 644 *.py* ) . endfor .endif .include Index: head/devel/gdb/distinfo =================================================================== --- head/devel/gdb/distinfo (revision 384977) +++ head/devel/gdb/distinfo (revision 384978) @@ -1,2 +1,2 @@ -SHA256 (gdb-7.8.2.tar.xz) = 605954d5747d5f08ea4b7f48e958d1ebbf39265e18f7f36738deeabb83744485 -SIZE (gdb-7.8.2.tar.xz) = 17678568 +SHA256 (gdb-7.9.tar.xz) = 9b315651a16528f7af8c7d8284699fb0c965df316cc7339bb0b7bae335848392 +SIZE (gdb-7.9.tar.xz) = 17859428 Index: head/devel/gdb/files/patch-gdb-amd64fbsd-tdep.c =================================================================== --- head/devel/gdb/files/patch-gdb-amd64fbsd-tdep.c (revision 384977) +++ head/devel/gdb/files/patch-gdb-amd64fbsd-tdep.c (nonexistent) @@ -1,20 +0,0 @@ ---- gdb/amd64fbsd-tdep.c.orig 2010-01-01 02:31:29.000000000 -0500 -+++ gdb/amd64fbsd-tdep.c 2011-01-05 17:27:29.264869000 -0500 -@@ -40,12 +39,16 @@ - static CORE_ADDR - amd64fbsd_sigcontext_addr (struct frame_info *this_frame) - { -+ struct gdbarch *gdbarch = get_frame_arch (this_frame); -+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp; -+ gdb_byte buf[8]; - - /* The `struct sigcontext' (which really is an `ucontext_t' on - FreeBSD/amd64) lives at a fixed offset in the signal frame. See - . */ -- sp = frame_unwind_register_unsigned (this_frame, AMD64_RSP_REGNUM); -+ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); -+ sp = extract_unsigned_integer (buf, 8, byte_order); - return sp + 16; - } - Property changes on: head/devel/gdb/files/patch-gdb-amd64fbsd-tdep.c ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/devel/gdb/files/patch-gdb-amd64fbsd-nat.c =================================================================== --- head/devel/gdb/files/patch-gdb-amd64fbsd-nat.c (revision 384977) +++ head/devel/gdb/files/patch-gdb-amd64fbsd-nat.c (nonexistent) @@ -1,56 +0,0 @@ ---- gdb/amd64fbsd-nat.c.orig 2014-06-11 18:34:41.000000000 +0200 -+++ gdb/amd64fbsd-nat.c 2014-09-24 18:27:50.618458853 +0200 -@@ -21,13 +21,16 @@ - #include "inferior.h" - #include "regcache.h" - #include "target.h" - - #include "gdb_assert.h" - #include - #include - #include -+#include - #include - #include -+#include -+#include - #include - - #include "fbsd-nat.h" -@@ -247,6 +291,10 @@ - - SC_RBP_OFFSET = offset; - -+// Newer versions of FreeBSD provide a better way to locate the signtramp -+#if ( __FreeBSD_version/100000 < 9 ) \ -+ || ( ( __FreeBSD_version/100000 == 9 ) && ( __FreeBSD_version < 902505 ) ) \ -+ || ( ( __FreeBSD_version/100000 == 10 ) && ( __FreeBSD_version < 1000700 ) ) - /* FreeBSD provides a kern.ps_strings sysctl that we can use to - locate the sigtramp. That way we can still recognize a sigtramp - if its location is changed in a new kernel. Of course this is -@@ -267,4 +315,25 @@ - amd64fbsd_sigtramp_end_addr = ps_strings; - } - } -+#else -+ /* FreeBSD provides a kern.proc.sigtramp sysctl that we can use to -+ locate the sigtramp. That way we can still recognize a sigtramp -+ if its location is changed in a new kernel. */ -+ { -+ int mib[4]; -+ struct kinfo_sigtramp kst; -+ size_t len; -+ -+ mib[0] = CTL_KERN; -+ mib[1] = KERN_PROC; -+ mib[2] = KERN_PROC_SIGTRAMP; -+ mib[3] = getpid(); -+ len = sizeof (kst); -+ if (sysctl (mib, sizeof(mib)/sizeof(mib[0]), &kst, &len, NULL, 0) == 0) -+ { -+ amd64fbsd_sigtramp_start_addr = kst.ksigtramp_start; -+ amd64fbsd_sigtramp_end_addr = kst.ksigtramp_end; -+ } -+ } -+#endif - } Property changes on: head/devel/gdb/files/patch-gdb-amd64fbsd-nat.c ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/devel/gdb/files/extrapatch-gdb-tui-tui-io.c =================================================================== --- head/devel/gdb/files/extrapatch-gdb-tui-tui-io.c (revision 384977) +++ head/devel/gdb/files/extrapatch-gdb-tui-tui-io.c (nonexistent) @@ -1,17 +0,0 @@ ---- ./gdb/tui/tui-io.c.orig 2013-12-08 04:33:14.000000000 +0000 -+++ ./gdb/tui/tui-io.c 2014-03-01 22:20:33.000000000 +0000 -@@ -128,10 +128,10 @@ - struct ui_out *tui_old_uiout; - - /* Readline previous hooks. */ --static Function *tui_old_rl_getc_function; --static VFunction *tui_old_rl_redisplay_function; --static VFunction *tui_old_rl_prep_terminal; --static VFunction *tui_old_rl_deprep_terminal; -+static rl_getc_func_t *tui_old_rl_getc_function; -+static rl_voidfunc_t *tui_old_rl_redisplay_function; -+static rl_voidfunc_t *tui_old_rl_prep_terminal; -+static rl_voidfunc_t *tui_old_rl_deprep_terminal; - static int tui_old_rl_echoing_p; - - /* Readline output stream. Property changes on: head/devel/gdb/files/extrapatch-gdb-tui-tui-io.c ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/devel/gdb/files/patch-xsave =================================================================== --- head/devel/gdb/files/patch-xsave (revision 384977) +++ head/devel/gdb/files/patch-xsave (nonexistent) @@ -1,606 +0,0 @@ -diff --git a/bfd/elf.c b/bfd/elf.c -index 3f377d1..9481435 100644 ---- bfd/elf.c -+++ bfd/elf.c -@@ -8609,6 +8609,9 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) - if (note->namesz == 6 - && strcmp (note->namedata, "LINUX") == 0) - return elfcore_grok_xstatereg (abfd, note); -+ else if (note->namesz == 8 -+ && strcmp (note->namedata, "FreeBSD") == 0) -+ return elfcore_grok_xstatereg (abfd, note); - else - return TRUE; - -diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h -index f1b039e..7a4c1dc 100644 ---- gdb/amd64-tdep.h -+++ gdb/amd64-tdep.h -@@ -84,6 +84,11 @@ enum amd64_regnum - - #define AMD64_NUM_REGS (AMD64_ZMM31H_REGNUM + 1) - -+extern struct target_desc *tdesc_amd64; -+extern struct target_desc *tdesc_amd64_avx; -+extern struct target_desc *tdesc_amd64_mpx; -+extern struct target_desc *tdesc_amd64_avx512; -+ - extern struct displaced_step_closure *amd64_displaced_step_copy_insn - (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, - struct regcache *regs); -diff --git a/gdb/amd64bsd-nat.c b/gdb/amd64bsd-nat.c -index 4b0a231..9e6a0df 100644 ---- gdb/amd64bsd-nat.c -+++ gdb/amd64bsd-nat.c -@@ -37,6 +37,10 @@ - #include "inf-ptrace.h" - - -+#ifdef PT_GETXSTATE_INFO -+size_t x86_xsave_len; -+#endif -+ - /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating-point registers). */ - -@@ -62,6 +66,20 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, - if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) - { - struct fpreg fpregs; -+#ifdef PT_GETXSTATE_INFO -+ char *xstateregs; -+ -+ if (x86_xsave_len != 0) -+ { -+ xstateregs = alloca(x86_xsave_len); -+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) -+ perror_with_name (_("Couldn't get extended state status")); -+ -+ amd64_supply_xsave (regcache, -1, xstateregs); -+ return; -+ } -+#endif - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) -@@ -111,6 +129,24 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, - if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) - { - struct fpreg fpregs; -+#ifdef PT_GETXSTATE_INFO -+ char *xstateregs; -+ -+ if (x86_xsave_len != 0) -+ { -+ xstateregs = alloca(x86_xsave_len); -+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) -+ perror_with_name (_("Couldn't get extended state status")); -+ -+ amd64_collect_xsave (regcache, regnum, xstateregs, 0); -+ -+ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) xstateregs, x86_xsave_len) == -1) -+ perror_with_name (_("Couldn't write extended state status")); -+ return; -+ } -+#endif - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) -diff --git a/gdb/amd64bsd-nat.h b/gdb/amd64bsd-nat.h -index 7ff95f3..9d85a1f 100644 ---- gdb/amd64bsd-nat.h -+++ gdb/amd64bsd-nat.h -@@ -20,6 +20,9 @@ - #ifndef AMD64BSD_NAT_H - #define AMD64BSD_NAT_H - -+/* Low level amd64 XSAVE info. */ -+extern size_t x86_xsave_len; -+ - /* Low level amd64 debug register functions. */ - - extern void amd64bsd_dr_set_control (unsigned long control); -diff --git a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c -index 08de9a1..eea2472 100644 ---- gdb/amd64fbsd-nat.c -+++ gdb/amd64fbsd-nat.c -@@ -36,6 +36,7 @@ - #include "amd64-nat.h" - #include "amd64bsd-nat.h" - #include "i386-nat.h" -+#include "i386-xstate.h" - - - /* Offset in `struct reg' where MEMBER is stored. */ -@@ -153,6 +154,68 @@ amd64fbsd_mourn_inferior (struct target_ops *ops) - super_mourn_inferior (ops); - } - -+static const struct target_desc * -+amd64fbsd_read_description (struct target_ops *ops) -+{ -+#ifdef PT_GETXSTATE_INFO -+ static int xsave_probed; -+ static uint64_t xcr0; -+#endif -+ struct reg regs; -+ int is64; -+ -+ if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) ®s, 0) == -1) -+ perror_with_name (_("Couldn't get registers")); -+ is64 = (regs.r_cs == GSEL(GUCODE_SEL, SEL_UPL)); -+#ifdef PT_GETXSTATE_INFO -+ if (!xsave_probed) -+ { -+ struct ptrace_xstate_info info; -+ -+ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) &info, sizeof(info)) == 0) -+ { -+ x86_xsave_len = info.xsave_len; -+ xcr0 = info.xsave_mask; -+ } -+ xsave_probed = 1; -+ } -+ -+ if (x86_xsave_len != 0) -+ { -+ switch (xcr0 & I386_XSTATE_ALL_MASK) -+ { -+ case I386_XSTATE_MPX_AVX512_MASK: -+ case I386_XSTATE_AVX512_MASK: -+ if (is64) -+ return tdesc_amd64_avx512; -+ else -+ return tdesc_i386_avx512; -+ case I386_XSTATE_MPX_MASK: -+ if (is64) -+ return tdesc_amd64_mpx; -+ else -+ return tdesc_i386_mpx; -+ case I386_XSTATE_AVX_MASK: -+ if (is64) -+ return tdesc_amd64_avx; -+ else -+ return tdesc_i386_avx; -+ default: -+ if (is64) -+ return tdesc_amd64; -+ else -+ return tdesc_i386; -+ } -+ } -+#endif -+ if (is64) -+ return tdesc_amd64; -+ else -+ return tdesc_i386; -+} -+ - /* Provide a prototype to silence -Wmissing-prototypes. */ - void _initialize_amd64fbsd_nat (void); - -@@ -183,6 +246,7 @@ _initialize_amd64fbsd_nat (void) - - super_mourn_inferior = t->to_mourn_inferior; - t->to_mourn_inferior = amd64fbsd_mourn_inferior; -+ t->to_read_description = amd64fbsd_read_description; - - t->to_pid_to_exec_file = fbsd_pid_to_exec_file; - t->to_find_memory_regions = fbsd_find_memory_regions; -diff --git a/gdb/amd64fbsd-tdep.c b/gdb/amd64fbsd-tdep.c -index 884fbc4..582ae50 100644 ---- gdb/amd64fbsd-tdep.c -+++ gdb/amd64fbsd-tdep.c -@@ -23,6 +23,9 @@ - #include "gdbcore.h" - #include "regcache.h" - #include "osabi.h" -+#include "regset.h" -+#include "i386fbsd-tdep.h" -+#include "i386-xstate.h" - - #include "gdb_assert.h" - #include -@@ -31,6 +34,15 @@ - #include "bsd-uthread.h" - #include "solib-svr4.h" - -+/* Supported register note sections. */ -+static struct core_regset_section amd64fbsd_regset_sections[] = -+{ -+ { ".reg", 22 * 8, "general-purpose" }, -+ { ".reg2", 512, "floating-point" }, -+ { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" }, -+ { NULL, 0 } -+}; -+ - /* Support for signal handlers. */ - - /* Assuming THIS_FRAME is for a BSD sigtramp routine, return the -@@ -144,6 +156,27 @@ static int amd64fbsd_jmp_buf_reg_offset[] = - 0 * 8 /* %rip */ - }; - -+static const struct target_desc * -+amd64fbsd_core_read_description (struct gdbarch *gdbarch, -+ struct target_ops *target, -+ bfd *abfd) -+{ -+ uint64_t xcr0 = i386fbsd_core_read_xcr0 (abfd); -+ -+ switch (xcr0 & I386_XSTATE_ALL_MASK) -+ { -+ case I386_XSTATE_MPX_AVX512_MASK: -+ case I386_XSTATE_AVX512_MASK: -+ return tdesc_amd64_avx512; -+ case I386_XSTATE_MPX_MASK: -+ return tdesc_amd64_mpx; -+ case I386_XSTATE_AVX_MASK: -+ return tdesc_amd64_avx; -+ default: -+ return tdesc_amd64; -+ } -+} -+ - static void - amd64fbsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -@@ -204,6 +237,14 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) - tdep->sc_reg_offset = amd64fbsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset); - -+ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; -+ -+ /* Install supported register note sections. */ -+ set_gdbarch_core_regset_sections (gdbarch, amd64fbsd_regset_sections); -+ -+ set_gdbarch_core_read_description (gdbarch, -+ amd64fbsd_core_read_description); -+ - /* FreeBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread); -diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h -index e0950a3..0498445 100644 ---- gdb/i386-tdep.h -+++ gdb/i386-tdep.h -@@ -325,6 +325,11 @@ enum record_i386_regnum - /* Size of the largest register. */ - #define I386_MAX_REGISTER_SIZE 64 - -+extern struct target_desc *tdesc_i386; -+extern struct target_desc *tdesc_i386_avx; -+extern struct target_desc *tdesc_i386_mpx; -+extern struct target_desc *tdesc_i386_avx512; -+ - /* Types for i386-specific registers. */ - extern struct type *i387_ext_type (struct gdbarch *gdbarch); - -diff --git a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c -index acae6cb..c26e830 100644 ---- gdb/i386bsd-nat.c -+++ gdb/i386bsd-nat.c -@@ -83,6 +83,10 @@ static int i386bsd_r_reg_offset[] = - so that we try PT_GETXMMREGS the first time around. */ - static int have_ptrace_xmmregs = -1; - #endif -+ -+#ifdef PT_GETXSTATE_INFO -+size_t x86_xsave_len; -+#endif - - - /* Supply the general-purpose registers in GREGS, to REGCACHE. */ -@@ -150,7 +154,25 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, - struct fpreg fpregs; - #ifdef HAVE_PT_GETXMMREGS - char xmmregs[512]; -+#endif -+ -+#ifdef PT_GETXSTATE_INFO -+ if (x86_xsave_len != 0) -+ { -+ char *xstateregs; -+ -+ xstateregs = alloca(x86_xsave_len); -+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) -+ perror_with_name (_("Couldn't get extended state status")); - -+ i387_supply_xsave (regcache, -1, xstateregs); -+ return; -+ } -+ else -+#endif -+ -+#ifdef HAVE_PT_GETXMMREGS - if (have_ptrace_xmmregs != 0 - && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) -@@ -160,18 +182,15 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, - } - else - { -+ have_ptrace_xmmregs = 0; -+#endif - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - i387_supply_fsave (regcache, -1, &fpregs); -+#ifdef HAVE_PT_GETXMMREGS - } --#else -- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), -- (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) -- perror_with_name (_("Couldn't get floating point status")); -- -- i387_supply_fsave (regcache, -1, &fpregs); - #endif - } - } -@@ -206,7 +225,27 @@ i386bsd_store_inferior_registers (struct target_ops *ops, - struct fpreg fpregs; - #ifdef HAVE_PT_GETXMMREGS - char xmmregs[512]; -+#endif -+ -+#ifdef PT_GETXSTATE_INFO -+ if (x86_xsave_len != 0) -+ { -+ char *xstateregs; - -+ xstateregs = alloca(x86_xsave_len); -+ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) -+ perror_with_name (_("Couldn't get extended state status")); -+ -+ i387_collect_xsave (regcache, -1, xstateregs, 0); -+ -+ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) xstateregs, x86_xsave_len) == -1) -+ perror_with_name (_("Couldn't write extended state status")); -+ } -+#endif -+ -+#ifdef HAVE_PT_GETXMMREGS - if (have_ptrace_xmmregs != 0 - && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) -diff --git a/gdb/i386bsd-nat.h b/gdb/i386bsd-nat.h -index a92fa56..044f530 100644 ---- gdb/i386bsd-nat.h -+++ gdb/i386bsd-nat.h -@@ -25,6 +25,9 @@ - - extern struct target_ops *i386bsd_target (void); - -+/* Low level i386 XSAVE info. */ -+extern size_t x86_xsave_len; -+ - /* low level i386 debug register functions used in i386fbsd-nat.c. */ - - extern void i386bsd_dr_set_control (unsigned long control); -diff --git a/gdb/i386fbsd-nat.c b/gdb/i386fbsd-nat.c -index fb80991..b9620e1 100644 ---- gdb/i386fbsd-nat.c -+++ gdb/i386fbsd-nat.c -@@ -31,6 +31,7 @@ - #include "i386-tdep.h" - #include "i386-nat.h" - #include "i386bsd-nat.h" -+#include "i386-xstate.h" - - /* Resume execution of the inferior process. If STEP is nonzero, - single-step it. If SIGNAL is nonzero, give it that signal. */ -@@ -116,6 +117,46 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) - } - - -+#ifdef PT_GETXSTATE_INFO -+static const struct target_desc * -+i386fbsd_read_description (struct target_ops *ops) -+{ -+ static int xsave_probed; -+ static uint64_t xcr0; -+ -+ if (!xsave_probed) -+ { -+ struct ptrace_xstate_info info; -+ -+ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), -+ (PTRACE_TYPE_ARG3) &info, sizeof(info)) == 0) -+ { -+ x86_xsave_len = info.xsave_len; -+ xcr0 = info.xsave_mask; -+ } -+ xsave_probed = 1; -+ } -+ -+ if (x86_xsave_len != 0) -+ { -+ switch (xcr0 & I386_XSTATE_ALL_MASK) -+ { -+ case I386_XSTATE_MPX_AVX512_MASK: -+ case I386_XSTATE_AVX512_MASK: -+ return tdesc_i386_avx512; -+ case I386_XSTATE_MPX_MASK: -+ return tdesc_i386_mpx; -+ case I386_XSTATE_AVX_MASK: -+ return tdesc_i386_avx; -+ default: -+ return tdesc_i386; -+ } -+ } -+ else -+ return tdesc_i386; -+} -+#endif -+ - /* Prevent warning from -Wmissing-prototypes. */ - void _initialize_i386fbsd_nat (void); - -@@ -140,6 +181,9 @@ _initialize_i386fbsd_nat (void) - - #endif /* HAVE_PT_GETDBREGS */ - -+#ifdef PT_GETXSTATE_INFO -+ t->to_read_description = i386fbsd_read_description; -+#endif - - t->to_pid_to_exec_file = fbsd_pid_to_exec_file; - t->to_find_memory_regions = fbsd_find_memory_regions; -diff --git a/gdb/i386fbsd-tdep.c b/gdb/i386fbsd-tdep.c -index ed6df6b..8f7109f 100644 ---- gdb/i386fbsd-tdep.c -+++ gdb/i386fbsd-tdep.c -@@ -22,6 +22,9 @@ - #include "gdbcore.h" - #include "osabi.h" - #include "regcache.h" -+#include "regset.h" -+#include "i386fbsd-tdep.h" -+#include "i386-xstate.h" - - #include "gdb_assert.h" - -@@ -32,6 +35,15 @@ - - /* FreeBSD 3.0-RELEASE or later. */ - -+/* Supported register note sections. */ -+static struct core_regset_section i386fbsd_regset_sections[] = -+{ -+ { ".reg", 19 * 4, "general-purpose" }, -+ { ".reg2", 512, "floating-point" }, -+ { ".reg-xstate", I386_XSTATE_MAX_SIZE, "XSAVE extended state" }, -+ { NULL, 0 } -+}; -+ - /* From . */ - static int i386fbsd_r_reg_offset[] = - { -@@ -82,6 +94,64 @@ static int i386fbsd_jmp_buf_reg_offset[] = - 0 * 4 /* %eip */ - }; - -+/* Get XSAVE extended state xcr0 from core dump. */ -+ -+uint64_t -+i386fbsd_core_read_xcr0 (bfd *abfd) -+{ -+ asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate"); -+ uint64_t xcr0; -+ -+ if (xstate) -+ { -+ size_t size = bfd_section_size (abfd, xstate); -+ -+ /* Check extended state size. */ -+ if (size < I386_XSTATE_AVX_SIZE) -+ xcr0 = I386_XSTATE_SSE_MASK; -+ else -+ { -+ char contents[8]; -+ -+ if (! bfd_get_section_contents (abfd, xstate, contents, -+ I386_FBSD_XSAVE_XCR0_OFFSET, -+ 8)) -+ { -+ warning (_("Couldn't read `xcr0' bytes from " -+ "`.reg-xstate' section in core file.")); -+ return 0; -+ } -+ -+ xcr0 = bfd_get_64 (abfd, contents); -+ } -+ } -+ else -+ xcr0 = 0; -+ -+ return xcr0; -+} -+ -+static const struct target_desc * -+i386fbsd_core_read_description (struct gdbarch *gdbarch, -+ struct target_ops *target, -+ bfd *abfd) -+{ -+ uint64_t xcr0 = i386fbsd_core_read_xcr0 (abfd); -+ -+ switch (xcr0 & I386_XSTATE_ALL_MASK) -+ { -+ case I386_XSTATE_MPX_AVX512_MASK: -+ case I386_XSTATE_AVX512_MASK: -+ return tdesc_i386_avx512; -+ case I386_XSTATE_MPX_MASK: -+ return tdesc_i386_mpx; -+ case I386_XSTATE_AVX_MASK: -+ return tdesc_i386_avx; -+ default: -+ return tdesc_i386; -+ } -+} -+ - static void - i386fbsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -@@ -218,6 +288,14 @@ i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) - /* FreeBSD 4.0 introduced a new `struct sigcontext'. */ - tdep->sc_reg_offset = i386fbsd4_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset); -+ -+ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; -+ -+ /* Install supported register note sections. */ -+ set_gdbarch_core_regset_sections (gdbarch, i386fbsd_regset_sections); -+ -+ set_gdbarch_core_read_description (gdbarch, -+ i386fbsd_core_read_description); - } - - -diff --git a/gdb/i386fbsd-tdep.h b/gdb/i386fbsd-tdep.h -new file mode 100644 -index 0000000..8935255 ---- /dev/null -+++ gdb/i386fbsd-tdep.h -@@ -0,0 +1,33 @@ -+/* Target-dependent code for FreeBSD x86. -+ -+ Copyright (C) 2014 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 3 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, see . */ -+ -+#ifndef I386FBSD_TDEP_H -+#define I386FBSD_TDEP_H -+ -+/* Get XSAVE extended state xcr0 from core dump. */ -+extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); -+ -+/* -+ * The format of the XSAVE extended area is determined by hardware. -+ * Cores store the XSAVE extended area in a NT_X86_XSTATE note that -+ * matches the layout on Linux. -+ */ -+#define I386_FBSD_XSAVE_XCR0_OFFSET 464 -+ -+#endif /* i386fbsd-tdep.h */ Property changes on: head/devel/gdb/files/patch-xsave ___________________________________________________________________ Deleted: fbsd:nokeywords ## -1 +0,0 ## -yes \ No newline at end of property Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: head/devel/gdb/files/commit-2526815 =================================================================== --- head/devel/gdb/files/commit-2526815 (nonexistent) +++ head/devel/gdb/files/commit-2526815 (revision 384978) @@ -0,0 +1,186 @@ +diff --git gdb/config.in gdb/config.in +index 3ccac37..8a27df0 100644 +--- gdb/config.in ++++ gdb/config.in +@@ -213,6 +213,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_INTTYPES_H + ++/* Define to 1 if your system has the kinfo_getvmmap function. */ ++#undef HAVE_KINFO_GETVMMAP ++ + /* Define if you have and nl_langinfo(CODESET). */ + #undef HAVE_LANGINFO_CODESET + +diff --git gdb/configure gdb/configure +index cca0aeb..78d206b 100755 +--- gdb/configure ++++ gdb/configure +@@ -7159,6 +7159,66 @@ if test "$ac_res" != no; then : + fi + + ++# On FreeBSD we may need libutil for kinfo_getvmmap (used by fbsd-nat.c). ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing kinfo_getvmmap" >&5 ++$as_echo_n "checking for library containing kinfo_getvmmap... " >&6; } ++if test "${ac_cv_search_kinfo_getvmmap+set}" = set; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_func_search_save_LIBS=$LIBS ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char kinfo_getvmmap (); ++int ++main () ++{ ++return kinfo_getvmmap (); ++ ; ++ return 0; ++} ++_ACEOF ++for ac_lib in '' util; do ++ if test -z "$ac_lib"; then ++ ac_res="none required" ++ else ++ ac_res=-l$ac_lib ++ LIBS="-l$ac_lib $ac_func_search_save_LIBS" ++ fi ++ if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_search_kinfo_getvmmap=$ac_res ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext ++ if test "${ac_cv_search_kinfo_getvmmap+set}" = set; then : ++ break ++fi ++done ++if test "${ac_cv_search_kinfo_getvmmap+set}" = set; then : ++ ++else ++ ac_cv_search_kinfo_getvmmap=no ++fi ++rm conftest.$ac_ext ++LIBS=$ac_func_search_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_kinfo_getvmmap" >&5 ++$as_echo "$ac_cv_search_kinfo_getvmmap" >&6; } ++ac_res=$ac_cv_search_kinfo_getvmmap ++if test "$ac_res" != no; then : ++ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ++ ++$as_echo "#define HAVE_KINFO_GETVMMAP 1" >>confdefs.h ++ ++fi ++ ++ + + + +diff --git gdb/configure.ac gdb/configure.ac +index 4a0b6a3..38747e8 100644 +--- gdb/configure.ac ++++ gdb/configure.ac +@@ -537,6 +537,11 @@ AM_ZLIB + # On HP/UX we may need libxpdl for dlgetmodinfo (used by solib-pa64.c). + AC_SEARCH_LIBS(dlgetmodinfo, [dl xpdl]) + ++# On FreeBSD we may need libutil for kinfo_getvmmap (used by fbsd-nat.c). ++AC_SEARCH_LIBS(kinfo_getvmmap, util, ++ [AC_DEFINE(HAVE_KINFO_GETVMMAP, 1, ++ [Define to 1 if your system has the kinfo_getvmmap function. ])]) ++ + AM_ICONV + + # GDB may fork/exec the iconv program to get the list of supported character +diff --git gdb/fbsd-nat.c gdb/fbsd-nat.c +index 062eede..1ce197d 100644 +--- gdb/fbsd-nat.c ++++ gdb/fbsd-nat.c +@@ -26,6 +26,10 @@ + #include + #include + #include ++#ifdef HAVE_KINFO_GETVMMAP ++#include ++#include ++#endif + + #include "elf-bfd.h" + #include "fbsd-nat.h" +@@ -62,6 +66,64 @@ fbsd_pid_to_exec_file (struct target_ops *self, int pid) + return NULL; + } + ++#ifdef HAVE_KINFO_GETVMMAP ++/* Iterate over all the memory regions in the current inferior, ++ calling FUNC for each memory region. OBFD is passed as the last ++ argument to FUNC. */ ++ ++int ++fbsd_find_memory_regions (struct target_ops *self, ++ find_memory_region_ftype func, void *obfd) ++{ ++ pid_t pid = ptid_get_pid (inferior_ptid); ++ struct kinfo_vmentry *vmentl, *kve; ++ uint64_t size; ++ struct cleanup *cleanup; ++ int i, nitems; ++ ++ vmentl = kinfo_getvmmap (pid, &nitems); ++ if (vmentl == NULL) ++ perror_with_name (_("Couldn't fetch VM map entries.")); ++ cleanup = make_cleanup (free, vmentl); ++ ++ for (i = 0; i < nitems; i++) ++ { ++ kve = &vmentl[i]; ++ ++ /* Skip unreadable segments and those where MAP_NOCORE has been set. */ ++ if (!(kve->kve_protection & KVME_PROT_READ) ++ || kve->kve_flags & KVME_FLAG_NOCOREDUMP) ++ continue; ++ ++ /* Skip segments with an invalid type. */ ++ if (kve->kve_type != KVME_TYPE_DEFAULT ++ && kve->kve_type != KVME_TYPE_VNODE ++ && kve->kve_type != KVME_TYPE_SWAP ++ && kve->kve_type != KVME_TYPE_PHYS) ++ continue; ++ ++ size = kve->kve_end - kve->kve_start; ++ if (info_verbose) ++ { ++ fprintf_filtered (gdb_stdout, ++ "Save segment, %ld bytes at %s (%c%c%c)\n", ++ (long) size, ++ paddress (target_gdbarch (), kve->kve_start), ++ kve->kve_protection & KVME_PROT_READ ? 'r' : '-', ++ kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-', ++ kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-'); ++ } ++ ++ /* Invoke the callback function to create the corefile segment. ++ Pass MODIFIED as true, we do not know the real modification state. */ ++ func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ, ++ kve->kve_protection & KVME_PROT_WRITE, ++ kve->kve_protection & KVME_PROT_EXEC, 1, obfd); ++ } ++ do_cleanups (cleanup); ++ return 0; ++} ++#else + static int + fbsd_read_mapping (FILE *mapfile, unsigned long *start, unsigned long *end, + char *protection) +@@ -137,3 +199,4 @@ fbsd_find_memory_regions (struct target_ops *self, + do_cleanups (cleanup); + return 0; + } ++#endif Property changes on: head/devel/gdb/files/commit-2526815 ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/devel/gdb/files/commit-3ce5b6e =================================================================== --- head/devel/gdb/files/commit-3ce5b6e (nonexistent) +++ head/devel/gdb/files/commit-3ce5b6e (revision 384978) @@ -0,0 +1,21 @@ +diff --git gdb/fbsd-tdep.c gdb/fbsd-tdep.c +index 5d17f03..9609cd8 100644 +--- gdb/fbsd-tdep.c ++++ gdb/fbsd-tdep.c +@@ -89,7 +89,7 @@ fbsd_collect_regset_section_cb (const char *sect_name, int size, + static char * + fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) + { +- const struct regcache *regcache = get_current_regcache (); ++ struct regcache *regcache = get_current_regcache (); + char *note_data; + Elf_Internal_Ehdr *i_ehdrp; + struct fbsd_collect_regset_section_cb_data data; +@@ -104,6 +104,7 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) + data.obfd = obfd; + data.note_data = NULL; + data.note_size = note_size; ++ target_fetch_registers (regcache, -1); + gdbarch_iterate_over_regset_sections (gdbarch, + fbsd_collect_regset_section_cb, + &data, regcache); Property changes on: head/devel/gdb/files/commit-3ce5b6e ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/devel/gdb/files/commit-773eacf =================================================================== --- head/devel/gdb/files/commit-773eacf (nonexistent) +++ head/devel/gdb/files/commit-773eacf (revision 384978) @@ -0,0 +1,99 @@ +diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c +index e11b0f3..62dcb83 100644 +--- gdb/amd64fbsd-tdep.c ++++ gdb/amd64fbsd-tdep.c +@@ -51,8 +51,8 @@ amd64fbsd_sigtramp_p (struct frame_info *this_frame) + + if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf)) + return 0; +- if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code) != +- 0) ++ if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code) ++ != 0) + return 0; + + return 1; +diff --git gdb/i386fbsd-tdep.c gdb/i386fbsd-tdep.c +index d4516ee..ed41706 100644 +--- gdb/i386fbsd-tdep.c ++++ gdb/i386fbsd-tdep.c +@@ -105,24 +105,24 @@ static const gdb_byte i386fbsd_osigtramp_end[] = + }; + + /* The three different trampolines are all the same size. */ +-gdb_static_assert (sizeof i386fbsd_sigtramp_start == +- sizeof i386fbsd_freebsd4_sigtramp_start); +-gdb_static_assert (sizeof i386fbsd_sigtramp_start == +- sizeof i386fbsd_osigtramp_start); +-gdb_static_assert (sizeof i386fbsd_sigtramp_middle == +- sizeof i386fbsd_freebsd4_sigtramp_middle); +-gdb_static_assert (sizeof i386fbsd_sigtramp_middle == +- sizeof i386fbsd_osigtramp_middle); +-gdb_static_assert (sizeof i386fbsd_sigtramp_end == +- sizeof i386fbsd_freebsd4_sigtramp_end); +-gdb_static_assert (sizeof i386fbsd_sigtramp_end == +- sizeof i386fbsd_osigtramp_end); ++gdb_static_assert (sizeof i386fbsd_sigtramp_start ++ == sizeof i386fbsd_freebsd4_sigtramp_start); ++gdb_static_assert (sizeof i386fbsd_sigtramp_start ++ == sizeof i386fbsd_osigtramp_start); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle ++ == sizeof i386fbsd_freebsd4_sigtramp_middle); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle ++ == sizeof i386fbsd_osigtramp_middle); ++gdb_static_assert (sizeof i386fbsd_sigtramp_end ++ == sizeof i386fbsd_freebsd4_sigtramp_end); ++gdb_static_assert (sizeof i386fbsd_sigtramp_end ++ == sizeof i386fbsd_osigtramp_end); + + /* We assume that the middle is the largest chunk below. */ +-gdb_static_assert (sizeof i386fbsd_sigtramp_middle > +- sizeof i386fbsd_sigtramp_start); +-gdb_static_assert (sizeof i386fbsd_sigtramp_middle > +- sizeof i386fbsd_sigtramp_end); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle ++ > sizeof i386fbsd_sigtramp_start); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle ++ > sizeof i386fbsd_sigtramp_end); + + static int + i386fbsd_sigtramp_p (struct frame_info *this_frame) +@@ -135,19 +135,25 @@ i386fbsd_sigtramp_p (struct frame_info *this_frame) + if (!safe_frame_unwind_memory (this_frame, pc, buf, + sizeof i386fbsd_sigtramp_start)) + return 0; +- if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start) == +- 0) { +- middle = i386fbsd_sigtramp_middle; +- end = i386fbsd_sigtramp_end; +- } else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start, +- sizeof i386fbsd_freebsd4_sigtramp_start) == 0) { +- middle = i386fbsd_freebsd4_sigtramp_middle; +- end = i386fbsd_freebsd4_sigtramp_end; +- } else if (memcmp (buf, i386fbsd_osigtramp_start, +- sizeof i386fbsd_osigtramp_start) == 0) { +- middle = i386fbsd_osigtramp_middle; +- end = i386fbsd_osigtramp_end; +- } else ++ if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start) ++ == 0) ++ { ++ middle = i386fbsd_sigtramp_middle; ++ end = i386fbsd_sigtramp_end; ++ } ++ else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start, ++ sizeof i386fbsd_freebsd4_sigtramp_start) == 0) ++ { ++ middle = i386fbsd_freebsd4_sigtramp_middle; ++ end = i386fbsd_freebsd4_sigtramp_end; ++ } ++ else if (memcmp (buf, i386fbsd_osigtramp_start, ++ sizeof i386fbsd_osigtramp_start) == 0) ++ { ++ middle = i386fbsd_osigtramp_middle; ++ end = i386fbsd_osigtramp_end; ++ } ++ else + return 0; + + /* Since the end is shorter than the middle, check for a matching end Property changes on: head/devel/gdb/files/commit-773eacf ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/devel/gdb/files/commit-97de354 =================================================================== --- head/devel/gdb/files/commit-97de354 (nonexistent) +++ head/devel/gdb/files/commit-97de354 (revision 384978) @@ -0,0 +1,690 @@ +diff --git bfd/elf.c bfd/elf.c +index a031b9e..41fb023 100644 +--- bfd/elf.c ++++ bfd/elf.c +@@ -8737,6 +8737,9 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_xstatereg (abfd, note); ++ else if (note->namesz == 8 ++ && strcmp (note->namedata, "FreeBSD") == 0) ++ return elfcore_grok_xstatereg (abfd, note); + else + return TRUE; + +@@ -9556,7 +9559,11 @@ char * + elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz, + const void *xfpregs, int size) + { +- char *note_name = "LINUX"; ++ char *note_name; ++ if (get_elf_backend_data (abfd)->elf_osabi == ELFOSABI_FREEBSD) ++ note_name = "FreeBSD"; ++ else ++ note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_X86_XSTATE, xfpregs, size); + } +diff --git gdb/amd64-tdep.c gdb/amd64-tdep.c +index 3e5d1bd..461b701 100644 +--- gdb/amd64-tdep.c ++++ gdb/amd64-tdep.c +@@ -39,6 +39,7 @@ + #include "disasm.h" + #include "amd64-tdep.h" + #include "i387-tdep.h" ++#include "x86-xstate.h" + + #include "features/i386/amd64.c" + #include "features/i386/amd64-avx.c" +@@ -3118,6 +3119,25 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + set_gdbarch_ptr_bit (gdbarch, 32); + } + ++/* Return the target description for a specified XSAVE feature mask. */ ++ ++const struct target_desc * ++amd64_target_description (uint64_t xcr0) ++{ ++ switch (xcr0 & X86_XSTATE_ALL_MASK) ++ { ++ case X86_XSTATE_MPX_AVX512_MASK: ++ case X86_XSTATE_AVX512_MASK: ++ return tdesc_amd64_avx512; ++ case X86_XSTATE_MPX_MASK: ++ return tdesc_amd64_mpx; ++ case X86_XSTATE_AVX_MASK: ++ return tdesc_amd64_avx; ++ default: ++ return tdesc_amd64; ++ } ++} ++ + /* Provide a prototype to silence -Wmissing-prototypes. */ + void _initialize_amd64_tdep (void); + +diff --git gdb/amd64-tdep.h gdb/amd64-tdep.h +index 318fd43..704225e 100644 +--- gdb/amd64-tdep.h ++++ gdb/amd64-tdep.h +@@ -84,6 +84,8 @@ enum amd64_regnum + + #define AMD64_NUM_REGS (AMD64_ZMM31H_REGNUM + 1) + ++extern struct target_desc *tdesc_amd64; ++ + extern struct displaced_step_closure *amd64_displaced_step_copy_insn + (struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to, + struct regcache *regs); +@@ -95,6 +97,7 @@ extern void amd64_displaced_step_fixup (struct gdbarch *gdbarch, + extern void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); + extern void amd64_x32_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch); ++extern const struct target_desc *amd64_target_description (uint64_t xcr0); + + /* Fill register REGNUM in REGCACHE with the appropriate + floating-point or SSE register value from *FXSAVE. If REGNUM is +diff --git gdb/amd64bsd-nat.c gdb/amd64bsd-nat.c +index 31060a123..66d4289 100644 +--- gdb/amd64bsd-nat.c ++++ gdb/amd64bsd-nat.c +@@ -35,6 +35,10 @@ + #include "inf-ptrace.h" + + ++#ifdef PT_GETXSTATE_INFO ++size_t amd64bsd_xsave_len; ++#endif ++ + /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +@@ -60,6 +64,20 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, + if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) + { + struct fpreg fpregs; ++#ifdef PT_GETXSTATE_INFO ++ char *xstateregs; ++ ++ if (amd64bsd_xsave_len != 0) ++ { ++ xstateregs = alloca (amd64bsd_xsave_len); ++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) ++ perror_with_name (_("Couldn't get extended state status")); ++ ++ amd64_supply_xsave (regcache, -1, xstateregs); ++ return; ++ } ++#endif + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) +@@ -99,6 +117,24 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, + if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) + { + struct fpreg fpregs; ++#ifdef PT_GETXSTATE_INFO ++ char *xstateregs; ++ ++ if (amd64bsd_xsave_len != 0) ++ { ++ xstateregs = alloca (amd64bsd_xsave_len); ++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) ++ perror_with_name (_("Couldn't get extended state status")); ++ ++ amd64_collect_xsave (regcache, regnum, xstateregs, 0); ++ ++ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) xstateregs, amd64bsd_xsave_len) == -1) ++ perror_with_name (_("Couldn't write extended state status")); ++ return; ++ } ++#endif + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) +diff --git gdb/amd64bsd-nat.h gdb/amd64bsd-nat.h +index 167eb56..09776ee 100644 +--- gdb/amd64bsd-nat.h ++++ gdb/amd64bsd-nat.h +@@ -20,6 +20,9 @@ + #ifndef AMD64BSD_NAT_H + #define AMD64BSD_NAT_H + ++/* Low level amd64 XSAVE info. */ ++extern size_t amd64bsd_xsave_len; ++ + /* Low level amd64 debug register functions. */ + + extern void amd64bsd_dr_set_control (unsigned long control); +diff --git gdb/amd64fbsd-nat.c gdb/amd64fbsd-nat.c +index b1b261c..a721f48 100644 +--- gdb/amd64fbsd-nat.c ++++ gdb/amd64fbsd-nat.c +@@ -151,6 +151,50 @@ amd64fbsd_mourn_inferior (struct target_ops *ops) + super_mourn_inferior (ops); + } + ++/* Implement the to_read_description method. */ ++ ++static const struct target_desc * ++amd64fbsd_read_description (struct target_ops *ops) ++{ ++#ifdef PT_GETXSTATE_INFO ++ static int xsave_probed; ++ static uint64_t xcr0; ++#endif ++ struct reg regs; ++ int is64; ++ ++ if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) ®s, 0) == -1) ++ perror_with_name (_("Couldn't get registers")); ++ is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL)); ++#ifdef PT_GETXSTATE_INFO ++ if (!xsave_probed) ++ { ++ struct ptrace_xstate_info info; ++ ++ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) ++ { ++ amd64bsd_xsave_len = info.xsave_len; ++ xcr0 = info.xsave_mask; ++ } ++ xsave_probed = 1; ++ } ++ ++ if (amd64bsd_xsave_len != 0) ++ { ++ if (is64) ++ return amd64_target_description (xcr0); ++ else ++ return i386_target_description (xcr0); ++ } ++#endif ++ if (is64) ++ return tdesc_amd64; ++ else ++ return tdesc_i386; ++} ++ + /* Provide a prototype to silence -Wmissing-prototypes. */ + void _initialize_amd64fbsd_nat (void); + +@@ -181,6 +225,7 @@ _initialize_amd64fbsd_nat (void) + + super_mourn_inferior = t->to_mourn_inferior; + t->to_mourn_inferior = amd64fbsd_mourn_inferior; ++ t->to_read_description = amd64fbsd_read_description; + + t->to_pid_to_exec_file = fbsd_pid_to_exec_file; + t->to_find_memory_regions = fbsd_find_memory_regions; +diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c +index 62dcb83..52705d9 100644 +--- gdb/amd64fbsd-tdep.c ++++ gdb/amd64fbsd-tdep.c +@@ -23,6 +23,9 @@ + #include "gdbcore.h" + #include "regcache.h" + #include "osabi.h" ++#include "regset.h" ++#include "i386fbsd-tdep.h" ++#include "x86-xstate.h" + + #include "amd64-tdep.h" + #include "bsd-uthread.h" +@@ -169,6 +172,59 @@ static int amd64fbsd_jmp_buf_reg_offset[] = + 0 * 8 /* %rip */ + }; + ++/* Implement the core_read_description gdbarch method. */ ++ ++static const struct target_desc * ++amd64fbsd_core_read_description (struct gdbarch *gdbarch, ++ struct target_ops *target, ++ bfd *abfd) ++{ ++ return amd64_target_description (i386fbsd_core_read_xcr0 (abfd)); ++} ++ ++/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */ ++ ++static void ++amd64fbsd_supply_xstateregset (const struct regset *regset, ++ struct regcache *regcache, int regnum, ++ const void *xstateregs, size_t len) ++{ ++ amd64_supply_xsave (regcache, regnum, xstateregs); ++} ++ ++/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */ ++ ++static void ++amd64fbsd_collect_xstateregset (const struct regset *regset, ++ const struct regcache *regcache, ++ int regnum, void *xstateregs, size_t len) ++{ ++ amd64_collect_xsave (regcache, regnum, xstateregs, 1); ++} ++ ++static const struct regset amd64fbsd_xstateregset = ++ { ++ NULL, ++ amd64fbsd_supply_xstateregset, ++ amd64fbsd_collect_xstateregset ++ }; ++ ++/* Iterate over core file register note sections. */ ++ ++static void ++amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, ++ iterate_over_regset_sections_cb *cb, ++ void *cb_data, ++ const struct regcache *regcache) ++{ ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ ++ cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); ++ cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data); ++ cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), ++ &amd64fbsd_xstateregset, "XSAVE extended state", cb_data); ++} ++ + static void + amd64fbsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +@@ -233,6 +289,15 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + tdep->sc_reg_offset = amd64fbsd_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset); + ++ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; ++ ++ /* Iterate over core file register note sections. */ ++ set_gdbarch_iterate_over_regset_sections ++ (gdbarch, amd64fbsd_iterate_over_regset_sections); ++ ++ set_gdbarch_core_read_description (gdbarch, ++ amd64fbsd_core_read_description); ++ + /* FreeBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread); +diff --git gdb/i386-tdep.c gdb/i386-tdep.c +index 4d97915..0c7eb5a 100644 +--- gdb/i386-tdep.c ++++ gdb/i386-tdep.c +@@ -8598,6 +8598,25 @@ i386_coff_osabi_sniffer (bfd *abfd) + } + + ++/* Return the target description for a specified XSAVE feature mask. */ ++ ++const struct target_desc * ++i386_target_description (uint64_t xcr0) ++{ ++ switch (xcr0 & X86_XSTATE_ALL_MASK) ++ { ++ case X86_XSTATE_MPX_AVX512_MASK: ++ case X86_XSTATE_AVX512_MASK: ++ return tdesc_i386_avx512; ++ case X86_XSTATE_MPX_MASK: ++ return tdesc_i386_mpx; ++ case X86_XSTATE_AVX_MASK: ++ return tdesc_i386_avx; ++ default: ++ return tdesc_i386; ++ } ++} ++ + /* Provide a prototype to silence -Wmissing-prototypes. */ + void _initialize_i386_tdep (void); + +diff --git gdb/i386-tdep.h gdb/i386-tdep.h +index 8bfd412..7880f6c 100644 +--- gdb/i386-tdep.h ++++ gdb/i386-tdep.h +@@ -328,6 +328,8 @@ enum record_i386_regnum + /* Size of the largest register. */ + #define I386_MAX_REGISTER_SIZE 64 + ++extern struct target_desc *tdesc_i386; ++ + /* Types for i386-specific registers. */ + extern struct type *i387_ext_type (struct gdbarch *gdbarch); + +@@ -416,6 +418,7 @@ extern void i386_svr4_init_abi (struct gdbarch_info, struct gdbarch *); + + extern int i386_process_record (struct gdbarch *gdbarch, + struct regcache *regcache, CORE_ADDR addr); ++extern const struct target_desc *i386_target_description (uint64_t xcr0); + + + +diff --git gdb/i386bsd-nat.c gdb/i386bsd-nat.c +index 16e0707..ac8a19b 100644 +--- gdb/i386bsd-nat.c ++++ gdb/i386bsd-nat.c +@@ -81,6 +81,10 @@ static int i386bsd_r_reg_offset[] = + so that we try PT_GETXMMREGS the first time around. */ + static int have_ptrace_xmmregs = -1; + #endif ++ ++#ifdef PT_GETXSTATE_INFO ++size_t i386bsd_xsave_len; ++#endif + + + /* Supply the general-purpose registers in GREGS, to REGCACHE. */ +@@ -148,7 +152,24 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, + struct fpreg fpregs; + #ifdef HAVE_PT_GETXMMREGS + char xmmregs[512]; ++#endif ++ ++#ifdef PT_GETXSTATE_INFO ++ if (i386bsd_xsave_len != 0) ++ { ++ char *xstateregs; ++ ++ xstateregs = alloca (i386bsd_xsave_len); ++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) ++ perror_with_name (_("Couldn't get extended state status")); + ++ i387_supply_xsave (regcache, -1, xstateregs); ++ return; ++ } ++#endif ++ ++#ifdef HAVE_PT_GETXMMREGS + if (have_ptrace_xmmregs != 0 + && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) +@@ -158,18 +179,15 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, + } + else + { ++ have_ptrace_xmmregs = 0; ++#endif + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + i387_supply_fsave (regcache, -1, &fpregs); ++#ifdef HAVE_PT_GETXMMREGS + } +-#else +- if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), +- (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) +- perror_with_name (_("Couldn't get floating point status")); +- +- i387_supply_fsave (regcache, -1, &fpregs); + #endif + } + } +@@ -204,7 +222,28 @@ i386bsd_store_inferior_registers (struct target_ops *ops, + struct fpreg fpregs; + #ifdef HAVE_PT_GETXMMREGS + char xmmregs[512]; ++#endif ++ ++#ifdef PT_GETXSTATE_INFO ++ if (i386bsd_xsave_len != 0) ++ { ++ char *xstateregs; ++ ++ xstateregs = alloca (i386bsd_xsave_len); ++ if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) ++ perror_with_name (_("Couldn't get extended state status")); + ++ i387_collect_xsave (regcache, -1, xstateregs, 0); ++ ++ if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1) ++ perror_with_name (_("Couldn't write extended state status")); ++ return; ++ } ++#endif ++ ++#ifdef HAVE_PT_GETXMMREGS + if (have_ptrace_xmmregs != 0 + && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) +diff --git gdb/i386bsd-nat.h gdb/i386bsd-nat.h +index a11f554..2f50c32 100644 +--- gdb/i386bsd-nat.h ++++ gdb/i386bsd-nat.h +@@ -25,6 +25,9 @@ + + extern struct target_ops *i386bsd_target (void); + ++/* Low level i386 XSAVE info. */ ++extern size_t i386bsd_xsave_len; ++ + /* low level i386 debug register functions used in i386fbsd-nat.c. */ + + extern void i386bsd_dr_set_control (unsigned long control); +diff --git gdb/i386fbsd-nat.c gdb/i386fbsd-nat.c +index ad439e3..6c43f2c 100644 +--- gdb/i386fbsd-nat.c ++++ gdb/i386fbsd-nat.c +@@ -116,6 +116,37 @@ i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) + } + + ++#ifdef PT_GETXSTATE_INFO ++/* Implement the to_read_description method. */ ++ ++static const struct target_desc * ++i386fbsd_read_description (struct target_ops *ops) ++{ ++ static int xsave_probed; ++ static uint64_t xcr0; ++ ++ if (!xsave_probed) ++ { ++ struct ptrace_xstate_info info; ++ ++ if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), ++ (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) ++ { ++ i386bsd_xsave_len = info.xsave_len; ++ xcr0 = info.xsave_mask; ++ } ++ xsave_probed = 1; ++ } ++ ++ if (i386bsd_xsave_len != 0) ++ { ++ return i386_target_description (xcr0); ++ } ++ else ++ return tdesc_i386; ++} ++#endif ++ + /* Prevent warning from -Wmissing-prototypes. */ + void _initialize_i386fbsd_nat (void); + +@@ -140,6 +171,9 @@ _initialize_i386fbsd_nat (void) + + #endif /* HAVE_PT_GETDBREGS */ + ++#ifdef PT_GETXSTATE_INFO ++ t->to_read_description = i386fbsd_read_description; ++#endif + + t->to_resume = i386fbsd_resume; + t->to_pid_to_exec_file = fbsd_pid_to_exec_file; +diff --git gdb/i386fbsd-tdep.c gdb/i386fbsd-tdep.c +index ed41706..99e08cb 100644 +--- gdb/i386fbsd-tdep.c ++++ gdb/i386fbsd-tdep.c +@@ -22,6 +22,9 @@ + #include "gdbcore.h" + #include "osabi.h" + #include "regcache.h" ++#include "regset.h" ++#include "i386fbsd-tdep.h" ++#include "x86-xstate.h" + + #include "i386-tdep.h" + #include "i387-tdep.h" +@@ -235,6 +238,100 @@ static int i386fbsd_jmp_buf_reg_offset[] = + 0 * 4 /* %eip */ + }; + ++/* Get XSAVE extended state xcr0 from core dump. */ ++ ++uint64_t ++i386fbsd_core_read_xcr0 (bfd *abfd) ++{ ++ asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate"); ++ uint64_t xcr0; ++ ++ if (xstate) ++ { ++ size_t size = bfd_section_size (abfd, xstate); ++ ++ /* Check extended state size. */ ++ if (size < X86_XSTATE_AVX_SIZE) ++ xcr0 = X86_XSTATE_SSE_MASK; ++ else ++ { ++ char contents[8]; ++ ++ if (! bfd_get_section_contents (abfd, xstate, contents, ++ I386_FBSD_XSAVE_XCR0_OFFSET, ++ 8)) ++ { ++ warning (_("Couldn't read `xcr0' bytes from " ++ "`.reg-xstate' section in core file.")); ++ return 0; ++ } ++ ++ xcr0 = bfd_get_64 (abfd, contents); ++ } ++ } ++ else ++ xcr0 = 0; ++ ++ return xcr0; ++} ++ ++/* Implement the core_read_description gdbarch method. */ ++ ++static const struct target_desc * ++i386fbsd_core_read_description (struct gdbarch *gdbarch, ++ struct target_ops *target, ++ bfd *abfd) ++{ ++ return i386_target_description (i386fbsd_core_read_xcr0 (abfd)); ++} ++ ++/* Similar to i386_supply_fpregset, but use XSAVE extended state. */ ++ ++static void ++i386fbsd_supply_xstateregset (const struct regset *regset, ++ struct regcache *regcache, int regnum, ++ const void *xstateregs, size_t len) ++{ ++ i387_supply_xsave (regcache, regnum, xstateregs); ++} ++ ++/* Similar to i386_collect_fpregset, but use XSAVE extended state. */ ++ ++static void ++i386fbsd_collect_xstateregset (const struct regset *regset, ++ const struct regcache *regcache, ++ int regnum, void *xstateregs, size_t len) ++{ ++ i387_collect_xsave (regcache, regnum, xstateregs, 1); ++} ++ ++/* Register set definitions. */ ++ ++static const struct regset i386fbsd_xstateregset = ++ { ++ NULL, ++ i386fbsd_supply_xstateregset, ++ i386fbsd_collect_xstateregset ++ }; ++ ++/* Iterate over core file register note sections. */ ++ ++static void ++i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, ++ iterate_over_regset_sections_cb *cb, ++ void *cb_data, ++ const struct regcache *regcache) ++{ ++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); ++ ++ cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); ++ cb (".reg2", tdep->sizeof_fpregset, &i386_fpregset, NULL, cb_data); ++ ++ if (tdep->xcr0 & X86_XSTATE_AVX) ++ cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), ++ &i386fbsd_xstateregset, "XSAVE extended state", cb_data); ++} ++ + static void + i386fbsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +@@ -376,6 +473,15 @@ i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + /* FreeBSD 4.0 introduced a new `struct sigcontext'. */ + tdep->sc_reg_offset = i386fbsd4_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset); ++ ++ tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; ++ ++ /* Iterate over core file register note sections. */ ++ set_gdbarch_iterate_over_regset_sections ++ (gdbarch, i386fbsd_iterate_over_regset_sections); ++ ++ set_gdbarch_core_read_description (gdbarch, ++ i386fbsd_core_read_description); + } + + +diff --git gdb/i386fbsd-tdep.h gdb/i386fbsd-tdep.h +new file mode 100644 +index 0000000..8d6f998 +--- /dev/null ++++ gdb/i386fbsd-tdep.h +@@ -0,0 +1,31 @@ ++/* Target-dependent code for FreeBSD x86. ++ ++ Copyright (C) 2015 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 3 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, see . */ ++ ++#ifndef I386FBSD_TDEP_H ++#define I386FBSD_TDEP_H ++ ++/* Get XSAVE extended state xcr0 from core dump. */ ++extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); ++ ++/* The format of the XSAVE extended area is determined by hardware. ++ Cores store the XSAVE extended area in a NT_X86_XSTATE note that ++ matches the layout on Linux. */ ++#define I386_FBSD_XSAVE_XCR0_OFFSET 464 ++ ++#endif /* i386fbsd-tdep.h */ Property changes on: head/devel/gdb/files/commit-97de354 ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/devel/gdb/files/commit-c5cb74e =================================================================== --- head/devel/gdb/files/commit-c5cb74e (nonexistent) +++ head/devel/gdb/files/commit-c5cb74e (revision 384978) @@ -0,0 +1,22 @@ +diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c +index 2d49cdf..abb0cab 100644 +--- gdb/amd64fbsd-tdep.c ++++ gdb/amd64fbsd-tdep.c +@@ -37,12 +37,16 @@ + static CORE_ADDR + amd64fbsd_sigcontext_addr (struct frame_info *this_frame) + { ++ struct gdbarch *gdbarch = get_frame_arch (this_frame); ++ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp; ++ gdb_byte buf[8]; + + /* The `struct sigcontext' (which really is an `ucontext_t' on + FreeBSD/amd64) lives at a fixed offset in the signal frame. See + . */ +- sp = frame_unwind_register_unsigned (this_frame, AMD64_RSP_REGNUM); ++ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); ++ sp = extract_unsigned_integer (buf, 8, byte_order); + return sp + 16; + } + Property changes on: head/devel/gdb/files/commit-c5cb74e ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/devel/gdb/files/commit-cf424ae =================================================================== --- head/devel/gdb/files/commit-cf424ae (nonexistent) +++ head/devel/gdb/files/commit-cf424ae (revision 384978) @@ -0,0 +1,348 @@ +diff --git gdb/amd64fbsd-nat.c gdb/amd64fbsd-nat.c +index 1c396e2..b1b261c 100644 +--- gdb/amd64fbsd-nat.c ++++ gdb/amd64fbsd-nat.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + + #include "fbsd-nat.h" +@@ -244,24 +245,31 @@ Please report this to ."), + + SC_RBP_OFFSET = offset; + +- /* FreeBSD provides a kern.ps_strings sysctl that we can use to +- locate the sigtramp. That way we can still recognize a sigtramp +- if its location is changed in a new kernel. Of course this is +- still based on the assumption that the sigtramp is placed +- directly under the location where the program arguments and +- environment can be found. */ ++#ifdef KERN_PROC_SIGTRAMP ++ /* Normally signal frames are detected via amd64fbsd_sigtramp_p. ++ However, FreeBSD 9.2 through 10.1 do not include the page holding ++ the signal code in core dumps. These releases do provide a ++ kern.proc.sigtramp. sysctl that returns the location of the ++ signal trampoline for a running process. We fetch the location ++ of the current (gdb) process and use this to identify signal ++ frames in core dumps from these releases. Note that this only ++ works for core dumps of 64-bit (FreeBSD/amd64) processes and does ++ not handle core dumps of 32-bit (FreeBSD/i386) processes. */ + { +- int mib[2]; +- long ps_strings; ++ int mib[4]; ++ struct kinfo_sigtramp kst; + size_t len; + + mib[0] = CTL_KERN; +- mib[1] = KERN_PS_STRINGS; +- len = sizeof (ps_strings); +- if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0) ++ mib[1] = KERN_PROC; ++ mib[2] = KERN_PROC_SIGTRAMP; ++ mib[3] = getpid (); ++ len = sizeof (kst); ++ if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) + { +- amd64fbsd_sigtramp_start_addr = ps_strings - 32; +- amd64fbsd_sigtramp_end_addr = ps_strings; ++ amd64fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; ++ amd64fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; + } + } ++#endif + } +diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c +index abb0cab..e11b0f3 100644 +--- gdb/amd64fbsd-tdep.c ++++ gdb/amd64fbsd-tdep.c +@@ -31,6 +31,33 @@ + + /* Support for signal handlers. */ + ++/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp ++ routine. */ ++ ++static const gdb_byte amd64fbsd_sigtramp_code[] = ++{ ++ 0x48, 0x8d, 0x7c, 0x24, 0x10, /* lea SIGF_UC(%rsp),%rdi */ ++ 0x6a, 0x00, /* pushq $0 */ ++ 0x48, 0xc7, 0xc0, 0xa1, 0x01, 0x00, 0x00, ++ /* movq $SYS_sigreturn,%rax */ ++ 0x0f, 0x05 /* syscall */ ++}; ++ ++static int ++amd64fbsd_sigtramp_p (struct frame_info *this_frame) ++{ ++ CORE_ADDR pc = get_frame_pc (this_frame); ++ gdb_byte buf[sizeof amd64fbsd_sigtramp_code]; ++ ++ if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf)) ++ return 0; ++ if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code) != ++ 0) ++ return 0; ++ ++ return 1; ++} ++ + /* Assuming THIS_FRAME is for a BSD sigtramp routine, return the + address of the associated sigcontext structure. */ + +@@ -88,8 +115,8 @@ static int amd64fbsd_r_reg_offset[] = + }; + + /* Location of the signal trampoline. */ +-CORE_ADDR amd64fbsd_sigtramp_start_addr = 0x7fffffffffc0ULL; +-CORE_ADDR amd64fbsd_sigtramp_end_addr = 0x7fffffffffe0ULL; ++CORE_ADDR amd64fbsd_sigtramp_start_addr; ++CORE_ADDR amd64fbsd_sigtramp_end_addr; + + /* From . */ + int amd64fbsd_sc_reg_offset[] = +@@ -199,6 +226,7 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + + amd64_init_abi (info, gdbarch); + ++ tdep->sigtramp_p = amd64fbsd_sigtramp_p; + tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr; + tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr; + tdep->sigcontext_addr = amd64fbsd_sigcontext_addr; +diff --git gdb/i386fbsd-nat.c gdb/i386fbsd-nat.c +index f4951d1..ad439e3 100644 +--- gdb/i386fbsd-nat.c ++++ gdb/i386fbsd-nat.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include "fbsd-nat.h" + #include "i386-tdep.h" +@@ -148,25 +149,28 @@ _initialize_i386fbsd_nat (void) + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (i386fbsd_supply_pcb); + +- /* FreeBSD provides a kern.ps_strings sysctl that we can use to +- locate the sigtramp. That way we can still recognize a sigtramp +- if its location is changed in a new kernel. Of course this is +- still based on the assumption that the sigtramp is placed +- directly under the location where the program arguments and +- environment can be found. */ +-#ifdef KERN_PS_STRINGS ++#ifdef KERN_PROC_SIGTRAMP ++ /* Normally signal frames are detected via i386fbsd_sigtramp_p. ++ However, FreeBSD 9.2 through 10.1 do not include the page holding ++ the signal code in core dumps. These releases do provide a ++ kern.proc.sigtramp. sysctl that returns the location of the ++ signal trampoline for a running process. We fetch the location ++ of the current (gdb) process and use this to identify signal ++ frames in core dumps from these releases. */ + { +- int mib[2]; +- u_long ps_strings; ++ int mib[4]; ++ struct kinfo_sigtramp kst; + size_t len; + + mib[0] = CTL_KERN; +- mib[1] = KERN_PS_STRINGS; +- len = sizeof (ps_strings); +- if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0) ++ mib[1] = KERN_PROC; ++ mib[2] = KERN_PROC_SIGTRAMP; ++ mib[3] = getpid (); ++ len = sizeof (kst); ++ if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) + { +- i386fbsd_sigtramp_start_addr = ps_strings - 128; +- i386fbsd_sigtramp_end_addr = ps_strings; ++ i386fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; ++ i386fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; + } + } + #endif +diff --git gdb/i386fbsd-tdep.c gdb/i386fbsd-tdep.c +index 8d237f0..d4516ee 100644 +--- gdb/i386fbsd-tdep.c ++++ gdb/i386fbsd-tdep.c +@@ -29,6 +29,154 @@ + #include "fbsd-tdep.h" + #include "solib-svr4.h" + ++/* Support for signal handlers. */ ++ ++/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp ++ routine. */ ++ ++/* FreeBSD/i386 supports three different signal trampolines, one for ++ versions before 4.0, a second for 4.x, and a third for 5.0 and ++ later. To complicate matters, FreeBSD/i386 binaries running under ++ an amd64 kernel use a different set of trampolines. These ++ trampolines differ from the i386 kernel trampolines in that they ++ omit a middle section that conditionally restores %gs. */ ++ ++static const gdb_byte i386fbsd_sigtramp_start[] = ++{ ++ 0x8d, 0x44, 0x24, 0x20, /* lea SIGF_UC(%esp),%eax */ ++ 0x50 /* pushl %eax */ ++}; ++ ++static const gdb_byte i386fbsd_sigtramp_middle[] = ++{ ++ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00, ++ /* testl $PSL_VM,UC_EFLAGS(%eax) */ ++ 0x75, 0x03, /* jne +3 */ ++ 0x8e, 0x68, 0x14 /* mov UC_GS(%eax),%gs */ ++}; ++ ++static const gdb_byte i386fbsd_sigtramp_end[] = ++{ ++ 0xb8, 0xa1, 0x01, 0x00, 0x00, /* movl $SYS_sigreturn,%eax */ ++ 0x50, /* pushl %eax */ ++ 0xcd, 0x80 /* int $0x80 */ ++}; ++ ++static const gdb_byte i386fbsd_freebsd4_sigtramp_start[] = ++{ ++ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC4(%esp),%eax */ ++ 0x50 /* pushl %eax */ ++}; ++ ++static const gdb_byte i386fbsd_freebsd4_sigtramp_middle[] = ++{ ++ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00, ++ /* testl $PSL_VM,UC4_EFLAGS(%eax) */ ++ 0x75, 0x03, /* jne +3 */ ++ 0x8e, 0x68, 0x14 /* mov UC4_GS(%eax),%gs */ ++}; ++ ++static const gdb_byte i386fbsd_freebsd4_sigtramp_end[] = ++{ ++ 0xb8, 0x58, 0x01, 0x00, 0x00, /* movl $344,%eax */ ++ 0x50, /* pushl %eax */ ++ 0xcd, 0x80 /* int $0x80 */ ++}; ++ ++static const gdb_byte i386fbsd_osigtramp_start[] = ++{ ++ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_SC(%esp),%eax */ ++ 0x50 /* pushl %eax */ ++}; ++ ++static const gdb_byte i386fbsd_osigtramp_middle[] = ++{ ++ 0xf7, 0x40, 0x18, 0x00, 0x00, 0x02, 0x00, ++ /* testl $PSL_VM,SC_PS(%eax) */ ++ 0x75, 0x03, /* jne +3 */ ++ 0x8e, 0x68, 0x44 /* mov SC_GS(%eax),%gs */ ++}; ++ ++static const gdb_byte i386fbsd_osigtramp_end[] = ++{ ++ 0xb8, 0x67, 0x00, 0x00, 0x00, /* movl $103,%eax */ ++ 0x50, /* pushl %eax */ ++ 0xcd, 0x80 /* int $0x80 */ ++}; ++ ++/* The three different trampolines are all the same size. */ ++gdb_static_assert (sizeof i386fbsd_sigtramp_start == ++ sizeof i386fbsd_freebsd4_sigtramp_start); ++gdb_static_assert (sizeof i386fbsd_sigtramp_start == ++ sizeof i386fbsd_osigtramp_start); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle == ++ sizeof i386fbsd_freebsd4_sigtramp_middle); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle == ++ sizeof i386fbsd_osigtramp_middle); ++gdb_static_assert (sizeof i386fbsd_sigtramp_end == ++ sizeof i386fbsd_freebsd4_sigtramp_end); ++gdb_static_assert (sizeof i386fbsd_sigtramp_end == ++ sizeof i386fbsd_osigtramp_end); ++ ++/* We assume that the middle is the largest chunk below. */ ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle > ++ sizeof i386fbsd_sigtramp_start); ++gdb_static_assert (sizeof i386fbsd_sigtramp_middle > ++ sizeof i386fbsd_sigtramp_end); ++ ++static int ++i386fbsd_sigtramp_p (struct frame_info *this_frame) ++{ ++ CORE_ADDR pc = get_frame_pc (this_frame); ++ gdb_byte buf[sizeof i386fbsd_sigtramp_middle]; ++ const gdb_byte *middle, *end; ++ ++ /* Look for a matching start. */ ++ if (!safe_frame_unwind_memory (this_frame, pc, buf, ++ sizeof i386fbsd_sigtramp_start)) ++ return 0; ++ if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start) == ++ 0) { ++ middle = i386fbsd_sigtramp_middle; ++ end = i386fbsd_sigtramp_end; ++ } else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start, ++ sizeof i386fbsd_freebsd4_sigtramp_start) == 0) { ++ middle = i386fbsd_freebsd4_sigtramp_middle; ++ end = i386fbsd_freebsd4_sigtramp_end; ++ } else if (memcmp (buf, i386fbsd_osigtramp_start, ++ sizeof i386fbsd_osigtramp_start) == 0) { ++ middle = i386fbsd_osigtramp_middle; ++ end = i386fbsd_osigtramp_end; ++ } else ++ return 0; ++ ++ /* Since the end is shorter than the middle, check for a matching end ++ next. */ ++ pc += sizeof i386fbsd_sigtramp_start; ++ if (!safe_frame_unwind_memory (this_frame, pc, buf, ++ sizeof i386fbsd_sigtramp_end)) ++ return 0; ++ if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) == 0) ++ return 1; ++ ++ /* If the end didn't match, check for a matching middle. */ ++ if (!safe_frame_unwind_memory (this_frame, pc, buf, ++ sizeof i386fbsd_sigtramp_middle)) ++ return 0; ++ if (memcmp (buf, middle, sizeof i386fbsd_sigtramp_middle) != 0) ++ return 0; ++ ++ /* The middle matched, check for a matching end. */ ++ pc += sizeof i386fbsd_sigtramp_middle; ++ if (!safe_frame_unwind_memory (this_frame, pc, buf, ++ sizeof i386fbsd_sigtramp_end)) ++ return 0; ++ if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) != 0) ++ return 0; ++ ++ return 1; ++} ++ + /* FreeBSD 3.0-RELEASE or later. */ + + /* From . */ +@@ -43,8 +191,8 @@ static int i386fbsd_r_reg_offset[] = + }; + + /* Sigtramp routine location. */ +-CORE_ADDR i386fbsd_sigtramp_start_addr = 0xbfbfdf20; +-CORE_ADDR i386fbsd_sigtramp_end_addr = 0xbfbfdff0; ++CORE_ADDR i386fbsd_sigtramp_start_addr; ++CORE_ADDR i386fbsd_sigtramp_end_addr; + + /* From . */ + int i386fbsd_sc_reg_offset[] = +@@ -139,6 +287,8 @@ i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) + /* FreeBSD uses -freg-struct-return by default. */ + tdep->struct_return = reg_struct_return; + ++ tdep->sigtramp_p = i386fbsd_sigtramp_p; ++ + /* FreeBSD uses a different memory layout. */ + tdep->sigtramp_start = i386fbsd_sigtramp_start_addr; + tdep->sigtramp_end = i386fbsd_sigtramp_end_addr; Property changes on: head/devel/gdb/files/commit-cf424ae ___________________________________________________________________ Added: fbsd:nokeywords ## -0,0 +1 ## +yes \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/devel/gdb/files/extrapatch-threads =================================================================== --- head/devel/gdb/files/extrapatch-threads (revision 384977) +++ head/devel/gdb/files/extrapatch-threads (revision 384978) @@ -1,712 +1,712 @@ -diff --git a/gdb/Makefile.in b/gdb/Makefile.in -index ea27cf5..d17752f 100644 +diff --git gdb/Makefile.in gdb/Makefile.in +index 7937801..6122f16 100644 --- gdb/Makefile.in +++ gdb/Makefile.in -@@ -668,6 +668,7 @@ ALL_TARGET_OBS = \ +@@ -691,6 +691,7 @@ ALL_TARGET_OBS = \ xtensa-config.o xtensa-tdep.o xtensa-linux-tdep.o \ glibc-tdep.o \ bsd-uthread.o \ + fbsd-threads.o \ nbsd-tdep.o obsd-tdep.o \ sol2-tdep.o \ - solib-frv.o solib-irix.o solib-svr4.o \ -@@ -1327,7 +1328,7 @@ libgdb.a: $(LIBGDB_OBS) + solib-frv.o solib-svr4.o \ +@@ -1366,7 +1367,7 @@ libgdb.a: $(LIBGDB_OBS) # Removing the old gdb first works better if it is running, at least on SunOS. gdb$(EXEEXT): gdb.o $(LIBGDB_OBS) $(ADD_DEPS) $(CDEPS) $(TDEPLIBS) rm -f gdb$(EXEEXT) - $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) \ + $(CC_LD) $(INTERNAL_LDFLAGS) $(WIN32LDAPP) -Wl,-E \ -o gdb$(EXEEXT) gdb.o $(LIBGDB_OBS) \ $(TDEPLIBS) $(TUI_LIBRARY) $(CLIBS) $(LOADLIBES) -@@ -1600,7 +1601,7 @@ ALLDEPFILES = \ +@@ -1639,7 +1640,7 @@ ALLDEPFILES = \ armnbsd-nat.c armbsd-tdep.c armnbsd-tdep.c armobsd-tdep.c \ avr-tdep.c \ bfin-linux-tdep.c bfin-tdep.c \ - bsd-uthread.c bsd-kvm.c \ + bsd-uthread.c fbsd-threads.c bsd-kvm.c \ core-regset.c \ dcache.c dicos-tdep.c darwin-nat.c \ exec.c \ -diff --git a/gdb/amd64bsd-nat.c b/gdb/amd64bsd-nat.c -index 9e6a0df..7aff6f0 100644 +diff --git gdb/amd64bsd-nat.c gdb/amd64bsd-nat.c +index b1d4a0e..7f189f6 100644 --- gdb/amd64bsd-nat.c +++ gdb/amd64bsd-nat.c -@@ -41,6 +41,19 @@ - size_t x86_xsave_len; +@@ -40,6 +40,19 @@ + size_t amd64bsd_xsave_len; #endif +static pid_t +ptrace_pid (ptid_t ptid) +{ + pid_t pid; + +#ifdef __FreeBSD__ + pid = ptid_get_lwp (ptid); + if (pid == 0) +#endif + pid = ptid_get_pid (ptid); + return pid; +} + /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this for all registers (including the floating-point registers). */ -@@ -54,7 +67,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, +@@ -53,7 +66,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, { struct reg regs; - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); -@@ -72,7 +85,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, - if (x86_xsave_len != 0) +@@ -71,7 +84,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, + if (amd64bsd_xsave_len != 0) { - xstateregs = alloca(x86_xsave_len); + xstateregs = alloca (amd64bsd_xsave_len); - if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETXSTATE, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); -@@ -81,7 +94,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, +@@ -80,7 +93,7 @@ amd64bsd_fetch_inferior_registers (struct target_ops *ops, } #endif - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); -@@ -104,11 +117,11 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, +@@ -103,11 +116,11 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, memset( ®s, 0, sizeof(struct reg)); memset( &oldregs, 0, sizeof(struct reg)); - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); - ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &oldregs, 0); amd64_collect_native_gregset (regcache, ®s, regnum); -@@ -118,7 +131,7 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, +@@ -117,7 +130,7 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, regs.r_rflags ^= (regs.r_rflags ^ oldregs.r_rflags ) & ~PSL_USERCHANGE; //printf(" allowed regs.r_rflags = 0x%8.8X\n", regs.r_rflags ); } - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); -@@ -135,26 +148,26 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, - if (x86_xsave_len != 0) +@@ -134,26 +147,26 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, + if (amd64bsd_xsave_len != 0) { - xstateregs = alloca(x86_xsave_len); + xstateregs = alloca (amd64bsd_xsave_len); - if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETXSTATE, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); amd64_collect_xsave (regcache, regnum, xstateregs, 0); - if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETXSTATE, ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, x86_xsave_len) == -1) + (PTRACE_TYPE_ARG3) xstateregs, amd64bsd_xsave_len) == -1) perror_with_name (_("Couldn't write extended state status")); return; } #endif - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); amd64_collect_fxsave (regcache, regnum, &fpregs); - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't write floating point status")); } -@@ -184,7 +197,7 @@ amd64bsd_dr_get (ptid_t ptid, int regnum) +@@ -183,7 +196,7 @@ amd64bsd_dr_get (ptid_t ptid, int regnum) { struct dbreg dbregs; - if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETDBREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) perror_with_name (_("Couldn't read debug registers")); -@@ -196,7 +209,7 @@ amd64bsd_dr_set (int regnum, unsigned long value) +@@ -195,7 +208,7 @@ amd64bsd_dr_set (int regnum, unsigned long value) { struct dbreg dbregs; - if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETDBREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) perror_with_name (_("Couldn't get debug registers")); -@@ -207,7 +220,7 @@ amd64bsd_dr_set (int regnum, unsigned long value) +@@ -206,7 +219,7 @@ amd64bsd_dr_set (int regnum, unsigned long value) DBREG_DRX ((&dbregs), regnum) = value; - if (ptrace (PT_SETDBREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETDBREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) perror_with_name (_("Couldn't write debug registers")); } -diff --git a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c -index eea2472..9ce6a54 100644 +diff --git gdb/amd64fbsd-nat.c gdb/amd64fbsd-nat.c +index a721f48..2534360 100644 --- gdb/amd64fbsd-nat.c +++ gdb/amd64fbsd-nat.c @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "gregset.h" #include "inferior.h" #include "regcache.h" #include "target.h" -@@ -95,6 +96,46 @@ static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] = +@@ -92,6 +93,46 @@ static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] = }; +/* Transfering the registers between GDB, inferiors and core files. */ + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) +{ + amd64_supply_native_gregset (regcache, gregsetp, -1); +} + +/* Fill register REGNUM (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNUM is -1, + do this for all registers. */ + +void +fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum) +{ + amd64_collect_native_gregset (regcache, gregsetp, regnum); +} + +/* Fill GDB's register array with the floating-point register values + in *FPREGSETP. */ + +void +supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) +{ + amd64_supply_fxsave (regcache, -1, fpregsetp); +} + +/* Fill register REGNUM (if it is a floating-point register) in + *FPREGSETP with the value in GDB's register array. If REGNUM is -1, + do this for all registers. */ + +void +fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum) +{ + amd64_collect_fxsave (regcache, regnum, fpregsetp); +} + /* Support for debugging kernel virtual memory images. */ #include -diff --git a/gdb/amd64fbsd-tdep.c b/gdb/amd64fbsd-tdep.c -index 582ae50..8e07369 100644 +diff --git gdb/amd64fbsd-tdep.c gdb/amd64fbsd-tdep.c +index 52705d9..6d48d8f 100644 --- gdb/amd64fbsd-tdep.c +++ gdb/amd64fbsd-tdep.c -@@ -31,7 +31,6 @@ - #include +@@ -28,7 +28,6 @@ + #include "x86-xstate.h" #include "amd64-tdep.h" -#include "bsd-uthread.h" + #include "fbsd-tdep.h" #include "solib-svr4.h" - /* Supported register note sections. */ -@@ -178,46 +177,6 @@ amd64fbsd_core_read_description (struct gdbarch *gdbarch, +@@ -226,46 +225,6 @@ amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, } static void -amd64fbsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[8]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++) - { - if (amd64fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8); - regcache_raw_supply (regcache, i, buf); - } - } -} - -static void -amd64fbsd_collect_uthread (const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[8]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++) - { - if (amd64fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - regcache_raw_collect (regcache, i, buf); - write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8); - } - } -} - -static void amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); -@@ -245,10 +204,6 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +@@ -298,10 +257,6 @@ amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_core_read_description (gdbarch, amd64fbsd_core_read_description); - /* FreeBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread); - /* FreeBSD uses SVR4-style shared libraries. */ set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets); -diff --git a/gdb/configure.tgt b/gdb/configure.tgt -index 01311b2..0929a25 100644 +diff --git gdb/configure.tgt gdb/configure.tgt +index 7fdd34e..64afacf 100644 --- gdb/configure.tgt +++ gdb/configure.tgt -@@ -189,7 +189,7 @@ i[34567]86-*-dicos*) +@@ -187,7 +187,7 @@ i[34567]86-*-dicos*) i[34567]86-*-freebsd* | i[34567]86-*-kfreebsd*-gnu) # Target: FreeBSD/i386 gdb_target_obs="i386-tdep.o i387-tdep.o i386bsd-tdep.o i386fbsd-tdep.o \ -- bsd-uthread.o solib-svr4.o" -+ fbsd-threads.o solib-svr4.o" +- bsd-uthread.o fbsd-tdep.o solib-svr4.o" ++ fbsd-threads.o fbsd-tdep.o solib-svr4.o" ;; i[34567]86-*-netbsd* | i[34567]86-*-knetbsd*-gnu) # Target: NetBSD/i386 -@@ -415,7 +415,7 @@ nios2*-*-*) +@@ -410,7 +410,7 @@ nios2*-*-*) powerpc*-*-freebsd*) # Target: FreeBSD/powerpc gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc64-tdep.o \ -- ppcfbsd-tdep.o solib-svr4.o \ -+ ppcfbsd-tdep.o solib-svr4.o fbsd-threads.o \ +- ppcfbsd-tdep.o fbsd-tdep.o solib-svr4.o \ ++ ppcfbsd-tdep.o fbsd-threads.o fbsd-tdep.o solib-svr4.o \ ravenscar-thread.o ppc-ravenscar-thread.o" ;; -@@ -667,7 +667,7 @@ x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) +@@ -663,7 +663,7 @@ x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) # Target: FreeBSD/amd64 gdb_target_obs="amd64-tdep.o amd64fbsd-tdep.o i386-tdep.o \ i387-tdep.o i386bsd-tdep.o i386fbsd-tdep.o \ -- bsd-uthread.o solib-svr4.o" -+ fbsd-threads.o solib-svr4.o" +- bsd-uthread.o fbsd-tdep.o solib-svr4.o" ++ fbsd-threads.o fbsd-tdep.o solib-svr4.o" ;; x86_64-*-mingw* | x86_64-*-cygwin*) # Target: MingW/amd64 -diff --git a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c -index c26e830..246acdd 100644 +diff --git gdb/i386bsd-nat.c gdb/i386bsd-nat.c +index ac8a19b..cb2d50e 100644 --- gdb/i386bsd-nat.c +++ gdb/i386bsd-nat.c -@@ -89,9 +89,22 @@ size_t x86_xsave_len; +@@ -87,9 +87,22 @@ size_t i386bsd_xsave_len; #endif +static pid_t +ptrace_pid (ptid_t ptid) +{ + pid_t pid; + +#ifdef __FreeBSD__ + pid = ptid_get_lwp (ptid); + if (pid == 0) +#endif + pid = ptid_get_pid (ptid); + return pid; +} + /* Supply the general-purpose registers in GREGS, to REGCACHE. */ -static void +void i386bsd_supply_gregset (struct regcache *regcache, const void *gregs) { const char *regs = gregs; -@@ -110,7 +123,7 @@ i386bsd_supply_gregset (struct regcache *regcache, const void *gregs) +@@ -108,7 +121,7 @@ i386bsd_supply_gregset (struct regcache *regcache, const void *gregs) GREGS. If REGNUM is -1, collect and store all appropriate registers. */ -static void +void i386bsd_collect_gregset (const struct regcache *regcache, void *gregs, int regnum) { -@@ -140,7 +153,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, +@@ -138,7 +151,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, { struct reg regs; - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); -@@ -162,7 +175,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, +@@ -160,7 +173,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, char *xstateregs; - xstateregs = alloca(x86_xsave_len); + xstateregs = alloca (i386bsd_xsave_len); - if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETXSTATE, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); -@@ -174,7 +187,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, +@@ -171,7 +184,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, #ifdef HAVE_PT_GETXMMREGS if (have_ptrace_xmmregs != 0 - && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), + && ptrace(PT_GETXMMREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) { have_ptrace_xmmregs = 1; -@@ -184,7 +197,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, +@@ -181,7 +194,7 @@ i386bsd_fetch_inferior_registers (struct target_ops *ops, { have_ptrace_xmmregs = 0; #endif - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); -@@ -206,13 +219,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, +@@ -203,13 +216,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, { struct reg regs; - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); i386bsd_collect_gregset (regcache, ®s, regnum); - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); -@@ -233,13 +246,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, +@@ -230,13 +243,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, char *xstateregs; - xstateregs = alloca(x86_xsave_len); + xstateregs = alloca (i386bsd_xsave_len); - if (ptrace (PT_GETXSTATE, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETXSTATE, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) perror_with_name (_("Couldn't get extended state status")); i387_collect_xsave (regcache, -1, xstateregs, 0); - if (ptrace (PT_SETXSTATE, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETXSTATE, ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, x86_xsave_len) == -1) + (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1) perror_with_name (_("Couldn't write extended state status")); - } -@@ -247,14 +260,14 @@ i386bsd_store_inferior_registers (struct target_ops *ops, + return; +@@ -245,14 +258,14 @@ i386bsd_store_inferior_registers (struct target_ops *ops, #ifdef HAVE_PT_GETXMMREGS if (have_ptrace_xmmregs != 0 - && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid), + && ptrace(PT_GETXMMREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) { have_ptrace_xmmregs = 1; i387_collect_fxsave (regcache, regnum, xmmregs); - if (ptrace (PT_SETXMMREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETXMMREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) xmmregs, 0) == -1) perror_with_name (_("Couldn't write XMM registers")); } -@@ -262,13 +275,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, +@@ -260,13 +273,13 @@ i386bsd_store_inferior_registers (struct target_ops *ops, { have_ptrace_xmmregs = 0; #endif - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get floating point status")); i387_collect_fsave (regcache, regnum, &fpregs); - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't write floating point status")); #ifdef HAVE_PT_GETXMMREGS -@@ -307,7 +320,7 @@ i386bsd_dr_get (ptid_t ptid, int regnum) +@@ -305,7 +318,7 @@ i386bsd_dr_get (ptid_t ptid, int regnum) { struct dbreg dbregs; - if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETDBREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) perror_with_name (_("Couldn't read debug registers")); -@@ -319,7 +332,7 @@ i386bsd_dr_set (int regnum, unsigned int value) +@@ -317,7 +330,7 @@ i386bsd_dr_set (int regnum, unsigned int value) { struct dbreg dbregs; - if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETDBREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) perror_with_name (_("Couldn't get debug registers")); -@@ -330,7 +343,7 @@ i386bsd_dr_set (int regnum, unsigned int value) +@@ -328,7 +341,7 @@ i386bsd_dr_set (int regnum, unsigned int value) DBREG_DRX ((&dbregs), regnum) = value; - if (ptrace (PT_SETDBREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETDBREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) perror_with_name (_("Couldn't write debug registers")); } -diff --git a/gdb/i386bsd-nat.h b/gdb/i386bsd-nat.h -index 044f530..2fca773 100644 +diff --git gdb/i386bsd-nat.h gdb/i386bsd-nat.h +index 2f50c32..bf7f2ff 100644 --- gdb/i386bsd-nat.h +++ gdb/i386bsd-nat.h @@ -38,6 +38,14 @@ extern CORE_ADDR i386bsd_dr_get_addr (int regnum); extern unsigned long i386bsd_dr_get_status (void); +/* low level i386 register functions used in i386fbsd-nat.c. */ + +extern void i386bsd_supply_gregset (struct regcache *regcache, + const void *gregs); + +extern void i386bsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum); + extern unsigned long i386bsd_dr_get_control (void); #endif /* i386bsd-nat.h */ -diff --git a/gdb/i386fbsd-nat.c b/gdb/i386fbsd-nat.c -index b9620e1..71abcdf 100644 +diff --git gdb/i386fbsd-nat.c gdb/i386fbsd-nat.c +index a205a26..29b9444 100644 --- gdb/i386fbsd-nat.c +++ gdb/i386fbsd-nat.c @@ -21,6 +21,7 @@ #include "inferior.h" #include "regcache.h" #include "target.h" +#include "gregset.h" #include #include -@@ -82,6 +83,49 @@ i386fbsd_resume (struct target_ops *ops, +@@ -81,6 +82,49 @@ i386fbsd_resume (struct target_ops *ops, } +/* Transfering the registers between GDB, inferiors and core files. */ + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) +{ + i386bsd_supply_gregset (regcache, gregsetp); +} + +/* Fill register REGNUM (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNUM is -1, + do this for all registers. */ + +void +fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum) +{ + i386bsd_collect_gregset (regcache, gregsetp, regnum); +} + +#include "i387-tdep.h" + +/* Fill GDB's register array with the floating-point register values + in *FPREGSETP. */ + +void +supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) +{ + i387_supply_fsave (regcache, -1, fpregsetp); +} + +/* Fill register REGNUM (if it is a floating-point register) in + *FPREGSETP with the value in GDB's register array. If REGNUM is -1, + do this for all registers. */ + +void +fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum) +{ + i387_collect_fsave (regcache, regnum, fpregsetp); +} + + /* Support for debugging kernel virtual memory images. */ #include -diff --git a/gdb/i386fbsd-tdep.c b/gdb/i386fbsd-tdep.c -index 8f7109f..fcb85d8 100644 +diff --git gdb/i386fbsd-tdep.c gdb/i386fbsd-tdep.c +index 99e08cb..5bb15f6 100644 --- gdb/i386fbsd-tdep.c +++ gdb/i386fbsd-tdep.c -@@ -30,7 +30,6 @@ +@@ -28,7 +28,6 @@ #include "i386-tdep.h" #include "i387-tdep.h" -#include "bsd-uthread.h" + #include "fbsd-tdep.h" #include "solib-svr4.h" - /* FreeBSD 3.0-RELEASE or later. */ -@@ -153,46 +152,6 @@ i386fbsd_core_read_description (struct gdbarch *gdbarch, +@@ -333,46 +332,6 @@ i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, } static void -i386fbsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[4]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++) - { - if (i386fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4); - regcache_raw_supply (regcache, i, buf); - } - } -} - -static void -i386fbsd_collect_uthread (const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[4]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++) - { - if (i386fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - regcache_raw_collect (regcache, i, buf); - write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4); - } - } -} - -static void i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); -@@ -217,10 +176,6 @@ i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +@@ -399,10 +358,6 @@ i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* FreeBSD has a more complete `struct sigcontext'. */ tdep->sc_reg_offset = i386fbsd_sc_reg_offset; tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset); - - /* FreeBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread); } static void -diff --git a/gdb/ppcfbsd-nat.c b/gdb/ppcfbsd-nat.c -index 079bd12..74922f2 100644 +diff --git gdb/ppcfbsd-nat.c gdb/ppcfbsd-nat.c +index 778b4bb..fa9285f 100644 --- gdb/ppcfbsd-nat.c +++ gdb/ppcfbsd-nat.c -@@ -39,6 +39,19 @@ +@@ -37,6 +37,19 @@ #include "inf-ptrace.h" #include "bsd-kvm.h" +static pid_t +ptrace_pid (ptid_t ptid) +{ + pid_t pid; + +#ifdef __FreeBSD__ + pid = ptid_get_lwp (ptid); + if (pid == 0) +#endif + pid = ptid_get_pid (ptid); + return pid; +} + /* Fill GDB's register array with the general-purpose register values in *GREGSETP. */ -@@ -123,7 +136,7 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops, +@@ -121,7 +134,7 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops, { gdb_gregset_t regs; - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); -@@ -134,7 +147,7 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops, +@@ -132,7 +145,7 @@ ppcfbsd_fetch_inferior_registers (struct target_ops *ops, const struct regset *fpregset = ppc_fbsd_fpregset (); gdb_fpregset_t fpregs; - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get FP registers")); -@@ -151,13 +164,13 @@ ppcfbsd_store_inferior_registers (struct target_ops *ops, +@@ -149,13 +162,13 @@ ppcfbsd_store_inferior_registers (struct target_ops *ops, { gdb_gregset_t regs; - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); fill_gregset (regcache, ®s, regno); - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); -@@ -165,13 +178,13 @@ ppcfbsd_store_inferior_registers (struct target_ops *ops, +@@ -163,13 +176,13 @@ ppcfbsd_store_inferior_registers (struct target_ops *ops, { gdb_fpregset_t fpregs; - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_GETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get FP registers")); fill_fpregset (regcache, &fpregs, regno); - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + if (ptrace (PT_SETFPREGS, ptrace_pid (inferior_ptid), (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't set FP registers")); } Index: head/devel/gdb/files/fbsd-threads.c =================================================================== --- head/devel/gdb/files/fbsd-threads.c (revision 384977) +++ head/devel/gdb/files/fbsd-threads.c (revision 384978) @@ -1,1573 +1,1611 @@ /* $FreeBSD$ */ /* FreeBSD libthread_db assisted debugging support. Copyright 1999, 2000, 2001 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 -#include -#include -#include - #include #include #include #include #include #include #include #include #include "proc_service.h" #include "thread_db.h" #include "defs.h" #include "bfd.h" #include "elf-bfd.h" #include "gdb_assert.h" #include "gdbcore.h" #include "gdbthread.h" #include "inferior.h" #include "objfiles.h" #include "regcache.h" #include "symfile.h" #include "symtab.h" #include "target.h" #include "observer.h" #include "gdbcmd.h" #include "gregset.h" #ifdef PT_GETXMMREGS #include "i387-tdep.h" #endif #define LIBTHREAD_DB_SO "libthread_db.so" struct private_thread_info { char *lwp_name; }; struct ps_prochandle { pid_t pid; }; /* Defining the prototype of _initialize_thread_db to remove warning */ extern initialize_file_ftype _initialize_thread_db; /* This module's target vectors. */ static struct target_ops fbsd_thread_ops; /* Non-zero if there is a thread module */ static int fbsd_thread_present; /* Non-zero if we're using this module's target vector. */ static int fbsd_thread_active; /* Non-zero if we have to keep this module's target vector active across re-runs. */ static int keep_thread_db; /* Structure that identifies the child process for the interface. */ static struct ps_prochandle proc_handle; /* Connection to the libthread_db library. */ static td_thragent_t *thread_agent; /* The last thread we are single stepping */ static ptid_t last_single_step_thread; /* Pointers to the libthread_db functions. */ static td_err_e (*td_init_p) (void); static td_err_e (*td_ta_new_p) (struct ps_prochandle *ps, td_thragent_t **ta); static td_err_e (*td_ta_delete_p) (td_thragent_t *); static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, td_thrhandle_t *__th); static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th); static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, td_thr_iter_f *callback, void *cbdata_p, td_thr_state_e state, int ti_pri, sigset_t *ti_sigmask_p, unsigned int ti_user_flags); static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, td_event_e event, td_notify_t *ptr); static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, td_thr_events_t *event); static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, td_event_msg_t *msg); static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, td_thrinfo_t *infop); #ifdef PT_GETXMMREGS static td_err_e (*td_thr_getxmmregs_p) (const td_thrhandle_t *th, char *regset); #endif static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, prfpregset_t *regset); static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, prgregset_t gregs); #ifdef PT_GETXMMREGS static td_err_e (*td_thr_setxmmregs_p) (const td_thrhandle_t *th, const char *fpregs); #endif static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, const prfpregset_t *fpregs); static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, prgregset_t gregs); static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int event); static td_err_e (*td_thr_sstep_p) (td_thrhandle_t *th, int step); static td_err_e (*td_ta_tsd_iter_p) (const td_thragent_t *ta, td_key_iter_f *func, void *data); static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, void *map_address, size_t offset, void **address); static td_err_e (*td_thr_dbsuspend_p) (const td_thrhandle_t *); static td_err_e (*td_thr_dbresume_p) (const td_thrhandle_t *); static CORE_ADDR td_create_bp_addr; /* Location of the thread death event breakpoint. */ static CORE_ADDR td_death_bp_addr; /* Prototypes for local functions. */ static void fbsd_find_lwp_name(long lwpid, struct private_thread_info *info); -static void fbsd_thread_find_new_threads (struct target_ops *ops); +static void fbsd_thread_update_thread_list (struct target_ops *ops); static int fbsd_thread_alive (struct target_ops *ops, ptid_t ptid); static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, const td_thrinfo_t *ti_p, int verbose); static void fbsd_thread_detach (struct target_ops *ops, const char *args, int from_tty); CORE_ADDR fbsd_thread_get_local_address(struct target_ops *ops, ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset); /* Building process ids. */ #define GET_PID(ptid) ptid_get_pid (ptid) #define GET_LWP(ptid) ptid_get_lwp (ptid) #define GET_THREAD(ptid) ptid_get_tid (ptid) #define IS_LWP(ptid) (GET_LWP (ptid) != 0) #define IS_THREAD(ptid) (GET_THREAD (ptid) != 0) #define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0) #define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid) static void free_private_thread_info(struct private_thread_info *info) { xfree(info->lwp_name); xfree(info); } static char * thread_db_err_str (td_err_e err) { static char buf[64]; switch (err) { case TD_OK: return "generic 'call succeeded'"; case TD_ERR: return "generic error"; case TD_NOTHR: return "no thread to satisfy query"; case TD_NOSV: return "no sync handle to satisfy query"; case TD_NOLWP: return "no LWP to satisfy query"; case TD_BADPH: return "invalid process handle"; case TD_BADTH: return "invalid thread handle"; case TD_BADSH: return "invalid synchronization handle"; case TD_BADTA: return "invalid thread agent"; case TD_BADKEY: return "invalid key"; case TD_NOMSG: return "no event message for getmsg"; case TD_NOFPREGS: return "FPU register set not available"; case TD_NOLIBTHREAD: return "application not linked with libthread"; case TD_NOEVENT: return "requested event is not supported"; case TD_NOCAPAB: return "capability not available"; case TD_DBERR: return "debugger service failed"; case TD_NOAPLIC: return "operation not applicable to"; case TD_NOTSD: return "no thread-specific data for this thread"; case TD_MALLOC: return "malloc failed"; case TD_PARTIALREG: return "only part of register set was written/read"; case TD_NOXREGS: return "X register set not available for this thread"; default: snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err); return buf; } } static char * thread_db_state_str (td_thr_state_e state) { static char buf[64]; switch (state) { case TD_THR_STOPPED: return "stopped by debugger"; case TD_THR_RUN: return "runnable"; case TD_THR_ACTIVE: return "active"; case TD_THR_ZOMBIE: return "zombie"; case TD_THR_SLEEP: return "sleeping"; case TD_THR_STOPPED_ASLEEP: return "stopped by debugger AND blocked"; default: snprintf (buf, sizeof (buf), "unknown thread_db state %d", state); return buf; } } /* Convert LWP to user-level thread id. */ static ptid_t thread_from_lwp (ptid_t ptid, td_thrhandle_t *th, td_thrinfo_t *ti) { td_err_e err; gdb_assert (IS_LWP (ptid)); if (fbsd_thread_active) { err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), th); if (err == TD_OK) { err = td_thr_get_info_p (th, ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); return BUILD_THREAD (ti->ti_tid, GET_PID (ptid)); } } /* the LWP is not mapped to user thread */ return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid)); } static void fbsd_core_get_first_lwp (bfd *abfd, asection *asect, void *obj) { if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) return; if (*(lwpid_t *)obj != 0) return; *(lwpid_t *)obj = atoi (bfd_section_name (abfd, asect) + 5); } static long get_current_lwp (int pid) { struct ptrace_lwpinfo pl; lwpid_t lwpid; if (!target_has_execution) { lwpid = 0; bfd_map_over_sections (core_bfd, fbsd_core_get_first_lwp, &lwpid); return lwpid; } if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof(pl))) perror_with_name("PT_LWPINFO"); return (long)pl.pl_lwpid; } static void get_current_thread (void) { td_thrhandle_t th; td_thrinfo_t ti; long lwp; ptid_t tmp, ptid; lwp = get_current_lwp (proc_handle.pid); tmp = BUILD_LWP (lwp, proc_handle.pid); ptid = thread_from_lwp (tmp, &th, &ti); if (in_thread_list (inferior_ptid) ) { struct thread_info * ti_inf = inferior_thread(); ti_inf->ptid = ptid; } if (!in_thread_list (ptid)) { attach_thread (ptid, &th, &ti, 1); } inferior_ptid = ptid; } static CORE_ADDR extract_func_ptr(void *value) { return (extract_typed_address ((gdb_byte *)value, builtin_type (target_gdbarch ())->builtin_func_ptr)); } static CORE_ADDR extract_data_ptr(void *value) { return (extract_typed_address ((gdb_byte *)value, builtin_type (target_gdbarch ())->builtin_data_ptr)); } static td_err_e enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp) { td_notify_t notify; td_err_e err; /* Get the breakpoint address for thread EVENT. */ err = td_ta_event_addr_p (thread_agent, event, ¬ify); if (err != TD_OK) return err; /* Set up the breakpoint. */ (*bp) = (gdbarch_convert_from_func_ptr_addr (target_gdbarch (), extract_func_ptr(¬ify.u.bptaddr), ¤t_target)); create_thread_event_breakpoint (target_gdbarch (), (*bp)); return TD_OK; } static void enable_thread_event_reporting (void) { td_thr_events_t events; td_notify_t notify; td_err_e err; /* We cannot use the thread event reporting facility if these functions aren't available. */ if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) return; /* Set the process wide mask saying which events we're interested in. */ td_event_emptyset (&events); td_event_addset (&events, TD_CREATE); td_event_addset (&events, TD_DEATH); err = td_ta_set_event_p (thread_agent, &events); if (err != TD_OK) { warning ("Unable to set global thread event mask: %s", thread_db_err_str (err)); return; } /* Delete previous thread event breakpoints, if any. */ remove_thread_event_breakpoints (); td_create_bp_addr = 0; td_death_bp_addr = 0; /* Set up the thread creation event. */ err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr); if (err != TD_OK) { warning ("Unable to get location for thread creation breakpoint: %s", thread_db_err_str (err)); return; } /* Set up the thread death event. */ err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr); if (err != TD_OK) { warning ("Unable to get location for thread death breakpoint: %s", thread_db_err_str (err)); return; } } static void disable_thread_event_reporting (void) { td_thr_events_t events; /* Set the process wide mask saying we aren't interested in any events anymore. */ td_event_emptyset (&events); td_ta_set_event_p (thread_agent, &events); td_create_bp_addr = 0; td_death_bp_addr = 0; } static void fbsd_thread_activate (void) { fbsd_thread_active = 1; if (target_has_execution) enable_thread_event_reporting (); - fbsd_thread_find_new_threads (NULL); + fbsd_thread_update_thread_list (NULL); get_current_thread (); } static void fbsd_thread_deactivate (void) { if (target_has_execution) disable_thread_event_reporting(); td_ta_delete_p (thread_agent); inferior_ptid = pid_to_ptid (proc_handle.pid); proc_handle.pid = 0; fbsd_thread_active = 0; fbsd_thread_present = 0; } static void check_for_thread_db (void) { td_err_e err; if (td_ta_new_p == NULL) return; /* Don't try to attach to a dead target if there is no core file. */ if (!target_has_execution && core_bfd == NULL) return; /* Nothing to do. The thread library was already detected and the target vector was already activated. */ if (fbsd_thread_active) return; /* Now, initialize libthread_db. This needs to be done after the shared libraries are located because it needs information from the user's thread library. */ err = td_init_p (); if (err != TD_OK) { warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err)); return; } /* Initialize the structure that identifies the child process. Note that at this point there is no guarantee that we actually have a child process. */ proc_handle.pid = GET_PID (inferior_ptid); /* Now attempt to open a connection to the thread library. */ err = td_ta_new_p (&proc_handle, &thread_agent); switch (err) { case TD_NOLIBTHREAD: /* No thread library was detected. */ break; case TD_OK: /* The thread library was detected. Activate the thread_db target. */ push_target(&fbsd_thread_ops); fbsd_thread_present = 1; fbsd_thread_activate(); break; default: warning ("Cannot initialize thread debugging library: %s", thread_db_err_str (err)); break; } } static void fbsd_thread_new_objfile (struct objfile *objfile) { if (objfile != NULL) check_for_thread_db (); } static void fbsd_thread_detach (struct target_ops *ops, const char *args, int from_tty) { struct target_ops *beneath = find_target_beneath (ops); fbsd_thread_deactivate (); /* Delete thread event breakpoints, if any. */ remove_thread_event_breakpoints (); unpush_target (&fbsd_thread_ops); beneath->to_detach (beneath, args, from_tty); } static int suspend_thread_callback (const td_thrhandle_t *th_p, void *data) { int err = td_thr_dbsuspend_p (th_p); if (err != 0) fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err)); return (err); } static int resume_thread_callback (const td_thrhandle_t *th_p, void *data) { int err = td_thr_dbresume_p (th_p); if (err != 0) fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err)); return (err); } static void fbsd_thread_resume (struct target_ops *ops, ptid_t ptid, int step, enum gdb_signal signo) { struct target_ops *beneath = find_target_beneath (ops); td_thrhandle_t th; td_thrinfo_t ti; ptid_t work_ptid; int resume_all, ret; long lwp, thvalid = 0; if (!fbsd_thread_active) { // XXX: I don't think this can happen printf_unfiltered ("%s: called without active threads\n", __func__); beneath->to_resume (beneath, ptid, step, signo); return; } if (GET_PID(ptid) != -1 && step != 0) { resume_all = 0; work_ptid = ptid; } else { resume_all = 1; work_ptid = inferior_ptid; } lwp = GET_LWP (work_ptid); if (lwp == 0) { /* check user thread */ ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(work_ptid), &th); if (ret) error ("%s: %s", __func__, thread_db_err_str (ret)); /* For M:N thread, we need to tell UTS to set/unset single step flag at context switch time, the flag will be written into thread mailbox. This becauses some architecture may not have machine single step flag in ucontext, so we put the flag in mailbox, when the thread switches back, kse_switchin restores the single step state. */ ret = td_thr_sstep_p (&th, step); if (ret) error ("%s: %s", __func__, thread_db_err_str (ret)); ret = td_thr_get_info_p (&th, &ti); if (ret) error ("%s: %s", __func__, thread_db_err_str (ret)); thvalid = 1; lwp = ti.ti_lid; } if (lwp) { int req = step ? PT_SETSTEP : PT_CLEARSTEP; if (ptrace (req, (pid_t) lwp, (caddr_t) 1, gdb_signal_to_host(signo))) perror_with_name ("PT_SETSTEP/PT_CLEARSTEP"); } if (!ptid_equal (last_single_step_thread, null_ptid)) { ret = td_ta_thr_iter_p (thread_agent, resume_thread_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); if (ret != TD_OK) error ("resume error: %s", thread_db_err_str (ret)); } if (!resume_all) { ret = td_ta_thr_iter_p (thread_agent, suspend_thread_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); if (ret != TD_OK) error ("suspend error: %s", thread_db_err_str (ret)); last_single_step_thread = work_ptid; } else last_single_step_thread = null_ptid; if (thvalid) { ret = td_thr_dbresume_p (&th); if (ret != TD_OK) error ("resume error: %s", thread_db_err_str (ret)); } else { /* it is not necessary, put it here for completness */ ret = ptrace(PT_RESUME, lwp, 0, 0); } /* now continue the process, suspended thread wont run */ if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1, gdb_signal_to_host(signo))) perror_with_name ("PT_CONTINUE"); } static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, const td_thrinfo_t *ti_p, int verbose) { struct private_thread_info *private; struct thread_info *tp = NULL; char *lwpstr = NULL; td_err_e err; /* Add the thread to GDB's thread list. */ if (!in_thread_list (ptid)) { /* Add thread with info */ private = xmalloc(sizeof(struct private_thread_info)); gdb_assert(private != NULL); // Thread name is assigned when printed memset(private, 0, sizeof(struct private_thread_info)); tp = add_thread_with_info(ptid, private); tp->private = private; tp->private_dtor = free_private_thread_info; } if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) return; /* A zombie thread -- do not attach. */ if (! IS_THREAD(ptid)) return; if (!target_has_execution) return; /* Enable thread event reporting for this thread. */ err = td_thr_event_enable_p (th_p, 1); if (err != TD_OK) error ("Cannot enable thread event reporting for %s: %s", target_pid_to_str (ptid), thread_db_err_str (err)); } static void detach_thread (ptid_t ptid, int verbose) { if (verbose) printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid)); } static void check_event (ptid_t ptid) { struct regcache *regcache = get_thread_regcache (ptid); struct gdbarch *gdbarch = get_regcache_arch (regcache); td_event_msg_t msg; td_thrinfo_t ti; td_err_e err; CORE_ADDR stop_pc; int loop = 0; /* Bail out early if we're not at a thread event breakpoint. */ stop_pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch); if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) return; loop = 1; do { err = td_ta_event_getmsg_p (thread_agent, &msg); if (err != TD_OK) { if (err == TD_NOMSG) return; error ("Cannot get thread event message: %s", thread_db_err_str (err)); } err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); switch (msg.event) { case TD_CREATE: /* We may already know about this thread, for instance when the user has issued the `info threads' command before the SIGTRAP for hitting the thread creation breakpoint was reported. */ attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1); break; case TD_DEATH: if (!in_thread_list (ptid)) error ("Spurious thread death event."); detach_thread (ptid, 1); break; default: error ("Spurious thread event."); } } while (loop); } static ptid_t fbsd_thread_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, int options) { struct target_ops *beneath = find_target_beneath (ops); ptid_t ret; long lwp; CORE_ADDR stop_pc; td_thrhandle_t th; td_thrinfo_t ti; ret = beneath->to_wait (beneath, ptid, ourstatus, options); if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED) { lwp = get_current_lwp (GET_PID(ret)); ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)), &th, &ti); if (!in_thread_list(ret)) { /* * We have to enable event reporting for initial thread * which was not mapped before. */ attach_thread(ret, &th, &ti, 1); } if (ourstatus->value.sig == GDB_SIGNAL_TRAP) check_event(ret); /* this is a hack, if an event won't cause gdb to stop, for example, SIGALRM, gdb resumes the process immediatly without setting inferior_ptid to the new thread returned here, this is a bug because inferior_ptid may already not exist there, and passing a non-existing thread to fbsd_thread_resume causes error. However, if the exiting thread is the currently selected thread, then that is handled later in handle_inferior_event(), and we must not delete the currently selected thread. */ if (!fbsd_thread_alive (ops, inferior_ptid) && !ptid_equal(inferior_ptid, ret)) { ptid_t save_ptid; save_ptid = inferior_ptid; inferior_ptid = ret; delete_thread (save_ptid); } } return (ret); } static void fbsd_thread_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { prgregset_t gregset; prfpregset_t fpregset; td_thrhandle_t th; + td_thrinfo_t ti; td_err_e err; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif if (!IS_THREAD (inferior_ptid)) { struct target_ops *beneath = find_target_beneath (ops); beneath->to_fetch_registers (ops, regcache, regnum); return; } err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) error ("Cannot find thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); + err = td_thr_get_info_p (&th, &ti); + if (err != TD_OK) + error ("Cannot get thread info, Thread ID=%ld, %s", + GET_THREAD (inferior_ptid), thread_db_err_str (err)); + + if (ti.ti_lid != 0) + { + struct target_ops *beneath = find_target_beneath (ops); + struct cleanup *old_chain; + + old_chain = save_inferior_ptid (); + + inferior_ptid = BUILD_LWP (ti.ti_lid, GET_PID (inferior_ptid)); + beneath->to_fetch_registers (ops, regcache, regnum); + + do_cleanups (old_chain); + return; + } + err = td_thr_getgregs_p (&th, gregset); if (err != TD_OK) error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); #ifdef PT_GETXMMREGS err = td_thr_getxmmregs_p (&th, xmmregs); if (err == TD_OK) { i387_supply_fxsave (regcache, -1, xmmregs); } else { #endif err = td_thr_getfpregs_p (&th, &fpregset); if (err != TD_OK) error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); supply_fpregset (regcache, &fpregset); #ifdef PT_GETXMMREGS } #endif supply_gregset (regcache, gregset); } static void fbsd_thread_store_registers (struct target_ops *ops, struct regcache *regcache, int regnum) { prgregset_t gregset; prfpregset_t fpregset; td_thrhandle_t th; + td_thrinfo_t ti; td_err_e err; #ifdef PT_GETXMMREGS char xmmregs[512]; #endif if (!IS_THREAD (inferior_ptid)) { struct target_ops *beneath = find_target_beneath (ops); beneath->to_store_registers (ops, regcache, regnum); return; } err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) error ("Cannot find thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); + err = td_thr_get_info_p (&th, &ti); + if (err != TD_OK) + error ("Cannot get thread info, Thread ID=%ld, %s", + GET_THREAD (inferior_ptid), thread_db_err_str (err)); + + if (ti.ti_lid != 0) + { + struct target_ops *beneath = find_target_beneath (ops); + struct cleanup *old_chain; + + old_chain = save_inferior_ptid (); + + inferior_ptid = BUILD_LWP (ti.ti_lid, GET_PID (inferior_ptid)); + beneath->to_store_registers (ops, regcache, regnum); + + do_cleanups (old_chain); + return; + } + if (regnum != -1) { char old_value[MAX_REGISTER_SIZE]; regcache_raw_collect (regcache, regnum, old_value); err = td_thr_getgregs_p (&th, gregset); if (err != TD_OK) error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err)); #ifdef PT_GETXMMREGS err = td_thr_getxmmregs_p (&th, xmmregs); if (err != TD_OK) { #endif err = td_thr_getfpregs_p (&th, &fpregset); if (err != TD_OK) error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err)); #ifdef PT_GETXMMREGS } #endif regcache_raw_supply (regcache, regnum, old_value); } fill_gregset (regcache, gregset, regnum); err = td_thr_setgregs_p (&th, gregset); if (err != TD_OK) error ("Cannot store general-purpose registers for thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); #ifdef PT_GETXMMREGS i387_collect_fxsave (regcache, regnum, xmmregs); err = td_thr_setxmmregs_p (&th, xmmregs); if (err == TD_OK) return; #endif fill_fpregset (regcache, &fpregset, regnum); err = td_thr_setfpregs_p (&th, &fpregset); if (err != TD_OK) error ("Cannot store floating-point registers for thread %d: Thread ID=%ld, %s", pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), thread_db_err_str (err)); } static void fbsd_thread_mourn_inferior (struct target_ops *ops) { struct target_ops *beneath = find_target_beneath (ops); fbsd_thread_deactivate (); beneath->to_mourn_inferior (beneath); /* Delete thread event breakpoints, if any. */ remove_thread_event_breakpoints (); unpush_target (ops); } static void fbsd_core_check_lwp (bfd *abfd, asection *asect, void *obj) { lwpid_t lwp; if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) return; /* already found */ if (*(lwpid_t *)obj == 0) return; lwp = atoi (bfd_section_name (abfd, asect) + 5); if (*(lwpid_t *)obj == lwp) *(lwpid_t *)obj = 0; } static int fbsd_thread_alive (struct target_ops *ops, ptid_t ptid) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; gregset_t gregs; lwpid_t lwp; if (IS_THREAD (ptid)) { err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); if (err != TD_OK) return 0; err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) return 0; /* A zombie thread. */ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) return 0; return 1; } else if (GET_LWP (ptid) == 0) { /* we sometimes are called with lwp == 0 */ return 1; } if (fbsd_thread_active) { err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); /* * if the lwp was already mapped to user thread, don't use it * directly, please use user thread id instead. */ if (err == TD_OK) return 0; } if (!target_has_execution) { lwp = GET_LWP (ptid); bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp); return (lwp == 0); } /* check lwp in kernel */ return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0; } static int -find_new_threads_callback (const td_thrhandle_t *th_p, void *data) +update_thread_list_callback (const td_thrhandle_t *th_p, void *data) { td_thrinfo_t ti; td_err_e err; ptid_t ptid; err = td_thr_get_info_p (th_p, &ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); /* Ignore zombie */ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) return 0; ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid); attach_thread (ptid, th_p, &ti, 1); return 0; } static void -fbsd_thread_find_new_threads (struct target_ops *ops) +fbsd_thread_update_thread_list (struct target_ops *ops) { td_err_e err; + /* Delete dead threads. */ + prune_threads(); + /* Iterate over all user-space threads to discover new threads. */ - err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL, + err = td_ta_thr_iter_p (thread_agent, update_thread_list_callback, NULL, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); if (err != TD_OK) error ("Cannot find new threads: %s", thread_db_err_str (err)); } static void fbsd_find_lwp_name(long lwpid, struct private_thread_info *info) { + struct cleanup *old_chain; int error, name[4]; unsigned int i; struct kinfo_proc *kipp, *kip; char *lwpstr = info->lwp_name; int pid = inferior_ptid.pid; size_t len = 0; name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; name[3] = pid; error = sysctl(name, 4, NULL, &len, NULL, 0); - if (error < 0 && errno != ESRCH) { - warn("sysctl: kern.proc.pid: %d", pid); - return; - } - if (error < 0) + if (error < 0) { + if (errno != ESRCH) + warning (_("sysctl: kern.proc.pid: %d: %s"), pid, + safe_strerror (errno)); return; + } - kip = malloc(len); + kip = xmalloc(len); if (kip == NULL) - err(-1, "malloc"); + return; + old_chain = make_cleanup(xfree, kip); if (sysctl(name, 4, kip, &len, NULL, 0) < 0) { - warn("sysctl: kern.proc.pid: %d", pid); - free(kip); - return; + warning (_("sysctl: kern.proc.pid: %d: %s"), pid, safe_strerror(errno)); + do_cleanups(old_chain); + return; } for (i = 0; i < len / sizeof(*kipp); i++) { kipp = &kip[i]; if ((kipp->ki_tid == lwpid) && strlen(kipp->ki_ocomm) && (strcmp(kipp->ki_comm, kipp->ki_ocomm) != 0)) { // Found the LWP, update the name field if (lwpstr != NULL) { if (strcmp(lwpstr, kipp->ki_ocomm) != 0) { xfree(lwpstr); } else { // Name hasn't changed, just return break; } } - len = strlen(kipp->ki_ocomm) + 1; - lwpstr = xmalloc(len); - strncpy(lwpstr, kipp->ki_ocomm, len); + lwpstr = xstrdup(kipp->ki_ocomm); info->lwp_name = lwpstr; break; } } - free(kip); + do_cleanups(old_chain); } static char * fbsd_thread_pid_to_str (struct target_ops *ops, ptid_t ptid) { static char buf[64]; struct thread_info *tinfo = NULL; if (IS_THREAD (ptid)) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); if (err != TD_OK) error ("Cannot find thread, Thread ID=%ld, %s", GET_THREAD (ptid), thread_db_err_str (err)); err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) error ("Cannot get thread info, Thread ID=%ld, %s", GET_THREAD (ptid), thread_db_err_str (err)); tinfo = find_thread_ptid(ptid); gdb_assert(tinfo != NULL); if (ti.ti_lid != 0) { // Need to find the name of this LWP, even though it shouldn't change fbsd_find_lwp_name(ti.ti_lid, tinfo->private); if (tinfo->private->lwp_name == NULL) { snprintf(buf, sizeof (buf), "Thread %llx (LWP %d)", (unsigned long long)th.th_thread, ti.ti_lid); } else { snprintf(buf, sizeof (buf), "Thread %llx (LWP %d %s)", (unsigned long long)th.th_thread, ti.ti_lid, tinfo->private->lwp_name); } } else { snprintf (buf, sizeof (buf), "Thread %llx (%s)", (unsigned long long)th.th_thread, thread_db_state_str (ti.ti_state)); } return buf; } else if (IS_LWP (ptid)) { snprintf (buf, sizeof (buf), "LWP %d", (int) GET_LWP (ptid)); return buf; } return normal_pid_to_str (ptid); } CORE_ADDR fbsd_thread_get_local_address(struct target_ops *ops, ptid_t ptid, CORE_ADDR lm, CORE_ADDR offset) { td_thrhandle_t th; void *address; int ret; if (IS_THREAD (ptid)) { if (!td_thr_tls_get_addr_p) error ("Cannot find thread-local interface in thread_db library."); ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th); /* get the address of the variable. */ ret = td_thr_tls_get_addr_p (&th, (void *)lm, offset, &address); if (ret != TD_OK) { error ("Cannot find thread-local storage for thread %ld\n%s", (long) GET_THREAD (ptid), thread_db_err_str (ret)); } /* Cast assuming host == target. */ return extract_data_ptr (&address); } return (0); } static int tsd_cb (thread_key_t key, void (*destructor)(void *), void *ignore) { struct bound_minimal_symbol bms; const char *name; bms = lookup_minimal_symbol_by_pc (extract_func_ptr (&destructor)); if (!bms.minsym) name = "???"; else name = MSYMBOL_PRINT_NAME (bms.minsym); printf_filtered ("Key %d, destructor %p <%s>\n", key, destructor, name); return 0; } static void fbsd_thread_tsd_cmd (char *exp, int from_tty) { if (fbsd_thread_active) td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL); } static void fbsd_print_sigset (sigset_t *set) { int i; for (i = 1; i <= _SIG_MAXSIG; ++i) { if (sigismember(set, i)) { if (i < sizeof(sys_signame)/sizeof(sys_signame[0])) printf_filtered("%s ", sys_signame[i]); else printf_filtered("sig%d ", i); } } printf_filtered("\n"); } static void fbsd_thread_signal_cmd (char *exp, int from_tty) { td_thrhandle_t th; td_thrinfo_t ti; td_err_e err; #ifdef PL_FLAG_SI const char *code; #endif if (!fbsd_thread_active || !IS_THREAD(inferior_ptid)) return; err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); if (err != TD_OK) return; err = td_thr_get_info_p (&th, &ti); if (err != TD_OK) return; printf_filtered("signal mask:\n"); fbsd_print_sigset(&ti.ti_sigmask); printf_filtered("signal pending:\n"); fbsd_print_sigset(&ti.ti_pending); #ifdef PL_FLAG_SI if (ti.ti_siginfo.si_signo != 0) { printf_filtered("si_signo %d si_errno %d", ti.ti_siginfo.si_signo, ti.ti_siginfo.si_errno); if (ti.ti_siginfo.si_errno != 0) printf_filtered(" (%s)", strerror(ti.ti_siginfo.si_errno)); printf_filtered("\n"); switch (ti.ti_siginfo.si_code) { case SI_NOINFO: code = "NOINFO"; break; case SI_USER: code = "USER"; break; case SI_QUEUE: code = "QUEUE"; break; case SI_TIMER: code = "TIMER"; break; case SI_ASYNCIO: code = "ASYNCIO"; break; case SI_MESGQ: code = "MESGQ"; break; case SI_KERNEL: code = "KERNEL"; break; default: code = "UNKNOWN"; break; } printf_filtered("si_code %s si_pid %d si_uid %d si_status %x si_addr %p\n", code, ti.ti_siginfo.si_pid, ti.ti_siginfo.si_uid, ti.ti_siginfo.si_status, ti.ti_siginfo.si_addr); } #endif } static void init_fbsd_thread_ops (void) { fbsd_thread_ops.to_shortname = "freebsd-threads"; fbsd_thread_ops.to_longname = "FreeBSD multithreaded child process."; fbsd_thread_ops.to_doc = "FreeBSD threads support."; fbsd_thread_ops.to_detach = fbsd_thread_detach; fbsd_thread_ops.to_resume = fbsd_thread_resume; fbsd_thread_ops.to_wait = fbsd_thread_wait; fbsd_thread_ops.to_fetch_registers = fbsd_thread_fetch_registers; fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers; fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior; fbsd_thread_ops.to_thread_alive = fbsd_thread_alive; - fbsd_thread_ops.to_find_new_threads = fbsd_thread_find_new_threads; + fbsd_thread_ops.to_update_thread_list = fbsd_thread_update_thread_list; fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str; fbsd_thread_ops.to_stratum = thread_stratum; fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address; fbsd_thread_ops.to_magic = OPS_MAGIC; } static int thread_db_load (void) { void *handle; td_err_e err; handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW); if (handle == NULL) return 0; #define resolve(X) \ if (!(X##_p = dlsym (handle, #X))) \ return 0; resolve(td_init); resolve(td_ta_new); resolve(td_ta_delete); resolve(td_ta_map_id2thr); resolve(td_ta_map_lwp2thr); resolve(td_ta_thr_iter); resolve(td_thr_get_info); #ifdef PT_GETXMMREGS resolve(td_thr_getxmmregs); #endif resolve(td_thr_getfpregs); resolve(td_thr_getgregs); #ifdef PT_GETXMMREGS resolve(td_thr_setxmmregs); #endif resolve(td_thr_setfpregs); resolve(td_thr_setgregs); resolve(td_thr_sstep); resolve(td_ta_tsd_iter); resolve(td_thr_dbsuspend); resolve(td_thr_dbresume); resolve(td_thr_tls_get_addr); /* These are not essential. */ td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); return 1; } void _initialize_thread_db (void) { init_fbsd_thread_ops (); if (thread_db_load ()) { add_target (&fbsd_thread_ops); /* "thread tsd" command */ add_cmd ("tsd", class_run, fbsd_thread_tsd_cmd, "Show the thread-specific data keys and destructors " "for the process.\n", &thread_cmd_list); add_cmd ("signal", class_run, fbsd_thread_signal_cmd, "Show the thread signal info.\n", &thread_cmd_list); /* Hook into new_objfile notification. */ observer_attach_new_objfile (fbsd_thread_new_objfile); } else { fprintf_unfiltered (gdb_stderr, "[GDB will not be able to debug user-mode threads: %s]\n", dlerror()); } } /* proc service functions */ void ps_plog (const char *fmt, ...) { va_list args; va_start (args, fmt); vfprintf_filtered (gdb_stderr, fmt, args); va_end (args); } ps_err_e ps_pglobal_lookup (struct ps_prochandle *ph, const char *obj, const char *name, psaddr_t *sym_addr) { struct bound_minimal_symbol ms; CORE_ADDR addr; ms = lookup_minimal_symbol (name, NULL, NULL); if (!ms.minsym) return PS_NOSYM; *sym_addr = BMSYMBOL_VALUE_ADDRESS (ms); return PS_OK; } ps_err_e ps_pread (struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t len) { int err = target_read_memory (extract_data_ptr (&addr), buf, len); return (err == 0 ? PS_OK : PS_ERR); } ps_err_e ps_pwrite (struct ps_prochandle *ph, psaddr_t addr, const void *buf, size_t len) { int err = target_write_memory (extract_data_ptr (&addr), (void *)buf, len); return (err == 0 ? PS_OK : PS_ERR); } ps_err_e ps_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset) { struct cleanup *old_chain; struct regcache *regcache; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, ph->pid); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); target_fetch_registers (regcache, -1); fill_gregset (regcache, gregset, -1); do_cleanups (old_chain); return PS_OK; } ps_err_e ps_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid, const prgregset_t gregset) { struct cleanup *old_chain; struct regcache *regcache; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, ph->pid); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); supply_gregset (regcache, gregset); target_store_registers (regcache, -1); do_cleanups (old_chain); return PS_OK; } ps_err_e ps_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, prfpregset_t *fpregset) { struct cleanup *old_chain; struct regcache *regcache; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, ph->pid); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); target_fetch_registers (regcache, -1); fill_fpregset (regcache, fpregset, -1); do_cleanups (old_chain); return PS_OK; } ps_err_e ps_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, const prfpregset_t *fpregset) { struct cleanup *old_chain; struct regcache *regcache; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, ph->pid); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); supply_fpregset (regcache, fpregset); target_store_registers (regcache, -1); do_cleanups (old_chain); return PS_OK; } #ifdef PT_GETXMMREGS ps_err_e ps_lgetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, char *xmmregs) { struct cleanup *old_chain; struct regcache *regcache; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, ph->pid); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); target_fetch_registers (regcache, -1); i387_collect_fxsave (regcache, -1, xmmregs); do_cleanups (old_chain); return PS_OK; } ps_err_e ps_lsetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, const char *xmmregs) { struct cleanup *old_chain; struct regcache *regcache; old_chain = save_inferior_ptid (); inferior_ptid = BUILD_LWP (lwpid, ph->pid); regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); i387_supply_fxsave (regcache, -1, xmmregs); target_store_registers (regcache, -1); do_cleanups (old_chain); return PS_OK; } #endif ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lwpid) { if (ptrace (PT_SUSPEND, lwpid, 0, 0) == -1) return PS_ERR; return PS_OK; } ps_err_e ps_lcontinue(struct ps_prochandle *ph, lwpid_t lwpid) { if (ptrace (PT_RESUME, lwpid, 0, 0) == -1) return PS_ERR; return PS_OK; } ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwpid, void *info) { if (!target_has_execution) { /* XXX should verify lwpid and make a pseudo lwp info */ memset(info, 0, sizeof(struct ptrace_lwpinfo)); return PS_OK; } if (ptrace (PT_LWPINFO, lwpid, info, sizeof(struct ptrace_lwpinfo)) == -1) return PS_ERR; return PS_OK; } Index: head/devel/gdb/files/patch-gdb-amd64bsd-nat.c =================================================================== --- head/devel/gdb/files/patch-gdb-amd64bsd-nat.c (revision 384977) +++ head/devel/gdb/files/patch-gdb-amd64bsd-nat.c (revision 384978) @@ -1,36 +1,38 @@ ---- gdb/amd64bsd-nat.c.orig 2013-04-09 16:45:15.000000000 +0200 -+++ gdb/amd64bsd-nat.c 2013-04-09 18:53:22.000000000 +0200 -@@ -29,6 +29,7 @@ +diff --git gdb/amd64bsd-nat.c gdb/amd64bsd-nat.c +index 66d4289..b1d4a0e 100644 +--- gdb/amd64bsd-nat.c ++++ gdb/amd64bsd-nat.c +@@ -28,6 +28,7 @@ #include #include #include +#include #include "amd64-tdep.h" #include "amd64-nat.h" -@@ -81,14 +82,24 @@ +@@ -98,14 +99,24 @@ amd64bsd_store_inferior_registers (struct target_ops *ops, if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) { - struct reg regs; + struct reg regs, oldregs; + memset( ®s, 0, sizeof(struct reg)); + memset( &oldregs, 0, sizeof(struct reg)); if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); + ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &oldregs, 0); amd64_collect_native_gregset (regcache, ®s, regnum); + if( (regs.r_rflags ^ oldregs.r_rflags ) & ~PSL_USERCHANGE) { + //printf("regs.r_rflags = 0x%8.8lX\n", regs.r_rflags ); + //printf("oldregs.r_rflags = 0x%8.8lX\n", oldregs.r_rflags ); + regs.r_rflags ^= (regs.r_rflags ^ oldregs.r_rflags ) & ~PSL_USERCHANGE; + //printf(" allowed regs.r_rflags = 0x%8.8X\n", regs.r_rflags ); + } if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); Index: head/devel/gdb/files/patch-gdb-configure =================================================================== --- head/devel/gdb/files/patch-gdb-configure (revision 384977) +++ head/devel/gdb/files/patch-gdb-configure (revision 384978) @@ -1,35 +1,37 @@ ---- gdb/configure.orig 2014-07-29 14:37:42.000000000 +0200 -+++ gdb/configure 2014-10-01 14:21:14.902231511 +0200 -@@ -11485,7 +11485,8 @@ +diff --git gdb/configure gdb/configure +index 355f190..9c60e01 100755 +--- gdb/configure ++++ gdb/configure +@@ -11423,7 +11423,8 @@ fi # See if supports the %fs and %gs i386 segment registers. # Older i386 BSD's don't have the r_fs and r_gs members of `struct reg'. -ac_fn_c_check_member "$LINENO" "struct reg" "r_fs" "ac_cv_member_struct_reg_r_fs" "#include +ac_fn_c_check_member "$LINENO" "struct reg" "r_fs" "ac_cv_member_struct_reg_r_fs" "#include +#include " if test "x$ac_cv_member_struct_reg_r_fs" = x""yes; then : -@@ -11495,7 +11496,8 @@ +@@ -11433,7 +11434,8 @@ _ACEOF fi -ac_fn_c_check_member "$LINENO" "struct reg" "r_gs" "ac_cv_member_struct_reg_r_gs" "#include +ac_fn_c_check_member "$LINENO" "struct reg" "r_gs" "ac_cv_member_struct_reg_r_gs" "#include +#include " if test "x$ac_cv_member_struct_reg_r_gs" = x""yes; then : -@@ -13007,10 +13009,9 @@ +@@ -12945,10 +12947,9 @@ fi build_warnings="-Wall -Wdeclaration-after-statement -Wpointer-arith \ -Wpointer-sign \ --Wno-unused -Wunused-value -Wunused-function \ +-Wno-unused -Wunused-value \ -Wno-switch -Wno-char-subscripts -Wmissing-prototypes \ --Wdeclaration-after-statement -Wempty-body -Wmissing-parameter-type \ --Wold-style-declaration -Wold-style-definition" +-Wdeclaration-after-statement -Wempty-body -Wold-style-definition" # Enable -Wno-format by default when using gcc on mingw since many # GCC versions complain about %I64. Index: head/devel/gdb/files/patch-gdb-gdb_wchar.h =================================================================== --- head/devel/gdb/files/patch-gdb-gdb_wchar.h (revision 384977) +++ head/devel/gdb/files/patch-gdb-gdb_wchar.h (revision 384978) @@ -1,20 +1,22 @@ ---- gdb/gdb_wchar.h.orig 2014-06-05 10:44:18.914279516 +0200 -+++ gdb/gdb_wchar.h 2014-06-05 10:46:07.264279306 +0200 -@@ -56,7 +56,7 @@ +diff --git gdb/gdb_wchar.h gdb/gdb_wchar.h +index 868fe04..1311080 100644 +--- gdb/gdb_wchar.h ++++ gdb/gdb_wchar.h +@@ -59,7 +59,7 @@ iconvlist. */ - #if defined (HAVE_ICONV) && defined (HAVE_WCHAR_H) && defined (HAVE_BTOWC) \ + #if defined (HAVE_ICONV) && defined (HAVE_BTOWC) \ && (defined (__STDC_ISO_10646__) \ - || (defined (_LIBICONV_VERSION) && _LIBICONV_VERSION >= 0x108)) + || (!defined (LIBICONV_PLUG) && defined (_LIBICONV_VERSION) && _LIBICONV_VERSION >= 0x108)) - #include - #include -@@ -82,7 +82,7 @@ + typedef wchar_t gdb_wchar_t; + typedef wint_t gdb_wint_t; +@@ -82,7 +82,7 @@ typedef wint_t gdb_wint_t; #define INTERMEDIATE_ENCODING intermediate_encoding () const char *intermediate_encoding (void); -#elif defined (_LIBICONV_VERSION) && _LIBICONV_VERSION >= 0x108 +#elif !defined (LIBICONV_PLUG) && defined (_LIBICONV_VERSION) && _LIBICONV_VERSION >= 0x108 #define INTERMEDIATE_ENCODING "wchar_t" #else /* This shouldn't happen, because the earlier #if should have filtered Index: head/devel/gdb/files/patch-gdb-i386fbsd-nat.c =================================================================== --- head/devel/gdb/files/patch-gdb-i386fbsd-nat.c (revision 384977) +++ head/devel/gdb/files/patch-gdb-i386fbsd-nat.c (revision 384978) @@ -1,58 +1,12 @@ ---- gdb/i386fbsd-nat.c.orig 2012-05-24 18:39:09.000000000 +0200 -+++ gdb/i386fbsd-nat.c 2012-08-29 17:19:57.000000000 +0200 -@@ -21,10 +21,12 @@ - #include "inferior.h" - #include "regcache.h" - #include "target.h" +diff --git gdb/i386fbsd-nat.c gdb/i386fbsd-nat.c +index 6c43f2c..a205a26 100644 +--- gdb/i386fbsd-nat.c ++++ gdb/i386fbsd-nat.c +@@ -175,7 +175,6 @@ _initialize_i386fbsd_nat (void) + t->to_read_description = i386fbsd_read_description; + #endif - #include -+#include - #include - #include -+#include - - #include "fbsd-nat.h" - #include "i386-tdep.h" -@@ -140,7 +141,6 @@ - #endif /* HAVE_PT_GETDBREGS */ - - - t->to_resume = i386fbsd_resume; t->to_pid_to_exec_file = fbsd_pid_to_exec_file; t->to_find_memory_regions = fbsd_find_memory_regions; - t->to_make_corefile_notes = fbsd_make_corefile_notes; -@@ -149,13 +149,33 @@ _initialize_i386fbsd_nat (void) - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (i386fbsd_supply_pcb); - -+#ifdef KERN_PROC_SIGTRAMP -+ /* FreeBSD provides a kern.proc.sigtramp sysctl that we can use to -+ locate the sigtramp. That way we can still recognize a sigtramp -+ if its location is changed in a new kernel. */ -+ { -+ int mib[4]; -+ struct kinfo_sigtramp kst; -+ size_t len; -+ -+ mib[0] = CTL_KERN; -+ mib[1] = KERN_PROC; -+ mib[2] = KERN_PROC_SIGTRAMP; -+ mib[3] = getpid(); -+ len = sizeof (kst); -+ if (sysctl (mib, sizeof(mib)/sizeof(mib[0]), &kst, &len, NULL, 0) == 0) -+ { -+ i386fbsd_sigtramp_start_addr = (uintptr_t)kst.ksigtramp_start; -+ i386fbsd_sigtramp_end_addr = (uintptr_t)kst.ksigtramp_end; -+ } -+ } -+#elif defined(KERN_PS_STRINGS) - /* FreeBSD provides a kern.ps_strings sysctl that we can use to - locate the sigtramp. That way we can still recognize a sigtramp - if its location is changed in a new kernel. Of course this is - still based on the assumption that the sigtramp is placed - directly under the location where the program arguments and - environment can be found. */ --#ifdef KERN_PS_STRINGS - { - int mib[2]; - u_long ps_strings; + add_target (t); Index: head/devel/gdb/files/patch-gdb-python-python-config.py =================================================================== --- head/devel/gdb/files/patch-gdb-python-python-config.py (revision 384977) +++ head/devel/gdb/files/patch-gdb-python-python-config.py (revision 384978) @@ -1,11 +1,13 @@ ---- gdb/python/python-config.py.orig 2013-10-17 11:24:52.000000000 +0200 -+++ gdb/python/python-config.py 2013-10-17 11:25:04.000000000 +0200 -@@ -59,6 +59,8 @@ +diff --git gdb/python/python-config.py gdb/python/python-config.py +index c2b2969..39af8d9 100644 +--- gdb/python/python-config.py ++++ gdb/python/python-config.py +@@ -59,6 +59,8 @@ for opt in opt_flags: elif opt in ('--libs', '--ldflags'): libs = [] + if getvar('LDFLAGS') is not None: + libs.extend(getvar('LDFLAGS').split()) if getvar('LIBS') is not None: libs.extend(getvar('LIBS').split()) if getvar('SYSLIBS') is not None: Index: head/devel/gdb/files/patch-sigev =================================================================== --- head/devel/gdb/files/patch-sigev (revision 384977) +++ head/devel/gdb/files/patch-sigev (revision 384978) @@ -1,59 +1,65 @@ ---- gdb/common/signals.c.orig 2013-01-01 07:32:54.000000000 +0100 -+++ gdb/common/signals.c 2013-11-25 16:12:56.000000000 +0100 -@@ -46,6 +46,12 @@ +diff --git gdb/common/signals.c gdb/common/signals.c +index d4cf953..019371e 100644 +--- gdb/common/signals.c ++++ gdb/common/signals.c +@@ -41,6 +41,12 @@ struct gdbarch; # endif #endif +#ifdef __FreeBSD__ +# ifndef SIGLIBRT +# define SIGLIBRT 33 /* Older versions do not define the constant */ +# endif +#endif + /* This table must match in order and size the signals in enum gdb_signal. */ -@@ -334,6 +340,11 @@ +@@ -332,6 +338,11 @@ gdb_signal_from_host (int hostsig) return GDB_SIGNAL_INFO; #endif +#if defined (SIGLIBRT) + if ( hostsig == SIGLIBRT ) + return GDB_SIGNAL_FBSD_LIBRT; +#endif + #if defined (REALTIME_LO) if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI) { -@@ -591,6 +602,11 @@ +@@ -585,6 +596,11 @@ do_gdb_signal_to_host (enum gdb_signal oursig, return SIGINFO; #endif +#if defined (SIGLIBRT) + case GDB_SIGNAL_FBSD_LIBRT: + return SIGLIBRT; +#endif + default: #if defined (REALTIME_LO) retsig = 0; ---- gdb/infrun.c.orig 2013-08-30 17:58:55.000000000 +0200 -+++ gdb/infrun.c 2013-11-22 16:12:58.000000000 +0100 -@@ -7291,6 +7291,8 @@ +diff --git gdb/infrun.c gdb/infrun.c +index 11dcc0e..6ec4d0b 100644 +--- gdb/infrun.c ++++ gdb/infrun.c +@@ -7715,6 +7715,8 @@ leave it stopped or free to run as needed."), signal_print[GDB_SIGNAL_WINCH] = 0; signal_stop[GDB_SIGNAL_PRIO] = 0; signal_print[GDB_SIGNAL_PRIO] = 0; + signal_stop[GDB_SIGNAL_FBSD_LIBRT] = 0; + signal_print[GDB_SIGNAL_FBSD_LIBRT] = 0; /* These signals are used internally by user-level thread implementations. (See signal(5) on Solaris.) Like the above ---- include/gdb/signals.def.orig 2013-01-01 07:41:30.000000000 +0100 -+++ include/gdb/signals.def 2013-11-25 16:13:42.000000000 +0100 -@@ -197,4 +197,5 @@ +diff --git include/gdb/signals.def include/gdb/signals.def +index 3f49980..857c69d 100644 +--- include/gdb/signals.def ++++ include/gdb/signals.def +@@ -197,4 +197,5 @@ SET (GDB_EXC_BREAKPOINT, 150, "EXC_BREAKPOINT", "Breakpoint") /* If you are adding a new signal, add it just above this comment. */ /* Last and unused enum value, for sizing arrays, etc. */ --SET (GDB_SIGNAL_LAST, 151, NULL, "GDB_SIGNAL_MAGIC") +-SET (GDB_SIGNAL_LAST, 151, NULL, "GDB_SIGNAL_LAST") +SET (GDB_SIGNAL_FBSD_LIBRT, 151, "SIGLIBRT", "GDB_SIGNAL_FBSD_LIBRT") +SET (GDB_SIGNAL_LAST, 152, NULL, "GDB_SIGNAL_MAGIC") Index: head/devel/gdb/files/patch-unified =================================================================== --- head/devel/gdb/files/patch-unified (revision 384977) +++ head/devel/gdb/files/patch-unified (revision 384978) @@ -1,15 +1,18 @@ ---- gdb/gdb.c Thu Feb 13 13:07:24 2003 -+++ gdb/gdb.c Wed May 17 00:24:39 2006 -@@ -31,5 +32,11 @@ +diff --git gdb/gdb.c gdb/gdb.c +index e554015..dcb9925 100644 +--- gdb/gdb.c ++++ gdb/gdb.c +@@ -28,6 +28,12 @@ main (int argc, char **argv) + memset (&args, 0, sizeof args); args.argc = argc; args.argv = argv; - args.interpreter_p = INTERP_CONSOLE; + if (strncmp(basename(argv[0]), "insight", 7) == 0) { + args.interpreter_p = "insight"; + } else if (strncmp(basename(argv[0]), "gdbtui", 6) == 0) { + args.interpreter_p = INTERP_TUI; + } else { + args.interpreter_p = INTERP_CONSOLE; + } return gdb_main (&args); }