event.c 24.4 KB
Newer Older
1
#include <linux/types.h>
2
#include <sys/mman.h>
3 4
#include "event.h"
#include "debug.h"
5
#include "hist.h"
6
#include "machine.h"
7
#include "sort.h"
8
#include "string.h"
9
#include "strlist.h"
10
#include "thread.h"
11
#include "thread_map.h"
12
#include "symbol/kallsyms.h"
13

14
static const char *perf_event__names[] = {
15 16
	[0]					= "TOTAL",
	[PERF_RECORD_MMAP]			= "MMAP",
17
	[PERF_RECORD_MMAP2]			= "MMAP2",
18 19 20 21 22 23 24 25 26 27 28 29 30
	[PERF_RECORD_LOST]			= "LOST",
	[PERF_RECORD_COMM]			= "COMM",
	[PERF_RECORD_EXIT]			= "EXIT",
	[PERF_RECORD_THROTTLE]			= "THROTTLE",
	[PERF_RECORD_UNTHROTTLE]		= "UNTHROTTLE",
	[PERF_RECORD_FORK]			= "FORK",
	[PERF_RECORD_READ]			= "READ",
	[PERF_RECORD_SAMPLE]			= "SAMPLE",
	[PERF_RECORD_HEADER_ATTR]		= "ATTR",
	[PERF_RECORD_HEADER_EVENT_TYPE]		= "EVENT_TYPE",
	[PERF_RECORD_HEADER_TRACING_DATA]	= "TRACING_DATA",
	[PERF_RECORD_HEADER_BUILD_ID]		= "BUILD_ID",
	[PERF_RECORD_FINISHED_ROUND]		= "FINISHED_ROUND",
A
Adrian Hunter 已提交
31
	[PERF_RECORD_ID_INDEX]			= "ID_INDEX",
32 33
};

34
const char *perf_event__name(unsigned int id)
35
{
36
	if (id >= ARRAY_SIZE(perf_event__names))
37
		return "INVALID";
38
	if (!perf_event__names[id])
39
		return "UNKNOWN";
40
	return perf_event__names[id];
41 42
}

43
static struct perf_sample synth_sample = {
44 45 46 47 48 49 50 51
	.pid	   = -1,
	.tid	   = -1,
	.time	   = -1,
	.stream_id = -1,
	.cpu	   = -1,
	.period	   = 1,
};

52 53
/*
 * Assumes that the first 4095 bytes of /proc/pid/stat contains
54
 * the comm, tgid and ppid.
55
 */
56 57
static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
				    pid_t *tgid, pid_t *ppid)
58 59
{
	char filename[PATH_MAX];
60 61 62
	char bf[4096];
	int fd;
	size_t size = 0, n;
63 64 65 66
	char *nl, *name, *tgids, *ppids;

	*tgid = -1;
	*ppid = -1;
67 68 69

	snprintf(filename, sizeof(filename), "/proc/%d/status", pid);

70 71
	fd = open(filename, O_RDONLY);
	if (fd < 0) {
72
		pr_debug("couldn't open %s\n", filename);
73
		return -1;
74 75
	}

76 77 78
	n = read(fd, bf, sizeof(bf) - 1);
	close(fd);
	if (n <= 0) {
79
		pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
80 81
			   pid);
		return -1;
82
	}
83
	bf[n] = '\0';
84

85 86
	name = strstr(bf, "Name:");
	tgids = strstr(bf, "Tgid:");
87
	ppids = strstr(bf, "PPid:");
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

	if (name) {
		name += 5;  /* strlen("Name:") */

		while (*name && isspace(*name))
			++name;

		nl = strchr(name, '\n');
		if (nl)
			*nl = '\0';

		size = strlen(name);
		if (size >= len)
			size = len - 1;
		memcpy(comm, name, size);
		comm[size] = '\0';
	} else {
		pr_debug("Name: string not found for pid %d\n", pid);
	}

	if (tgids) {
		tgids += 5;  /* strlen("Tgid:") */
110
		*tgid = atoi(tgids);
111 112 113
	} else {
		pr_debug("Tgid: string not found for pid %d\n", pid);
	}
114

115 116 117 118 119 120 121 122
	if (ppids) {
		ppids += 5;  /* strlen("PPid:") */
		*ppid = atoi(ppids);
	} else {
		pr_debug("PPid: string not found for pid %d\n", pid);
	}

	return 0;
