Date: Tue, 04 Aug 2015 10:56:09 -0700 From: John Baldwin <jhb@freebsd.org> To: 'freebsd-arch' <freebsd-arch@freebsd.org> Subject: Supporting cross-debugging vmcores in libkvm Message-ID: <3121152.ujdxFEovO3@ralph.baldwin.cx>
next in thread | raw e-mail | index | archive | help
Many debuggers (recent gdb and lldb) support cross-architecture debugging just fine. My current WIP port of kgdb to gdb7 supports cross-debugging for remote targets already, but I wanted it to also support cross-debugging for vmcores. The existing libkvm/kgdb code in the tree has some limited support for cross-debugging. It requires building a custom libkvm (e.g. libkvm-i386.a) and custom kgdb for each target platform. However, gdb (and lldb) both support multiple targets in a single binary, so I'd like to have a single kgdb binary that can cross-debug anything. I started hacking on libkvm last weekend and have a prototype that I've used (along with some patches to my kgdb port) to debug an amd64 vmcore on an i386 machine and vice versa. To do this I've made some additions to the libkvm API: 1) A new 'kvaddr_t' type represents a kernel virtual address. This is similar to the psaddr_t type used for MI process addresses in userland debugging. I almost reused psaddr_t directly, but that would have made <libkvm.h> depend on <sys/procfs.h>. Instead, I opted for a separate type. It is currently a uint64_t. 2) A new 'struct kvm_nlist'. This is a stripped-down version of 'struct nlist' that uses kvadd_t for n_value instead of an unsigned long. 3) kvm_native() returns true if an open kvm descriptor is for a native kernel and memory image. 4) kvm_nlist2() is like kvm_nlist() but it uses 'struct kvm_nlist' instead of 'struct nlist'. Internally symbol names are always resolved to kvaddr_t addresses rather than u_long addresses. Native kernels still use _fdnlist() from libc to resolve symbols. Cross kernels use a caller supplied function to resolve symbols (the older cross code for libkvm required the caller to provide a global ps_pglobal_lookup symbol typically provided for <proc_service.h>). 5) kvm_open2() is like kvm_openfiles() except that it drops the unused 'swapfile' argument and adds a new function pointer argument to a symbol resolving function. The function pointer can be NULL in which case only native kernels can be opened. Kernels used with /dev/mem or /dev/kmem must be native. 6) kvm_read2() is like kvm_read() except that it uses kvaddr_t instead of unsigned long for the kernel virtual address. Adding new symbols (specifically kvm_nlist2 and kvm_read2) preserves ABI and API compatibility. Note that most libkvm functions such as kvm_getprocs(), etc. only work with native kernels. I have not yet done a full sweep to force them to fail for non-native kernels. Also, the vnet and dpcpu stuff only works for native kernels currently though that can be fixed at some point in the future. For the MD backends, I've added a new kvm_arch switch: struct kvm_arch { int (*ka_probe)(kvm_t *); int (*ka_initvtop)(kvm_t *); void (*ka_freevtop)(kvm_t *); int (*ka_kvatop)(kvm_t *, kvaddr_t, off_t *); int (*ka_uvatop)(kvm_t *, const struct proc *, kvaddr_t, off_t *); int ka_native; }; Each backend implements the necessary callbacks (uvatop is optional) and is added to a global linker set that kvm_open2() walks to find the appropriate kvm_arch for a given kernel + vmcore. On x86 I've used separate kvm_arch structures for "plain" vs minidumps. The backends now have to avoid using native headers. For ELF handling this means using libelf instead of <machine/elf.h> and raw mmap(). For the x86 backends it meant defining some duplicate constants for certain page table fields since <machine/pmap.h> can't be relied on (e.g. I386_PG_V instead of PG_V). I added static assertions in the "native" case (e.g. building kvm_i386.c on i386) to ensure the duplicate constants match the originals. You can see the current WIP patches here: https://github.com/freebsd/freebsd/compare/master...bsdjhb:kgdb_enhancements What I'm mostly after is comments on the API, etc. Once that is settled I will move forward on converting and/or stubbing the other backends (the stub route would be to only support other backends on native systems for now). Oh, and I do hope to have a 'KGDB' option for the devel/gdb port in the near future. -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3121152.ujdxFEovO3>