Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/tprof split ksyms stuff into ksyms.[ch]



details:   https://anonhg.NetBSD.org/src/rev/35f3ac118c2a
branches:  trunk
changeset: 372480:35f3ac118c2a
user:      ryo <ryo%NetBSD.org@localhost>
date:      Thu Dec 01 00:41:10 2022 +0000

description:
split ksyms stuff into ksyms.[ch]

diffstat:

 usr.sbin/tprof/Makefile        |    4 +-
 usr.sbin/tprof/ksyms.c         |  181 +++++++++++++++++++++++++++++++++++++++++
 usr.sbin/tprof/ksyms.h         |   44 +++++++++
 usr.sbin/tprof/tprof_analyze.c |  148 +--------------------------------
 4 files changed, 230 insertions(+), 147 deletions(-)

diffs (truncated from 425 to 300 lines):

diff -r e5943acac59c -r 35f3ac118c2a usr.sbin/tprof/Makefile
--- a/usr.sbin/tprof/Makefile   Thu Dec 01 00:40:05 2022 +0000
+++ b/usr.sbin/tprof/Makefile   Thu Dec 01 00:41:10 2022 +0000
@@ -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
diff -r e5943acac59c -r 35f3ac118c2a usr.sbin/tprof/ksyms.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.sbin/tprof/ksyms.c    Thu Dec 01 00:41:10 2022 +0000
@@ -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;
+}
diff -r e5943acac59c -r 35f3ac118c2a usr.sbin/tprof/ksyms.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.sbin/tprof/ksyms.h    Thu Dec 01 00:41:10 2022 +0000
@@ -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_ */
diff -r e5943acac59c -r 35f3ac118c2a usr.sbin/tprof/tprof_analyze.c
--- a/usr.sbin/tprof/tprof_analyze.c    Thu Dec 01 00:40:05 2022 +0000
+++ b/usr.sbin/tprof/tprof_analyze.c    Thu Dec 01 00:41:10 2022 +0000
@@ -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 @@
 #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 @@
 
 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;



Home | Main Index | Thread Index | Old Index