123 124
}

125 126 127
static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
				    struct machine *machine,
				    pid_t *tgid, pid_t *ppid)
128 129
{
	size_t size;
130 131

	*ppid = -1;
132 133 134

	memset(&event->comm, 0, sizeof(event->comm));

135 136 137 138 139 140 141 142 143
	if (machine__is_host(machine)) {
		if (perf_event__get_comm_ids(pid, event->comm.comm,
					     sizeof(event->comm.comm),
					     tgid, ppid) != 0) {
			return -1;
		}
	} else {
		*tgid = machine->pid;
	}
144

145 146
	if (*tgid < 0)
		return -1;
147

148
	event->comm.pid = *tgid;
149
	event->comm.header.type = PERF_RECORD_COMM;
150 151

	size = strlen(event->comm.comm) + 1;
152
	size = PERF_ALIGN(size, sizeof(u64));
153
	memset(event->comm.comm + size, 0, machine->id_hdr_size);
154 155
	event->comm.header.size = (sizeof(event->comm) -
				(sizeof(event->comm.comm) - size) +
156
				machine->id_hdr_size);
157
	event->comm.tid = pid;
158 159

	return 0;
160 161 162 163 164 165 166
}

static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
					 union perf_event *event, pid_t pid,
					 perf_event__handler_t process,
					 struct machine *machine)
{
167
	pid_t tgid, ppid;
168

169 170
	if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
		return -1;
171

172 173
	if (process(tool, event, &synth_sample, machine) != 0)
		return -1;
174

175
	return tgid;
176 177
}

178
static int perf_event__synthesize_fork(struct perf_tool *tool,
179 180 181
				       union perf_event *event,
				       pid_t pid, pid_t tgid, pid_t ppid,
				       perf_event__handler_t process,
182 183 184 185
				       struct machine *machine)
{
	memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);

186 187 188 189 190 191 192 193 194 195 196 197
	/*
	 * for main thread set parent to ppid from status file. For other
	 * threads set parent pid to main thread. ie., assume main thread
	 * spawns all threads in a process
	*/
	if (tgid == pid) {
		event->fork.ppid = ppid;
		event->fork.ptid = ppid;
	} else {
		event->fork.ppid = tgid;
		event->fork.ptid = tgid;
	}
198 199 200 201 202 203 204 205 206 207 208 209
	event->fork.pid  = tgid;
	event->fork.tid  = pid;
	event->fork.header.type = PERF_RECORD_FORK;

	event->fork.header.size = (sizeof(event->fork) + machine->id_hdr_size);

	if (process(tool, event, &synth_sample, machine) != 0)
		return -1;

	return 0;
}

210 211 212 213 214 215
int perf_event__synthesize_mmap_events(struct perf_tool *tool,
				       union perf_event *event,
				       pid_t pid, pid_t tgid,
				       perf_event__handler_t process,
				       struct machine *machine,
				       bool mmap_data)
216 217 218
{
	char filename[PATH_MAX];
	FILE *fp;
219
	int rc = 0;
220

221 222 223
	if (machine__is_default_guest(machine))
		return 0;

224 225
	snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
		 machine->root_dir, pid);
226 227 228 229 230 231 232 233 234 235

	fp = fopen(filename, "r");
	if (fp == NULL) {
		/*
		 * We raced with a task exiting - just return:
		 */
		pr_debug("couldn't open %s\n", filename);
		return -1;
	}

236
	event->header.type = PERF_RECORD_MMAP2;
237

238
	while (1) {
239 240 241 242
		char bf[BUFSIZ];
		char prot[5];
		char execname[PATH_MAX];
		char anonstr[] = "//anon";
243
		unsigned int ino;
244
		size_t size;
245
		ssize_t n;
246

247 248 249
		if (fgets(bf, sizeof(bf), fp) == NULL)
			break;

250 251 252
		/* ensure null termination since stack will be reused. */
		strcpy(execname, "");

253
		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
254 255 256 257 258 259
		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n",
		       &event->mmap2.start, &event->mmap2.len, prot,
		       &event->mmap2.pgoff, &event->mmap2.maj,
		       &event->mmap2.min,
		       &ino, execname);

260 261 262
		/*
 		 * Anon maps don't have the execname.
 		 */
263
		if (n < 7)
