perf dso: Add BPF DSO read and size hooks

Add BPF related code into DSO reading paths to return size (bpf_size)
and read the BPF code (bpf_read).

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Song Liu <songliubraving@fb.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stanislav Fomichev <sdf@google.com>
Link: http://lkml.kernel.org/r/20190508132010.14512-5-jolsa@kernel.org
[ Use uintptr_t when casting from u64 to u8 pointers ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Jiri Olsa 2019-05-08 15:20:02 +02:00 committed by Arnaldo Carvalho de Melo
parent cacddfe7b0
commit 6c398d723a
1 changed files with 48 additions and 1 deletions

View File

@ -9,6 +9,8 @@
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <bpf/libbpf.h>
#include "bpf-event.h"
#include "compress.h"
#include "namespaces.h"
#include "path.h"
@ -706,6 +708,44 @@ bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
return false;
}
static ssize_t bpf_read(struct dso *dso, u64 offset, char *data)
{
struct bpf_prog_info_node *node;
ssize_t size = DSO__DATA_CACHE_SIZE;
u64 len;
u8 *buf;
node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
if (!node || !node->info_linear) {
dso->data.status = DSO_DATA_STATUS_ERROR;
return -1;
}
len = node->info_linear->info.jited_prog_len;
buf = (u8 *)(uintptr_t)node->info_linear->info.jited_prog_insns;
if (offset >= len)
return -1;
size = (ssize_t)min(len - offset, (u64)size);
memcpy(data, buf + offset, size);
return size;
}
static int bpf_size(struct dso *dso)
{
struct bpf_prog_info_node *node;
node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, dso->bpf_prog.id);
if (!node || !node->info_linear) {
dso->data.status = DSO_DATA_STATUS_ERROR;
return -1;
}
dso->data.file_size = node->info_linear->info.jited_prog_len;
return 0;
}
static void
dso_cache__free(struct dso *dso)
{
@ -832,7 +872,11 @@ dso_cache__read(struct dso *dso, struct machine *machine,
if (!cache)
return -ENOMEM;
ret = file_read(dso, machine, cache_offset, cache->data);
if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
ret = bpf_read(dso, cache_offset, cache->data);
else
ret = file_read(dso, machine, cache_offset, cache->data);
if (ret > 0) {
cache->offset = cache_offset;
cache->size = ret;
@ -941,6 +985,9 @@ int dso__data_file_size(struct dso *dso, struct machine *machine)
if (dso->data.status == DSO_DATA_STATUS_ERROR)
return -1;
if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO)
return bpf_size(dso);
return file_size(dso, machine);
}