mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Fix the argv ui browser code to correctly display more entries than fit on the screen without crashing. The problem was some type confusion with pointer types in the ->seek function. Do the argv arithmetic correctly with char ** pointers. Also add some asserts to find overruns and limit the display function correctly. Then finally remove a workaround for this in the res sample browser. Committer testing: 1) Resize the x terminal to have just some 5 lines 2) Use 'perf report --samples 1' to activate the sample browser options in the menu 3) Press ENTER, this will cause the crash: # perf report --samples 1 perf: Segmentation fault -------- backtrace -------- perf[0x5a514a] /lib64/libc.so.6(+0x385bf)[0x7f27281b55bf] /lib64/libc.so.6(+0x161a67)[0x7f27282dea67] /lib64/libslang.so.2(SLsmg_write_wrapped_string+0x82)[0x7f272874a0b2] perf(ui_browser__argv_refresh+0x77)[0x5939a7] perf[0x5924cc] perf(ui_browser__run+0x39)[0x593449] perf(ui__popup_menu+0x83)[0x5a5263] perf[0x59f421] perf(perf_evlist__tui_browse_hists+0x3a0)[0x5a3780] perf(cmd_report+0x2746)[0x447136] perf[0x4a95fe] perf(main+0x61c)[0x42dc6c] /lib64/libc.so.6(__libc_start_main+0xf2)[0x7f27281a1412] perf(_start+0x2d)[0x42de9d] # After applying this patch no crash takes place in such situation. Signed-off-by: Andi Kleen <ak@linux.intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Link: http://lkml.kernel.org/r/20190311144502.15423-12-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
		
			
				
	
	
		
			91 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/* Display a menu with individual samples to browse with perf script */
 | 
						|
#include "util.h"
 | 
						|
#include "hist.h"
 | 
						|
#include "evsel.h"
 | 
						|
#include "hists.h"
 | 
						|
#include "sort.h"
 | 
						|
#include "config.h"
 | 
						|
#include "time-utils.h"
 | 
						|
#include <linux/time64.h>
 | 
						|
 | 
						|
static u64 context_len = 10 * NSEC_PER_MSEC;
 | 
						|
 | 
						|
static int res_sample_config(const char *var, const char *value, void *data __maybe_unused)
 | 
						|
{
 | 
						|
	if (!strcmp(var, "samples.context"))
 | 
						|
		return perf_config_u64(&context_len, var, value);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
void res_sample_init(void)
 | 
						|
{
 | 
						|
	perf_config(res_sample_config, NULL);
 | 
						|
}
 | 
						|
 | 
						|
int res_sample_browse(struct res_sample *res_samples, int num_res,
 | 
						|
		      struct perf_evsel *evsel, enum rstype rstype)
 | 
						|
{
 | 
						|
	char **names;
 | 
						|
	int i, n;
 | 
						|
	int choice;
 | 
						|
	char *cmd;
 | 
						|
	char pbuf[256], tidbuf[32], cpubuf[32];
 | 
						|
	const char *perf = perf_exe(pbuf, sizeof pbuf);
 | 
						|
	char trange[128], tsample[64];
 | 
						|
	struct res_sample *r;
 | 
						|
	char extra_format[256];
 | 
						|
 | 
						|
	names = calloc(num_res, sizeof(char *));
 | 
						|
	if (!names)
 | 
						|
		return -1;
 | 
						|
	for (i = 0; i < num_res; i++) {
 | 
						|
		char tbuf[64];
 | 
						|
 | 
						|
		timestamp__scnprintf_nsec(res_samples[i].time, tbuf, sizeof tbuf);
 | 
						|
		if (asprintf(&names[i], "%s: CPU %d tid %d", tbuf,
 | 
						|
			     res_samples[i].cpu, res_samples[i].tid) < 0) {
 | 
						|
			while (--i >= 0)
 | 
						|
				free(names[i]);
 | 
						|
			free(names);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	choice = ui__popup_menu(num_res, names);
 | 
						|
	for (i = 0; i < num_res; i++)
 | 
						|
		free(names[i]);
 | 
						|
	free(names);
 | 
						|
 | 
						|
	if (choice < 0 || choice >= num_res)
 | 
						|
		return -1;
 | 
						|
	r = &res_samples[choice];
 | 
						|
 | 
						|
	n = timestamp__scnprintf_nsec(r->time - context_len, trange, sizeof trange);
 | 
						|
	trange[n++] = ',';
 | 
						|
	timestamp__scnprintf_nsec(r->time + context_len, trange + n, sizeof trange - n);
 | 
						|
 | 
						|
	timestamp__scnprintf_nsec(r->time, tsample, sizeof tsample);
 | 
						|
 | 
						|
	attr_to_script(extra_format, &evsel->attr);
 | 
						|
 | 
						|
	if (asprintf(&cmd, "%s script %s%s --time %s %s%s %s%s --ns %s %s %s %s %s | less +/%s",
 | 
						|
		     perf,
 | 
						|
		     input_name ? "-i " : "",
 | 
						|
		     input_name ? input_name : "",
 | 
						|
		     trange,
 | 
						|
		     r->cpu >= 0 ? "--cpu " : "",
 | 
						|
		     r->cpu >= 0 ? (sprintf(cpubuf, "%d", r->cpu), cpubuf) : "",
 | 
						|
		     r->tid ? "--tid " : "",
 | 
						|
		     r->tid ? (sprintf(tidbuf, "%d", r->tid), tidbuf) : "",
 | 
						|
		     extra_format,
 | 
						|
		     rstype == A_ASM ? "-F +insn --xed" :
 | 
						|
		     rstype == A_SOURCE ? "-F +srcline,+srccode" : "",
 | 
						|
		     symbol_conf.inline_name ? "--inline" : "",
 | 
						|
		     "--show-lost-events ",
 | 
						|
		     r->tid ? "--show-switch-events --show-task-events " : "",
 | 
						|
		     tsample) < 0)
 | 
						|
		return -1;
 | 
						|
	run_script(cmd);
 | 
						|
	free(cmd);
 | 
						|
	return 0;
 | 
						|
}
 |