Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Aug 2015 11:27:05 -0700
From:      John-Mark Gurney <jmg@funkthat.com>
To:        John Baldwin <jhb@freebsd.org>
Cc:        "'freebsd-arch'" <freebsd-arch@freebsd.org>
Subject:   Re: Supporting cross-debugging vmcores in libkvm
Message-ID:  <20150828182705.GD33167@funkthat.com>
In-Reply-To: <3121152.ujdxFEovO3@ralph.baldwin.cx>
References:  <3121152.ujdxFEovO3@ralph.baldwin.cx>

next in thread | previous in thread | raw e-mail | index | archive | help
John Baldwin wrote this message on Tue, Aug 04, 2015 at 10:56 -0700:
> 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.

I like this..  W/ the work Lovasko has been working on, having this
type is good and makes the most sense...

> 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.

All the above looks good...

How will we prevent native only aware apps from getting confused when
accessing non-native cores?  Will kvm_openfiles fail for non-native
cores? or will kvm_read fail for non-native cores?

> 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.

For things like getprocs, we could move to using Lovasko's project
to use ctf data to read the proc structures for non-native cores...
Then the core parts of getprocs would not have to change, and it'd
just work in all places..

> 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).

You're API looks good...  I can't see anything wrong w/ it...

> Oh, and I do hope to have a 'KGDB' option for the devel/gdb port in the
> near future.

-- 
  John-Mark Gurney				Voice: +1 415 225 5579

     "All that I will do, has been done, All that I have, has not."



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20150828182705.GD33167>