diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile index 9fce7b9d467d..cd4872bd5b03 100644 --- a/lib/libkvm/Makefile +++ b/lib/libkvm/Makefile @@ -25,8 +25,8 @@ INCS= kvm.h LIBADD= elf MAN= kvm.3 kvm_getcptime.3 kvm_geterr.3 kvm_getloadavg.3 \ - kvm_getpcpu.3 kvm_getprocs.3 kvm_getswapinfo.3 kvm_native.3 \ - kvm_nlist.3 kvm_open.3 kvm_read.3 + kvm_getpcpu.3 kvm_getprocs.3 kvm_getswapinfo.3 kvm_kerndisp.3 \ + kvm_native.3 kvm_nlist.3 kvm_open.3 kvm_read.3 MLINKS+=kvm_getpcpu.3 kvm_getmaxcpu.3 \ kvm_getpcpu.3 kvm_dpcpu_setcpu.3 \ diff --git a/lib/libkvm/kvm.3 b/lib/libkvm/kvm.3 index 7fd5373eec7a..fbddcd475cc8 100644 --- a/lib/libkvm/kvm.3 +++ b/lib/libkvm/kvm.3 @@ -32,7 +32,7 @@ .\" @(#)kvm.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd April 30, 2016 +.Dd February 5, 2020 .Dt KVM 3 .Os .Sh NAME @@ -133,7 +133,8 @@ respectively. Finally, only a limited subset of operations are supported for non-native crash dumps: .Fn kvm_close , -.Fn kvm_geterr +.Fn kvm_geterr , +.Fn kvm_kerndisp , .Fn kvm_open2 , .Fn kvm_native , .Fn kvm_nlist2 , @@ -147,6 +148,7 @@ and .Xr kvm_getloadavg 3 , .Xr kvm_getprocs 3 , .Xr kvm_getswapinfo 3 , +.Xr kvm_kerndisp 3 , .Xr kvm_native 3 , .Xr kvm_nlist 3 , .Xr kvm_nlist2 3 , diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c index 2f35f26df1ca..c22f84ed64fa 100644 --- a/lib/libkvm/kvm.c +++ b/lib/libkvm/kvm.c @@ -46,6 +46,7 @@ __SCCSID("@(#)kvm.c 8.2 (Berkeley) 2/13/94"); #include #include #include +#include #include #include @@ -499,3 +500,32 @@ kvm_walk_pages(kvm_t *kd, kvm_walk_pages_cb_t *cb, void *closure) return (kd->arch->ka_walk_pages(kd, cb, closure)); } + +kssize_t +kvm_kerndisp(kvm_t *kd) +{ + unsigned long kernbase, rel_kernbase; + size_t kernbase_len = sizeof(kernbase); + size_t rel_kernbase_len = sizeof(rel_kernbase); + + if (ISALIVE(kd)) { + if (sysctlbyname("kern.base_address", &kernbase, + &kernbase_len, NULL, 0) == -1) { + _kvm_syserr(kd, kd->program, + "failed to get kernel base address"); + return (0); + } + if (sysctlbyname("kern.relbase_address", &rel_kernbase, + &rel_kernbase_len, NULL, 0) == -1) { + _kvm_syserr(kd, kd->program, + "failed to get relocated kernel base address"); + return (0); + } + return (rel_kernbase - kernbase); + } + + if (kd->arch->ka_kerndisp == NULL) + return (0); + + return (kd->arch->ka_kerndisp(kd)); +} diff --git a/lib/libkvm/kvm.h b/lib/libkvm/kvm.h index d568a27e6963..e6dd767c9193 100644 --- a/lib/libkvm/kvm.h +++ b/lib/libkvm/kvm.h @@ -124,6 +124,7 @@ ssize_t kvm_read(kvm_t *, unsigned long, void *, size_t); ssize_t kvm_read_zpcpu(kvm_t *, unsigned long, void *, size_t, int); ssize_t kvm_read2(kvm_t *, kvaddr_t, void *, size_t); ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t); +kssize_t kvm_kerndisp(kvm_t *); typedef int kvm_walk_pages_cb_t(struct kvm_page *, void *); int kvm_walk_pages(kvm_t *, kvm_walk_pages_cb_t *, void *); diff --git a/lib/libkvm/kvm_kerndisp.3 b/lib/libkvm/kvm_kerndisp.3 new file mode 100644 index 000000000000..a1d53a4ecb2f --- /dev/null +++ b/lib/libkvm/kvm_kerndisp.3 @@ -0,0 +1,57 @@ +.\" +.\" Copyright (c) 2020 Leandro Lupori +.\" +.\" 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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$ +.\" +.Dd February 5, 2020 +.Dt KVM_KERNDISP 3 +.Os +.Sh NAME +.Nm kvm_kerndisp +.Nd get kernel displacement +.Sh LIBRARY +.Lb libkvm +.Sh SYNOPSIS +.In kvm.h +.Ft kssize_t +.Fn kvm_kerndisp "kvm_t *kd" +.Sh DESCRIPTION +.Fn kvm_kerndisp +returns the number of bytes by which the kernel referenced by +.Fa kd +is displaced. +This is the difference between the kernel's base virtual address at run time +and the kernel base virtual address specified in the kernel image file. +.Pp +Note that if the kernel is moved to a lower memory address, +the displacement will be negative. +.Sh RETURN VALUES +.Fn kvm_kerndisp +returns the number of bytes by which the kernel is displaced. +If the kernel is not displaced or if it is not possible to find the +displacement then 0 is returned. +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_close 3 , +.Xr kvm_open 3 diff --git a/lib/libkvm/kvm_minidump_powerpc64.c b/lib/libkvm/kvm_minidump_powerpc64.c index 39c8d03fefa6..6e95b40aab2a 100644 --- a/lib/libkvm/kvm_minidump_powerpc64.c +++ b/lib/libkvm/kvm_minidump_powerpc64.c @@ -184,6 +184,12 @@ _powerpc64_native(kvm_t *kd __unused) #endif } +static kssize_t +_powerpc64_kerndisp(kvm_t *kd) +{ + return (kd->vmst->hdr.startkernel - PPC64_KERNBASE); +} + static int _powerpc64_minidump_walk_pages(kvm_t *kd, kvm_walk_pages_cb_t *cb, void *arg) { @@ -197,6 +203,7 @@ static struct kvm_arch kvm_powerpc64_minidump = { .ka_kvatop = _powerpc64_minidump_kvatop, .ka_walk_pages = _powerpc64_minidump_walk_pages, .ka_native = _powerpc64_native, + .ka_kerndisp = _powerpc64_kerndisp, }; KVM_ARCH(kvm_powerpc64_minidump); diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h index 39a743c922fc..e71dde92a2f1 100644 --- a/lib/libkvm/kvm_private.h +++ b/lib/libkvm/kvm_private.h @@ -47,6 +47,7 @@ struct kvm_arch { int (*ka_kvatop)(kvm_t *, kvaddr_t, off_t *); int (*ka_native)(kvm_t *); int (*ka_walk_pages)(kvm_t *, kvm_walk_pages_cb_t *, void *); + kssize_t (*ka_kerndisp)(kvm_t *); }; #define KVM_ARCH(ka) DATA_SET(kvm_arch, ka) diff --git a/sys/sys/types.h b/sys/sys/types.h index 678f8e358925..74750098fc8f 100644 --- a/sys/sys/types.h +++ b/sys/sys/types.h @@ -260,6 +260,7 @@ typedef struct cap_rights cap_rights_t; typedef __uint64_t kpaddr_t; typedef __uint64_t kvaddr_t; typedef __uint64_t ksize_t; +typedef __int64_t kssize_t; typedef __vm_offset_t vm_offset_t; typedef __uint64_t vm_ooffset_t;