264
			continue;
265 266 267

		event->mmap2.ino = (u64)ino;

268 269 270
		/*
		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
		 */
271 272 273 274
		if (machine__is_host(machine))
			event->header.misc = PERF_RECORD_MISC_USER;
		else
			event->header.misc = PERF_RECORD_MISC_GUEST_USER;
275

276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
		/* map protection and flags bits */
		event->mmap2.prot = 0;
		event->mmap2.flags = 0;
		if (prot[0] == 'r')
			event->mmap2.prot |= PROT_READ;
		if (prot[1] == 'w')
			event->mmap2.prot |= PROT_WRITE;
		if (prot[2] == 'x')
			event->mmap2.prot |= PROT_EXEC;

		if (prot[3] == 's')
			event->mmap2.flags |= MAP_SHARED;
		else
			event->mmap2.flags |= MAP_PRIVATE;

291 292 293 294 295 296
		if (prot[2] != 'x') {
			if (!mmap_data || prot[0] != 'r')
				continue;

			event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
		}
297 298 299 300 301

		if (!strcmp(execname, ""))
			strcpy(execname, anonstr);

		size = strlen(execname) + 1;
302
		memcpy(event->mmap2.filename, execname, size);
303
		size = PERF_ALIGN(size, sizeof(u64));
304 305 306 307 308 309 310
		event->mmap2.len -= event->mmap.start;
		event->mmap2.header.size = (sizeof(event->mmap2) -
					(sizeof(event->mmap2.filename) - size));
		memset(event->mmap2.filename + size, 0, machine->id_hdr_size);
		event->mmap2.header.size += machine->id_hdr_size;
		event->mmap2.pid = tgid;
		event->mmap2.tid = pid;
311 312 313 314

		if (process(tool, event, &synth_sample, machine) != 0) {
			rc = -1;
			break;
315 316 317 318
		}
	}

	fclose(fp);
319
	return rc;
320 321
}

322
int perf_event__synthesize_modules(struct perf_tool *tool,
323
				   perf_event__handler_t process,
324
				   struct machine *machine)
325
{
326
	int rc = 0;
327
	struct rb_node *nd;
328
	struct map_groups *kmaps = &machine->kmaps;
329
	union perf_event *event = zalloc((sizeof(event->mmap) +
330
					  machine->id_hdr_size));
331 332 333 334 335 336 337
	if (event == NULL) {
		pr_debug("Not enough memory synthesizing mmap event "
			 "for kernel modules\n");
		return -1;
	}

	event->header.type = PERF_RECORD_MMAP;
338

339 340 341 342
	/*
	 * kernel uses 0 for user space maps, see kernel/perf_event.c
	 * __perf_event_mmap
	 */
343
	if (machine__is_host(machine))
344
		event->header.misc = PERF_RECORD_MISC_KERNEL;
345
	else
346
		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
347 348

	for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
349 350 351 352 353 354 355
	     nd; nd = rb_next(nd)) {
		size_t size;
		struct map *pos = rb_entry(nd, struct map, rb_node);

		if (pos->dso->kernel)
			continue;

356
		size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
357 358 359
		event->mmap.header.type = PERF_RECORD_MMAP;
		event->mmap.header.size = (sizeof(event->mmap) -
				        (sizeof(event->mmap.filename) - size));
360 361
		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
		event->mmap.header.size += machine->id_hdr_size;
362 363 364 365 366
		event->mmap.start = pos->start;
		event->mmap.len   = pos->end - pos->start;
		event->mmap.pid   = machine->pid;

		memcpy(event->mmap.filename, pos->dso->long_name,
367
		       pos->dso->long_name_len + 1);
368 369 370 371
		if (process(tool, event, &synth_sample, machine) != 0) {
			rc = -1;
			break;
		}
372 373
	}

374
	free(event);
375
	return rc;
376 377
}

378 379
static int __event__synthesize_thread(union perf_event *comm_event,
				      union perf_event *mmap_event,
380
				      union perf_event *fork_event,
381 382
				      pid_t pid, int full,
					  perf_event__handler_t process,
383
				      struct perf_tool *tool,
384
				      struct machine *machine, bool mmap_data)
