diff --git a/devel/gdb/Makefile b/devel/gdb/Makefile index 378ed1e197ca..921a14b566de 100644 --- a/devel/gdb/Makefile +++ b/devel/gdb/Makefile @@ -1,190 +1,190 @@ PORTNAME= gdb DISTVERSION= 13.1 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= devel MASTER_SITES= GNU MAINTAINER= pizzamig@FreeBSD.org COMMENT= GNU Project Debugger WWW= https://www.gnu.org/software/gdb/ LICENSE= GPLv3 LICENSE_FILE= ${WRKSRC}/COPYING3 LIB_DEPENDS= libexpat.so:textproc/expat2 \ libgmp.so:math/gmp \ libmpfr.so:math/mpfr \ libzstd.so:archivers/zstd TEST_DEPENDS= runtest:misc/dejagnu USES= compiler:c++11-lang cpe gmake libtool makeinfo pkgconfig tar:xz USE_PYTHON= flavors py3kplist TEST_TARGET= check CPE_VENDOR= gnu GNU_CONFIGURE= yes CONFIGURE_ENV= CONFIGURED_M4=m4 CONFIGURED_BISON=byacc CONFIGURE_ARGS= --program-suffix=${DISTVERSION:S/.//g} \ --enable-targets=all --enable-64-bit-bfd \ --with-separate-debug-dir=/usr/lib/debug \ ${ICONV_CONFIGURE_ARG} \ --without-libunwind-ia64 --with-system-zlib CONFIGURE_OUTSOURCE= yes CFLAGS:= ${CFLAGS:C/ +$//} # blanks at EOL creep in sometimes CFLAGS+= -DRL_NO_COMPAT EXCLUDE= dejagnu expect sim texinfo intl EXTRACT_AFTER_ARGS= ${EXCLUDE:S/^/--exclude /} EXTRA_PATCHES= ${FILESDIR}/commit-a980a7d24b9 EXTRA_PATCHES+= ${FILESDIR}/commit-ae61525fcf4 VER= ${DISTVERSION:S/.//g} PLIST_SUB= VER=${VER} OPTIONS_DEFINE= GDB_LINK GUILE KGDB NLS PYTHON SOURCE_HIGHLIGHT \ TUI XXHASH OPTIONS_DEFAULT= GDB_LINK KGDB NLS PYTHON SOURCE_HIGHLIGHT \ TUI XXHASH OPTIONS_DEFAULT+= PORT_READLINE PORT_ICONV SYSTEM_ZLIB OPTIONS_SINGLE= READLINE ICONV ZLIB OPTIONS_SINGLE_READLINE= BUNDLED_READLINE PORT_READLINE OPTIONS_SINGLE_ICONV= PORT_ICONV SYSTEM_ICONV OPTIONS_SINGLE_ZLIB= BUNDLED_ZLIB SYSTEM_ZLIB GDB_LINK_DESC= Create ${PREFIX}/bin/gdb symlink KGDB_DESC= Kernel debugging support BUNDLED_READLINE_DESC= from gdb distfile BUNDLED_ZLIB_DESC= from gdb distfile PORT_READLINE_DESC= from devel/readline port PORT_ICONV_DESC= use libiconv, with wider charset support SOURCE_HIGHLIGHT_DESC= Syntax highlighting support SYSTEM_ICONV_DESC= use libc iconv, with no wchar support SYSTEM_ZLIB_DESC= use system zlib TUI_DESC= Text User Interface support XXHASH_DESC= Use xxHash for hashing (faster) OPTIONS_SUB= yes BUNDLED_READLINE_CONFIGURE_OFF= --with-system-readline GUILE_CONFIGURE_WITH= guile=guile-${GUILE_VER} GUILE_USES= guile:2.2,3.0 NLS_USES= gettext-runtime PORT_READLINE_USES= readline PORT_ICONV_USES= iconv:wchar_t PYTHON_CONFIGURE_ON= --with-python=${PYTHON_CMD} PYTHON_CONFIGURE_OFF= --without-python PYTHON_USES= python SOURCE_HIGHLIGHT_CONFIGURE_ENABLE= source-highlight SOURCE_HIGHLIGHT_LIB_DEPENDS= \ libsource-highlight.so:textproc/source-highlight SYSTEM_ICONV_USES= iconv SYSTEM_ZLIB_WITH= system-zlib TUI_CONFIGURE_ENABLE= tui XXHASH_CONFIGURE_OFF= --with-xxhash=no XXHASH_LIB_DEPENDS= libxxhash.so:devel/xxhash .include .if ${PORT_OPTIONS:MPYTHON} .if ${PYTHON_VER} != ${PYTHON_DEFAULT} PKGNAMESUFFIX= ${PYTHON_PKGNAMESUFFIX} .endif .endif .if ${PORT_OPTIONS:MPYTHON} && \ (exists(/usr/lib/libc++.so.1) || exists(/lib/libc++.so.1)) USE_GITHUB= nodefault GH_ACCOUNT= bsdjhb:libcxx GH_PROJECT= libcxx-gdbpy:libcxx GH_TAGNAME= 03d0d9b:libcxx # Workaround USE_GITHUB preventing the default DISTFILES DISTFILES= ${DISTNAME}${EXTRACT_SUFX} .if exists(/usr/lib/libc++.so.1) LIBCXX_DIR= /usr/lib .else LIBCXX_DIR= /lib .endif PLIST_SUB+= LIBCXX_DIR="${LIBCXX_DIR}" PLIST_SUB+= LIBCXX="" .else PLIST_SUB+= LIBCXX="@comment " .endif .if ! ${PORT_OPTIONS:MBUNDLED_ZLIB} EXCLUDE+= zlib .endif .if ${ARCH} == amd64 CONFIGURE_TARGET= x86_64-portbld-freebsd${OSREL} .endif post-patch: @${REINPLACE_CMD} -e 's|$$| [GDB v${DISTVERSION} for FreeBSD]|' \ ${WRKSRC}/gdb/version.in post-patch-KGDB-on: @${CP} -r ${FILESDIR}/kgdb/*.[ch] ${WRKSRC}/gdb/ @${PATCH} -d ${PATCH_WRKSRC} ${PATCH_ARGS} < ${FILESDIR}/extrapatch-kgdb do-install: ${INSTALL_PROGRAM} ${INSTALL_WRKSRC}/gdb/gdb \ ${STAGEDIR}${PREFIX}/bin/gdb${VER} ${INSTALL_MAN} ${WRKSRC}/gdb/doc/gdb.1 \ ${STAGEDIR}${MAN1PREFIX}/man/man1/gdb${VER}.1 (cd ${INSTALL_WRKSRC}/gdb/data-directory ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-syscalls ) do-install-KGDB-on: ${INSTALL_PROGRAM} ${INSTALL_WRKSRC}/gdb/kgdb \ ${STAGEDIR}${PREFIX}/bin/kgdb${VER} ${INSTALL_MAN} ${FILESDIR}/kgdb/kgdb.1 \ ${STAGEDIR}${MAN1PREFIX}/man/man1/kgdb${VER}.1 do-install-TUI-on: ${LN} -sf gdb${VER} ${STAGEDIR}${PREFIX}/bin/gdbtui${VER} do-install-GDB_LINK-on: ${LN} -sf gdb${VER} ${STAGEDIR}${PREFIX}/bin/gdb ${LN} -sf gdb${VER}.1 ${STAGEDIR}${MAN1PREFIX}/man/man1/gdb.1 .if ${PORT_OPTIONS:MKGDB} ${LN} -sf kgdb${VER} ${STAGEDIR}${PREFIX}/bin/kgdb ${LN} -sf kgdb${VER}.1 ${STAGEDIR}${MAN1PREFIX}/man/man1/kgdb.1 .endif do-install-PYTHON-on: (cd ${INSTALL_WRKSRC}/gdb ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-python ) (cd ${INSTALL_WRKSRC}/gdb/data-directory ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-python ) @(cd ${STAGEDIR}${PREFIX}/share/gdb/python && \ ${PYTHON_CMD} -m compileall .) . for f in gdb gdb/command gdb/function gdb/printer @(cd ${STAGEDIR}${PREFIX}/share/gdb/python/${f} ; ${CHMOD} 644 *.py* ) . endfor .if exists(/usr/lib/libc++.so.1) || exists(/lib/libc++.so.1) @(cd ${WRKSRC_libcxx} ; \ ${SETENV} ${MAKE_ENV} ${MAKE} ${MAKE_ARGS} \ LIBCXX_DIR="${LIBCXX_DIR}" install ) @(cd ${STAGEDIR}${PREFIX}/share/gdb/auto-load/${LIBCXX_DIR} && \ ${PYTHON_CMD} -m compileall .) @(cd ${STAGEDIR}${PREFIX}/share/libcxx-gdbpy/libcxx && \ ${PYTHON_CMD} -m compileall .) .endif # DO NOT try and add rules here to strip .go files, no matter how loudly # testport / stage-qa shouts at you about it, because .go files (which are # compiled bytecode) are not intended to be stripped and doing so causes # breakage at run time. do-install-GUILE-on: (cd ${INSTALL_WRKSRC}/gdb ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-guile ) (cd ${INSTALL_WRKSRC}/gdb/data-directory ; \ ${SETENV} ${MAKE_ENV} ${MAKE_CMD} ${MAKE_ARGS} install-guile ) .include diff --git a/devel/gdb/files/kgdb/aarch64-fbsd-kern.c b/devel/gdb/files/kgdb/aarch64-fbsd-kern.c index f2d8f6511ff7..4d813c786b52 100644 --- a/devel/gdb/files/kgdb/aarch64-fbsd-kern.c +++ b/devel/gdb/files/kgdb/aarch64-fbsd-kern.c @@ -1,194 +1,279 @@ /*- * Copyright (c) 2017 John Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Target-dependent code for FreeBSD/aarch64 kernels. */ #include "defs.h" #include "aarch64-tdep.h" #include "frame-unwind.h" #include "gdbarch.h" #include "gdbcore.h" #include "osabi.h" #include "regcache.h" #include "regset.h" #include "solib.h" #include "target.h" #include "trad-frame.h" #include "kgdb.h" +struct aarch64fbsd_info +{ + int osreldate; +}; + +/* Per-program-space data key. */ +static const registry::key aarch64fbsd_pspace_data; + +static void +aarch64fbsd_pspace_data_cleanup (struct program_space *pspace, void *arg) +{ + struct aarch64fbsd_info *info = (struct aarch64fbsd_info *)arg; + + xfree (info); +} + +/* Get the current aarch64_fbsd data. If none is found yet, add it + now. This function always returns a valid object. */ + +static struct aarch64fbsd_info * +get_aarch64fbsd_info (void) +{ + struct aarch64fbsd_info *info; + + info = aarch64fbsd_pspace_data.get (current_program_space); + if (info != nullptr) + return info; + + info = aarch64fbsd_pspace_data.emplace (current_program_space); + + info->osreldate = parse_and_eval_long ("osreldate"); + return info; +} + static const struct regcache_map_entry aarch64_fbsd_pcbmap[] = { - { 30, AARCH64_X0_REGNUM, 8 }, /* x0 ... x29 */ + { 11, AARCH64_X0_REGNUM + 19, 8 }, /* x19 ... x29 */ { 1, AARCH64_PC_REGNUM, 8 }, - { 1, REGCACHE_MAP_SKIP, 8 }, { 1, AARCH64_SP_REGNUM, 8 }, { 0 } }; static const struct regset aarch64_fbsd_pcbregset = { aarch64_fbsd_pcbmap, regcache_supply_regset, regcache_collect_regset }; +/* In kernels prior to __FreeBSD_version 1400084, struct pcb used an + alternate layout. */ + +static const struct regcache_map_entry aarch64_fbsd13_pcbmap[] = + { + { 30, AARCH64_X0_REGNUM, 8 }, /* x0 ... x29 */ + { 1, AARCH64_PC_REGNUM, 8 }, + { 1, REGCACHE_MAP_SKIP, 8 }, + { 1, AARCH64_SP_REGNUM, 8 }, + { 0 } + }; + +static const struct regset aarch64_fbsd13_pcbregset = + { + aarch64_fbsd13_pcbmap, + regcache_supply_regset, regcache_collect_regset + }; + static void aarch64_fbsd_supply_pcb(struct regcache *regcache, CORE_ADDR pcb_addr) { + const struct regset *pcbregset; + struct aarch64fbsd_info *info = get_aarch64fbsd_info(); gdb_byte buf[8 * 33]; + if (info->osreldate >= 1400084) + pcbregset = &aarch64_fbsd_pcbregset; + else + pcbregset = &aarch64_fbsd13_pcbregset; + if (target_read_memory (pcb_addr, buf, sizeof buf) == 0) - regcache_supply_regset (&aarch64_fbsd_pcbregset, regcache, -1, buf, + regcache_supply_regset (pcbregset, regcache, -1, buf, sizeof (buf)); } +static const struct regcache_map_entry aarch64_fbsd_trapframe_map[] = + { + { 1, AARCH64_SP_REGNUM, 0 }, + { 1, AARCH64_LR_REGNUM, 0 }, + { 1, AARCH64_PC_REGNUM, 0 }, + { 1, AARCH64_CPSR_REGNUM, 0 }, + { 1, REGCACHE_MAP_SKIP, 8 }, /* esr */ + { 1, REGCACHE_MAP_SKIP, 8 }, /* far */ + { 30, AARCH64_X0_REGNUM, 0 }, /* x0 ... x29 */ + { 0 }, + }; + +/* In kernels prior to __FreeBSD_version 1400084, struct trapframe + used an alternate layout. */ + +static const struct regcache_map_entry aarch64_fbsd13_trapframe_map[] = + { + { 1, AARCH64_SP_REGNUM, 0 }, + { 1, AARCH64_LR_REGNUM, 0 }, + { 1, AARCH64_PC_REGNUM, 0 }, + { 1, AARCH64_CPSR_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* esr */ + { 30, AARCH64_X0_REGNUM, 0 }, /* x0 ... x29 */ + { 0 }, + }; + static struct trad_frame_cache * aarch64_fbsd_trapframe_cache (frame_info_ptr this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct aarch64fbsd_info *info = get_aarch64fbsd_info(); struct trad_frame_cache *cache; CORE_ADDR func, pc, sp; const char *name; - int i; + int i, tf_size; if (*this_cache != NULL) return ((struct trad_frame_cache *)*this_cache); + const struct regcache_map_entry *trapframe_map; + + if (info->osreldate >= 1400084) + { + trapframe_map = aarch64_fbsd_trapframe_map; + } + else + { + trapframe_map = aarch64_fbsd13_trapframe_map; + } + cache = trad_frame_cache_zalloc (this_frame); *this_cache = cache; func = get_frame_func (this_frame); sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); - if (strcmp(name, "fork_trampoline") == 0 && get_frame_pc (this_frame) == func) - { - /* fork_exit hasn't been called (kthread has never run), so SP - hasn't been initialized yet. The stack pointer is stored in - the X2 in the pcb. */ - sp = get_frame_register_unsigned (this_frame, AARCH64_X0_REGNUM + 2); - } - trad_frame_set_reg_addr (cache, AARCH64_SP_REGNUM, sp); - trad_frame_set_reg_addr (cache, AARCH64_LR_REGNUM, sp + 8); - trad_frame_set_reg_addr (cache, AARCH64_PC_REGNUM, sp + 16); - trad_frame_set_reg_addr (cache, AARCH64_CPSR_REGNUM, sp + 24); - for (i = 0; i < 30; i++) - trad_frame_set_reg_addr (cache, AARCH64_X0_REGNUM + i, sp + 32 + i * 8); + tf_size = regcache_map_entry_size (trapframe_map); + trad_frame_set_reg_regmap (cache, trapframe_map, sp, tf_size); /* Read $PC from trap frame. */ - pc = read_memory_unsigned_integer (sp + 16, 8, byte_order); + pc = read_memory_unsigned_integer (sp + 2 * 8, 8, byte_order); if (pc == 0 && strcmp(name, "fork_trampoline") == 0) { /* Initial frame of a kthread; terminate backtrace. */ trad_frame_set_id (cache, outer_frame_id); } else { /* Construct the frame ID using the function start. */ - trad_frame_set_id (cache, frame_id_build (sp + 8 * 34, func)); + trad_frame_set_id (cache, frame_id_build (sp + tf_size, func)); } return cache; } static void aarch64_fbsd_trapframe_this_id (frame_info_ptr this_frame, void **this_cache, struct frame_id *this_id) { struct trad_frame_cache *cache = aarch64_fbsd_trapframe_cache (this_frame, this_cache); trad_frame_get_id (cache, this_id); } static struct value * aarch64_fbsd_trapframe_prev_register (frame_info_ptr this_frame, void **this_cache, int regnum) { struct trad_frame_cache *cache = aarch64_fbsd_trapframe_cache (this_frame, this_cache); return trad_frame_get_register (cache, this_frame, regnum); } static int aarch64_fbsd_trapframe_sniffer (const struct frame_unwind *self, frame_info_ptr this_frame, void **this_prologue_cache) { const char *name; find_pc_partial_function (get_frame_func (this_frame), &name, NULL, NULL); return (name && ((strcmp (name, "handle_el1h_sync") == 0) || (strcmp (name, "handle_el1h_irq") == 0) || (strcmp (name, "handle_el0_sync") == 0) || (strcmp (name, "handle_el0_irq") == 0) || (strcmp (name, "handle_el0_error") == 0) || (strcmp (name, "fork_trampoline") == 0))); } static const struct frame_unwind aarch64_fbsd_trapframe_unwind = { "aarch64 FreeBSD kernel trap", SIGTRAMP_FRAME, default_frame_unwind_stop_reason, aarch64_fbsd_trapframe_this_id, aarch64_fbsd_trapframe_prev_register, NULL, aarch64_fbsd_trapframe_sniffer }; /* Implement the 'init_osabi' method of struct gdb_osabi_handler. */ static void aarch64_fbsd_kernel_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { aarch64_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); frame_unwind_prepend_unwinder (gdbarch, &aarch64_fbsd_trapframe_unwind); set_gdbarch_so_ops (gdbarch, &kld_so_ops); /* Enable longjmp. */ tdep->jb_pc = 13; fbsd_vmcore_set_supply_pcb (gdbarch, aarch64_fbsd_supply_pcb); fbsd_vmcore_set_cpu_pcb_addr (gdbarch, kgdb_trgt_stop_pcb); } void _initialize_aarch64_kgdb_tdep (); void _initialize_aarch64_kgdb_tdep () { gdbarch_register_osabi_sniffer(bfd_arch_aarch64, bfd_target_elf_flavour, fbsd_kernel_osabi_sniffer); gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_FREEBSD_KERNEL, aarch64_fbsd_kernel_init_abi); }