summaryrefslogtreecommitdiff
path: root/tools/perf/util/machine.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r--tools/perf/util/machine.c135
1 files changed, 82 insertions, 53 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index e76f8c86e62a..0d2ebf6a84bc 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -4,10 +4,12 @@
#include <inttypes.h>
#include <regex.h>
#include <stdlib.h>
+#include <string.h>
#include "callchain.h"
#include "debug.h"
#include "dso.h"
#include "env.h"
+#include "dwarf-regs.h"
#include "event.h"
#include "evsel.h"
#include "hist.h"
@@ -77,15 +79,14 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
int err = -ENOMEM;
memset(machine, 0, sizeof(*machine));
- machine->kmaps = maps__new(machine);
- if (machine->kmaps == NULL)
- return -ENOMEM;
-
RB_CLEAR_NODE(&machine->rb_node);
dsos__init(&machine->dsos);
-
threads__init(&machine->threads);
+ machine->kmaps = maps__new(machine);
+ if (machine->kmaps == NULL)
+ goto out;
+
machine->vdso_info = NULL;
machine->env = NULL;
@@ -122,11 +123,11 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
out:
if (err) {
- zfree(&machine->kmaps);
+ maps__zput(machine->kmaps);
zfree(&machine->root_dir);
zfree(&machine->mmap_name);
}
- return 0;
+ return err;
}
static struct machine *__machine__new_host(struct perf_env *host_env, bool kernel_maps)
@@ -136,7 +137,10 @@ static struct machine *__machine__new_host(struct perf_env *host_env, bool kerne
if (!machine)
return NULL;
- machine__init(machine, "", HOST_KERNEL_ID);
+ if (machine__init(machine, "", HOST_KERNEL_ID) != 0) {
+ free(machine);
+ return NULL;
+ }
if (kernel_maps && machine__create_kernel_maps(machine) < 0) {
free(machine);
@@ -229,10 +233,12 @@ void machine__delete(struct machine *machine)
}
}
-void machines__init(struct machines *machines)
+int machines__init(struct machines *machines)
{
- machine__init(&machines->host, "", HOST_KERNEL_ID);
+ int err = machine__init(&machines->host, "", HOST_KERNEL_ID);
+
machines->guests = RB_ROOT_CACHED;
+ return err;
}
void machines__exit(struct machines *machines)
@@ -327,7 +333,7 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid)
if ((pid != HOST_KERNEL_ID) &&
(pid != DEFAULT_GUEST_KERNEL_ID) &&
(symbol_conf.guestmount)) {
- sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
+ snprintf(path, sizeof(path), "%s/%d", symbol_conf.guestmount, pid);
if (access(path, R_OK)) {
static struct strlist *seen;
@@ -729,9 +735,15 @@ static int machine__process_ksymbol_register(struct machine *machine,
{
struct symbol *sym;
struct dso *dso = NULL;
- struct map *map = maps__find(machine__kernel_maps(machine), event->ksymbol.addr);
+ struct map *map;
int err = 0;
+ /* Ignore mapping symbols in ksymbol events - check early before any state mutation */
+ if (is_ignored_kernel_symbol(event->ksymbol.name))
+ return 0;
+
+ map = maps__find(machine__kernel_maps(machine), event->ksymbol.addr);
+
if (!map) {
dso = dso__new(event->ksymbol.name);
@@ -790,6 +802,10 @@ static int machine__process_ksymbol_unregister(struct machine *machine,
struct symbol *sym;
struct map *map;
+ /* Ignore mapping symbols in ksymbol events */
+ if (is_ignored_kernel_symbol(event->ksymbol.name))
+ return 0;
+
map = maps__find(machine__kernel_maps(machine), event->ksymbol.addr);
if (!map)
return 0;
@@ -814,6 +830,11 @@ int machine__process_ksymbol(struct machine *machine __maybe_unused,
if (dump_trace)
perf_event__fprintf_ksymbol(event, stdout);
+ if (event->header.size < offsetof(struct perf_record_ksymbol, name) + 2 ||
+ !memchr(event->ksymbol.name, '\0',
+ event->header.size - offsetof(struct perf_record_ksymbol, name)))
+ return -EINVAL;
+
/* no need to process non-JIT BPF as it cannot get samples */
if (event->ksymbol.len == 0)
return 0;
@@ -1078,7 +1099,7 @@ static u64 find_entry_trampoline(struct dso *dso)
unsigned int i;
for (; sym; sym = dso__next_symbol(sym)) {
- if (sym->binding != STB_GLOBAL)
+ if (symbol__binding(sym) != STB_GLOBAL)
continue;
for (i = 0; i < ARRAY_SIZE(syms); i++) {
if (!strcmp(sym->name, syms[i]))
@@ -1239,9 +1260,9 @@ int machines__create_guest_kernel_maps(struct machines *machines)
namelist[i]->d_name);
continue;
}
- sprintf(path, "%s/%s/proc/kallsyms",
- symbol_conf.guestmount,
- namelist[i]->d_name);
+ snprintf(path, sizeof(path), "%s/%s/proc/kallsyms",
+ symbol_conf.guestmount,
+ namelist[i]->d_name);
ret = access(path, R_OK);
if (ret) {
pr_debug("Can't access file %s\n", path);
@@ -1319,7 +1340,7 @@ static char *get_kernel_version(const char *root_dir)
char *name, *tmp;
const char *prefix = "Linux version ";
- sprintf(version, "%s/proc/version", root_dir);
+ snprintf(version, sizeof(version), "%s/proc/version", root_dir);
file = fopen(version, "r");
if (!file)
return NULL;
@@ -1522,22 +1543,30 @@ static void machine__set_kernel_mmap(struct machine *machine,
map__set_end(machine->vmlinux_map, ~0ULL);
}
-static int machine__update_kernel_mmap(struct machine *machine,
- u64 start, u64 end)
+struct kernel_mmap_mutation_ctx {
+ u64 start;
+ u64 end;
+};
+
+static int kernel_mmap_mutate_cb(struct map *map, void *data)
{
- struct map *orig, *updated;
- int err;
+ struct kernel_mmap_mutation_ctx *ctx = data;
- orig = machine->vmlinux_map;
- updated = map__get(orig);
+ map__set_start(map, ctx->start);
+ map__set_end(map, ctx->end);
+ if (ctx->start == 0 && ctx->end == 0)
+ map__set_end(map, ~0ULL);
+ return 0;
+}
- machine->vmlinux_map = updated;
- maps__remove(machine__kernel_maps(machine), orig);
- machine__set_kernel_mmap(machine, start, end);
- err = maps__insert(machine__kernel_maps(machine), updated);
- map__put(orig);
+static int machine__update_kernel_mmap(struct machine *machine,
+ u64 start, u64 end)
+{
+ struct kernel_mmap_mutation_ctx ctx = { .start = start, .end = end };
- return err;
+ return maps__mutate_mapping(machine__kernel_maps(machine),
+ machine->vmlinux_map,
+ kernel_mmap_mutate_cb, &ctx);
}
int machine__create_kernel_maps(struct machine *machine)
@@ -1611,10 +1640,24 @@ static bool machine__uses_kcore(struct machine *machine)
return dsos__for_each_dso(&machine->dsos, machine__uses_kcore_cb, NULL) != 0 ? true : false;
}
+static bool machine__is(struct machine *machine, uint16_t e_machine)
+{
+ if (!machine)
+ return false;
+
+ if (!machine->env) {
+ if (machine__is_host(machine))
+ return e_machine == EM_HOST;
+ return false;
+ }
+
+ return perf_env__e_machine(machine->env, NULL) == e_machine;
+}
+
static bool perf_event__is_extra_kernel_mmap(struct machine *machine,
struct extra_kernel_map *xm)
{
- return machine__is(machine, "x86_64") &&
+ return machine__is(machine, EM_X86_64) &&
is_entry_trampoline(xm->name);
}
@@ -2770,7 +2813,7 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
static u64 get_leaf_frame_caller(struct perf_sample *sample,
struct thread *thread, int usr_idx)
{
- if (machine__normalized_is(maps__machine(thread__maps(thread)), "arm64"))
+ if (thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL) == EM_AARCH64)
return get_leaf_frame_caller_aarch64(sample, thread, usr_idx);
else
return 0;
@@ -2778,13 +2821,13 @@ static u64 get_leaf_frame_caller(struct perf_sample *sample,
static int thread__resolve_callchain_sample(struct thread *thread,
struct callchain_cursor *cursor,
- struct evsel *evsel,
struct perf_sample *sample,
struct symbol **parent,
struct addr_location *root_al,
int max_stack,
bool symbols)
{
+ struct evsel *evsel = sample->evsel;
struct branch_stack *branch = sample->branch_stack;
struct branch_entry *entries = perf_sample__branch_entries(sample);
struct ip_callchain *chain = sample->callchain;
@@ -2986,10 +3029,11 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
static int thread__resolve_callchain_unwind(struct thread *thread,
struct callchain_cursor *cursor,
- struct evsel *evsel,
struct perf_sample *sample,
int max_stack, bool symbols)
{
+ struct evsel *evsel = sample->evsel;
+
/* Can we do dwarf post unwind? */
if (!((evsel->core.attr.sample_type & PERF_SAMPLE_REGS_USER) &&
(evsel->core.attr.sample_type & PERF_SAMPLE_STACK_USER)))
@@ -3009,7 +3053,6 @@ static int thread__resolve_callchain_unwind(struct thread *thread,
int __thread__resolve_callchain(struct thread *thread,
struct callchain_cursor *cursor,
- struct evsel *evsel,
struct perf_sample *sample,
struct symbol **parent,
struct addr_location *root_al,
@@ -3025,22 +3068,22 @@ int __thread__resolve_callchain(struct thread *thread,
if (callchain_param.order == ORDER_CALLEE) {
ret = thread__resolve_callchain_sample(thread, cursor,
- evsel, sample,
+ sample,
parent, root_al,
max_stack, symbols);
if (ret)
return ret;
ret = thread__resolve_callchain_unwind(thread, cursor,
- evsel, sample,
+ sample,
max_stack, symbols);
} else {
ret = thread__resolve_callchain_unwind(thread, cursor,
- evsel, sample,
+ sample,
max_stack, symbols);
if (ret)
return ret;
ret = thread__resolve_callchain_sample(thread, cursor,
- evsel, sample,
+ sample,
parent, root_al,
max_stack, symbols);
}
@@ -3141,20 +3184,6 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
return 0;
}
-/*
- * Compares the raw arch string. N.B. see instead perf_env__arch() or
- * machine__normalized_is() if a normalized arch is needed.
- */
-bool machine__is(struct machine *machine, const char *arch)
-{
- return machine && !strcmp(perf_env__raw_arch(machine->env), arch);
-}
-
-bool machine__normalized_is(struct machine *machine, const char *arch)
-{
- return machine && !strcmp(perf_env__arch(machine->env), arch);
-}
-
int machine__nr_cpus_avail(struct machine *machine)
{
return machine ? perf_env__nr_cpus_avail(machine->env) : 0;
@@ -3181,7 +3210,7 @@ int machine__get_kernel_start(struct machine *machine)
* start of kernel text, but still above 2^63. So leave
* kernel_start = 1ULL << 63 for x86_64.
*/
- if (!err && !machine__is(machine, "x86_64"))
+ if (!err && !machine__is(machine, EM_X86_64))
machine->kernel_start = map__start(map);
}
return err;