@ -33,6 +33,7 @@ enum perf_output_field {
PERF_OUTPUT_IP = 1U < < 7 ,
PERF_OUTPUT_SYM = 1U < < 8 ,
PERF_OUTPUT_DSO = 1U < < 9 ,
PERF_OUTPUT_ADDR = 1U < < 10 ,
} ;
struct output_option {
@ -49,6 +50,7 @@ struct output_option {
{ . str = " ip " , . field = PERF_OUTPUT_IP } ,
{ . str = " sym " , . field = PERF_OUTPUT_SYM } ,
{ . str = " dso " , . field = PERF_OUTPUT_DSO } ,
{ . str = " addr " , . field = PERF_OUTPUT_ADDR } ,
} ;
/* default set to maintain compatibility with current format */
@ -173,14 +175,22 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
! ( attr - > sample_type & PERF_SAMPLE_CALLCHAIN ) )
symbol_conf . use_callchain = false ;
}
if ( PRINT_FIELD ( SYM ) & & ! PRINT_FIELD ( IP ) ) {
pr_err ( " Display of symbols requested but IP is not selected. \n "
" No addresses to convert to symbols. \n " ) ;
if ( PRINT_FIELD ( ADDR ) & &
perf_event_attr__check_stype ( attr , PERF_SAMPLE_ADDR , " ADDR " ,
PERF_OUTPUT_ADDR ) )
return - EINVAL ;
if ( PRINT_FIELD ( SYM ) & & ! PRINT_FIELD ( IP ) & & ! PRINT_FIELD ( ADDR ) ) {
pr_err ( " Display of symbols requested but neither sample IP nor "
" sample address \n is selected. Hence, no addresses to convert "
" to symbols. \n " ) ;
return - EINVAL ;
}
if ( PRINT_FIELD ( DSO ) & & ! PRINT_FIELD ( IP ) ) {
pr_err ( " Display of DSO requested but IP is not selected. \n "
" No addresses to convert to dso. \n " ) ;
if ( PRINT_FIELD ( DSO ) & & ! PRINT_FIELD ( IP ) & & ! PRINT_FIELD ( ADDR ) ) {
pr_err ( " Display of DSO requested but neither sample IP nor "
" sample address \n is selected. Hence, no addresses to convert "
" to DSO. \n " ) ;
return - EINVAL ;
}
@ -288,6 +298,63 @@ static void print_sample_start(struct perf_sample *sample,
}
}
static bool sample_addr_correlates_sym ( struct perf_event_attr * attr )
{
if ( ( attr - > type = = PERF_TYPE_SOFTWARE ) & &
( ( attr - > config = = PERF_COUNT_SW_PAGE_FAULTS ) | |
( attr - > config = = PERF_COUNT_SW_PAGE_FAULTS_MIN ) | |
( attr - > config = = PERF_COUNT_SW_PAGE_FAULTS_MAJ ) ) )
return true ;
return false ;
}
static void print_sample_addr ( union perf_event * event ,
struct perf_sample * sample ,
struct perf_session * session ,
struct thread * thread ,
struct perf_event_attr * attr )
{
struct addr_location al ;
u8 cpumode = event - > header . misc & PERF_RECORD_MISC_CPUMODE_MASK ;
const char * symname , * dsoname ;
printf ( " %16 " PRIx64 , sample - > addr ) ;
if ( ! sample_addr_correlates_sym ( attr ) )
return ;
thread__find_addr_map ( thread , session , cpumode , MAP__FUNCTION ,
event - > ip . pid , sample - > addr , & al ) ;
if ( ! al . map )
thread__find_addr_map ( thread , session , cpumode , MAP__VARIABLE ,
event - > ip . pid , sample - > addr , & al ) ;
al . cpu = sample - > cpu ;
al . sym = NULL ;
if ( al . map )
al . sym = map__find_symbol ( al . map , al . addr , NULL ) ;
if ( PRINT_FIELD ( SYM ) ) {
if ( al . sym & & al . sym - > name )
symname = al . sym - > name ;
else
symname = " " ;
printf ( " %16s " , symname ) ;
}
if ( PRINT_FIELD ( DSO ) ) {
if ( al . map & & al . map - > dso & & al . map - > dso - > name )
dsoname = al . map - > dso - > name ;
else
dsoname = " " ;
printf ( " (%s) " , dsoname ) ;
}
}
static void process_event ( union perf_event * event __unused ,
struct perf_sample * sample ,
struct perf_evsel * evsel ,
@ -305,6 +372,9 @@ static void process_event(union perf_event *event __unused,
print_trace_event ( sample - > cpu , sample - > raw_data ,
sample - > raw_size ) ;
if ( PRINT_FIELD ( ADDR ) )
print_sample_addr ( event , sample , session , thread , attr ) ;
if ( PRINT_FIELD ( IP ) ) {
if ( ! symbol_conf . use_callchain )
printf ( " " ) ;
@ -1003,7 +1073,7 @@ static const struct option options[] = {
OPT_STRING ( 0 , " symfs " , & symbol_conf . symfs , " directory " ,
" Look for files with symbols relative to this directory " ) ,
OPT_CALLBACK ( ' f ' , " fields " , NULL , " str " ,
" comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso " ,
" comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr " ,
parse_output_fields ) ,
OPT_END ( )