perf evsel: Update sample_size when setting sample_type bits
We use evsel->sample_size to detect underflows in perf_evsel__parse_sample, but we were failing to update it after perf_evsel__init(), i.e. when we decide, after creating an evsel, that we want some extra field bit set. Fix it by introducing methods to set a bit that will take care of correctly adjusting evsel->sample_size. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-2ny5pzsing0dcth7hws48x9c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
		
							parent
							
								
									3f067dcab7
								
							
						
					
					
						commit
						7be5ebe876
					
				| @ -286,7 +286,7 @@ try_again: | ||||
| 					 */ | ||||
| 					opts->sample_id_all_missing = true; | ||||
| 					if (!opts->sample_time && !opts->raw_samples && !time_needed) | ||||
| 						attr->sample_type &= ~PERF_SAMPLE_TIME; | ||||
| 						perf_evsel__reset_sample_bit(pos, TIME); | ||||
| 
 | ||||
| 					goto retry_sample_id; | ||||
| 				} | ||||
|  | ||||
| @ -901,24 +901,25 @@ static void perf_top__start_counters(struct perf_top *top) | ||||
| 	list_for_each_entry(counter, &evlist->entries, node) { | ||||
| 		struct perf_event_attr *attr = &counter->attr; | ||||
| 
 | ||||
| 		attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; | ||||
| 		perf_evsel__set_sample_bit(counter, IP); | ||||
| 		perf_evsel__set_sample_bit(counter, TID); | ||||
| 
 | ||||
| 		if (top->freq) { | ||||
| 			attr->sample_type |= PERF_SAMPLE_PERIOD; | ||||
| 			perf_evsel__set_sample_bit(counter, PERIOD); | ||||
| 			attr->freq	  = 1; | ||||
| 			attr->sample_freq = top->freq; | ||||
| 		} | ||||
| 
 | ||||
| 		if (evlist->nr_entries > 1) { | ||||
| 			attr->sample_type |= PERF_SAMPLE_ID; | ||||
| 			perf_evsel__set_sample_bit(counter, ID); | ||||
| 			attr->read_format |= PERF_FORMAT_ID; | ||||
| 		} | ||||
| 
 | ||||
| 		if (perf_target__has_cpu(&top->target)) | ||||
| 			attr->sample_type |= PERF_SAMPLE_CPU; | ||||
| 			perf_evsel__set_sample_bit(counter, CPU); | ||||
| 
 | ||||
| 		if (symbol_conf.use_callchain) | ||||
| 			attr->sample_type |= PERF_SAMPLE_CALLCHAIN; | ||||
| 			perf_evsel__set_sample_bit(counter, CALLCHAIN); | ||||
| 
 | ||||
| 		attr->mmap = 1; | ||||
| 		attr->comm = 1; | ||||
|  | ||||
| @ -103,9 +103,9 @@ int test__PERF_RECORD(void) | ||||
| 	 * Config the evsels, setting attr->comm on the first one, etc. | ||||
| 	 */ | ||||
| 	evsel = perf_evlist__first(evlist); | ||||
| 	evsel->attr.sample_type |= PERF_SAMPLE_CPU; | ||||
| 	evsel->attr.sample_type |= PERF_SAMPLE_TID; | ||||
| 	evsel->attr.sample_type |= PERF_SAMPLE_TIME; | ||||
| 	perf_evsel__set_sample_bit(evsel, CPU); | ||||
| 	perf_evsel__set_sample_bit(evsel, TID); | ||||
| 	perf_evsel__set_sample_bit(evsel, TIME); | ||||
| 	perf_evlist__config_attrs(evlist, &opts); | ||||
| 
 | ||||
| 	err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); | ||||
|  | ||||
| @ -61,7 +61,7 @@ void perf_evlist__config_attrs(struct perf_evlist *evlist, | ||||
| 		perf_evsel__config(evsel, opts); | ||||
| 
 | ||||
| 		if (evlist->nr_entries > 1) | ||||
| 			evsel->attr.sample_type |= PERF_SAMPLE_ID; | ||||
| 			perf_evsel__set_sample_bit(evsel, ID); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -50,6 +50,24 @@ void hists__init(struct hists *hists) | ||||
| 	pthread_mutex_init(&hists->lock, NULL); | ||||
| } | ||||
| 
 | ||||
