|
@@ -1385,19 +1385,46 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
|
|
|
static int add_callchain_ip(struct thread *thread,
|
|
|
struct symbol **parent,
|
|
|
struct addr_location *root_al,
|
|
|
- int cpumode,
|
|
|
+ bool branch_history,
|
|
|
u64 ip)
|
|
|
{
|
|
|
struct addr_location al;
|
|
|
|
|
|
al.filtered = 0;
|
|
|
al.sym = NULL;
|
|
|
- if (cpumode == -1)
|
|
|
+ if (branch_history)
|
|
|
thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
|
|
|
ip, &al);
|
|
|
- else
|
|
|
+ else {
|
|
|
+ u8 cpumode = PERF_RECORD_MISC_USER;
|
|
|
+
|
|
|
+ if (ip >= PERF_CONTEXT_MAX) {
|
|
|
+ switch (ip) {
|
|
|
+ case PERF_CONTEXT_HV:
|
|
|
+ cpumode = PERF_RECORD_MISC_HYPERVISOR;
|
|
|
+ break;
|
|
|
+ case PERF_CONTEXT_KERNEL:
|
|
|
+ cpumode = PERF_RECORD_MISC_KERNEL;
|
|
|
+ break;
|
|
|
+ case PERF_CONTEXT_USER:
|
|
|
+ cpumode = PERF_RECORD_MISC_USER;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ pr_debug("invalid callchain context: "
|
|
|
+ "%"PRId64"\n", (s64) ip);
|
|
|
+ /*
|
|
|
+ * It seems the callchain is corrupted.
|
|
|
+ * Discard all.
|
|
|
+ */
|
|
|
+ callchain_cursor_reset(&callchain_cursor);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
|
|
|
ip, &al);
|
|
|
+ }
|
|
|
+
|
|
|
if (al.sym != NULL) {
|
|
|
if (sort__has_parent && !*parent &&
|
|
|
symbol__match_regex(al.sym, &parent_regex))
|
|
@@ -1480,11 +1507,8 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
|
|
struct addr_location *root_al,
|
|
|
int max_stack)
|
|
|
{
|
|
|
- u8 cpumode = PERF_RECORD_MISC_USER;
|
|
|
int chain_nr = min(max_stack, (int)chain->nr);
|
|
|
- int i;
|
|
|
- int j;
|
|
|
- int err;
|
|
|
+ int i, j, err;
|
|
|
int skip_idx = -1;
|
|
|
int first_call = 0;
|
|
|
|
|
@@ -1542,10 +1566,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
|
|
|
|
|
|
for (i = 0; i < nr; i++) {
|
|
|
err = add_callchain_ip(thread, parent, root_al,
|
|
|
- -1, be[i].to);
|
|
|
+ true, be[i].to);
|
|
|
if (!err)
|
|
|
err = add_callchain_ip(thread, parent, root_al,
|
|
|
- -1, be[i].from);
|
|
|
+ true, be[i].from);
|
|
|
if (err == -EINVAL)
|
|
|
break;
|
|
|
if (err)
|
|
@@ -1574,36 +1598,10 @@ check_calls:
|
|
|
#endif
|
|
|
ip = chain->ips[j];
|
|
|
|
|
|
- if (ip >= PERF_CONTEXT_MAX) {
|
|
|
- switch (ip) {
|
|
|
- case PERF_CONTEXT_HV:
|
|
|
- cpumode = PERF_RECORD_MISC_HYPERVISOR;
|
|
|
- break;
|
|
|
- case PERF_CONTEXT_KERNEL:
|
|
|
- cpumode = PERF_RECORD_MISC_KERNEL;
|
|
|
- break;
|
|
|
- case PERF_CONTEXT_USER:
|
|
|
- cpumode = PERF_RECORD_MISC_USER;
|
|
|
- break;
|
|
|
- default:
|
|
|
- pr_debug("invalid callchain context: "
|
|
|
- "%"PRId64"\n", (s64) ip);
|
|
|
- /*
|
|
|
- * It seems the callchain is corrupted.
|
|
|
- * Discard all.
|
|
|
- */
|
|
|
- callchain_cursor_reset(&callchain_cursor);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- continue;
|
|
|
- }
|
|
|
+ err = add_callchain_ip(thread, parent, root_al, false, ip);
|
|
|
|
|
|
- err = add_callchain_ip(thread, parent, root_al,
|
|
|
- cpumode, ip);
|
|
|
- if (err == -EINVAL)
|
|
|
- break;
|
|
|
if (err)
|
|
|
- return err;
|
|
|
+ return (err < 0) ? err : 0;
|
|
|
}
|
|
|
|
|
|
return 0;
|