diff options
Diffstat (limited to 'tools/perf/util/machine.c')
| -rw-r--r-- | tools/perf/util/machine.c | 50 | 
1 files changed, 47 insertions, 3 deletions
| diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index fb8496df8432..3901440aeff9 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -34,6 +34,7 @@  #include "bpf-event.h"  #include <internal/lib.h> // page_size  #include "cgroup.h" +#include "arm64-frame-pointer-unwind-support.h"  #include <linux/ctype.h>  #include <symbol/kallsyms.h> @@ -2710,6 +2711,15 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,  	return err;  } +static u64 get_leaf_frame_caller(struct perf_sample *sample, +		struct thread *thread, int usr_idx) +{ +	if (machine__normalized_is(thread->maps->machine, "arm64")) +		return get_leaf_frame_caller_aarch64(sample, thread, usr_idx); +	else +		return 0; +} +  static int thread__resolve_callchain_sample(struct thread *thread,  					    struct callchain_cursor *cursor,  					    struct evsel *evsel, @@ -2723,9 +2733,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,  	struct ip_callchain *chain = sample->callchain;  	int chain_nr = 0;  	u8 cpumode = PERF_RECORD_MISC_USER; -	int i, j, err, nr_entries; +	int i, j, err, nr_entries, usr_idx;  	int skip_idx = -1;  	int first_call = 0; +	u64 leaf_frame_caller;  	if (chain)  		chain_nr = chain->nr; @@ -2850,6 +2861,34 @@ check_calls:  			continue;  		} +		/* +		 * PERF_CONTEXT_USER allows us to locate where the user stack ends. +		 * Depending on callchain_param.order and the position of PERF_CONTEXT_USER, +		 * the index will be different in order to add the missing frame +		 * at the right place. +		 */ + +		usr_idx = callchain_param.order == ORDER_CALLEE ? j-2 : j-1; + +		if (usr_idx >= 0 && chain->ips[usr_idx] == PERF_CONTEXT_USER) { + +			leaf_frame_caller = get_leaf_frame_caller(sample, thread, usr_idx); + +			/* +			 * check if leaf_frame_Caller != ip to not add the same +			 * value twice. +			 */ + +			if (leaf_frame_caller && leaf_frame_caller != ip) { + +				err = add_callchain_ip(thread, cursor, parent, +					       root_al, &cpumode, leaf_frame_caller, +					       false, NULL, NULL, 0); +				if (err) +					return (err < 0) ? err : 0; +			} +		} +  		err = add_callchain_ip(thread, cursor, parent,  				       root_al, &cpumode, ip,  				       false, NULL, NULL, 0); @@ -3079,14 +3118,19 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,  }  /* - * Compares the raw arch string. N.B. see instead perf_env__arch() if a - * normalized arch is needed. + * 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; |