diff options
Diffstat (limited to 'tools/perf/util/annotate.c')
| -rw-r--r-- | tools/perf/util/annotate.c | 194 | 
1 files changed, 75 insertions, 119 deletions
| diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index ca73fb74ad03..0ea95be84b3b 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1143,93 +1143,70 @@ out:  }  struct annotate_args { -	size_t			 privsize; -	struct arch		*arch; -	struct map_symbol	 ms; -	struct evsel	*evsel; +	struct arch		  *arch; +	struct map_symbol	  ms; +	struct evsel		  *evsel;  	struct annotation_options *options; -	s64			 offset; -	char			*line; -	int			 line_nr; +	s64			  offset; +	char			  *line; +	int			  line_nr;  }; -static void annotation_line__delete(struct annotation_line *al) +static void annotation_line__init(struct annotation_line *al, +				  struct annotate_args *args, +				  int nr)  { -	void *ptr = (void *) al - al->privsize; +	al->offset = args->offset; +	al->line = strdup(args->line); +	al->line_nr = args->line_nr; +	al->data_nr = nr; +} +static void annotation_line__exit(struct annotation_line *al) +{  	free_srcline(al->path);  	zfree(&al->line); -	free(ptr);  } -/* - * Allocating the annotation line data with following - * structure: - * - *    -------------------------------------- - *    private space | struct annotation_line - *    -------------------------------------- - * - * Size of the private space is stored in 'struct annotation_line'. - * - */ -static struct annotation_line * -annotation_line__new(struct annotate_args *args, size_t privsize) +static size_t disasm_line_size(int nr)  {  	struct annotation_line *al; -	struct evsel *evsel = args->evsel; -	size_t size = privsize + sizeof(*al); -	int nr = 1; - -	if (perf_evsel__is_group_event(evsel)) -		nr = evsel->core.nr_members; -	size += sizeof(al->data[0]) * nr; - -	al = zalloc(size); -	if (al) { -		al = (void *) al + privsize; -		al->privsize   = privsize; -		al->offset     = args->offset; -		al->line       = strdup(args->line); -		al->line_nr    = args->line_nr; -		al->data_nr    = nr; -	} - -	return al; +	return (sizeof(struct disasm_line) + (sizeof(al->data[0]) * nr));  }  /*   * Allocating the disasm annotation line data with   * following structure:   * - *    ------------------------------------------------------------ - *    privsize space | struct disasm_line | struct annotation_line - *    ------------------------------------------------------------ + *    ------------------------------------------- + *    struct disasm_line | struct annotation_line + *    -------------------------------------------   *   * We have 'struct annotation_line' member as last member   * of 'struct disasm_line' to have an easy access. - *   */  static struct disasm_line *disasm_line__new(struct annotate_args *args)  {  	struct disasm_line *dl = NULL; -	struct annotation_line *al; -	size_t privsize = args->privsize + offsetof(struct disasm_line, al); +	int nr = 1; -	al = annotation_line__new(args, privsize); -	if (al != NULL) { -		dl = disasm_line(al); +	if (perf_evsel__is_group_event(args->evsel)) +		nr = args->evsel->core.nr_members; -		if (dl->al.line == NULL) -			goto out_delete; +	dl = zalloc(disasm_line_size(nr)); +	if (!dl) +		return NULL; -		if (args->offset != -1) { -			if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0) -				goto out_free_line; +	annotation_line__init(&dl->al, args, nr); +	if (dl->al.line == NULL) +		goto out_delete; -			disasm_line__init_ins(dl, args->arch, &args->ms); -		} +	if (args->offset != -1) { +		if (disasm_line__parse(dl->al.line, &dl->ins.name, &dl->ops.raw) < 0) +			goto out_free_line; + +		disasm_line__init_ins(dl, args->arch, &args->ms);  	}  	return dl; @@ -1248,7 +1225,8 @@ void disasm_line__free(struct disasm_line *dl)  	else  		ins__delete(&dl->ops);  	zfree(&dl->ins.name); -	annotation_line__delete(&dl->al); +	annotation_line__exit(&dl->al); +	free(dl);  }  int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw, int max_ins_name) @@ -2149,13 +2127,12 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel)  	annotation__calc_percent(notes, evsel, symbol__size(sym));  } -int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, size_t privsize, +int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,  		     struct annotation_options *options, struct arch **parch)  {  	struct symbol *sym = ms->sym;  	struct annotation *notes = symbol__annotation(sym);  	struct annotate_args args = { -		.privsize	= privsize,  		.evsel		= evsel,  		.options	= options,  	}; @@ -2644,6 +2621,8 @@ void annotation__set_offsets(struct annotation *notes, s64 size)  	struct annotation_line *al;  	notes->max_line_len = 0; +	notes->nr_entries = 0; +	notes->nr_asm_entries = 0;  	list_for_each_entry(al, ¬es->src->source, node) {  		size_t line_len = strlen(al->line); @@ -2790,7 +2769,7 @@ int symbol__tty_annotate(struct map_symbol *ms, struct evsel *evsel,  	struct symbol *sym = ms->sym;  	struct rb_root source_line = RB_ROOT; -	if (symbol__annotate(ms, evsel, 0, opts, NULL) < 0) +	if (symbol__annotate(ms, evsel, opts, NULL) < 0)  		return -1;  	symbol__calc_percent(sym, evsel); @@ -2915,9 +2894,9 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati  			percent = annotation_data__percent(&al->data[i], percent_type);  			obj__set_percent_color(obj, percent, current_entry); -			if (notes->options->show_total_period) { +			if (symbol_conf.show_total_period) {  				obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period); -			} else if (notes->options->show_nr_samples) { +			} else if (symbol_conf.show_nr_samples) {  				obj__printf(obj, "%6" PRIu64 " ",  						   al->data[i].he.nr_samples);  			} else { @@ -2931,8 +2910,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati  			obj__printf(obj, "%-*s", pcnt_width, " ");  		else {  			obj__printf(obj, "%-*s", pcnt_width, -					   notes->options->show_total_period ? "Period" : -					   notes->options->show_nr_samples ? "Samples" : "Percent"); +					   symbol_conf.show_total_period ? "Period" : +					   symbol_conf.show_nr_samples ? "Samples" : "Percent");  		}  	} @@ -3070,7 +3049,7 @@ int symbol__annotate2(struct map_symbol *ms, struct evsel *evsel,  	if (perf_evsel__is_group_event(evsel))  		nr_pcnt = evsel->core.nr_members; -	err = symbol__annotate(ms, evsel, 0, options, parch); +	err = symbol__annotate(ms, evsel, options, parch);  	if (err)  		goto out_free_offsets; @@ -3094,69 +3073,46 @@ out_free_offsets:  	return err;  } -#define ANNOTATION__CFG(n) \ -	{ .name = #n, .value = &annotation__default_options.n, } - -/* - * Keep the entries sorted, they are bsearch'ed - */ -static struct annotation_config { -	const char *name; -	void *value; -} annotation__configs[] = { -	ANNOTATION__CFG(hide_src_code), -	ANNOTATION__CFG(jump_arrows), -	ANNOTATION__CFG(offset_level), -	ANNOTATION__CFG(show_linenr), -	ANNOTATION__CFG(show_nr_jumps), -	ANNOTATION__CFG(show_nr_samples), -	ANNOTATION__CFG(show_total_period), -	ANNOTATION__CFG(use_offset), -}; - -#undef ANNOTATION__CFG - -static int annotation_config__cmp(const void *name, const void *cfgp) -{ -	const struct annotation_config *cfg = cfgp; - -	return strcmp(name, cfg->name); -} - -static int annotation__config(const char *var, const char *value, -			    void *data __maybe_unused) +static int annotation__config(const char *var, const char *value, void *data)  { -	struct annotation_config *cfg; -	const char *name; +	struct annotation_options *opt = data;  	if (!strstarts(var, "annotate."))  		return 0; -	name = var + 9; -	cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs), -		      sizeof(struct annotation_config), annotation_config__cmp); - -	if (cfg == NULL) -		pr_debug("%s variable unknown, ignoring...", var); -	else if (strcmp(var, "annotate.offset_level") == 0) { -		perf_config_int(cfg->value, name, value); - -		if (*(int *)cfg->value > ANNOTATION__MAX_OFFSET_LEVEL) -			*(int *)cfg->value = ANNOTATION__MAX_OFFSET_LEVEL; -		else if (*(int *)cfg->value < ANNOTATION__MIN_OFFSET_LEVEL) -			*(int *)cfg->value = ANNOTATION__MIN_OFFSET_LEVEL; +	if (!strcmp(var, "annotate.offset_level")) { +		perf_config_u8(&opt->offset_level, "offset_level", value); + +		if (opt->offset_level > ANNOTATION__MAX_OFFSET_LEVEL) +			opt->offset_level = ANNOTATION__MAX_OFFSET_LEVEL; +		else if (opt->offset_level < ANNOTATION__MIN_OFFSET_LEVEL) +			opt->offset_level = ANNOTATION__MIN_OFFSET_LEVEL; +	} else if (!strcmp(var, "annotate.hide_src_code")) { +		opt->hide_src_code = perf_config_bool("hide_src_code", value); +	} else if (!strcmp(var, "annotate.jump_arrows")) { +		opt->jump_arrows = perf_config_bool("jump_arrows", value); +	} else if (!strcmp(var, "annotate.show_linenr")) { +		opt->show_linenr = perf_config_bool("show_linenr", value); +	} else if (!strcmp(var, "annotate.show_nr_jumps")) { +		opt->show_nr_jumps = perf_config_bool("show_nr_jumps", value); +	} else if (!strcmp(var, "annotate.show_nr_samples")) { +		symbol_conf.show_nr_samples = perf_config_bool("show_nr_samples", +								value); +	} else if (!strcmp(var, "annotate.show_total_period")) { +		symbol_conf.show_total_period = perf_config_bool("show_total_period", +								value); +	} else if (!strcmp(var, "annotate.use_offset")) { +		opt->use_offset = perf_config_bool("use_offset", value);  	} else { -		*(bool *)cfg->value = perf_config_bool(name, value); +		pr_debug("%s variable unknown, ignoring...", var);  	} +  	return 0;  } -void annotation_config__init(void) +void annotation_config__init(struct annotation_options *opt)  { -	perf_config(annotation__config, NULL); - -	annotation__default_options.show_total_period = symbol_conf.show_total_period; -	annotation__default_options.show_nr_samples   = symbol_conf.show_nr_samples; +	perf_config(annotation__config, opt);  }  static unsigned int parse_percent_type(char *str1, char *str2) |