diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-09 11:15:52 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-09 11:15:52 -0700 |
commit | 608745f12462e2d8d94d5cc5dc94bf0960a881e3 (patch) | |
tree | e938bc957d235018d1cf4b018b09aaffae8a5f34 /tools/perf/util/dso.c | |
parent | cdc5ffc4100549654e19e6f068cf1fc0871a85c2 (diff) | |
parent | d1d59b817939821bee149e870ce7723f61ffb512 (diff) |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
"The main changes in this cycle on the kernel side were:
- CPU PMU and uncore driver updates to Intel Snow Ridge, IceLake,
KabyLake, AmberLake and WhiskeyLake CPUs.
- Rework the MSR probing infrastructure to make it more robust, make
it work better on virtualized systems and to better expose it on
sysfs.
- Rework PMU attributes group support based on the feedback from
Greg. The core sysfs patch that adds sysfs_update_groups() was
acked by Greg.
There's a lot of perf tooling changes as well, all around the place:
- vendor updates to Intel, cs-etm (ARM), ARM64, s390,
- various enhancements to Intel PT tooling support:
- Improve CBR (Core to Bus Ratio) packets support.
- Export power and ptwrite events to sqlite and postgresql.
- Add support for decoding PEBS via PT packets.
- Add support for samples to contain IPC ratio, collecting cycles
information from CYC packets, showing the IPC info periodically
- Allow using time ranges
- lots of updates to perf pmu, perf stat, perf trace, eBPF support,
perf record, perf diff, etc. - please see the shortlog and Git log
for details"
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (252 commits)
tools arch x86: Sync asm/cpufeatures.h with the with the kernel
tools build: Check if gettid() is available before providing helper
perf jvmti: Address gcc string overflow warning for strncpy()
perf python: Remove -fstack-protector-strong if clang doesn't have it
perf annotate TUI browser: Do not use member from variable within its own initialization
perf tests: Fix record+probe_libc_inet_pton.sh for powerpc64
perf evsel: Do not rely on errno values for precise_ip fallback
perf thread: Allow references to thread objects after machine__exit()
perf header: Assign proper ff->ph in perf_event__synthesize_features()
tools arch kvm: Sync kvm headers with the kernel sources
perf script: Allow specifying the files to process guest samples
perf tools metric: Don't include duration_time in group
perf list: Avoid extra : for --raw metrics
perf vendor events intel: Metric fixes for SKX/CLX
perf tools: Fix typos / broken sentences
perf jevents: Add support for Hisi hip08 L3C PMU aliasing
perf jevents: Add support for Hisi hip08 HHA PMU aliasing
perf jevents: Add support for Hisi hip08 DDRC PMU aliasing
perf pmu: Support more complex PMU event aliasing
perf diff: Documentation -c cycles option
...
Diffstat (limited to 'tools/perf/util/dso.c')
-rw-r--r-- | tools/perf/util/dso.c | 128 |
1 files changed, 91 insertions, 37 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index e059976d9d93..c7fde04400f7 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <asm/bug.h> #include <linux/kernel.h> +#include <linux/string.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/types.h> @@ -9,6 +10,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" @@ -392,7 +395,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, return -ENOMEM; } - strxfrchar(m->name, '-', '_'); + strreplace(m->name, '-', '_'); } return 0; @@ -706,6 +709,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) { @@ -794,48 +835,53 @@ dso_cache__memcpy(struct dso_cache *cache, u64 offset, return cache_size; } -static ssize_t -dso_cache__read(struct dso *dso, struct machine *machine, - u64 offset, u8 *data, ssize_t size) +static ssize_t file_read(struct dso *dso, struct machine *machine, + u64 offset, char *data) { - struct dso_cache *cache; - struct dso_cache *old; ssize_t ret; - do { - u64 cache_offset; + pthread_mutex_lock(&dso__data_open_lock); - cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE); - if (!cache) - return -ENOMEM; + /* + * dso->data.fd might be closed if other thread opened another + * file (dso) due to open file limit (RLIMIT_NOFILE). + */ + try_to_open_dso(dso, machine); - pthread_mutex_lock(&dso__data_open_lock); + if (dso->data.fd < 0) { + dso->data.status = DSO_DATA_STATUS_ERROR; + ret = -errno; + goto out; + } - /* - * dso->data.fd might be closed if other thread opened another - * file (dso) due to open file limit (RLIMIT_NOFILE). - */ - try_to_open_dso(dso, machine); + ret = pread(dso->data.fd, data, DSO__DATA_CACHE_SIZE, offset); +out: + pthread_mutex_unlock(&dso__data_open_lock); + return ret; +} - if (dso->data.fd < 0) { - ret = -errno; - dso->data.status = DSO_DATA_STATUS_ERROR; - break; - } +static ssize_t +dso_cache__read(struct dso *dso, struct machine *machine, + u64 offset, u8 *data, ssize_t size) +{ + u64 cache_offset = offset & DSO__DATA_CACHE_MASK; + struct dso_cache *cache; + struct dso_cache *old; + ssize_t ret; - cache_offset = offset & DSO__DATA_CACHE_MASK; + cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE); + if (!cache) + return -ENOMEM; - ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset); - if (ret <= 0) - break; + 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; - } while (0); - - pthread_mutex_unlock(&dso__data_open_lock); - if (ret > 0) { old = dso_cache__insert(dso, cache); if (old) { /* we lose the race */ @@ -898,18 +944,12 @@ static ssize_t cached_read(struct dso *dso, struct machine *machine, return r; } -int dso__data_file_size(struct dso *dso, struct machine *machine) +static int file_size(struct dso *dso, struct machine *machine) { int ret = 0; struct stat st; char sbuf[STRERR_BUFSIZE]; - if (dso->data.file_size) - return 0; - - if (dso->data.status == DSO_DATA_STATUS_ERROR) - return -1; - pthread_mutex_lock(&dso__data_open_lock); /* @@ -938,6 +978,20 @@ out: return ret; } +int dso__data_file_size(struct dso *dso, struct machine *machine) +{ + if (dso->data.file_size) + return 0; + + 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); +} + /** * dso__data_size - Return dso data size * @dso: dso object |