| void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, | ||||
| 				  enum perf_event_sample_format bit) | ||||
| { | ||||
| 	if (!(evsel->attr.sample_type & bit)) { | ||||
| 		evsel->attr.sample_type |= bit; | ||||
| 		evsel->sample_size += sizeof(u64); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, | ||||
| 				    enum perf_event_sample_format bit) | ||||
| { | ||||
| 	if (evsel->attr.sample_type & bit) { | ||||
| 		evsel->attr.sample_type &= ~bit; | ||||
| 		evsel->sample_size -= sizeof(u64); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void perf_evsel__init(struct perf_evsel *evsel, | ||||
| 		      struct perf_event_attr *attr, int idx) | ||||
| { | ||||
| @ -445,7 +463,8 @@ void perf_evsel__config(struct perf_evsel *evsel, | ||||
| 			      PERF_FORMAT_TOTAL_TIME_RUNNING | | ||||
| 			      PERF_FORMAT_ID; | ||||
| 
 | ||||
| 	attr->sample_type  |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; | ||||
| 	perf_evsel__set_sample_bit(evsel, IP); | ||||
| 	perf_evsel__set_sample_bit(evsel, TID); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We default some events to a 1 default interval. But keep | ||||
| @ -454,7 +473,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | ||||
| 	if (!attr->sample_period || (opts->user_freq != UINT_MAX && | ||||
| 				     opts->user_interval != ULLONG_MAX)) { | ||||
| 		if (opts->freq) { | ||||
| 			attr->sample_type	|= PERF_SAMPLE_PERIOD; | ||||
| 			perf_evsel__set_sample_bit(evsel, PERIOD); | ||||
| 			attr->freq		= 1; | ||||
| 			attr->sample_freq	= opts->freq; | ||||
| 		} else { | ||||
| @ -469,16 +488,16 @@ void perf_evsel__config(struct perf_evsel *evsel, | ||||
| 		attr->inherit_stat = 1; | ||||
| 
 | ||||
| 	if (opts->sample_address) { | ||||
| 		attr->sample_type	|= PERF_SAMPLE_ADDR; | ||||
| 		perf_evsel__set_sample_bit(evsel, ADDR); | ||||
| 		attr->mmap_data = track; | ||||
| 	} | ||||
| 
 | ||||
| 	if (opts->call_graph) { | ||||
| 		attr->sample_type	|= PERF_SAMPLE_CALLCHAIN; | ||||
| 		perf_evsel__set_sample_bit(evsel, CALLCHAIN); | ||||
| 
 | ||||
| 		if (opts->call_graph == CALLCHAIN_DWARF) { | ||||
| 			attr->sample_type |= PERF_SAMPLE_REGS_USER | | ||||
| 					     PERF_SAMPLE_STACK_USER; | ||||
| 			perf_evsel__set_sample_bit(evsel, REGS_USER); | ||||
| 			perf_evsel__set_sample_bit(evsel, STACK_USER); | ||||
| 			attr->sample_regs_user = PERF_REGS_MASK; | ||||
| 			attr->sample_stack_user = opts->stack_dump_size; | ||||
| 			attr->exclude_callchain_user = 1; | ||||
| @ -486,20 +505,20 @@ void perf_evsel__config(struct perf_evsel *evsel, | ||||
| 	} | ||||
| 
 | ||||
| 	if (perf_target__has_cpu(&opts->target)) | ||||
| 		attr->sample_type	|= PERF_SAMPLE_CPU; | ||||
| 		perf_evsel__set_sample_bit(evsel, CPU); | ||||
| 
 | ||||
| 	if (opts->period) | ||||
| 		attr->sample_type	|= PERF_SAMPLE_PERIOD; | ||||
| 		perf_evsel__set_sample_bit(evsel, PERIOD); | ||||
| 
 | ||||
| 	if (!opts->sample_id_all_missing && | ||||
| 	    (opts->sample_time || !opts->no_inherit || | ||||
| 	     perf_target__has_cpu(&opts->target))) | ||||
| 		attr->sample_type	|= PERF_SAMPLE_TIME; | ||||
| 		perf_evsel__set_sample_bit(evsel, TIME); | ||||
| 
 | ||||
| 	if (opts->raw_samples) { | ||||
| 		attr->sample_type	|= PERF_SAMPLE_TIME; | ||||
| 		attr->sample_type	|= PERF_SAMPLE_RAW; | ||||
| 		attr->sample_type	|= PERF_SAMPLE_CPU; | ||||
| 		perf_evsel__set_sample_bit(evsel, TIME); | ||||
| 		perf_evsel__set_sample_bit(evsel, RAW); | ||||
| 		perf_evsel__set_sample_bit(evsel, CPU); | ||||
| 	} | ||||
| 
 | ||||
| 	if (opts->no_delay) { | ||||
| @ -507,7 +526,7 @@ void perf_evsel__config(struct perf_evsel *evsel, | ||||
| 		attr->wakeup_events = 1; | ||||
| 	} | ||||
| 	if (opts->branch_stack) { | ||||
| 		attr->sample_type	|= PERF_SAMPLE_BRANCH_STACK; | ||||
| 		perf_evsel__set_sample_bit(evsel, BRANCH_STACK); | ||||
| 		attr->branch_sample_type = opts->branch_stack; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -118,6 +118,17 @@ void perf_evsel__free_fd(struct perf_evsel *evsel); | ||||
| void perf_evsel__free_id(struct perf_evsel *evsel); | ||||
| void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | ||||
| 
 | ||||
| void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, | ||||
| 				  enum perf_event_sample_format bit); | ||||
| void __perf_evsel__reset_sample_bit(struct perf_evsel *evsel, | ||||
| 				    enum perf_event_sample_format bit); | ||||
| 
 | ||||
| #define perf_evsel__set_sample_bit(evsel, bit) \ | ||||
| 	__perf_evsel__set_sample_bit(evsel, PERF_SAMPLE_##bit) | ||||
| 
 | ||||
| #define perf_evsel__reset_sample_bit(evsel, bit) \ | ||||
| 	__perf_evsel__reset_sample_bit(evsel, PERF_SAMPLE_##bit) | ||||
| 
 | ||||
| int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, | ||||
| 			   const char *filter); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user