Index: head/devel/gdb/Makefile =================================================================== --- head/devel/gdb/Makefile (revision 560807) +++ head/devel/gdb/Makefile (revision 560808) @@ -1,181 +1,181 @@ # Created by: Steven Kreuzer # $FreeBSD$ PORTNAME= gdb PORTVERSION= 10.1 -PORTREVISION= 0 +PORTREVISION= 1 CATEGORIES= devel MASTER_SITES= GNU MAINTAINER= pizzamig@FreeBSD.org COMMENT= GNU Project Debugger LICENSE= GPLv3 LICENSE_FILE= ${WRKSRC}/COPYING3 # untested on sparc64, might work NOT_FOR_ARCHS= sparc64 LIB_DEPENDS= libmpfr.so:math/mpfr 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=${PORTVERSION:S/.//g} \ --enable-targets=all --enable-64-bit-bfd \ --with-separate-debug-dir=/usr/lib/debug \ ${ICONV_CONFIGURE_ARG} \ --with-expat=yes --with-libexpat-prefix=${LOCALBASE} \ --without-libunwind-ia64 --with-system-zlib CONFIGURE_OUTSOURCE= yes CFLAGS:= ${CFLAGS:C/ +$//} # blanks at EOL creep in sometimes CFLAGS+= -DRL_NO_COMPAT -Wno-unused-function -Wno-unused-variable CFLAGS+= -Wno-unknown-warning-option EXCLUDE= dejagnu expect sim texinfo intl EXTRACT_AFTER_ARGS= ${EXCLUDE:S/^/--exclude /} LIB_DEPENDS+= libexpat.so:textproc/expat2 VER= ${PORTVERSION:S/.//g} PLIST_SUB= VER=${VER} OPTIONS_DEFINE= DEBUG GDB_LINK GUILE KGDB NLS PYTHON SOURCE_HIGHLIGHT TUI OPTIONS_DEFAULT= GDB_LINK KGDB NLS PYTHON SOURCE_HIGHLIGHT TUI 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= Source Code Styling SYSTEM_ICONV_DESC= use libc iconv, with no wchar support SYSTEM_ZLIB_DESC= use system zlib TUI_DESC= Text User Interface enabled OPTIONS_SUB= yes BUNDLED_READLINE_CONFIGURE_OFF= --with-system-readline DEBUG_CFLAGS= -g GUILE_CONFIGURE_WITH= guile GUILE_LIB_DEPENDS= libguile-2.2.so:lang/guile2 GUILE_EXTRA_PATCHES= ${FILESDIR}/extrapatch-guile22 NLS_USES= gettext-runtime PORT_READLINE_USES= readline:port PORT_ICONV_USES= iconv:wchar_t PYTHON_CONFIGURE_ON= --with-python=${PYTHON_CMD} PYTHON_CONFIGURE_OFF= --without-python PYTHON_USES= python:3.6+ SOURCE_HIGHLIGHT_WITH= 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 .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) USE_GITHUB= nodefault GH_ACCOUNT= bsdjhb:libcxx GH_PROJECT= libcxx-gdbpy:libcxx GH_TAGNAME= 229610a:libcxx # Workaround USE_GITHUB preventing the default DISTFILES DISTFILES= ${DISTNAME}${EXTRACT_SUFX} 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 .if ${CHOSEN_COMPILER_TYPE} == clang CFLAGS+= -Wno-extended-offsetof .endif post-patch: @${REINPLACE_CMD} -e 's|$$| [GDB v${PORTVERSION} 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) @(cd ${WRKSRC_libcxx} ; \ ${SETENV} ${MAKE_ENV} ${MAKE} ${MAKE_ARGS} install ) @(cd ${STAGEDIR}${PREFIX}/share/gdb/auto-load/usr/lib && \ ${PYTHON_CMD} -m compileall .) @(cd ${STAGEDIR}${PREFIX}/share/libcxx-gdbpy/libcxx && \ ${PYTHON_CMD} -m compileall .) .endif 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 Index: head/devel/gdb/files/kgdb/arm-fbsd-kern.c =================================================================== --- head/devel/gdb/files/kgdb/arm-fbsd-kern.c (revision 560807) +++ head/devel/gdb/files/kgdb/arm-fbsd-kern.c (revision 560808) @@ -1,199 +1,214 @@ /*- * Copyright (c) 2018 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. * * $FreeBSD$ */ /* Target-dependent code for FreeBSD/arm kernels. */ #include "defs.h" #include "arm-tdep.h" #include "frame-unwind.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" static const struct regcache_map_entry arm_fbsd_pcbmap[] = { { 9, 4, 4 }, /* r4 ... r12 */ { 1, ARM_SP_REGNUM, 4 }, { 1, ARM_LR_REGNUM, 4 }, { 1, ARM_PC_REGNUM, 4 }, { 0 } }; static const struct regset arm_fbsd_pcbregset = { arm_fbsd_pcbmap, regcache_supply_regset, regcache_collect_regset }; static void arm_fbsd_supply_pcb(struct regcache *regcache, CORE_ADDR pcb_addr) { gdb_byte buf[4 * 12]; if (target_read_memory (pcb_addr, buf, sizeof buf) == 0) regcache->supply_regset (&arm_fbsd_pcbregset, -1, buf, sizeof (buf)); /* * XXX: This is a gross hack, but the ARM frame unwinders need the value * of xPSR to determine if Thumb mode is active. FreeBSD's kernels never * use Thumb. */ regcache->raw_supply_unsigned(ARM_PS_REGNUM, 0); } +#define PSR_MODE 0x0000001f /* mode mask */ +#define PSR_USR32_MODE 0x00000010 + static struct trad_frame_cache * arm_fbsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct trad_frame_cache *cache; + uint32_t psr; CORE_ADDR func, pc, sp; const char *name; int i; if (*this_cache != NULL) return ((struct trad_frame_cache *)*this_cache); cache = trad_frame_cache_zalloc (this_frame); *this_cache = cache; func = get_frame_func (this_frame); sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); find_pc_partial_function (func, &name, NULL, NULL); + /* Read $PSR to determine where SP and LR are. */ + psr = read_memory_unsigned_integer (sp, 4, byte_order); + for (i = 0; i <= 12; i++) trad_frame_set_reg_addr (cache, ARM_A1_REGNUM + i, sp + 4 + i * 4); - trad_frame_set_reg_addr (cache, ARM_SP_REGNUM, sp + 14 * 4); - trad_frame_set_reg_addr (cache, ARM_LR_REGNUM, sp + 15 * 4); + if ((psr & PSR_MODE) == PSR_USR32_MODE) + { + trad_frame_set_reg_addr (cache, ARM_SP_REGNUM, sp + 14 * 4); + trad_frame_set_reg_addr (cache, ARM_LR_REGNUM, sp + 15 * 4); + } + else + { + trad_frame_set_reg_addr (cache, ARM_SP_REGNUM, sp + 16 * 4); + trad_frame_set_reg_addr (cache, ARM_LR_REGNUM, sp + 17 * 4); + } trad_frame_set_reg_addr (cache, ARM_PC_REGNUM, sp + 18 * 4); trad_frame_set_reg_addr (cache, ARM_PS_REGNUM, sp); /* Read $PC from trap frame. */ pc = read_memory_unsigned_integer (sp + 18 * 4, 4, byte_order); if (pc == 0 && strcmp(name, "swi_entry") == 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 + 4 * 19, func)); } return cache; } static void arm_fbsd_trapframe_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) { struct trad_frame_cache *cache = arm_fbsd_trapframe_cache (this_frame, this_cache); trad_frame_get_id (cache, this_id); } static struct value * arm_fbsd_trapframe_prev_register (struct frame_info *this_frame, void **this_cache, int regnum) { struct trad_frame_cache *cache = arm_fbsd_trapframe_cache (this_frame, this_cache); return trad_frame_get_register (cache, this_frame, regnum); } static int arm_fbsd_trapframe_sniffer (const struct frame_unwind *self, struct frame_info *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, "data_abort_entry") == 0) || (strcmp (name, "prefetch_abort_entry") == 0) || (strcmp (name, "undefined_entry") == 0) || (strcmp (name, "exception_exit") == 0) || (strcmp (name, "irq_entry") == 0) || (strcmp (name, "swi_entry") == 0) || (strcmp (name, "swi_exit") == 0))); } static const struct frame_unwind arm_fbsd_trapframe_unwind = { SIGTRAMP_FRAME, default_frame_unwind_stop_reason, arm_fbsd_trapframe_this_id, arm_fbsd_trapframe_prev_register, NULL, arm_fbsd_trapframe_sniffer }; /* Implement the 'init_osabi' method of struct gdb_osabi_handler. */ static void arm_fbsd_kernel_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); frame_unwind_prepend_unwinder (gdbarch, &arm_fbsd_trapframe_unwind); set_solib_ops (gdbarch, &kld_so_ops); tdep->jb_pc = 24; tdep->jb_elt_size = 4; fbsd_vmcore_set_supply_pcb (gdbarch, arm_fbsd_supply_pcb); fbsd_vmcore_set_cpu_pcb_addr (gdbarch, kgdb_trgt_stop_pcb); /* Single stepping. */ set_gdbarch_software_single_step (gdbarch, arm_software_single_step); } /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_arm_kgdb_tdep; void _initialize_arm_kgdb_tdep (void) { gdbarch_register_osabi_sniffer(bfd_arch_arm, bfd_target_elf_flavour, fbsd_kernel_osabi_sniffer); gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_FREEBSD_KERNEL, arm_fbsd_kernel_init_abi); } Index: head/devel/gdb/files/kgdb/fbsd-kthr.c =================================================================== --- head/devel/gdb/files/kgdb/fbsd-kthr.c (revision 560807) +++ head/devel/gdb/files/kgdb/fbsd-kthr.c (revision 560808) @@ -1,366 +1,437 @@ /* * Copyright (c) 2004 Marcel Moolenaar * 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. + * + * $FreeBSD$ */ -#include -__FBSDID("$FreeBSD$"); - #include #include #include -#include +#include "defs.h" #include "gdbcore.h" #include "objfiles.h" #include "value.h" #include "kgdb.h" static CORE_ADDR dumppcb; static LONGEST dumptid; static CORE_ADDR stopped_cpus; static LONGEST mp_maxid; static struct kthr *first, *last; struct kthr *curkthr; -static int proc_off_p_pid, proc_off_p_comm, proc_off_p_list, proc_off_p_threads; +static int proc_off_p_pid, proc_off_p_comm, proc_off_p_hash, proc_off_p_list; +static int proc_off_p_threads; static int thread_off_td_tid, thread_off_td_oncpu, thread_off_td_pcb; static int thread_off_td_name, thread_off_td_plist; static int thread_oncpu_size; CORE_ADDR kgdb_lookup(const char *sym) { struct bound_minimal_symbol msym; msym = lookup_minimal_symbol(sym, NULL, NULL); if (msym.minsym == NULL) return (0); return (BMSYMBOL_VALUE_ADDRESS(msym)); } /* * Perform the equivalent of CPU_ISSET() to see if 'cpu' is set in the * kernel's stopped_cpus set. The set contains an array of longs. * This function determines the specific long to read and tests the * necessary bit in the long. */ static bool cpu_stopped(int cpu) { struct gdbarch *gdbarch = target_gdbarch (); CORE_ADDR addr; ULONGEST mask; int bit, long_bytes, word; if (cpu < 0 || cpu > mp_maxid || stopped_cpus == 0) return (false); bit = cpu % gdbarch_long_bit (gdbarch); word = cpu / gdbarch_long_bit (gdbarch); long_bytes = gdbarch_long_bit (gdbarch) / 8; addr = stopped_cpus + word * long_bytes; mask = read_memory_unsigned_integer (addr, long_bytes, gdbarch_byte_order (gdbarch)); return (mask & ((ULONGEST)1 << bit)) != 0; } struct kthr * kgdb_thr_first(void) { return (first); } static void -kgdb_thr_add_procs(CORE_ADDR paddr, CORE_ADDR (*cpu_pcb_addr) (u_int)) +kgdb_thr_add_proc(CORE_ADDR paddr, CORE_ADDR (*cpu_pcb_addr) (u_int)) { struct gdbarch *gdbarch = target_gdbarch (); struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct kthr *kt; - CORE_ADDR pcb, pnext, tdaddr, tdnext; + CORE_ADDR pcb, tdaddr, tdnext; ULONGEST oncpu; LONGEST pid, tid; - while (paddr != 0) { + try { + tdaddr = read_memory_typed_address (paddr + proc_off_p_threads, + ptr_type); + pid = read_memory_integer (paddr + proc_off_p_pid, 4, byte_order); + } catch (const gdb_exception_error &e) { + return; + } + + while (tdaddr != 0) { try { - tdaddr = read_memory_typed_address (paddr + - proc_off_p_threads, ptr_type); - pid = read_memory_integer (paddr + proc_off_p_pid, 4, - byte_order); - pnext = read_memory_typed_address (paddr + - proc_off_p_list, ptr_type); + tid = read_memory_integer (tdaddr + thread_off_td_tid, + 4, byte_order); + oncpu = read_memory_unsigned_integer (tdaddr + + thread_off_td_oncpu, thread_oncpu_size, byte_order); + pcb = read_memory_typed_address (tdaddr + + thread_off_td_pcb, ptr_type); + tdnext = read_memory_typed_address (tdaddr + + thread_off_td_plist, ptr_type); } catch (const gdb_exception_error &e) { - break; + return; } - while (tdaddr != 0) { + kt = XNEW (struct kthr); + if (last == NULL) + first = last = kt; + else + last->next = kt; + kt->next = NULL; + kt->kaddr = tdaddr; + if (tid == dumptid) + kt->pcb = dumppcb; + else if (cpu_stopped(oncpu)) + kt->pcb = cpu_pcb_addr(oncpu); + else + kt->pcb = pcb; + kt->tid = tid; + kt->pid = pid; + kt->paddr = paddr; + kt->cpu = oncpu; + last = kt; + tdaddr = tdnext; + } +} + +static void +kgdb_thr_add_procs_hash(CORE_ADDR pidhashtbl, CORE_ADDR (*cpu_pcb_addr) (u_int)) +{ + struct gdbarch *gdbarch = target_gdbarch (); + struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR paddr, pnext; + ULONGEST i, pidhash; + + pidhash = parse_and_eval_long("pidhash"); + for (i = 0; i < pidhash; i++) { + try { + paddr = read_memory_typed_address (pidhashtbl + + i * TYPE_LENGTH(ptr_type), ptr_type); + } catch (const gdb_exception_error &e) { + continue; + } + while (paddr != 0) { try { - tid = read_memory_integer (tdaddr + - thread_off_td_tid, 4, byte_order); - oncpu = read_memory_unsigned_integer (tdaddr + - thread_off_td_oncpu, thread_oncpu_size, - byte_order); - pcb = read_memory_typed_address (tdaddr + - thread_off_td_pcb, ptr_type); - tdnext = read_memory_typed_address (tdaddr + - thread_off_td_plist, ptr_type); + pnext = read_memory_typed_address (paddr + + proc_off_p_hash, ptr_type); } catch (const gdb_exception_error &e) { break; } - kt = XNEW (struct kthr); - if (last == NULL) - first = last = kt; - else - last->next = kt; - kt->next = NULL; - kt->kaddr = tdaddr; - if (tid == dumptid) - kt->pcb = dumppcb; - else if (cpu_stopped(oncpu)) - kt->pcb = cpu_pcb_addr(oncpu); - else - kt->pcb = pcb; - kt->tid = tid; - kt->pid = pid; - kt->paddr = paddr; - kt->cpu = oncpu; - last = kt; - tdaddr = tdnext; + kgdb_thr_add_proc(paddr, cpu_pcb_addr); + paddr = pnext; } + } +} + +static void +kgdb_thr_add_procs_list(CORE_ADDR paddr, CORE_ADDR (*cpu_pcb_addr) (u_int)) +{ + struct gdbarch *gdbarch = target_gdbarch (); + struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR pnext; + + while (paddr != 0) { + try { + pnext = read_memory_typed_address (paddr + + proc_off_p_list, ptr_type); + } catch (const gdb_exception_error &e) { + break; + } + kgdb_thr_add_proc(paddr, cpu_pcb_addr); paddr = pnext; } } struct kthr * kgdb_thr_init(CORE_ADDR (*cpu_pcb_addr) (u_int)) { struct gdbarch *gdbarch = target_gdbarch (); struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr; struct kthr *kt; CORE_ADDR addr, paddr; while (first != NULL) { kt = first; first = kt->next; free(kt); } last = NULL; - addr = kgdb_lookup("allproc"); - if (addr == 0) - return (NULL); - try { - paddr = read_memory_typed_address (addr, ptr_type); - } catch (const gdb_exception_error &e) { - return (NULL); - } - dumppcb = kgdb_lookup("dumppcb"); if (dumppcb == 0) return (NULL); try { dumptid = parse_and_eval_long("dumptid"); } catch (const gdb_exception_error &e) { dumptid = -1; } try { mp_maxid = parse_and_eval_long("mp_maxid"); } catch (const gdb_exception_error &e) { mp_maxid = 0; } stopped_cpus = kgdb_lookup("stopped_cpus"); /* * Newer kernels export a set of global variables with the offsets * of certain members in struct proc and struct thread. For older * kernels, try to extract these offsets using debug symbols. If * that fails, use native values. */ try { proc_off_p_pid = parse_and_eval_long("proc_off_p_pid"); proc_off_p_comm = parse_and_eval_long("proc_off_p_comm"); proc_off_p_list = parse_and_eval_long("proc_off_p_list"); proc_off_p_threads = parse_and_eval_long("proc_off_p_threads"); thread_off_td_tid = parse_and_eval_long("thread_off_td_tid"); thread_off_td_name = parse_and_eval_long("thread_off_td_name"); thread_off_td_oncpu = parse_and_eval_long("thread_off_td_oncpu"); thread_off_td_pcb = parse_and_eval_long("thread_off_td_pcb"); thread_off_td_plist = parse_and_eval_long("thread_off_td_plist"); thread_oncpu_size = 4; } catch (const gdb_exception_error &e) { try { struct symbol *proc_sym = lookup_symbol_in_language ("struct proc", NULL, STRUCT_DOMAIN, language_c, NULL).symbol; if (proc_sym == NULL) error (_("Unable to find struct proc symbol")); proc_off_p_pid = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "p_pid", 0).offset / 8; proc_off_p_comm = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "p_comm", 0).offset / 8; proc_off_p_list = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "p_list", 0).offset / 8; proc_off_p_threads = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "p_threads", 0).offset / 8; struct symbol *thread_sym = lookup_symbol_in_language ("struct thread", NULL, STRUCT_DOMAIN, language_c, NULL).symbol; if (thread_sym == NULL) error (_("Unable to find struct thread symbol")); thread_off_td_tid = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "td_tid", 0).offset / 8; thread_off_td_name = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "td_name", 0).offset / 8; thread_off_td_pcb = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "td_pcb", 0).offset / 8; thread_off_td_plist = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "td_plist", 0).offset / 8; struct_elt td_oncpu = lookup_struct_elt (SYMBOL_TYPE (proc_sym), "td_oncpu", 0); thread_off_td_oncpu = td_oncpu.offset / 8; thread_oncpu_size = FIELD_BITSIZE(*td_oncpu.field) / 8; } catch (const gdb_exception_error &e2) { proc_off_p_pid = offsetof(struct proc, p_pid); proc_off_p_comm = offsetof(struct proc, p_comm); proc_off_p_list = offsetof(struct proc, p_list); proc_off_p_threads = offsetof(struct proc, p_threads); thread_off_td_tid = offsetof(struct thread, td_tid); thread_off_td_name = offsetof(struct thread, td_name); thread_off_td_oncpu = offsetof(struct thread, td_oncpu); thread_off_td_pcb = offsetof(struct thread, td_pcb); thread_off_td_plist = offsetof(struct thread, td_plist); thread_oncpu_size = sizeof(((struct thread *)0)->td_oncpu); } } - kgdb_thr_add_procs(paddr, cpu_pcb_addr); + /* + * Handle p_hash separately. + */ + try { + proc_off_p_hash = parse_and_eval_long("proc_off_p_hash"); + } catch (const gdb_exception_error &e) { + try { + struct symbol *proc_sym = + lookup_symbol_in_language ("struct proc", NULL, + STRUCT_DOMAIN, language_c, NULL).symbol; + if (proc_sym == NULL) + error (_("Unable to find struct proc symbol")); + + proc_off_p_hash = + lookup_struct_elt (SYMBOL_TYPE (proc_sym), "p_hash", + 0).offset / 8; + } catch (const gdb_exception_error &e2) { + proc_off_p_hash = offsetof(struct proc, p_hash); + } + } + addr = kgdb_lookup("zombproc"); if (addr != 0) { + addr = kgdb_lookup("allproc"); try { paddr = read_memory_typed_address (addr, ptr_type); - kgdb_thr_add_procs(paddr, cpu_pcb_addr); + kgdb_thr_add_procs_list(paddr, cpu_pcb_addr); } catch (const gdb_exception_error &e) { + return (NULL); + } + + try { + paddr = read_memory_typed_address (addr, ptr_type); + kgdb_thr_add_procs_list(paddr, cpu_pcb_addr); + } catch (const gdb_exception_error &e) { + } + } else { + addr = kgdb_lookup("pidhashtbl"); + try { + addr = read_memory_typed_address (addr, ptr_type); + kgdb_thr_add_procs_hash(addr, cpu_pcb_addr); + } catch (const gdb_exception_error &e) { + return (NULL); } } curkthr = kgdb_thr_lookup_tid(dumptid); if (curkthr == NULL) curkthr = first; return (first); } struct kthr * kgdb_thr_lookup_tid(int tid) { struct kthr *kt; kt = first; while (kt != NULL && kt->tid != tid) kt = kt->next; return (kt); } struct kthr * kgdb_thr_lookup_taddr(uintptr_t taddr) { struct kthr *kt; kt = first; while (kt != NULL && kt->kaddr != taddr) kt = kt->next; return (kt); } struct kthr * kgdb_thr_lookup_pid(int pid) { struct kthr *kt; kt = first; while (kt != NULL && kt->pid != pid) kt = kt->next; return (kt); } struct kthr * kgdb_thr_lookup_paddr(uintptr_t paddr) { struct kthr *kt; kt = first; while (kt != NULL && kt->paddr != paddr) kt = kt->next; return (kt); } struct kthr * kgdb_thr_next(struct kthr *kt) { return (kt->next); } const char * kgdb_thr_extra_thread_info(int tid) { static char buf[64]; struct kthr *kt = kgdb_thr_lookup_tid(tid); if (kt == nullptr) return (nullptr); snprintf(buf, sizeof (buf), "PID=%d", kt->pid); gdb::unique_xmalloc_ptr comm = target_read_string (kt->paddr + proc_off_p_comm, MAXCOMLEN + 1); if (comm != nullptr) { strlcat(buf, ": ", sizeof (buf)); strlcat(buf, comm.get (), sizeof (buf)); gdb::unique_xmalloc_ptr td_name = target_read_string (kt->kaddr + thread_off_td_name, MAXCOMLEN + 1); if (td_name != nullptr && strcmp (comm.get (), td_name.get ()) != 0) { strlcat(buf, "/", sizeof (buf)); strlcat(buf, td_name.get (), sizeof (buf)); } } return (buf); }