385
{
386 387 388
	char filename[PATH_MAX];
	DIR *tasks;
	struct dirent dirent, *next;
389
	pid_t tgid, ppid;
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423

	/* special case: only send one comm event using passed in pid */
	if (!full) {
		tgid = perf_event__synthesize_comm(tool, comm_event, pid,
						   process, machine);

		if (tgid == -1)
			return -1;

		return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
							  process, machine, mmap_data);
	}

	if (machine__is_default_guest(machine))
		return 0;

	snprintf(filename, sizeof(filename), "%s/proc/%d/task",
		 machine->root_dir, pid);

	tasks = opendir(filename);
	if (tasks == NULL) {
		pr_debug("couldn't open %s\n", filename);
		return 0;
	}

	while (!readdir_r(tasks, &dirent, &next) && next) {
		char *end;
		int rc = 0;
		pid_t _pid;

		_pid = strtol(dirent.d_name, &end, 10);
		if (*end)
			continue;

424 425
		if (perf_event__prepare_comm(comm_event, _pid, machine,
					     &tgid, &ppid) != 0)
426 427
			return -1;

428
		if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
429
						ppid, process, machine) < 0)
430 431 432 433 434 435 436
			return -1;
		/*
		 * Send the prepared comm event
		 */
		if (process(tool, comm_event, &synth_sample, machine) != 0)
			return -1;

437 438 439 440 441
		if (_pid == pid) {
			/* process the parent's maps too */
			rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
						process, machine, mmap_data);
		}
442 443 444 445 446 447 448

		if (rc)
			return rc;
	}

	closedir(tasks);
	return 0;
449 450
}

451
int perf_event__synthesize_thread_map(struct perf_tool *tool,
452
				      struct thread_map *threads,
453
				      perf_event__handler_t process,
454 455
				      struct machine *machine,
				      bool mmap_data)
456
{
457
	union perf_event *comm_event, *mmap_event, *fork_event;
458
	int err = -1, thread, j;
459

460
	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
461 462 463
	if (comm_event == NULL)
		goto out;

464
	mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
465 466 467
	if (mmap_event == NULL)
		goto out_free_comm;

468 469 470 471
	fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
	if (fork_event == NULL)
		goto out_free_mmap;

472 473 474
	err = 0;
	for (thread = 0; thread < threads->nr; ++thread) {
		if (__event__synthesize_thread(comm_event, mmap_event,
475
					       fork_event,
476
					       threads->map[thread], 0,
477 478
					       process, tool, machine,
					       mmap_data)) {
479 480 481
			err = -1;
			break;
		}
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499

		/*
		 * comm.pid is set to thread group id by
		 * perf_event__synthesize_comm
		 */
		if ((int) comm_event->comm.pid != threads->map[thread]) {
			bool need_leader = true;

			/* is thread group leader in thread_map? */
			for (j = 0; j < threads->nr; ++j) {
				if ((int) comm_event->comm.pid == threads->map[j]) {
					need_leader = false;
					break;
				}
			}

			/* if not, generate events for it */
			if (need_leader &&
500
			    __event__synthesize_thread(comm_event, mmap_event,
501
						       fork_event,
502 503 504
						       comm_event->comm.pid, 0,
						       process, tool, machine,
						       mmap_data)) {
505 506 507 508
				err = -1;
				break;
			}
		}
509
	}
510 511
	free(fork_event);
out_free_mmap:
512 513 514 515 516 517 518
	free(mmap_event);
out_free_comm:
	free(comm_event);
out:
	return err;
}

519
int perf_event__synthesize_threads(struct perf_tool *tool,
520
				   perf_event__handler_t process,
521
				   struct machine *machine, bool mmap_data)
522 523
{
	DIR *proc;
524
	char proc_path[PATH_MAX];
525
	struct dirent dirent, *next;
526
	union perf_event *comm_event, *mmap_event, *fork_event;
527 528
	int err = -1;

529 530 531
	if (machine__is_default_guest(machine))
		return 0;

532
	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
533 534 535
	if (comm_event == NULL)
		goto out;

536
	mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
537 538
	if (mmap_event == NULL)
		goto out_free_comm;
539

540 541 542 543
	fork_event = malloc(sizeof(fork_event->fork) + machine->id_hdr_size);
	if (fork_event == NULL)
		goto out_free_mmap;

544 545 546
	snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
	proc = opendir(proc_path);

547
	if (proc == NULL)
548
		goto out_free_fork;
549 550 551 552 553 554 555

	while (!readdir_r(proc, &dirent, &next) && next) {
		char *end;
		pid_t pid = strtol(dirent.d_name, &end, 10);

		if (*end) /* only interested in proper numerical dirents */
			continue;
556 557 558 559
		/*
 		 * We may race with exiting thread, so don't stop just because
 		 * one thread couldn't be synthesized.
 		 */
560 561
		__event__synthesize_thread(comm_event, mmap_event, fork_event, pid,
					   1, process, tool, machine, mmap_data);
562 563
	}

564
	err = 0;
565
	closedir(proc);
566 567
out_free_fork:
	free(fork_event);
568 569 570 571 572 573
out_free_mmap:
	free(mmap_event);
out_free_comm:
	free(comm_event);
out:
	return err;
574
}
575

