From: Jovi Zhangwei <jovi.zhangwei@gmail.com>
To: Ingo Molnar <mingo@redhat.com>, Steven Rostedt <rostedt@goodmis.org>
Cc: linux-kernel@vger.kernel.org,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Frederic Weisbecker <fweisbec@gmail.com>,
Andi Kleen <andi@firstfloor.org>,
Jovi Zhangwei <jovi.zhangwei@gmail.com>
Subject: [PATCH v2 21/29] ktap: add symbol handling code(tools/ktap/symbol.[c|h])
Date: Fri, 28 Mar 2014 10:45:16 -0400 [thread overview]
Message-ID: <1396017924-7754-22-git-send-email-jovi.zhangwei@gmail.com> (raw)
In-Reply-To: <1396017924-7754-1-git-send-email-jovi.zhangwei@gmail.com>
This file is use for uprobe(include SDT) symbol lookup,
for example:
trace probe:/lib64/libc.so.6:malloc {
print("malloc entry:", execname)
}
trace sdt:/lib64/libc.so.6:* {
print(execname, argstr)
}
It need libelf library support.
Signed-off-by: Jovi Zhangwei <jovi.zhangwei@gmail.com>
---
tools/ktap/kp_symbol.c | 360 +++++++++++++++++++++++++++++++++++++++++++++++++
tools/ktap/kp_symbol.h | 50 +++++++
2 files changed, 410 insertions(+)
create mode 100644 tools/ktap/kp_symbol.c
create mode 100644 tools/ktap/kp_symbol.h
diff --git a/tools/ktap/kp_symbol.c b/tools/ktap/kp_symbol.c
new file mode 100644
index 0000000..1d5b73e
--- /dev/null
+++ b/tools/ktap/kp_symbol.c
@@ -0,0 +1,360 @@
+/*
+ * symbol.c
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2013 Azat Khuzhin <a3at.mail@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <linux/limits.h>
+
+#include <libelf.h>
+
+#include "../../include/uapi/ktap/ktap_types.h"
+#include "kp_symbol.h"
+
+const char *dbg_link_name = ".gnu_debuglink";
+const char *dbg_bin_dir = "/usr/lib/debug";
+
+static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
+ GElf_Shdr *shp, const char *name)
+{
+ Elf_Scn *scn = NULL;
+
+ /* Elf is corrupted/truncated, avoid calling elf_strptr. */
+ if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL))
+ return NULL;
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ char *str;
+
+ gelf_getshdr(scn, shp);
+ str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
+ if (!strcmp(name, str))
+ break;
+ }
+
+ return scn;
+}
+
+/**
+ * @return v_addr of "LOAD" program header, that have zero offset.
+ */
+static int find_load_address(Elf *elf, vaddr_t *load_address)
+{
+ GElf_Phdr phdr;
+ size_t i, phdrnum;
+
+ if (elf_getphdrnum(elf, &phdrnum))
+ return -1;
+
+ for (i = 0; i < phdrnum; i++) {
+ if (gelf_getphdr(elf, i, &phdr) == NULL)
+ return -1;
+
+ if (phdr.p_type != PT_LOAD || phdr.p_offset != 0)
+ continue;
+
+ *load_address = phdr.p_vaddr;
+ return 0;
+ }
+
+ /* cannot found load address */
+ return -1;
+}
+
+static size_t elf_symbols(GElf_Shdr shdr)
+{
+ return shdr.sh_size / shdr.sh_entsize;
+}
+
+static int dso_symbols(Elf *elf, symbol_actor actor, void *arg)
+{
+ Elf_Data *elf_data = NULL;
+ Elf_Scn *scn = NULL;
+ GElf_Sym sym;
+ GElf_Shdr shdr;
+ int symbols_count = 0;
+ vaddr_t load_address;
+
+ if (find_load_address(elf, &load_address))
+ return -1;
+
+ while ((scn = elf_nextscn(elf, scn))) {
+ int i;
+
+ gelf_getshdr(scn, &shdr);
+
+ if (shdr.sh_type != SHT_SYMTAB)
+ continue;
+
+ elf_data = elf_getdata(scn, elf_data);
+
+ for (i = 0; i < elf_symbols(shdr); i++) {
+ char *name;
+ vaddr_t addr;
+ int ret;
+
+ gelf_getsym(elf_data, i, &sym);
+
+ if (GELF_ST_TYPE(sym.st_info) != STT_FUNC)
+ continue;
+
+ name = elf_strptr(elf, shdr.sh_link, sym.st_name);
+ addr = sym.st_value - load_address;
+
+ ret = actor(name, addr, arg);
+ if (ret)
+ return ret;
+
+ ++symbols_count;
+ }
+ }
+
+ return symbols_count;
+}
+
+#define SDT_NOTE_TYPE 3
+#define SDT_NOTE_COUNT 3
+#define SDT_NOTE_SCN ".note.stapsdt"
+#define SDT_NOTE_NAME "stapsdt"
+
+static vaddr_t sdt_note_addr(Elf *elf, const char *data, size_t len, int type)
+{
+ vaddr_t vaddr;
+
+ /*
+ * Three addresses need to be obtained :
+ * Marker location, address of base section and semaphore location
+ */
+ union {
+ Elf64_Addr a64[3];
+ Elf32_Addr a32[3];
+ } buf;
+
+ /*
+ * dst and src are required for translation from file to memory
+ * representation
+ */
+ Elf_Data dst = {
+ .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+ .d_size = gelf_fsize(elf, ELF_T_ADDR, SDT_NOTE_COUNT, EV_CURRENT),
+ .d_off = 0, .d_align = 0
+ };
+
+ Elf_Data src = {
+ .d_buf = (void *) data, .d_type = ELF_T_ADDR,
+ .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
+ .d_align = 0
+ };
+
+ /* Check the type of each of the notes */
+ if (type != SDT_NOTE_TYPE)
+ return 0;
+
+ if (len < dst.d_size + SDT_NOTE_COUNT)
+ return 0;
+
+ /* Translation from file representation to memory representation */
+ if (gelf_xlatetom(elf, &dst, &src,
+ elf_getident(elf, NULL)[EI_DATA]) == NULL)
+ return 0; /* TODO */
+
+ memcpy(&vaddr, &buf, sizeof(vaddr));
+
+ return vaddr;
+}
+
+static const char *sdt_note_name(Elf *elf, GElf_Nhdr *nhdr, const char *data)
+{
+ const char *provider = data + gelf_fsize(elf,
+ ELF_T_ADDR, SDT_NOTE_COUNT, EV_CURRENT);
+ const char *name = (const char *)memchr(provider, '\0',
+ data + nhdr->n_descsz - provider);
+
+ if (name++ == NULL)
+ return NULL;
+
+ return name;
+}
+
+static const char *sdt_note_data(const Elf_Data *data, size_t off)
+{
+ return ((data->d_buf) + off);
+}
+
+static int dso_sdt_notes(Elf *elf, symbol_actor actor, void *arg)
+{
+ GElf_Ehdr ehdr;
+ Elf_Scn *scn = NULL;
+ Elf_Data *data;
+ GElf_Shdr shdr;
+ size_t shstrndx;
+ size_t next;
+ GElf_Nhdr nhdr;
+ size_t name_off, desc_off, offset;
+ vaddr_t vaddr = 0;
+ int symbols_count = 0;
+
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ return 0;
+ if (elf_getshdrstrndx(elf, &shstrndx) != 0)
+ return 0;
+
+ /*
+ * Look for section type = SHT_NOTE, flags = no SHF_ALLOC
+ * and name = .note.stapsdt
+ */
+ scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN);
+ if (!scn)
+ return 0;
+ if (!(shdr.sh_type == SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC))
+ return 0;
+
+ data = elf_getdata(scn, NULL);
+
+ for (offset = 0;
+ (next = gelf_getnote(data, offset, &nhdr, &name_off, &desc_off)) > 0;
+ offset = next) {
+ const char *name;
+ int ret;
+
+ if (nhdr.n_namesz != sizeof(SDT_NOTE_NAME) ||
+ memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
+ sizeof(SDT_NOTE_NAME)))
+ continue;
+
+ name = sdt_note_name(elf, &nhdr, sdt_note_data(data, desc_off));
+ if (!name)
+ continue;
+
+ vaddr = sdt_note_addr(elf, sdt_note_data(data, desc_off),
+ nhdr.n_descsz, nhdr.n_type);
+ if (!vaddr)
+ continue;
+
+ ret = actor(name, vaddr, arg);
+ if (ret)
+ return ret;
+
+ ++symbols_count;
+ }
+
+ return symbols_count;
+}
+
+int dso_follow_debuglink(Elf *elf,
+ const char *orig_exec,
+ int type,
+ symbol_actor actor,
+ void *arg)
+{
+ GElf_Ehdr ehdr;
+ size_t shstrndx, orig_exec_dir_len;
+ GElf_Shdr shdr;
+ Elf_Scn *dbg_link_scn;
+ Elf_Data *dbg_link_scn_data;
+ char *dbg_link, *dbg_bin, *last_slash;
+ int symbols_count;
+
+ /* First try to find the .gnu_debuglink section in the binary. */
+ if (gelf_getehdr(elf, &ehdr) == NULL)
+ return 0;
+ if (elf_getshdrstrndx(elf, &shstrndx) != 0)
+ return 0;
+
+ dbg_link_scn = elf_section_by_name(elf, &ehdr, &shdr, dbg_link_name);
+ if (dbg_link_scn == NULL)
+ return 0;
+
+ /* Debug link section found, read of the content (only get the first
+ string, no checksum checking atm). This is debug binary file name. */
+ dbg_link_scn_data = elf_getdata(dbg_link_scn, NULL);
+ if (dbg_link_scn_data == NULL ||
+ dbg_link_scn_data->d_size <= 0 ||
+ dbg_link_scn_data->d_buf == NULL)
+ return 0;
+
+ /* Now compose debug executable name */
+ dbg_link = (char *)(dbg_link_scn_data->d_buf);
+ dbg_bin = malloc(strlen(dbg_bin_dir) + 1 +
+ strlen(orig_exec) + 1 +
+ strlen(dbg_link) + 1);
+ if (!dbg_bin)
+ return 0;
+
+ orig_exec_dir_len = PATH_MAX;
+ last_slash = strrchr(orig_exec, '/');
+ if (last_slash != NULL)
+ orig_exec_dir_len = last_slash - orig_exec;
+
+ sprintf(dbg_bin, "%s/%.*s/%s",
+ dbg_bin_dir, (int)orig_exec_dir_len, orig_exec, dbg_link);
+
+ /* Retry symbol seach with the debug binary */
+ symbols_count = parse_dso_symbols(dbg_bin, type, actor, arg);
+
+ free(dbg_bin);
+
+ return symbols_count;
+}
+
+int parse_dso_symbols(const char *exec, int type, symbol_actor actor, void *arg)
+{
+ int symbols_count = 0;
+ Elf *elf;
+ int fd;
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ return -1;
+
+ fd = open(exec, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ elf = elf_begin(fd, ELF_C_READ, NULL);
+ if (elf) {
+ switch (type) {
+ case FIND_SYMBOL:
+ symbols_count = dso_symbols(elf, actor, arg);
+ if (symbols_count != 0)
+ break;
+ /* If no symbols found, try in the debuglink binary. */
+ symbols_count = dso_follow_debuglink(elf,
+ exec,
+ type,
+ actor,
+ arg);
+ break;
+ case FIND_STAPSDT_NOTE:
+ symbols_count = dso_sdt_notes(elf, actor, arg);
+ break;
+ }
+
+ elf_end(elf);
+ }
+
+ close(fd);
+ return symbols_count;
+}
diff --git a/tools/ktap/kp_symbol.h b/tools/ktap/kp_symbol.h
new file mode 100644
index 0000000..650e785
--- /dev/null
+++ b/tools/ktap/kp_symbol.h
@@ -0,0 +1,50 @@
+/*
+ * symbol.h - extract symbols from DSO.
+ *
+ * This file is part of ktap by Jovi Zhangwei.
+ *
+ * Copyright (C) 2013 Azat Khuzhin <a3at.mail@gmail.com>.
+ *
+ * ktap is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * ktap is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#define FIND_SYMBOL 1
+#define FIND_STAPSDT_NOTE 2
+
+#ifndef NO_LIBELF
+
+#include <gelf.h>
+#include <sys/queue.h>
+
+typedef GElf_Addr vaddr_t;
+typedef int (*symbol_actor)(const char *name, vaddr_t addr, void *arg);
+
+/**
+ * Parse all DSO symbols/sdt notes and all for every of them
+ * an actor.
+ *
+ * @exec - path to DSO
+ * @type - see FIND_*
+ * @symbol_actor - actor to call (callback)
+ * @arg - argument for @actor
+ *
+ * @return
+ * If there have errors, return negative value;
+ * No symbols found, return 0;
+ * Otherwise return number of dso symbols found
+ */
+int
+parse_dso_symbols(const char *exec, int type, symbol_actor actor, void *arg);
+#endif
--
1.8.1.4
next prev parent reply other threads:[~2014-03-29 15:31 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-28 14:44 [RFC PATCH v2 00/29] ktap: A lightweight dynamic tracing tool for Linux Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 01/29] ktap: add tools/ktap/README.md file Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 02/29] ktap: add ktap tutorial(tools/ktap/doc/tutorial.md) Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 03/29] ktap: add sample scripts(tools/ktap/samples/*) Jovi Zhangwei
2014-03-28 14:44 ` [PATCH v2 04/29] ktap: add basic ktap types definition(include/uapi/ktap/ktap_types.h) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 05/29] ktap: add bytecode definition(include/uapi/ktap/ktap_bc.h) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 06/29] ktap: add ktap_arch.h and error header file(include/uapi/ktap/) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 07/29] ktap: add kernel module main entry(kernel/trace/ktap/ktap.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 08/29] ktap: add bytecode reader(kernel/trace/ktap/kp_bcread.[c|h]) Jovi Zhangwei
2014-03-30 2:47 ` Andi Kleen
2014-03-30 8:02 ` Jovi Zhangwei
2014-03-30 17:17 ` Andi Kleen
2014-03-31 2:05 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 09/29] ktap: add bytecode execution engine(kernel/trace/ktap/kp_vm.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 10/29] ktap: add string handling code(kernel/trace/ktap/kp_[str|mempool].[c|h]) Jovi Zhangwei
2014-03-30 3:50 ` Andi Kleen
2014-03-30 9:12 ` Jovi Zhangwei
2014-03-30 17:19 ` Andi Kleen
2014-03-31 2:35 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 11/29] ktap: add table handling code(kernel/trace/ktap/kp_tab.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 12/29] ktap: add generic object handling code(kernel/trace/ktap/kp_obj.[c|h]) Jovi Zhangwei
2014-03-30 3:56 ` Andi Kleen
2014-03-30 8:14 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 13/29] ktap: add ring buffer handling code(kernel/trace/ktap/kp_transport.[c|h]) Jovi Zhangwei
2014-03-30 3:58 ` Andi Kleen
2014-03-30 7:40 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 14/29] ktap: add events management(kernel/trace/ktap/kp_events.[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 15/29] ktap: add built-in functions and library(kernel/trace/ktap/lib_*.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 16/29] ktap: add amalgamation build(kernel/trace/ktap/amalg.c) Jovi Zhangwei
2014-03-31 2:17 ` Li Zefan
2014-03-31 3:22 ` Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 17/29] ktap: add Makefile for kernel module(kernel/trace/ktap/Makefile) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 18/29] ktap: add Kconfig(kernel/trace/ktap/Kconfig) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 19/29] ktap: add main file for ktap binary(tools/ktap/kp_main.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 20/29] ktap: add compiler(tools/ktap/kp_[lex|parse].[c|h]) Jovi Zhangwei
2014-03-28 14:45 ` Jovi Zhangwei [this message]
2014-03-28 14:45 ` [PATCH v2 22/29] ktap: add events parse code(tools/ktap/kp_parse_events.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 23/29] ktap: add ring buffer reader(tools/ktap/kp_reader.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 24/29] ktap: add bytecode writer(tools/ktap/kp_bcwrite.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 25/29] ktap: add userspace util(tools/ktap/kp_util.c) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 26/29] ktap: add userspace binary Makefile(tools/ktap/Makefile) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 27/29] ktap: add testsuite and benchmark(tools/ktap/test/*) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 28/29] ktap: add vim syntax file(tools/ktap/vim/*) Jovi Zhangwei
2014-03-28 14:45 ` [PATCH v2 29/29] ktap: add COPYRIGHT file(tools/ktap/COPYRIGHT) Jovi Zhangwei
2014-03-30 1:00 ` [RFC PATCH v2 00/29] ktap: A lightweight dynamic tracing tool for Linux Andi Kleen
2014-03-30 9:18 ` Jovi Zhangwei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1396017924-7754-22-git-send-email-jovi.zhangwei@gmail.com \
--to=jovi.zhangwei@gmail.com \
--cc=andi@firstfloor.org \
--cc=fweisbec@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@redhat.com \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®