Module Name: src Committed By: ryo Date: Thu Dec 1 00:41:10 UTC 2022
Modified Files: src/usr.sbin/tprof: Makefile tprof_analyze.c Added Files: src/usr.sbin/tprof: ksyms.c ksyms.h Log Message: split ksyms stuff into ksyms.[ch] To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/usr.sbin/tprof/Makefile cvs rdiff -u -r0 -r1.1 src/usr.sbin/tprof/ksyms.c src/usr.sbin/tprof/ksyms.h cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/tprof/tprof_analyze.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/tprof/Makefile diff -u src/usr.sbin/tprof/Makefile:1.10 src/usr.sbin/tprof/Makefile:1.11 --- src/usr.sbin/tprof/Makefile:1.10 Tue Nov 17 10:47:17 2020 +++ src/usr.sbin/tprof/Makefile Thu Dec 1 00:41:10 2022 @@ -1,10 +1,10 @@ -# $NetBSD: Makefile,v 1.10 2020/11/17 10:47:17 rin Exp $ +# $NetBSD: Makefile,v 1.11 2022/12/01 00:41:10 ryo Exp $ .PATH: ${.CURDIR}/arch PROG= tprof MAN= tprof.8 -SRCS= tprof.c tprof_analyze.c +SRCS= tprof.c tprof_analyze.c ksyms.c .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "x86_64" SRCS+= tprof_x86.c Index: src/usr.sbin/tprof/tprof_analyze.c diff -u src/usr.sbin/tprof/tprof_analyze.c:1.6 src/usr.sbin/tprof/tprof_analyze.c:1.7 --- src/usr.sbin/tprof/tprof_analyze.c:1.6 Thu Dec 1 00:32:52 2022 +++ src/usr.sbin/tprof/tprof_analyze.c Thu Dec 1 00:41:10 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tprof_analyze.c,v 1.6 2022/12/01 00:32:52 ryo Exp $ */ +/* $NetBSD: tprof_analyze.c,v 1.7 2022/12/01 00:41:10 ryo Exp $ */ /* * Copyright (c) 2010,2011,2012 YAMAMOTO Takashi, @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: tprof_analyze.c,v 1.6 2022/12/01 00:32:52 ryo Exp $"); +__RCSID("$NetBSD: tprof_analyze.c,v 1.7 2022/12/01 00:41:10 ryo Exp $"); #endif /* not lint */ #include <assert.h> @@ -46,8 +46,7 @@ __RCSID("$NetBSD: tprof_analyze.c,v 1.6 #include <util.h> #include <dev/tprof/tprof_ioctl.h> #include "tprof.h" - -#define _PATH_KSYMS "/dev/ksyms" +#include "ksyms.h" #include <sys/rbtree.h> @@ -68,147 +67,6 @@ struct addr { static rb_tree_t addrtree; -struct sym { - char *name; - uint64_t value; - uint64_t size; -}; - -static struct sym **syms = NULL; -static size_t nsyms = 0; - -static int -compare_value(const void *p1, const void *p2) -{ - const struct sym *s1 = *(const struct sym * const *)p1; - const struct sym *s2 = *(const struct sym * const *)p2; - - if (s1->value > s2->value) { - return -1; - } else if (s1->value < s2->value) { - return 1; - } - /* - * to produce a stable result, it's better not to return 0 - * even for __strong_alias. - */ - if (s1->size > s2->size) { - return -1; - } else if (s1->size < s2->size) { - return 1; - } - return strcmp(s1->name, s2->name); -} - -static void -ksymload(void) -{ - Elf *e; - Elf_Scn *s; - GElf_Shdr sh_store; - GElf_Shdr *sh; - Elf_Data *d; - int fd; - size_t size, i; - - fd = open(_PATH_KSYMS, O_RDONLY); - if (fd == -1) { - err(EXIT_FAILURE, "open " _PATH_KSYMS); - } - if (elf_version(EV_CURRENT) == EV_NONE) { - goto elffail; - } - e = elf_begin(fd, ELF_C_READ, NULL); - if (e == NULL) { - goto elffail; - } - for (s = elf_nextscn(e, NULL); s != NULL; s = elf_nextscn(e, s)) { - sh = gelf_getshdr(s, &sh_store); - if (sh == NULL) { - goto elffail; - } - if (sh->sh_type == SHT_SYMTAB) { - break; - } - } - if (s == NULL) { - errx(EXIT_FAILURE, "no symtab"); - } - d = elf_getdata(s, NULL); - if (d == NULL) { - goto elffail; - } - assert(sh->sh_size == d->d_size); - size = sh->sh_size / sh->sh_entsize; - for (i = 1; i < size; i++) { - GElf_Sym st_store; - GElf_Sym *st; - struct sym *sym; - - st = gelf_getsym(d, (int)i, &st_store); - if (st == NULL) { - goto elffail; - } - if (ELF_ST_TYPE(st->st_info) != STT_FUNC) { - continue; - } - sym = emalloc(sizeof(*sym)); - sym->name = estrdup(elf_strptr(e, sh->sh_link, st->st_name)); - sym->value = (uint64_t)st->st_value; - sym->size = st->st_size; - nsyms++; - syms = erealloc(syms, sizeof(*syms) * nsyms); - syms[nsyms - 1] = sym; - } - qsort(syms, nsyms, sizeof(*syms), compare_value); - return; -elffail: - errx(EXIT_FAILURE, "libelf: %s", elf_errmsg(elf_errno())); -} - -static const char * -ksymlookup(uint64_t value, uint64_t *offset) -{ - size_t hi; - size_t lo; - size_t i; - - /* - * try to find the smallest i for which syms[i]->value <= value. - * syms[] is ordered by syms[]->value in the descending order. - */ - - hi = nsyms - 1; - lo = 0; - while (lo < hi) { - const size_t mid = (lo + hi) / 2; - const struct sym *sym = syms[mid]; - - assert(syms[lo]->value >= sym->value); - assert(sym->value >= syms[hi]->value); - if (sym->value <= value) { - hi = mid; - continue; - } - lo = mid + 1; - } - assert(lo == nsyms - 1 || syms[lo]->value <= value); - assert(lo == 0 || syms[lo - 1]->value > value); - for (i = lo; i < nsyms; i++) { - const struct sym *sym = syms[i]; - - if (sym->value <= value && - (sym->size == 0 || value - sym->value <= sym->size )) { - *offset = value - sym->value; - return sym->name; - } - if (sym->size != 0 && sym->value + sym->size < value) { - break; - } - } - return NULL; -} - static signed int addrtree_compare_key(void *ctx, const void *n1, const void *keyp) { Added files: Index: src/usr.sbin/tprof/ksyms.c diff -u /dev/null src/usr.sbin/tprof/ksyms.c:1.1 --- /dev/null Thu Dec 1 00:41:10 2022 +++ src/usr.sbin/tprof/ksyms.c Thu Dec 1 00:41:10 2022 @@ -0,0 +1,181 @@ +/* $NetBSD: ksyms.c,v 1.1 2022/12/01 00:41:10 ryo Exp $ */ + +/* + * Copyright (c) 2010,2011,2012 YAMAMOTO Takashi, + * All rights reserved. + * + * 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 <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: ksyms.c,v 1.1 2022/12/01 00:41:10 ryo Exp $"); +#endif /* not lint */ + +#include <assert.h> +#include <err.h> +#include <fcntl.h> +#include <gelf.h> +#include <libelf.h> +#include <paths.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <util.h> +#include "ksyms.h" + +struct sym **syms = NULL; +size_t nsyms = 0; + +static int +compare_value(const void *p1, const void *p2) +{ + const struct sym *s1 = *(const struct sym * const *)p1; + const struct sym *s2 = *(const struct sym * const *)p2; + + if (s1->value > s2->value) { + return -1; + } else if (s1->value < s2->value) { + return 1; + } + /* + * to produce a stable result, it's better not to return 0 + * even for __strong_alias. + */ + if (s1->size > s2->size) { + return -1; + } else if (s1->size < s2->size) { + return 1; + } + return strcmp(s1->name, s2->name); +} + +void +ksymload(void) +{ + Elf *e; + Elf_Scn *s; + GElf_Shdr sh_store; + GElf_Shdr *sh; + Elf_Data *d; + int fd; + size_t size, i; + + fd = open(_PATH_KSYMS, O_RDONLY); + if (fd == -1) { + err(EXIT_FAILURE, "open " _PATH_KSYMS); + } + if (elf_version(EV_CURRENT) == EV_NONE) { + goto elffail; + } + e = elf_begin(fd, ELF_C_READ, NULL); + if (e == NULL) { + goto elffail; + } + for (s = elf_nextscn(e, NULL); s != NULL; s = elf_nextscn(e, s)) { + sh = gelf_getshdr(s, &sh_store); + if (sh == NULL) { + goto elffail; + } + if (sh->sh_type == SHT_SYMTAB) { + break; + } + } + if (s == NULL) { + errx(EXIT_FAILURE, "no symtab"); + } + d = elf_getdata(s, NULL); + if (d == NULL) { + goto elffail; + } + assert(sh->sh_size == d->d_size); + size = sh->sh_size / sh->sh_entsize; + for (i = 1; i < size; i++) { + GElf_Sym st_store; + GElf_Sym *st; + struct sym *sym; + + st = gelf_getsym(d, (int)i, &st_store); + if (st == NULL) { + goto elffail; + } + if (ELF_ST_TYPE(st->st_info) != STT_FUNC) { + continue; + } + sym = emalloc(sizeof(*sym)); + sym->name = estrdup(elf_strptr(e, sh->sh_link, st->st_name)); + sym->value = (uint64_t)st->st_value; + sym->size = st->st_size; + nsyms++; + syms = erealloc(syms, sizeof(*syms) * nsyms); + syms[nsyms - 1] = sym; + } + elf_end(e); + close(fd); + qsort(syms, nsyms, sizeof(*syms), compare_value); + return; +elffail: + errx(EXIT_FAILURE, "libelf: %s", elf_errmsg(elf_errno())); +} + +const char * +ksymlookup(uint64_t value, uint64_t *offset) +{ + size_t hi; + size_t lo; + size_t i; + + /* + * try to find the smallest i for which syms[i]->value <= value. + * syms[] is ordered by syms[]->value in the descending order. + */ + + hi = nsyms - 1; + lo = 0; + while (lo < hi) { + const size_t mid = (lo + hi) / 2; + const struct sym *sym = syms[mid]; + + assert(syms[lo]->value >= sym->value); + assert(sym->value >= syms[hi]->value); + if (sym->value <= value) { + hi = mid; + continue; + } + lo = mid + 1; + } + assert(lo == nsyms - 1 || syms[lo]->value <= value); + assert(lo == 0 || syms[lo - 1]->value > value); + for (i = lo; i < nsyms; i++) { + const struct sym *sym = syms[i]; + + if (sym->value <= value && + (sym->size == 0 || value - sym->value <= sym->size )) { + *offset = value - sym->value; + return sym->name; + } + if (sym->size != 0 && sym->value + sym->size < value) { + break; + } + } + return NULL; +} Index: src/usr.sbin/tprof/ksyms.h diff -u /dev/null src/usr.sbin/tprof/ksyms.h:1.1 --- /dev/null Thu Dec 1 00:41:10 2022 +++ src/usr.sbin/tprof/ksyms.h Thu Dec 1 00:41:10 2022 @@ -0,0 +1,44 @@ +/* $NetBSD: ksyms.h,v 1.1 2022/12/01 00:41:10 ryo Exp $ */ + +/* + * Copyright (c) 2010,2011,2012 YAMAMOTO Takashi, + * All rights reserved. + * + * 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 _KSYMS_H_ +#define _KSYMS_H_ + +struct sym { + char *name; + uint64_t value; + uint64_t size; +}; + +extern struct sym **syms; +extern size_t nsyms; + +void ksymload(void); +const char *ksymlookup(uint64_t, uint64_t *); + +#endif /* _KSYMS_H_ */