diff options
Diffstat (limited to 'tools/perf/util/event.c')
| -rw-r--r-- | tools/perf/util/event.c | 302 | 
1 files changed, 58 insertions, 244 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 6715b1938725..3cf2c3e0605f 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -1,6 +1,7 @@  #include <linux/types.h>  #include "event.h"  #include "debug.h" +#include "machine.h"  #include "sort.h"  #include "string.h"  #include "strlist.h" @@ -192,55 +193,43 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,  	event->header.misc = PERF_RECORD_MISC_USER;  	while (1) { -		char bf[BUFSIZ], *pbf = bf; -		int n; +		char bf[BUFSIZ]; +		char prot[5]; +		char execname[PATH_MAX]; +		char anonstr[] = "//anon";  		size_t size; +  		if (fgets(bf, sizeof(bf), fp) == NULL)  			break; +		/* ensure null termination since stack will be reused. */ +		strcpy(execname, ""); +  		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */ -		n = hex2u64(pbf, &event->mmap.start); -		if (n < 0) -			continue; -		pbf += n + 1; -		n = hex2u64(pbf, &event->mmap.len); -		if (n < 0) +		sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n", +		       &event->mmap.start, &event->mmap.len, prot, +		       &event->mmap.pgoff, execname); + +		if (prot[2] != 'x')  			continue; -		pbf += n + 3; -		if (*pbf == 'x') { /* vm_exec */ -			char anonstr[] = "//anon\n"; -			char *execname = strchr(bf, '/'); - -			/* Catch VDSO */ -			if (execname == NULL) -				execname = strstr(bf, "[vdso]"); - -			/* Catch anonymous mmaps */ -			if ((execname == NULL) && !strstr(bf, "[")) -				execname = anonstr; - -			if (execname == NULL) -				continue; - -			pbf += 3; -			n = hex2u64(pbf, &event->mmap.pgoff); - -			size = strlen(execname); -			execname[size - 1] = '\0'; /* Remove \n */ -			memcpy(event->mmap.filename, execname, size); -			size = PERF_ALIGN(size, sizeof(u64)); -			event->mmap.len -= event->mmap.start; -			event->mmap.header.size = (sizeof(event->mmap) - -					        (sizeof(event->mmap.filename) - size)); -			memset(event->mmap.filename + size, 0, machine->id_hdr_size); -			event->mmap.header.size += machine->id_hdr_size; -			event->mmap.pid = tgid; -			event->mmap.tid = pid; - -			if (process(tool, event, &synth_sample, machine) != 0) { -				rc = -1; -				break; -			} + +		if (!strcmp(execname, "")) +			strcpy(execname, anonstr); + +		size = strlen(execname) + 1; +		memcpy(event->mmap.filename, execname, size); +		size = PERF_ALIGN(size, sizeof(u64)); +		event->mmap.len -= event->mmap.start; +		event->mmap.header.size = (sizeof(event->mmap) - +					   (sizeof(event->mmap.filename) - size)); +		memset(event->mmap.filename + size, 0, machine->id_hdr_size); +		event->mmap.header.size += machine->id_hdr_size; +		event->mmap.pid = tgid; +		event->mmap.tid = pid; + +		if (process(tool, event, &synth_sample, machine) != 0) { +			rc = -1; +			break;  		}  	} @@ -404,16 +393,15 @@ int perf_event__synthesize_threads(struct perf_tool *tool,  		if (*end) /* only interested in proper numerical dirents */  			continue; - -		if (__event__synthesize_thread(comm_event, mmap_event, pid, 1, -					   process, tool, machine) != 0) { -			err = -1; -			goto out_closedir; -		} +		/* + 		 * We may race with exiting thread, so don't stop just because + 		 * one thread couldn't be synthesized. + 		 */ +		__event__synthesize_thread(comm_event, mmap_event, pid, 1, +					   process, tool, machine);  	}  	err = 0; -out_closedir:  	closedir(proc);  out_free_mmap:  	free(mmap_event); @@ -519,134 +507,15 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,  			     struct perf_sample *sample __maybe_unused,  			     struct machine *machine)  { -	struct thread *thread = machine__findnew_thread(machine, event->comm.tid); - -	if (dump_trace) -		perf_event__fprintf_comm(event, stdout); - -	if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { -		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); -		return -1; -	} - -	return 0; +	return machine__process_comm_event(machine, event);  }  int perf_event__process_lost(struct perf_tool *tool __maybe_unused,  			     union perf_event *event,  			     struct perf_sample *sample __maybe_unused, -			     struct machine *machine __maybe_unused) -{ -	dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", -		    event->lost.id, event->lost.lost); -	return 0; -} - -static void perf_event__set_kernel_mmap_len(union perf_event *event, -					    struct map **maps) -{ -	maps[MAP__FUNCTION]->start = event->mmap.start; -	maps[MAP__FUNCTION]->end   = event->mmap.start + event->mmap.len; -	/* -	 * Be a bit paranoid here, some perf.data file came with -	 * a zero sized synthesized MMAP event for the kernel. -	 */ -	if (maps[MAP__FUNCTION]->end == 0) -		maps[MAP__FUNCTION]->end = ~0ULL; -} - -static int perf_event__process_kernel_mmap(struct perf_tool *tool -					   __maybe_unused, -					   union perf_event *event, -					   struct machine *machine) +			     struct machine *machine)  { -	struct map *map; -	char kmmap_prefix[PATH_MAX]; -	enum dso_kernel_type kernel_type; -	bool is_kernel_mmap; - -	machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); -	if (machine__is_host(machine)) -		kernel_type = DSO_TYPE_KERNEL; -	else -		kernel_type = DSO_TYPE_GUEST_KERNEL; - -	is_kernel_mmap = memcmp(event->mmap.filename, -				kmmap_prefix, -				strlen(kmmap_prefix) - 1) == 0; -	if (event->mmap.filename[0] == '/' || -	    (!is_kernel_mmap && event->mmap.filename[0] == '[')) { - -		char short_module_name[1024]; -		char *name, *dot; - -		if (event->mmap.filename[0] == '/') { -			name = strrchr(event->mmap.filename, '/'); -			if (name == NULL) -				goto out_problem; - -			++name; /* skip / */ -			dot = strrchr(name, '.'); -			if (dot == NULL) -				goto out_problem; -			snprintf(short_module_name, sizeof(short_module_name), -					"[%.*s]", (int)(dot - name), name); -			strxfrchar(short_module_name, '-', '_'); -		} else -			strcpy(short_module_name, event->mmap.filename); - -		map = machine__new_module(machine, event->mmap.start, -					  event->mmap.filename); -		if (map == NULL) -			goto out_problem; - -		name = strdup(short_module_name); -		if (name == NULL) -			goto out_problem; - -		map->dso->short_name = name; -		map->dso->sname_alloc = 1; -		map->end = map->start + event->mmap.len; -	} else if (is_kernel_mmap) { -		const char *symbol_name = (event->mmap.filename + -				strlen(kmmap_prefix)); -		/* -		 * Should be there already, from the build-id table in -		 * the header. -		 */ -		struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, -						     kmmap_prefix); -		if (kernel == NULL) -			goto out_problem; - -		kernel->kernel = kernel_type; -		if (__machine__create_kernel_maps(machine, kernel) < 0) -			goto out_problem; - -		perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); - -		/* -		 * Avoid using a zero address (kptr_restrict) for the ref reloc -		 * symbol. Effectively having zero here means that at record -		 * time /proc/sys/kernel/kptr_restrict was non zero. -		 */ -		if (event->mmap.pgoff != 0) { -			maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, -							 symbol_name, -							 event->mmap.pgoff); -		} - -		if (machine__is_default_guest(machine)) { -			/* -			 * preload dso of guest kernel and modules -			 */ -			dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], -				  NULL); -		} -	} -	return 0; -out_problem: -	return -1; +	return machine__process_lost_event(machine, event);  }  size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) @@ -656,43 +525,12 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)  		       event->mmap.len, event->mmap.pgoff, event->mmap.filename);  } -int perf_event__process_mmap(struct perf_tool *tool, +int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,  			     union perf_event *event,  			     struct perf_sample *sample __maybe_unused,  			     struct machine *machine)  { -	struct thread *thread; -	struct map *map; -	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; -	int ret = 0; - -	if (dump_trace) -		perf_event__fprintf_mmap(event, stdout); - -	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || -	    cpumode == PERF_RECORD_MISC_KERNEL) { -		ret = perf_event__process_kernel_mmap(tool, event, machine); -		if (ret < 0) -			goto out_problem; -		return 0; -	} - -	thread = machine__findnew_thread(machine, event->mmap.pid); -	if (thread == NULL) -		goto out_problem; -	map = map__new(&machine->user_dsos, event->mmap.start, -			event->mmap.len, event->mmap.pgoff, -			event->mmap.pid, event->mmap.filename, -			MAP__FUNCTION); -	if (map == NULL) -		goto out_problem; - -	thread__insert_map(thread, map); -	return 0; - -out_problem: -	dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); -	return 0; +	return machine__process_mmap_event(machine, event);  }  size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) @@ -702,29 +540,20 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)  		       event->fork.ppid, event->fork.ptid);  } -int perf_event__process_task(struct perf_tool *tool __maybe_unused, +int perf_event__process_fork(struct perf_tool *tool __maybe_unused,  			     union perf_event *event,  			     struct perf_sample *sample __maybe_unused, -			      struct machine *machine) +			     struct machine *machine)  { -	struct thread *thread = machine__findnew_thread(machine, event->fork.tid); -	struct thread *parent = machine__findnew_thread(machine, event->fork.ptid); - -	if (dump_trace) -		perf_event__fprintf_task(event, stdout); - -	if (event->header.type == PERF_RECORD_EXIT) { -		machine__remove_thread(machine, thread); -		return 0; -	} - -	if (thread == NULL || parent == NULL || -	    thread__fork(thread, parent) < 0) { -		dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); -		return -1; -	} +	return machine__process_fork_event(machine, event); +} -	return 0; +int perf_event__process_exit(struct perf_tool *tool __maybe_unused, +			     union perf_event *event, +			     struct perf_sample *sample __maybe_unused, +			     struct machine *machine) +{ +	return machine__process_exit_event(machine, event);  }  size_t perf_event__fprintf(union perf_event *event, FILE *fp) @@ -750,27 +579,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)  	return ret;  } -int perf_event__process(struct perf_tool *tool, union perf_event *event, -			struct perf_sample *sample, struct machine *machine) +int perf_event__process(struct perf_tool *tool __maybe_unused, +			union perf_event *event, +			struct perf_sample *sample __maybe_unused, +			struct machine *machine)  { -	switch (event->header.type) { -	case PERF_RECORD_COMM: -		perf_event__process_comm(tool, event, sample, machine); -		break; -	case PERF_RECORD_MMAP: -		perf_event__process_mmap(tool, event, sample, machine); -		break; -	case PERF_RECORD_FORK: -	case PERF_RECORD_EXIT: -		perf_event__process_task(tool, event, sample, machine); -		break; -	case PERF_RECORD_LOST: -		perf_event__process_lost(tool, event, sample, machine); -	default: -		break; -	} - -	return 0; +	return machine__process_event(machine, event);  }  void thread__find_addr_map(struct thread *self,  | 
