diff --git a/lib/libkvm/Makefile b/lib/libkvm/Makefile --- a/lib/libkvm/Makefile +++ b/lib/libkvm/Makefile @@ -7,6 +7,7 @@ SRCS= kvm.c kvm_cptime.c kvm_getloadavg.c \ kvm_getswapinfo.c kvm_pcpu.c kvm_private.c kvm_proc.c kvm_vnet.c \ + kvm_minidump_helpers.c \ kvm_minidump_aarch64.c \ kvm_amd64.c kvm_minidump_amd64.c \ kvm_arm.c kvm_minidump_arm.c \ @@ -20,7 +21,7 @@ MAN= kvm.3 kvm_getcptime.3 kvm_geterr.3 kvm_getloadavg.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 + kvm_lookup_symbol.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.h b/lib/libkvm/kvm.h --- a/lib/libkvm/kvm.h +++ b/lib/libkvm/kvm.h @@ -124,6 +124,9 @@ typedef int kvm_walk_pages_cb_t(struct kvm_page *, void *); int kvm_walk_pages(kvm_t *, kvm_walk_pages_cb_t *, void *); + +int kvm_lookup_symbol(kvm_t *, int, struct kvm_nlist *); +int kvm_lookup_kld(kvm_t *, const char *); __END_DECLS #endif /* !_KVM_H_ */ diff --git a/lib/libkvm/kvm.c b/lib/libkvm/kvm.c --- a/lib/libkvm/kvm.c +++ b/lib/libkvm/kvm.c @@ -211,6 +211,19 @@ */ if (kd->arch->ka_initvtop(kd) < 0) goto failed; + + TAILQ_INIT(&kd->linker_files_list); + if (kd->arch->ka_walk_linker_files != NULL) { + /* + * Walk the linker_files list so that kvm_nlist works properly + * against loaded kernel modules. + */ + if (kd->arch->ka_walk_linker_files(kd) != 0) { + _kvm_err(kd, kd->program, + "failed to walk linker_files list"); + goto failed; + } + } return (kd); failed: /* @@ -273,11 +286,16 @@ kvm_close(kvm_t *kd) { int error = 0; + struct kvm_linker_file *lf; if (kd == NULL) { errno = EINVAL; return (-1); } + while ((lf = TAILQ_FIRST(&kd->linker_files_list)) != NULL) { + TAILQ_REMOVE(&kd->linker_files_list, lf, link); + _kvm_linker_file_free(lf); + } if (kd->vmst != NULL) kd->arch->ka_freevtop(kd); if (kd->pmfd >= 0) @@ -534,3 +552,59 @@ return (kd->arch->ka_kerndisp(kd)); } + +int +kvm_lookup_symbol(kvm_t *kd, int fileid, struct kvm_nlist *nl) +{ + struct kvm_linker_file *p; + int error, nfail = 0; + int i; + + if (kd->arch->ka_lookup_symbol == NULL) { + _kvm_err(kd, kd->program, "unsupported architecture"); + return (-1); + } + + for (i = 0; nl[i].n_name != NULL && nl[i].n_name[0] != '\0'; i++) { + bool found = false; + + TAILQ_FOREACH(p, &kd->linker_files_list, link) { + /* For fileid == 0 go through all the images */ + if (fileid != 0 && p->id != fileid) + continue; + if (kd->arch->ka_lookup_symbol(kd, p, &nl[i]) == 0) { + found = true; + break; + } + if (fileid != 0) { + /* + * For exact match fileid, just bail out if the + * request symbol is not found. It is + * meaningless to go through the rest of the + * image list. + */ + break; + } + } + if (!found) + nfail++; + } + return (nfail); +} + +int +kvm_lookup_kld(kvm_t *kd, const char *filename) +{ + struct kvm_linker_file *p; + int id = -1; + + TAILQ_FOREACH(p, &kd->linker_files_list, link) { + if (strcmp(p->filename, filename) == 0) { + id = p->id; + break; + } + } + if (id == -1) + _kvm_err(kd, kd->program, "KLD not found"); + return (id); +} diff --git a/lib/libkvm/kvm_lookup_kld.3 b/lib/libkvm/kvm_lookup_kld.3 new file mode 100644 --- /dev/null +++ b/lib/libkvm/kvm_lookup_kld.3 @@ -0,0 +1,51 @@ +.\" +.\" Copyright (c) 2024 Juniper Networks, Inc. +.\" +.\" 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. +.\" +.Dd August 30, 2024 +.Dt KVM_LOOKUP_KLD 3 +.Os +.Sh NAME +.Nm kvm_lookup_kld +.Nd look up the file id of a kld file +.Sh LIBRARY +.Lb libkvm +.Sh SYNOPSIS +.In kvm.h +.Ft int +.Fn kvm_lookup_kld "kvm_t *kd" "const char *filename" +.Sh DESCRIPTION +The +.Fn kvm_lookup_kld +function looks up the corresponding file id of a kld file. +The +.Fa filename +argument points to a memory location storing the kld image's file name. +.Sh RETURN VALUES +The +.Fn kvm_lookup_kld +function returns a positive value indicating the file id of the loaded kld. +If the kld specified by the file name does not exist, the function returns -1. +.Sh SEE ALSO +.Xr kvm 3 , +.Xr kvm_open2 3 diff --git a/lib/libkvm/kvm_lookup_symbol.3 b/lib/libkvm/kvm_lookup_symbol.3 new file mode 100644 --- /dev/null +++ b/lib/libkvm/kvm_lookup_symbol.3 @@ -0,0 +1,96 @@ +.\" Copyright (c) 1992, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2024 Juniper Networks, Inc. +.\" +.\" This code is derived from software developed by the Computer Systems +.\" Engineering group at Lawrence Berkeley Laboratory under DARPA contract +.\" BG 91-66 and contributed to Berkeley. +.\" +.\" 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. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +.\" +.Dd August 30, 2024 +.Dt KVM_LOOKUP_SYMBOL 3 +.Os +.Sh NAME +.Nm kvm_lookup_symbol +.Nd retrieve symbol table names from a kernel image +.Sh LIBRARY +.Lb libkvm +.Sh SYNOPSIS +.In kvm.h +.Ft int +.Fn kvm_lookup_symbol "kvm_t *kd" "int fileid" "struct kvm_nlist *nl" +.Sh DESCRIPTION +The +.Fn kvm_lookup_symbol +function retrieves the symbol table entries from the image specified by the +.Fa fileid +argument, and indicated by the name list argument +.Fa nl . +The +.Fa nl +argument points to an array of +.Vt "struct kvm_nlist" +structures, +terminated by an entry whose +.Fa n_name +field is +.Dv NULL +These structures are similar to the nlist structures used by +.Fn kvm_nlist +except that the +.Fa n_value +field uses a different type +.Pq Vt kvaddr_t +to avoid truncation when examining non-native kernel images. +If the value of 0 is passed to the +.Fa fileid +argument, +the +.Fn kvm_lookup_symbol +function will look through all the loaded images. +.Sh RETURN VALUES +The +.Fn kvm_lookup_symbol +function return the number of invalid entries found. +If the symbol table of the specified image was unreadable, -1 is returned. +.Sh SEE ALSO +.Xr kldsym 2 , +.Xr kvm 3 , +.Xr kvm_close 3 , +.Xr kvm_getargv 3 , +.Xr kvm_getenvv 3 , +.Xr kvm_geterr 3 , +.Xr kvm_getprocs 3 , +.Xr kvm_native 3 , +.Xr kvm_open 3 , +.Xr kvm_openfiles 3 , +.Xr kvm_read 3 , +.Xr kvm_write 3 +.Sh HISTORY +The +.Fn kvm_lookup_symbol +function first appeared in +.Fx 15.0 . diff --git a/lib/libkvm/kvm_minidump_aarch64.c b/lib/libkvm/kvm_minidump_aarch64.c --- a/lib/libkvm/kvm_minidump_aarch64.c +++ b/lib/libkvm/kvm_minidump_aarch64.c @@ -31,6 +31,12 @@ */ #include +#define _WANT_LINKER +#include +#include +#undef _WANT_LINKER +#include +#include #include #include #include @@ -44,6 +50,7 @@ #include "kvm_private.h" #include "kvm_aarch64.h" +#include "kvm_minidump_helpers.h" #define aarch64_round_page(x, size) roundup2((kvaddr_t)(x), size) #define aarch64_trunc_page(x, size) rounddown2((kvaddr_t)(x), size) @@ -311,6 +318,20 @@ return (ret); } +static int +_aarch64_minidump_walk_linker_files(kvm_t *kd) +{ + return (_kvm_minidump_walk_linker_files(kd)); +} + +static int +_aarch64_minidump_lookup_symbol(kvm_t *kd, struct kvm_linker_file *lf, + struct kvm_nlist *nl) +{ + return (_kvm_minidump_lookup_symbol(kd, lf, nl)); +} + + static struct kvm_arch kvm_aarch64_minidump = { .ka_probe = _aarch64_minidump_probe, .ka_initvtop = _aarch64_minidump_initvtop, @@ -318,6 +339,8 @@ .ka_kvatop = _aarch64_minidump_kvatop, .ka_native = _aarch64_native, .ka_walk_pages = _aarch64_minidump_walk_pages, + .ka_walk_linker_files = _aarch64_minidump_walk_linker_files, + .ka_lookup_symbol = _aarch64_minidump_lookup_symbol, }; KVM_ARCH(kvm_aarch64_minidump); diff --git a/lib/libkvm/kvm_minidump_amd64.c b/lib/libkvm/kvm_minidump_amd64.c --- a/lib/libkvm/kvm_minidump_amd64.c +++ b/lib/libkvm/kvm_minidump_amd64.c @@ -32,11 +32,18 @@ #include #include +#define _WANT_LINKER +#include +#include +#undef _WANT_LINKER +#include +#include +#include +#include #include #include #include #include -#include #include #include "../../sys/amd64/include/minidump.h" @@ -45,6 +52,7 @@ #include "kvm_private.h" #include "kvm_amd64.h" +#include "kvm_minidump_helpers.h" #define amd64_round_page(x) roundup2((kvaddr_t)(x), AMD64_PAGE_SIZE) #define VM_IS_V1(vm) (vm->hdr.version == 1) @@ -428,6 +436,19 @@ return (ret); } +static int +_amd64_minidump_walk_linker_files(kvm_t *kd) +{ + return (_kvm_minidump_walk_linker_files(kd)); +} + +static int +_amd64_minidump_lookup_symbol(kvm_t *kd, struct kvm_linker_file *lf, + struct kvm_nlist *nl) +{ + return (_kvm_minidump_lookup_symbol(kd, lf, nl)); +} + static struct kvm_arch kvm_amd64_minidump = { .ka_probe = _amd64_minidump_probe, .ka_initvtop = _amd64_minidump_initvtop, @@ -435,6 +456,8 @@ .ka_kvatop = _amd64_minidump_kvatop, .ka_native = _amd64_native, .ka_walk_pages = _amd64_minidump_walk_pages, + .ka_walk_linker_files = _amd64_minidump_walk_linker_files, + .ka_lookup_symbol = _amd64_minidump_lookup_symbol, }; KVM_ARCH(kvm_amd64_minidump); diff --git a/lib/libkvm/kvm_minidump_helpers.h b/lib/libkvm/kvm_minidump_helpers.h new file mode 100644 --- /dev/null +++ b/lib/libkvm/kvm_minidump_helpers.h @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Juniper Networks, Inc. + * + * 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. + */ + +#ifndef _KVM_MINIDUMP_HELPERS_H_ +#define _KVM_MINIDUMP_HELPERS_H_ + +int _kvm_minidump_walk_linker_files(kvm_t *); +int _kvm_minidump_lookup_symbol(kvm_t *, struct kvm_linker_file *, + struct kvm_nlist *); + +#endif /* _KVM_MINIDUMP_HELPERS_H_ */ diff --git a/lib/libkvm/kvm_minidump_helpers.c b/lib/libkvm/kvm_minidump_helpers.c new file mode 100644 --- /dev/null +++ b/lib/libkvm/kvm_minidump_helpers.c @@ -0,0 +1,170 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Juniper Networks, Inc. + * + * 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. + */ + +#include +#include +#define _WANT_LINKER +#include +#include +#include +#undef _WANT_LINKER +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kvm_private.h" +#include "kvm_minidump_helpers.h" + +/* from src/lib/libc/gen/nlist.c */ +int __fdnlist(int, struct nlist *); + +static int +_elf_file_parse(kvm_t *kd, kvaddr_t lfkva, const struct elf_file_base *buf, + struct kvm_linker_file *klf) +{ + ssize_t nbytes; + size_t i; + + klf->address = (uintptr_t)buf->address; + klf->ddbsymcnt = buf->ddbsymcnt; + klf->ddbstrcnt = buf->ddbstrcnt; + klf->ddbsymtab = calloc(buf->ddbsymcnt, sizeof(*klf->ddbsymtab)); + klf->ddbstrtab = malloc(buf->ddbstrcnt); + if (klf->ddbsymtab == NULL || klf->ddbstrtab == NULL) + return (-1); + + nbytes = kvm_read2(kd, (kvaddr_t)buf->ddbsymtab, klf->ddbsymtab, + buf->ddbsymcnt * sizeof(*klf->ddbsymtab)); + if (nbytes != buf->ddbsymcnt * sizeof(*klf->ddbsymtab)) + return (-1); + nbytes = kvm_read2(kd, (kvaddr_t)buf->ddbstrtab, klf->ddbstrtab, + buf->ddbstrcnt); + if (nbytes != buf->ddbstrcnt) + return (-1); + + if (!buf->is_obj) { + for (i = 0; i < klf->ddbsymcnt; i++) + klf->ddbsymtab[i].st_value += (uintptr_t)buf->address; + } + + return (0); +} + +int +_kvm_minidump_walk_linker_files(kvm_t *kd) +{ + int nfail; + ssize_t nbytes; + kvaddr_t ptr; + struct kvm_linker_file *p = NULL; + struct elf_file_base efb; + struct nlist nl[2] = { + { .n_name = "linker_files" }, + { .n_name = NULL }, + }; + + assert(!ISALIVE(kd)); + + /* We are here without knowing other modules. So nlist is the only + * way to move forward. */ + nfail = __fdnlist(kd->nlfd, nl); + if (nfail != 0) + return (-1); + + nbytes = kvm_read2(kd, + nl[0].n_value + offsetof(linker_file_list_t, tqh_first), &ptr, + sizeof(ptr)); + if (nbytes != sizeof(ptr)) + return (-1); + + while (ptr != 0) { + nbytes = kvm_read2(kd, ptr, &efb, sizeof(efb)); + if (nbytes != sizeof(efb) || + efb.version != ELF_FILE_BASE_VERSION) + goto errout; + + p = malloc(sizeof(struct kvm_linker_file)); + if (p == NULL) + goto errout; + p->id = efb.lf.id; + p->size = efb.lf.size; + p->filename = malloc(MAXPATHLEN); + p->pathname = malloc(MAXPATHLEN); + if (p->filename == NULL || p->pathname == NULL) + goto errout; + nbytes = kvm_read2(kd, (kvaddr_t)efb.lf.filename, p->filename, + MAXPATHLEN); + if (nbytes != MAXPATHLEN) + goto errout; + nbytes = kvm_read2(kd, (kvaddr_t)efb.lf.pathname, p->pathname, + MAXPATHLEN); + if (nbytes != MAXPATHLEN) + goto errout; + if (_elf_file_parse(kd, ptr, &efb, p) != 0) + goto errout; + + TAILQ_INSERT_TAIL(&kd->linker_files_list, p, link); + ptr = (kvaddr_t)efb.lf.link.tqe_next; + } + + return (0); +errout: + _kvm_linker_file_free(p); + return (-1); +} + +int +_kvm_minidump_lookup_symbol(kvm_t *kd, struct kvm_linker_file *lf, + struct kvm_nlist *nl) +{ + const char *name; + Elf_Sym *sym; + size_t i; + + for (i = 0; i < lf->ddbsymcnt; ++i) { + sym = &lf->ddbsymtab[i]; + name = lf->ddbstrtab + sym->st_name; + if (((nl->n_name[0] == '_' && + strcmp(name, nl->n_name + 1) == 0) || + strcmp(name, nl->n_name) == 0) && sym->st_value != 0) { + /* + * For now, just set n_type up like what has been done in + * the kldsym(2) calling. + */ + nl->n_type = N_TEXT; + nl->n_value = sym->st_value; + return (0); + } + } + return (-1); +} diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h --- a/lib/libkvm/kvm_private.h +++ b/lib/libkvm/kvm_private.h @@ -35,8 +35,23 @@ #include #include +#include +#include #include +struct kvm_linker_file { + TAILQ_ENTRY(kvm_linker_file) link; + char *filename; + char *pathname; + int id; + uintptr_t address; + size_t size; + size_t ddbsymcnt; + size_t ddbstrcnt; + Elf_Sym *ddbsymtab; + char *ddbstrtab; +}; + struct kvm_arch { int (*ka_probe)(kvm_t *); int (*ka_initvtop)(kvm_t *); @@ -45,6 +60,9 @@ int (*ka_native)(kvm_t *); int (*ka_walk_pages)(kvm_t *, kvm_walk_pages_cb_t *, void *); kssize_t (*ka_kerndisp)(kvm_t *); + int (*ka_walk_linker_files)(kvm_t *); + int (*ka_lookup_symbol)(kvm_t *, struct kvm_linker_file *, + struct kvm_nlist *); }; #define KVM_ARCH(ka) DATA_SET(kvm_arch, ka) @@ -115,6 +133,9 @@ uint32_t page_map_size; off_t page_map_off; void *sparse_map; + + /* List of loaded klds known */ + TAILQ_HEAD(, kvm_linker_file) linker_files_list; }; struct kvm_bitmap { @@ -193,3 +214,5 @@ int _kvm_pmap_init(kvm_t *, uint32_t, off_t); void * _kvm_pmap_get(kvm_t *, u_long, size_t); void * _kvm_map_get(kvm_t *, u_long, unsigned int); + +void _kvm_linker_file_free(struct kvm_linker_file *); diff --git a/lib/libkvm/kvm_private.c b/lib/libkvm/kvm_private.c --- a/lib/libkvm/kvm_private.c +++ b/lib/libkvm/kvm_private.c @@ -822,3 +822,15 @@ return cb(&p, arg); } + +void +_kvm_linker_file_free(struct kvm_linker_file *lf) +{ + if (lf == NULL) + return; + free(lf->filename); + free(lf->pathname); + free(lf->ddbsymtab); + free(lf->ddbstrtab); + free(lf); +}