576 577 578 579 580
struct process_symbol_args {
	const char *name;
	u64	   start;
};

581
static int find_symbol_cb(void *arg, const char *name, char type,
582
			  u64 start)
583 584 585
{
	struct process_symbol_args *args = arg;

586 587 588 589 590 591
	/*
	 * Must be a function or at least an alias, as in PARISC64, where "_text" is
	 * an 'A' to the same address as "_stext".
	 */
	if (!(symbol_type__is_a(type, MAP__FUNCTION) ||
	      type == 'A') || strcmp(name, args->name))
592 593 594 595 596 597
		return 0;

	args->start = start;
	return 1;
}

598 599 600 601 602 603 604 605 606 607 608
u64 kallsyms__get_function_start(const char *kallsyms_filename,
				 const char *symbol_name)
{
	struct process_symbol_args args = { .name = symbol_name, };

	if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
		return 0;

	return args.start;
}

609
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
610
				       perf_event__handler_t process,
611
				       struct machine *machine)
612 613
{
	size_t size;
614
	const char *mmap_name;
615 616
	char name_buff[PATH_MAX];
	struct map *map;
617
	struct kmap *kmap;
618
	int err;
619 620 621 622 623
	union perf_event *event;

	if (machine->vmlinux_maps[0] == NULL)
		return -1;

624 625 626 627 628
	/*
	 * We should get this from /sys/kernel/sections/.text, but till that is
	 * available use this, and after it is use this as a fallback for older
	 * kernels.
	 */
629
	event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
630 631 632 633 634
	if (event == NULL) {
		pr_debug("Not enough memory synthesizing mmap event "
			 "for kernel modules\n");
		return -1;
	}
635

636
	mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
637
	if (machine__is_host(machine)) {
638 639 640 641
		/*
		 * kernel uses PERF_RECORD_MISC_USER for user space maps,
		 * see kernel/perf_event.c __perf_event_mmap
		 */
642
		event->header.misc = PERF_RECORD_MISC_KERNEL;
643
	} else {
644
		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
645
	}
646

647
	map = machine->vmlinux_maps[MAP__FUNCTION];
648
	kmap = map__kmap(map);
649
	size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
650
			"%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
651
	size = PERF_ALIGN(size, sizeof(u64));
652 653
	event->mmap.header.type = PERF_RECORD_MMAP;
	event->mmap.header.size = (sizeof(event->mmap) -
654
			(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
655
	event->mmap.pgoff = kmap->ref_reloc_sym->addr;
656 657 658 659
	event->mmap.start = map->start;
	event->mmap.len   = map->end - event->mmap.start;
	event->mmap.pid   = machine->pid;

660
	err = process(tool, event, &synth_sample, machine);
661 662 663
	free(event);

	return err;
664 665
}

666 667
size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
{
668 669 670 671 672 673 674
	const char *s;

	if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC)
		s = " exec";
	else
		s = "";

675
	return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
676 677
}

678
int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
679
			     union perf_event *event,
680
			     struct perf_sample *sample,
681
			     struct machine *machine)
682
{
683
	return machine__process_comm_event(machine, event, sample);
684 685
}

686
int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
687
			     union perf_event *event,
688
			     struct perf_sample *sample,
689
			     struct machine *machine)
690
{
691
	return machine__process_lost_event(machine, event, sample);
692
}
693

694 695
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
{
696
	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
697
		       event->mmap.pid, event->mmap.tid, event->mmap.start,
698 699 700
		       event->mmap.len, event->mmap.pgoff,
		       (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
		       event->mmap.filename);
701 702
}

