Date: Mon, 07 Oct 2002 17:09:39 +0100 From: Ian Dowse <iedowse@maths.tcd.ie> To: hackers@freebsd.org Subject: gdb support for kernel modules Message-ID: <200210071709.aa25499@salmon.maths.tcd.ie>
next in thread | raw e-mail | index | archive | help
This is something I have been meaning to investigate for a while: when gdb encounters a userland executable that uses shared libraries it automatically adds the symbols from each library, so it seemed likely that gdb could be made do the same thing with kernel modules. I am aware of the existence of `gdbmods' etc, but it would be nicer to have the support built in to gdb. Anyway, below is a proof-of-concept patch that does the basics, but among other things, its logic for locating the kernel module files needs a lot of work - currently it just assumes /boot/kernel/<module>, which is almost never what you actually want. It works for debugging vmcores and live /dev/mem access, but I don't know if it can work for remote debugging. Does anybody know gdb internals enough to comment on how this is done or suggest improvements? Ian # gdb -k kernel.debug /dev/mem ... This GDB was configured as "i386-undermydesk-freebsd"... panic messages: --- --- warning: skipping first file (kernel) Reading symbols from /boot/kernel/ufs.ko...done. Loaded symbols for /boot/kernel/ufs.ko Reading symbols from /boot/kernel/md.ko...done. Loaded symbols for /boot/kernel/md.ko Reading symbols from /boot/kernel/vinum.ko...done. Loaded symbols for /boot/kernel/vinum.ko #0 mi_switch () at ../../../kern/kern_synch.c:849 849 td->td_kse->ke_oncpu = PCPU_GET(cpuid); (kgdb) info sharedlibrary warning: skipping first file (kernel) From To Syms Read Shared Object Library 0xc1098dd0 0xc10bfc10 Yes /boot/kernel/ufs.ko 0xc11e24d0 0xc11e4270 Yes /boot/kernel/md.ko 0xc10cf940 0xc10ddc30 Yes /boot/kernel/vinum.ko (kgdb) proc 316 (kgdb) bt #0 mi_switch () at ../../../kern/kern_synch.c:849 #1 0xc01b7d14 in msleep (ident=0xc1292e00, mtx=0x0, priority=76, wmesg=0x0, timo=0) at ../../../kern/kern_synch.c:559 #2 0xc11e3052 in md_kthread (arg=0xc1292e00) at /usr/src/sys/dev/md/md.c:578 #3 0xc019d2e5 in fork_exit (callout=0xc11e2fd0 <md_kthread>, arg=0x0, frame=0x0) at ../../../kern/kern_fork.c:853 (kgdb) Index: Makefile =================================================================== RCS file: /dump/FreeBSD-CVS/src/gnu/usr.bin/binutils/gdb/Makefile,v retrieving revision 1.61 diff -u -r1.61 Makefile --- Makefile 29 Jun 2002 03:16:10 -0000 1.61 +++ Makefile 7 Oct 2002 10:31:41 -0000 @@ -37,7 +37,7 @@ ui-file.c ui-out.c wrapper.c cli-out.c \ cli-cmds.c cli-cmds.h cli-decode.c cli-decode.h cli-script.c \ cli-script.h cli-setshow.c cli-setshow.h cli-utils.c cli-utils.h -XSRCS+= freebsd-uthread.c kvm-fbsd.c +XSRCS+= freebsd-uthread.c kvm-fbsd.c solib-fbsd-kld.c SRCS= init.c ${XSRCS} nm.h tm.h xm.h gdbversion.c xregex.h .if exists(${.CURDIR}/Makefile.${TARGET_ARCH}) Index: fbsd-kgdb.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/gnu/usr.bin/binutils/gdb/fbsd-kgdb.h,v retrieving revision 1.3 diff -u -r1.3 fbsd-kgdb.h --- fbsd-kgdb.h 18 Sep 2002 16:20:49 -0000 1.3 +++ fbsd-kgdb.h 6 Oct 2002 23:32:14 -0000 @@ -7,6 +7,7 @@ extern int kernel_debugging; extern int kernel_writablecore; +extern struct target_so_ops kgdb_so_ops; #define ADDITIONAL_OPTIONS \ {"kernel", no_argument, &kernel_debugging, 1}, \ Index: kvm-fbsd.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/gnu/usr.bin/binutils/gdb/kvm-fbsd.c,v retrieving revision 1.42 diff -u -r1.42 kvm-fbsd.c --- kvm-fbsd.c 18 Sep 2002 16:19:05 -0000 1.42 +++ kvm-fbsd.c 6 Oct 2002 23:41:56 -0000 @@ -56,6 +56,7 @@ #include "bfd.h" #include "target.h" #include "gdbcore.h" +#include "solist.h" static void kcore_files_info (struct target_ops *); @@ -72,6 +73,10 @@ static int xfer_umem (CORE_ADDR, char *, int, int); +#ifdef SOLIB_ADD +static int kcore_solib_add_stub (PTR); +#endif + static char *core_file; static kvm_t *core_kd; static struct pcb cur_pcb; @@ -209,6 +214,12 @@ inferior_ptid = null_ptid; /* Avoid confusion from thread stuff. */ + /* Clear out solib state while the bfd is still open. See + comments in clear_solib in solib.c. */ +#ifdef CLEAR_SOLIB + CLEAR_SOLIB (); +#endif + if (core_kd) { kvm_close (core_kd); @@ -305,7 +316,16 @@ printf ("---\n"); } - if (!ontop) + if (ontop) + { + /* Add symbols and section mappings for any kernel modules. */ +#ifdef SOLIB_ADD + current_target_so_ops = &kgdb_so_ops; + catch_errors (kcore_solib_add_stub, &from_tty, (char *) 0, + RETURN_MASK_ALL); +#endif + } + else { warning ("you won't be able to access this core file until you terminate\n" "your %s; do ``info files''", target_longname); @@ -651,6 +671,15 @@ if (set_context ((CORE_ADDR) val)) error ("invalid proc address"); } + +#ifdef SOLIB_ADD +static int +kcore_solib_add_stub (PTR from_ttyp) +{ + SOLIB_ADD (NULL, *(int *) from_ttyp, ¤t_target, auto_solib_add); + return 0; +} +#endif /* SOLIB_ADD */ void _initialize_kcorelow (void) Index: solib-fbsd-kld.c =================================================================== RCS file: solib-fbsd-kld.c diff -N solib-fbsd-kld.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ solib-fbsd-kld.c 7 Oct 2002 10:39:48 -0000 @@ -0,0 +1,181 @@ +/* Handle FreeBSD kernel modules as shared libraries. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 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 <sys/param.h> +#include <sys/queue.h> +#define _KERNEL +#include <sys/linker.h> +#undef _KERNEL + +#include "defs.h" +#include "symtab.h" +#include "bfd.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdbcore.h" +#include "target.h" +#include "inferior.h" + +#include "solist.h" + +struct lm_info + { + CORE_ADDR address; + }; + +static void +kgdb_relocate_section_addresses (struct so_list *so, + struct section_table *sec) +{ + sec->addr += so->lm_info->address; + sec->endaddr += so->lm_info->address; +} + +static int +kgdb_open_symbol_file_object (void *from_ttyp) +{ + warning ("kgdb_open_symbol_file_object called\n"); + return 0; +} + +static struct so_list * +kgdb_current_sos (void) +{ + linker_file_list_t linker_files; + struct linker_file lfile; + struct minimal_symbol *msymbol; + struct linker_file *lfilek; + struct so_list *head = NULL; + struct so_list **link_ptr = &head; + + CORE_ADDR lfiles_addr; + + msymbol = lookup_minimal_symbol ("linker_files", NULL, symfile_objfile); + if (msymbol == NULL || SYMBOL_VALUE_ADDRESS (msymbol) == 0) + { + warning ("failed to find linker_files symbol\n"); + return 0; + } + lfiles_addr = SYMBOL_VALUE_ADDRESS (msymbol); + if (target_read_memory (lfiles_addr, (char *)&linker_files, + sizeof (linker_files))) + { + warning ("failed to read linker_files data\n"); + return 0; + } + for (lfilek = TAILQ_FIRST (&linker_files); lfilek != NULL; + lfilek = TAILQ_NEXT (&lfile, link)) + { + struct so_list *new; + struct cleanup *old_chain; + char *buf; + int errcode; + + if (target_read_memory ((CORE_ADDR) lfilek, (char *) &lfile, + sizeof (lfile))) + { + warning ("failed to read linker file data at %p\n", lfilek); + return 0; + } + target_read_string ((CORE_ADDR) lfile.filename, &buf, + SO_NAME_MAX_PATH_SIZE - 1, &errcode); + if (errcode != 0) + { + warning ("cannot read linker file pathname: %s\n", + safe_strerror (errcode)); + return 0; + } + if (lfilek == TAILQ_FIRST (&linker_files)) /* XXX kernel always first? */ + { + warning ("skipping first file (%s)\n", buf); + xfree (buf); + continue; + } + + new = (struct so_list *) xmalloc (sizeof (struct so_list)); + old_chain = make_cleanup (xfree, new); + + memset (new, 0, sizeof (*new)); + + new->lm_info = xmalloc (sizeof (struct lm_info)); + make_cleanup (xfree, new->lm_info); + + new->lm_info->address = (CORE_ADDR) lfile.address; + + strncpy (new->so_original_name, buf, SO_NAME_MAX_PATH_SIZE - 1); + new->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; + xfree (buf); + snprintf (new->so_name, SO_NAME_MAX_PATH_SIZE, "/boot/kernel/%s", + new->so_original_name); + + new->next = NULL; + *link_ptr = new; + link_ptr = &new->next; + + discard_cleanups (old_chain); + } + return head; +} + +static int +kgdb_in_dynsym_resolve_code (CORE_ADDR pc) +{ + warning ("kgdb_in_dynsym_resolve_code called\n"); + return 0; +} + +static void +kgdb_special_symbol_handling (void) +{ +} + +static void +kgdb_solib_create_inferior_hook (void) +{ + warning ("kgdb_solib_create_inferior_hook called\n"); +} + +static void +kgdb_clear_solib (void) +{ +} + +static void +kgdb_free_so (struct so_list *so) +{ + xfree (so->lm_info); +} + +struct target_so_ops kgdb_so_ops; + +void +_initialize_kgdb_solib (void) +{ + kgdb_so_ops.relocate_section_addresses = kgdb_relocate_section_addresses; + kgdb_so_ops.free_so = kgdb_free_so; + kgdb_so_ops.clear_solib = kgdb_clear_solib; + kgdb_so_ops.solib_create_inferior_hook = kgdb_solib_create_inferior_hook; + kgdb_so_ops.special_symbol_handling = kgdb_special_symbol_handling; + kgdb_so_ops.current_sos = kgdb_current_sos; + kgdb_so_ops.open_symbol_file_object = kgdb_open_symbol_file_object; + kgdb_so_ops.in_dynsym_resolve_code = kgdb_in_dynsym_resolve_code; +} To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200210071709.aa25499>