2015-05-27 10:51:51 -07:00
# include "perf.h"
# include "util/util.h"
# include "util/debug.h"
# include "util/parse-options.h"
# include "util/parse-branch-options.h"
# define BRANCH_OPT(n, m) \
{ . name = n , . mode = ( m ) }
# define BRANCH_END { .name = NULL }
struct branch_mode {
const char * name ;
int mode ;
} ;
static const struct branch_mode branch_modes [ ] = {
BRANCH_OPT ( " u " , PERF_SAMPLE_BRANCH_USER ) ,
BRANCH_OPT ( " k " , PERF_SAMPLE_BRANCH_KERNEL ) ,
BRANCH_OPT ( " hv " , PERF_SAMPLE_BRANCH_HV ) ,
BRANCH_OPT ( " any " , PERF_SAMPLE_BRANCH_ANY ) ,
BRANCH_OPT ( " any_call " , PERF_SAMPLE_BRANCH_ANY_CALL ) ,
BRANCH_OPT ( " any_ret " , PERF_SAMPLE_BRANCH_ANY_RETURN ) ,
BRANCH_OPT ( " ind_call " , PERF_SAMPLE_BRANCH_IND_CALL ) ,
BRANCH_OPT ( " abort_tx " , PERF_SAMPLE_BRANCH_ABORT_TX ) ,
BRANCH_OPT ( " in_tx " , PERF_SAMPLE_BRANCH_IN_TX ) ,
BRANCH_OPT ( " no_tx " , PERF_SAMPLE_BRANCH_NO_TX ) ,
BRANCH_OPT ( " cond " , PERF_SAMPLE_BRANCH_COND ) ,
2015-05-14 23:10:00 +02:00
BRANCH_OPT ( " ind_jmp " , PERF_SAMPLE_BRANCH_IND_JUMP ) ,
2015-05-27 10:51:51 -07:00
BRANCH_END
} ;
int
parse_branch_stack ( const struct option * opt , const char * str , int unset )
{
# define ONLY_PLM \
( PERF_SAMPLE_BRANCH_USER | \
PERF_SAMPLE_BRANCH_KERNEL | \
PERF_SAMPLE_BRANCH_HV )
uint64_t * mode = ( uint64_t * ) opt - > value ;
const struct branch_mode * br ;
char * s , * os = NULL , * p ;
int ret = - 1 ;
if ( unset )
return 0 ;
/*
* cannot set it twice , - b + - - branch - filter for instance
*/
if ( * mode )
return - 1 ;
/* str may be NULL in case no arg is passed to -b */
if ( str ) {
/* because str is read-only */
s = os = strdup ( str ) ;
if ( ! s )
return - 1 ;
for ( ; ; ) {
p = strchr ( s , ' , ' ) ;
if ( p )
* p = ' \0 ' ;
for ( br = branch_modes ; br - > name ; br + + ) {
if ( ! strcasecmp ( s , br - > name ) )
break ;
}
if ( ! br - > name ) {
ui__warning ( " unknown branch filter %s, "
" check man page \n " , s ) ;
goto error ;
}
* mode | = br - > mode ;
if ( ! p )
break ;
s = p + 1 ;
}
}
ret = 0 ;
/* default to any branch */
if ( ( * mode & ~ ONLY_PLM ) = = 0 ) {
* mode = PERF_SAMPLE_BRANCH_ANY ;
}
error :
free ( os ) ;
return ret ;
}