703 704 705
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
{
	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
706
			   " %02x:%02x %"PRIu64" %"PRIu64"]: %c%c%c%c %s\n",
707 708 709 710
		       event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
		       event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
		       event->mmap2.min, event->mmap2.ino,
		       event->mmap2.ino_generation,
711 712 713 714
		       (event->mmap2.prot & PROT_READ) ? 'r' : '-',
		       (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
		       (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
		       (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
715 716 717
		       event->mmap2.filename);
}

718
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
719
			     union perf_event *event,
720
			     struct perf_sample *sample,
721
			     struct machine *machine)
722
{
723
	return machine__process_mmap_event(machine, event, sample);
724 725
}

726 727
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
			     union perf_event *event,
728
			     struct perf_sample *sample,
729 730
			     struct machine *machine)
{
731
	return machine__process_mmap2_event(machine, event, sample);
732 733
}

734 735 736 737 738 739 740
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
{
	return fprintf(fp, "(%d:%d):(%d:%d)\n",
		       event->fork.pid, event->fork.tid,
		       event->fork.ppid, event->fork.ptid);
}

741
int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
742
			     union perf_event *event,
743
			     struct perf_sample *sample,
744
			     struct machine *machine)
745
{
746
	return machine__process_fork_event(machine, event, sample);
747
}
748

749 750
int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
			     union perf_event *event,
751
			     struct perf_sample *sample,
752 753
			     struct machine *machine)
{
754
	return machine__process_exit_event(machine, event, sample);
755 756
}

757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
{
	size_t ret = fprintf(fp, "PERF_RECORD_%s",
			     perf_event__name(event->header.type));

	switch (event->header.type) {
	case PERF_RECORD_COMM:
		ret += perf_event__fprintf_comm(event, fp);
		break;
	case PERF_RECORD_FORK:
	case PERF_RECORD_EXIT:
		ret += perf_event__fprintf_task(event, fp);
		break;
	case PERF_RECORD_MMAP:
		ret += perf_event__fprintf_mmap(event, fp);
		break;
773 774 775
	case PERF_RECORD_MMAP2:
		ret += perf_event__fprintf_mmap2(event, fp);
		break;
776 777 778 779 780 781 782
	default:
		ret += fprintf(fp, "\n");
	}

	return ret;
}

783 784
int perf_event__process(struct perf_tool *tool __maybe_unused,
			union perf_event *event,
785
			struct perf_sample *sample,
786
			struct machine *machine)
787
{
788
	return machine__process_event(machine, event, sample);
789 790
}

791
void thread__find_addr_map(struct thread *thread, u8 cpumode,
792
			   enum map_type type, u64 addr,
793
			   struct addr_location *al)
794
{
795
	struct map_groups *mg = thread->mg;
796
	struct machine *machine = mg->machine;
797
	bool load_map = false;
798

799
	al->machine = machine;
800
	al->thread = thread;
801
	al->addr = addr;
802
	al->cpumode = cpumode;
803
	al->filtered = 0;
804

805 806 807 808 809
	if (machine == NULL) {
		al->map = NULL;
		return;
	}

810
	if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
811
		al->level = 'k';
812
		mg = &machine->kmaps;
813
		load_map = true;
814
	} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
815
		al->level = '.';
816 817
	} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
		al->level = 'g';
818
		mg = &machine->kmaps;
819
		load_map = true;
820 821
	} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
		al->level = 'u';
822
	} else {
823
		al->level = 'H';
824
		al->map = NULL;
825 826 827 828

		if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
			cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
			!perf_guest)
829
			al->filtered |= (1 << HIST_FILTER__GUEST);
830 831 832
		if ((cpumode == PERF_RECORD_MISC_USER ||
			cpumode == PERF_RECORD_MISC_KERNEL) &&
			!perf_host)
833
			al->filtered |= (1 << HIST_FILTER__HOST);
834

835 836 837
		return;
	}
try_again:
838
	al->map = map_groups__find(mg, type, al->addr);
