Commit 6c398d72 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarJiri Olsa <jolsa@kernel.org>
Acked-by: default avatarSong 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent cacddfe7
Loading
Loading
Loading
Loading
+48 −1
Original line number Diff line number Diff line
@@ -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;

	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);
}