From: "Tzvetomir Stoyanov (VMware)" <tz.stoyanov@gmail.com>
To: rostedt@goodmis.org
Cc: linux-trace-devel@vger.kernel.org
Subject: [PATCH 4/5] trace-cmd: Add a new option in trace.dat file for the address to function name mapping
Date: Thu, 3 Dec 2020 08:02:25 +0200 [thread overview]
Message-ID: <20201203060226.476475-5-tz.stoyanov@gmail.com> (raw)
In-Reply-To: <20201203060226.476475-1-tz.stoyanov@gmail.com>
There are cases where resolving a user space address recorded in the
trace file to function name is required, when this file is visualised.
This mapping is available during the trace. A new trace.dat file option
TRACECMD_OPTION_PID_SYMBOLS is added, for storing the mapping in the
file. A new API is introduced, to resolve address to name, using
information stored in the TRACECMD_OPTION_PID_SYMBOLS option:
struct tracecmd_debug_symbols *
tracecmd_search_task_symbol(struct tracecmd_input *handle,
int pid, unsigned long long addr);
Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
.../include/private/trace-cmd-private.h | 5 +
lib/trace-cmd/trace-input.c | 144 ++++++++++++++++++
tracecmd/trace-dump.c | 3 +
3 files changed, 152 insertions(+)
diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h
index a0dac5da..8c99faa3 100644
--- a/lib/trace-cmd/include/private/trace-cmd-private.h
+++ b/lib/trace-cmd/include/private/trace-cmd-private.h
@@ -112,6 +112,7 @@ enum {
TRACECMD_OPTION_TRACEID,
TRACECMD_OPTION_TIME_SHIFT,
TRACECMD_OPTION_GUEST,
+ TRACECMD_OPTION_PID_SYMBOLS,
};
enum {
@@ -231,6 +232,10 @@ unsigned int tracecmd_record_ts_delta(struct tracecmd_input *handle,
struct tracecmd_proc_addr_map *
tracecmd_search_task_map(struct tracecmd_input *handle,
int pid, unsigned long long addr);
+
+struct tracecmd_debug_symbols *
+tracecmd_search_task_symbol(struct tracecmd_input *handle,
+ int pid, unsigned long long addr);
#ifndef SWIG
/* hack for function graph work around */
extern __thread struct tracecmd_input *tracecmd_curr_thread_handle;
diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c
index af97883e..39da0cb8 100644
--- a/lib/trace-cmd/trace-input.c
+++ b/lib/trace-cmd/trace-input.c
@@ -19,6 +19,8 @@
#include "trace-local.h"
#include "kbuffer.h"
#include "list.h"
+#include "trace-hash.h"
+#include "trace-hash-local.h"
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
@@ -98,6 +100,18 @@ struct host_trace_info {
struct ts_offset_sample *ts_samples;
};
+struct pid_function_map {
+ struct trace_hash_item hash;
+ struct tracecmd_debug_symbols symb;
+};
+
+struct pid_symbol_maps {
+ struct pid_symbol_maps *next;
+ int pid;
+ int symb_count;
+ struct trace_hash symbols;
+};
+
struct tracecmd_input {
struct tep_handle *pevent;
struct tep_plugin_list *plugin_list;
@@ -130,6 +144,7 @@ struct tracecmd_input {
struct hook_list *hooks;
struct pid_addr_maps *pid_maps;
+ struct pid_symbol_maps *pid_symbols;
/* file information */
size_t header_files_start;
size_t ftrace_files_start;
@@ -2430,6 +2445,92 @@ static int trace_pid_map_search(const void *a, const void *b)
return 0;
}
+static void trace_pid_symbols_free(struct pid_symbol_maps *maps)
+{
+ struct pid_symbol_maps *del;
+ struct pid_function_map *fmap;
+ struct trace_hash_item **bucket;
+ struct trace_hash_item *item;
+
+ while (maps) {
+ del = maps;
+ maps = maps->next;
+ trace_hash_for_each_bucket(bucket, &del->symbols) {
+ trace_hash_while_item(item, bucket) {
+ trace_hash_del(item);
+ fmap = (struct pid_function_map *)item;
+ free(fmap->symb.name);
+ free(fmap->symb.fname);
+ free(fmap);
+ }
+ }
+ trace_hash_free(&del->symbols);
+ }
+}
+
+#define MAX_FUNC_NAME 256
+static int trace_pid_symbols_load(struct tracecmd_input *handle, char *buf)
+{
+ struct pid_symbol_maps *maps = NULL;
+ struct pid_function_map *s;
+ char file[PATH_MAX];
+ char fname[MAX_FUNC_NAME];
+ char *line;
+ int res;
+ int ret;
+ int i;
+
+ maps = calloc(1, sizeof(*maps));
+ if (!maps)
+ return -ENOMEM;
+
+ ret = -EINVAL;
+ line = strchr(buf, '\n');
+ if (!line)
+ goto out_fail;
+
+ *line = '\0';
+ res = sscanf(buf, "%x %d", &maps->pid, &maps->symb_count);
+ if (res != 2)
+ goto out_fail;
+
+ ret = -ENOMEM;
+ if (trace_hash_init(&maps->symbols, 64) < 0)
+ goto out_fail;
+
+ buf = line + 1;
+ line = strchr(buf, '\n');
+ for (i = 0; i < maps->symb_count; i++) {
+ if (!line)
+ break;
+ *line = '\0';
+ s = calloc(1, sizeof(*s));
+ if (!s)
+ goto out_fail;
+ res = sscanf(buf, "%"STRINGIFY(PATH_MAX)"s %"STRINGIFY(MAX_FUNC_NAME)"s %llx %llx",
+ file, fname, &s->symb.vma_start, &s->symb.vma_near);
+ if (res != 4)
+ break;
+ s->symb.fname = strdup(file);
+ s->symb.name = strdup(fname);
+ if (!s->symb.fname || !s->symb.name)
+ goto out_fail;
+ s->hash.key = trace_hash(s->symb.vma_near);
+ trace_hash_add(&maps->symbols, (struct trace_hash_item *)s);
+ buf = line + 1;
+ line = strchr(buf, '\n');
+ }
+
+ maps->next = handle->pid_symbols;
+ handle->pid_symbols = maps;
+
+ return 0;
+
+out_fail:
+ trace_pid_symbols_free(maps);
+ return ret;
+}
+
/**
* tracecmd_search_task_map - Search task memory address map
* @handle: input handle to the trace.dat file
@@ -2469,6 +2570,43 @@ tracecmd_search_task_map(struct tracecmd_input *handle,
return lib;
}
+/**
+ * tracecmd_search_task_symbol - Resolve address to function name
+ * @handle: input handle to the trace.dat file
+ * @pid: pid of the task, which function information is stored in the trace.dat
+ * @addr: address of the function
+ *
+ * Mapping of some functions to addresses of traced PIDs can be saved in the
+ * trace.dat file, using the "perf" sub command. If there is such information,
+ * this API can be used to look up into this function maps to find the name of
+ * the function and the name of the file where that function is loaded.
+ *
+ * A pointer to struct tracecmd_debug_symbols is returned, containing information
+ * about the reuquested @addr: the name of the function, its start address, the
+ * name of the binary file that contains the function.
+ */
+struct tracecmd_debug_symbols *
+tracecmd_search_task_symbol(struct tracecmd_input *handle,
+ int pid, unsigned long long addr)
+{
+ struct pid_function_map *symb = NULL;
+ struct pid_symbol_maps *map;
+
+ for (map = handle->pid_symbols; map; map = map->next) {
+ if (pid == map->pid)
+ break;
+ }
+
+ if (map)
+ symb = (struct pid_function_map *)trace_hash_find(&map->symbols,
+ trace_hash(addr), NULL, NULL);
+
+ if (symb)
+ return &symb->symb;
+
+ return NULL;
+}
+
static int handle_options(struct tracecmd_input *handle)
{
long long offset;
@@ -2610,6 +2748,10 @@ static int handle_options(struct tracecmd_input *handle)
case TRACECMD_OPTION_GUEST:
trace_guest_load(handle, buf, size);
break;
+ case TRACECMD_OPTION_PID_SYMBOLS:
+ if (buf[size-1] == '\0')
+ trace_pid_symbols_load(handle, buf);
+ break;
default:
warning("unknown option %d", option);
break;
@@ -3352,6 +3494,8 @@ void tracecmd_close(struct tracecmd_input *handle)
trace_pid_map_free(handle->pid_maps);
handle->pid_maps = NULL;
+ trace_pid_symbols_free(handle->pid_symbols);
+ handle->pid_symbols = NULL;
trace_tsync_offset_free(&handle->host);
trace_guests_free(handle);
diff --git a/tracecmd/trace-dump.c b/tracecmd/trace-dump.c
index c55e2389..a3e7acf7 100644
--- a/tracecmd/trace-dump.c
+++ b/tracecmd/trace-dump.c
@@ -530,6 +530,9 @@ static void dump_options(int fd)
case TRACECMD_OPTION_GUEST:
dump_option_guest(fd, size);
break;
+ case TRACECMD_OPTION_PID_SYMBOLS:
+ dump_option_string(fd, size, "PIDSYMBOLS");
+ break;
default:
do_print(OPTIONS, " %d %d\t[Unknown option, size - skipping]\n",
option, size);
--
2.28.0
next prev parent reply other threads:[~2020-12-03 6:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-03 6:02 [PATCH 0/5] Initial trace-cmd perf support Tzvetomir Stoyanov (VMware)
2020-12-03 6:02 ` [PATCH 1/5] trace-cmd: Internal refactoring of pid address map logic Tzvetomir Stoyanov (VMware)
2020-12-03 6:02 ` [PATCH 2/5] trace-cmd: Make read_file_string() non static Tzvetomir Stoyanov (VMware)
2020-12-03 6:02 ` [PATCH 3/5] trace-cmd: New internal APIs for reading ELF header Tzvetomir Stoyanov (VMware)
2020-12-03 6:02 ` Tzvetomir Stoyanov (VMware) [this message]
2020-12-03 6:02 ` [PATCH 5/5] [WIP] trace-cmd: Add new subcomand "trace-cmd perf" Tzvetomir Stoyanov (VMware)
2021-02-19 2:03 ` Steven Rostedt
2021-02-19 3:53 ` Steven Rostedt
2021-02-19 17:51 ` Dario Faggioli
2021-02-19 7:16 ` Tzvetomir Stoyanov
2021-02-19 14:36 ` Steven Rostedt
2021-02-19 17:56 ` Tzvetomir Stoyanov
2021-02-19 19:11 ` Steven Rostedt
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=20201203060226.476475-5-tz.stoyanov@gmail.com \
--to=tz.stoyanov@gmail.com \
--cc=linux-trace-devel@vger.kernel.org \
--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;
as well as URLs for NNTP newsgroup(s).