839 840 841 842 843 844 845 846 847 848
	if (al->map == NULL) {
		/*
		 * If this is outside of all known maps, and is a negative
		 * address, try to look it up in the kernel dso, as it might be
		 * a vsyscall or vdso (which executes in user-mode).
		 *
		 * XXX This is nasty, we should have a symbol list in the
		 * "[vdso]" dso, but for now lets use the old trick of looking
		 * in the whole kernel symbol list.
		 */
849 850 851
		if (cpumode == PERF_RECORD_MISC_USER && machine &&
		    mg != &machine->kmaps &&
		    machine__kernel_ip(machine, al->addr)) {
852
			mg = &machine->kmaps;
853
			load_map = true;
854 855
			goto try_again;
		}
856 857 858 859 860 861
	} else {
		/*
		 * Kernel maps might be changed when loading symbols so loading
		 * must be done prior to using kernel maps.
		 */
		if (load_map)
862
			map__load(al->map, machine->symbol_filter);
863
		al->addr = al->map->map_ip(al->map, al->addr);
864
	}
865 866
}

867
void thread__find_addr_location(struct thread *thread,
868
				u8 cpumode, enum map_type type, u64 addr,
869
				struct addr_location *al)
870
{
871
	thread__find_addr_map(thread, cpumode, type, addr, al);
872
	if (al->map != NULL)
873
		al->sym = map__find_symbol(al->map, al->addr,
874
					   thread->mg->machine->symbol_filter);
875 876
	else
		al->sym = NULL;
877 878
}

879
int perf_event__preprocess_sample(const union perf_event *event,
880
				  struct machine *machine,
881
				  struct addr_location *al,
882
				  struct perf_sample *sample)
883
{
884
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
885
	struct thread *thread = machine__findnew_thread(machine, sample->pid,
886
							sample->tid);
887

888 889 890
	if (thread == NULL)
		return -1;

891
	dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
892
	/*
893
	 * Have we already created the kernel maps for this machine?
894 895 896 897 898 899
	 *
	 * This should have happened earlier, when we processed the kernel MMAP
	 * events, but for older perf.data files there was no such thing, so do
	 * it now.
	 */
	if (cpumode == PERF_RECORD_MISC_KERNEL &&
900 901
	    machine->vmlinux_maps[MAP__FUNCTION] == NULL)
		machine__create_kernel_maps(machine);
902

903
	thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
904 905 906
	dump_printf(" ...... dso: %s\n",
		    al->map ? al->map->dso->long_name :
			al->level == 'H' ? "[hypervisor]" : "<not found>");
907 908 909 910

	if (thread__is_filtered(thread))
		al->filtered |= (1 << HIST_FILTER__THREAD);

911
	al->sym = NULL;
912
	al->cpu = sample->cpu;
913 914

	if (al->map) {
915 916
		struct dso *dso = al->map->dso;

917
		if (symbol_conf.dso_list &&
918 919 920 921
		    (!dso || !(strlist__has_entry(symbol_conf.dso_list,
						  dso->short_name) ||
			       (dso->short_name != dso->long_name &&
				strlist__has_entry(symbol_conf.dso_list,
922 923 924
						   dso->long_name))))) {
			al->filtered |= (1 << HIST_FILTER__DSO);
		}
925

926 927
		al->sym = map__find_symbol(al->map, al->addr,
					   machine->symbol_filter);
928
	}
929

930 931
	if (symbol_conf.sym_list &&
		(!al->sym || !strlist__has_entry(symbol_conf.sym_list,
932 933 934
						al->sym->name))) {
		al->filtered |= (1 << HIST_FILTER__SYMBOL);
	}
935 936

	return 0;
937
}
938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966

bool is_bts_event(struct perf_event_attr *attr)
{
	return attr->type == PERF_TYPE_HARDWARE &&
	       (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
	       attr->sample_period == 1;
}

bool sample_addr_correlates_sym(struct perf_event_attr *attr)
{
	if (attr->type == PERF_TYPE_SOFTWARE &&
	    (attr->config == PERF_COUNT_SW_PAGE_FAULTS ||
	     attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
	     attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))
		return true;

	if (is_bts_event(attr))
		return true;

	return false;
}

void perf_event__preprocess_sample_addr(union perf_event *event,
					struct perf_sample *sample,
					struct thread *thread,
					struct addr_location *al)
{
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

967
	thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
968
	if (!al->map)
969
		thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
970 971 972 973 974 975 976 977
				      sample->addr, al);

	al->cpu = sample->cpu;
	al->sym = NULL;

	if (al->map)
		al->sym = map__find_symbol(al->map, al->addr, NULL);
}