From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932150AbbCCDRD (ORCPT ); Mon, 2 Mar 2015 22:17:03 -0500 Received: from lgeamrelo01.lge.com ([156.147.1.125]:44586 "EHLO lgeamrelo01.lge.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754728AbbCCDMU (ORCPT ); Mon, 2 Mar 2015 22:12:20 -0500 X-Original-SENDERIP: 10.177.220.203 X-Original-MAILFROM: namhyung@kernel.org From: Namhyung Kim To: Arnaldo Carvalho de Melo Cc: Ingo Molnar , Peter Zijlstra , Jiri Olsa , LKML , Frederic Weisbecker , Adrian Hunter , Stephane Eranian , Andi Kleen , David Ahern Subject: [PATCH 21/38] perf tools: Introduce session__find_addr_location() and friends Date: Tue, 3 Mar 2015 12:07:33 +0900 Message-Id: <1425352070-1115-22-git-send-email-namhyung@kernel.org> X-Mailer: git-send-email 2.2.2 In-Reply-To: <1425352070-1115-1-git-send-email-namhyung@kernel.org> References: <1425352070-1115-1-git-send-email-namhyung@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org These new functions are for find appropriate map (and symbol) at the given time when used with an indexed data file. This is based on the fact that map_groups list is sorted by time in the previous patch. Cc: Frederic Weisbecker Signed-off-by: Namhyung Kim --- tools/perf/util/event.c | 57 ++++++++++++++++++++++++++++++++++++++--------- tools/perf/util/hist.c | 4 ++-- tools/perf/util/machine.c | 37 ++++++++++++++++++++---------- tools/perf/util/machine.h | 2 ++ tools/perf/util/session.h | 38 +++++++++++++++++++++++++++++++ tools/perf/util/thread.c | 21 +++++++++++++++++ tools/perf/util/thread.h | 10 +++++++++ 7 files changed, 145 insertions(+), 24 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 8d4a5cb829d0..5abf7086c97c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -746,16 +746,14 @@ int perf_event__process(struct perf_tool *tool __maybe_unused, return machine__process_event(machine, event, sample); } -void thread__find_addr_map(struct thread *thread, u8 cpumode, - enum map_type type, u64 addr, - struct addr_location *al) +static void map_groups__find_addr_map(struct map_groups *mg, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al) { - struct map_groups *mg = thread->mg; struct machine *machine = mg->machine; bool load_map = false; al->machine = machine; - al->thread = thread; al->addr = addr; al->cpumode = cpumode; al->filtered = 0; @@ -824,6 +822,26 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode, } } +void thread__find_addr_map(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al) +{ + al->thread = thread; + map_groups__find_addr_map(thread->mg, cpumode, type, addr, al); +} + +void thread__find_addr_map_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp) +{ + struct map_groups *mg; + + mg = thread__get_map_groups(thread, timestamp); + + al->thread = thread; + map_groups__find_addr_map(mg, cpumode, type, addr, al); +} + void thread__find_addr_location(struct thread *thread, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al) @@ -836,6 +854,21 @@ void thread__find_addr_location(struct thread *thread, al->sym = NULL; } +void thread__find_addr_location_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp) +{ + struct map_groups *mg; + + mg = thread__get_map_groups(thread, timestamp); + map_groups__find_addr_map(mg, cpumode, type, addr, al); + if (al->map != NULL) + al->sym = map__find_symbol(al->map, al->addr, + mg->machine->symbol_filter); + else + al->sym = NULL; +} + int perf_event__preprocess_sample(const union perf_event *event, struct machine *machine, struct addr_location *al, @@ -868,7 +901,9 @@ int perf_event__preprocess_sample(const union perf_event *event, machine->vmlinux_maps[MAP__FUNCTION] == NULL) machine__create_kernel_maps(machine); - thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); + session__find_addr_map(session, thread, cpumode, MAP__FUNCTION, + sample->ip, al, sample->time); + dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); @@ -929,14 +964,16 @@ void perf_event__preprocess_sample_addr(union perf_event *event, struct perf_sample *sample, struct thread *thread, struct addr_location *al, - struct perf_session *session __maybe_unused) + struct perf_session *session) { u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; - thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al); + session__find_addr_map(session, thread, cpumode, MAP__FUNCTION, + sample->addr, al, sample->time); + if (!al->map) - thread__find_addr_map(thread, cpumode, MAP__VARIABLE, - sample->addr, al); + session__find_addr_map(session, thread, cpumode, MAP__VARIABLE, + sample->addr, al, sample->time); al->cpu = sample->cpu; al->sym = NULL; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 0553a14a80a4..0d189ae76922 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -496,7 +496,7 @@ iter_prepare_mem_entry(struct hist_entry_iter *iter, struct addr_location *al) struct perf_sample *sample = iter->sample; struct mem_info *mi; - mi = sample__resolve_mem(sample, al); + mi = sample__resolve_mem(sample, iter->session, al); if (mi == NULL) return -ENOMEM; @@ -570,7 +570,7 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al struct branch_info *bi; struct perf_sample *sample = iter->sample; - bi = sample__resolve_bstack(sample, al); + bi = sample__resolve_bstack(sample, iter->session, al); if (!bi) return -ENOMEM; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index b14e4dc5261d..4743718d4bf1 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -8,6 +8,7 @@ #include "sort.h" #include "strlist.h" #include "thread.h" +#include "session.h" #include "vdso.h" #include #include @@ -1469,9 +1470,10 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex) return 0; } -static void ip__resolve_ams(struct thread *thread, +static void ip__resolve_ams(struct perf_session *session, + struct thread *thread, struct addr_map_symbol *ams, - u64 ip) + u64 ip, u64 timestamp) { struct addr_location al; @@ -1483,7 +1485,8 @@ static void ip__resolve_ams(struct thread *thread, * Thus, we have to try consecutively until we find a match * or else, the symbol is unknown */ - thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al); + session__find_cpumode_addr_location(session, thread, MAP__FUNCTION, + ip, &al, timestamp); ams->addr = ip; ams->al_addr = al.addr; @@ -1491,21 +1494,25 @@ static void ip__resolve_ams(struct thread *thread, ams->map = al.map; } -static void ip__resolve_data(struct thread *thread, - u8 m, struct addr_map_symbol *ams, u64 addr) +static void ip__resolve_data(struct perf_session *session, + struct thread *thread, u8 m, + struct addr_map_symbol *ams, + u64 addr, u64 timestamp) { struct addr_location al; memset(&al, 0, sizeof(al)); - thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al); + session__find_addr_location(session, thread, m, MAP__VARIABLE, addr, + &al, timestamp); if (al.map == NULL) { /* * some shared data regions have execute bit set which puts * their mapping in the MAP__FUNCTION type array. * Check there as a fallback option before dropping the sample. */ - thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al); + session__find_addr_location(session, thread, m, MAP__FUNCTION, + addr, &al, timestamp); } ams->addr = addr; @@ -1515,6 +1522,7 @@ static void ip__resolve_data(struct thread *thread, } struct mem_info *sample__resolve_mem(struct perf_sample *sample, + struct perf_session *session, struct addr_location *al) { struct mem_info *mi = zalloc(sizeof(*mi)); @@ -1522,8 +1530,10 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, if (!mi) return NULL; - ip__resolve_ams(al->thread, &mi->iaddr, sample->ip); - ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr); + ip__resolve_ams(session, al->thread, &mi->iaddr, sample->ip, + sample->time); + ip__resolve_data(session, al->thread, al->cpumode, &mi->daddr, + sample->addr, sample->time); mi->data_src.val = sample->data_src; return mi; @@ -1539,6 +1549,7 @@ static int add_callchain_ip(struct thread *thread, al.filtered = 0; al.sym = NULL; + if (branch_history) thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al); @@ -1589,6 +1600,7 @@ static int add_callchain_ip(struct thread *thread, } struct branch_info *sample__resolve_bstack(struct perf_sample *sample, + struct perf_session *session, struct addr_location *al) { unsigned int i; @@ -1599,8 +1611,10 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, return NULL; for (i = 0; i < bs->nr; i++) { - ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to); - ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from); + ip__resolve_ams(session, al->thread, &bi[i].to, + bs->entries[i].to, sample->time); + ip__resolve_ams(session, al->thread, &bi[i].from, + bs->entries[i].from, sample->time); bi[i].flags = bs->entries[i].flags; } return bi; @@ -1826,7 +1840,6 @@ static int thread__resolve_callchain_sample(struct thread *thread, ip = chain->ips[j]; err = add_callchain_ip(thread, parent, root_al, false, ip); - if (err) return (err < 0) ? err : 0; } diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 9571b6b1c5b5..45aee0c329ef 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -121,8 +121,10 @@ void machine__delete_threads(struct machine *machine); void machine__delete(struct machine *machine); struct branch_info *sample__resolve_bstack(struct perf_sample *sample, + struct perf_session *session, struct addr_location *al); struct mem_info *sample__resolve_mem(struct perf_sample *sample, + struct perf_session *session, struct addr_location *al); int thread__resolve_callchain(struct thread *thread, struct perf_evsel *evsel, diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index aff0d2b4cc0b..dbd21f8e7cf1 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -142,4 +142,42 @@ static inline bool perf_session__has_index(struct perf_session *session) return perf_header__has_feat(&session->header, HEADER_DATA_INDEX); } +static inline void +session__find_addr_map(struct perf_session *session, struct thread *thread, + u8 cpumode, enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp) +{ + if (session && perf_session__has_index(session)) + thread__find_addr_map_time(thread, cpumode, type, addr, al, + timestamp); + else + thread__find_addr_map(thread, cpumode, type, addr, al); +} + +static inline void +session__find_addr_location(struct perf_session *session, struct thread *thread, + u8 cpumode, enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp) +{ + if (session && perf_session__has_index(session)) + thread__find_addr_location_time(thread, cpumode, type, addr, al, + timestamp); + else + thread__find_addr_location(thread, cpumode, type, addr, al); +} + +static inline void +session__find_cpumode_addr_location(struct perf_session *session, + struct thread *thread, enum map_type type, + u64 addr, struct addr_location *al, + u64 timestamp) +{ + if (session && perf_session__has_index(session)) + thread__find_cpumode_addr_location_time(thread, type, addr, al, + timestamp); + else + thread__find_cpumode_addr_location(thread, type, addr, al); +} + + #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 7b01c171dcfa..9ae1ce8606af 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -359,3 +359,24 @@ void thread__find_cpumode_addr_location(struct thread *thread, break; } } + +void thread__find_cpumode_addr_location_time(struct thread *thread, + enum map_type type, u64 addr, + struct addr_location *al, + u64 timestamp) +{ + size_t i; + const u8 const cpumodes[] = { + PERF_RECORD_MISC_USER, + PERF_RECORD_MISC_KERNEL, + PERF_RECORD_MISC_GUEST_USER, + PERF_RECORD_MISC_GUEST_KERNEL + }; + + for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { + thread__find_addr_location_time(thread, cpumodes[i], type, + addr, al, timestamp); + if (al->map) + break; + } +} diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 08cafa2d97f9..5209ad5adadf 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -66,14 +66,24 @@ size_t thread__fprintf(struct thread *thread, FILE *fp); void thread__find_addr_map(struct thread *thread, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al); +void thread__find_addr_map_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp); void thread__find_addr_location(struct thread *thread, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al); +void thread__find_addr_location_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp); void thread__find_cpumode_addr_location(struct thread *thread, enum map_type type, u64 addr, struct addr_location *al); +void thread__find_cpumode_addr_location_time(struct thread *thread, + enum map_type type, u64 addr, + struct addr_location *al, + u64 timestamp); static inline void *thread__priv(struct thread *thread) { -- 2.2.2