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

12
static const char *perf_event__names[] = {
13 14
	[0]					= "TOTAL",
	[PERF_RECORD_MMAP]			= "MMAP",
15
	[PERF_RECORD_MMAP2]			= "MMAP2",
16 17 18 19 20 21 22 23 24 25 26 27 28
	[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",
29 30
};

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

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

49
static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
50 51 52 53 54
{
	char filename[PATH_MAX];
	char bf[BUFSIZ];
	FILE *fp;
	size_t size = 0;
55
	pid_t tgid = -1;
56 57 58 59 60 61 62 63 64

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

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

65
	while (!comm[0] || (tgid < 0)) {
66
		if (fgets(bf, sizeof(bf), fp) == NULL) {
67 68 69
			pr_warning("couldn't get COMM and pgid, malformed %s\n",
				   filename);
			break;
70
		}
71 72 73 74 75 76

		if (memcmp(bf, "Name:", 5) == 0) {
			char *name = bf + 5;
			while (*name && isspace(*name))
				++name;
			size = strlen(name) - 1;
77 78 79
			if (size >= len)
				size = len - 1;
			memcpy(comm, name, size);
80
			comm[size] = '\0';
81

82 83 84 85
		} else if (memcmp(bf, "Tgid:", 5) == 0) {
			char *tgids = bf + 5;
			while (*tgids && isspace(*tgids))
				++tgids;
86
			tgid = atoi(tgids);
87 88 89
		}
	}

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	fclose(fp);

	return tgid;
}

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)
{
	size_t size;
	pid_t tgid;

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

105 106 107 108 109 110
	if (machine__is_host(machine))
		tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
						 sizeof(event->comm.comm));
	else
		tgid = machine->pid;

111 112 113 114
	if (tgid < 0)
		goto out;

	event->comm.pid = tgid;
115
	event->comm.header.type = PERF_RECORD_COMM;
116 117

	size = strlen(event->comm.comm) + 1;
118
	size = PERF_ALIGN(size, sizeof(u64));
119
	memset(event->comm.comm + size, 0, machine->id_hdr_size);
120 121
	event->comm.header.size = (sizeof(event->comm) -
				(sizeof(event->comm.comm) - size) +
122
				machine->id_hdr_size);
123
	event->comm.tid = pid;
124

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

128 129
out:
	return tgid;
130 131
}

132 133 134 135 136 137
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)
138 139 140
{
	char filename[PATH_MAX];
	FILE *fp;
141
	int rc = 0;
142

143 144 145
	if (machine__is_default_guest(machine))
		return 0;

146 147
	snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
		 machine->root_dir, pid);
148 149 150 151 152 153 154 155 156 157

	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;
	}

158
	event->header.type = PERF_RECORD_MMAP;
159

160
	while (1) {
161 162 163 164
		char bf[BUFSIZ];
		char prot[5];
		char execname[PATH_MAX];
		char anonstr[] = "//anon";
165
		size_t size;
166
		ssize_t n;
167

168 169 170
		if (fgets(bf, sizeof(bf), fp) == NULL)
			break;

171 172 173
		/* ensure null termination since stack will be reused. */
		strcpy(execname, "");

174
		/* 00400000-0040c000 r-xp 00000000 fd:01 41038  /bin/cat */
175 176 177 178
		n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n",
		       &event->mmap.start, &event->mmap.len, prot,
		       &event->mmap.pgoff,
		       execname);
179 180 181 182
		/*
 		 * Anon maps don't have the execname.
 		 */
		if (n < 4)
183
			continue;
184 185 186
		/*
		 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
		 */
187 188 189 190
		if (machine__is_host(machine))
			event->header.misc = PERF_RECORD_MISC_USER;
		else
			event->header.misc = PERF_RECORD_MISC_GUEST_USER;
191

192 193 194 195 196 197
		if (prot[2] != 'x') {
			if (!mmap_data || prot[0] != 'r')
				continue;

			event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
		}
198 199 200 201 202

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

		size = strlen(execname) + 1;
203
		memcpy(event->mmap.filename, execname, size);
204
		size = PERF_ALIGN(size, sizeof(u64));
205 206 207 208 209 210 211
		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;
212 213 214 215

		if (process(tool, event, &synth_sample, machine) != 0) {
			rc = -1;
			break;
216 217 218 219
		}
	}

	fclose(fp);
220
	return rc;
221 222
}

223
int perf_event__synthesize_modules(struct perf_tool *tool,
224
				   perf_event__handler_t process,
225
				   struct machine *machine)
226
{
227
	int rc = 0;
228
	struct rb_node *nd;
229
	struct map_groups *kmaps = &machine->kmaps;
230
	union perf_event *event = zalloc((sizeof(event->mmap) +
231
					  machine->id_hdr_size));
232 233 234 235 236 237 238
	if (event == NULL) {
		pr_debug("Not enough memory synthesizing mmap event "
			 "for kernel modules\n");
		return -1;
	}

	event->header.type = PERF_RECORD_MMAP;
239

240 241 242 243
	/*
	 * kernel uses 0 for user space maps, see kernel/perf_event.c
	 * __perf_event_mmap
	 */
244
	if (machine__is_host(machine))
245
		event->header.misc = PERF_RECORD_MISC_KERNEL;
246
	else
247
		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
248 249

	for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
250 251 252 253 254 255 256
	     nd; nd = rb_next(nd)) {
		size_t size;
		struct map *pos = rb_entry(nd, struct map, rb_node);

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

257
		size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
258 259 260
		event->mmap.header.type = PERF_RECORD_MMAP;
		event->mmap.header.size = (sizeof(event->mmap) -
				        (sizeof(event->mmap.filename) - size));
261 262
		memset(event->mmap.filename + size, 0, machine->id_hdr_size);
		event->mmap.header.size += machine->id_hdr_size;
263 264 265 266 267
		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,
268
		       pos->dso->long_name_len + 1);
269 270 271 272
		if (process(tool, event, &synth_sample, machine) != 0) {
			rc = -1;
			break;
		}
273 274
	}

275
	free(event);
276
	return rc;
277 278
}

279 280
static int __event__synthesize_thread(union perf_event *comm_event,
				      union perf_event *mmap_event,
281 282
				      pid_t pid, int full,
					  perf_event__handler_t process,
283
				      struct perf_tool *tool,
284
				      struct machine *machine, bool mmap_data)
285
{
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
	char filename[PATH_MAX];
	DIR *tasks;
	struct dirent dirent, *next;
	pid_t tgid;

	/* 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;

		tgid = perf_event__synthesize_comm(tool, comm_event, _pid,
						   process, machine);
		if (tgid == -1)
			return -1;

		/* process the thread's maps too */
		rc = perf_event__synthesize_mmap_events(tool, mmap_event, _pid, tgid,
							process, machine, mmap_data);

		if (rc)
			return rc;
	}

	closedir(tasks);
	return 0;
339 340
}

341
int perf_event__synthesize_thread_map(struct perf_tool *tool,
342
				      struct thread_map *threads,
343
				      perf_event__handler_t process,
344 345
				      struct machine *machine,
				      bool mmap_data)
346
{
347
	union perf_event *comm_event, *mmap_event;
348
	int err = -1, thread, j;
349

350
	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
351 352 353
	if (comm_event == NULL)
		goto out;

354
	mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
355 356 357
	if (mmap_event == NULL)
		goto out_free_comm;

358 359 360
	err = 0;
	for (thread = 0; thread < threads->nr; ++thread) {
		if (__event__synthesize_thread(comm_event, mmap_event,
361
					       threads->map[thread], 0,
362 363
					       process, tool, machine,
					       mmap_data)) {
364 365 366
			err = -1;
			break;
		}
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384

		/*
		 * 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 &&
385 386 387 388
			    __event__synthesize_thread(comm_event, mmap_event,
						       comm_event->comm.pid, 0,
						       process, tool, machine,
						       mmap_data)) {
389 390 391 392
				err = -1;
				break;
			}
		}
393
	}
394 395 396 397 398 399 400
	free(mmap_event);
out_free_comm:
	free(comm_event);
out:
	return err;
}

401
int perf_event__synthesize_threads(struct perf_tool *tool,
402
				   perf_event__handler_t process,
403
				   struct machine *machine, bool mmap_data)
404 405
{
	DIR *proc;
406
	char proc_path[PATH_MAX];
407
	struct dirent dirent, *next;
408
	union perf_event *comm_event, *mmap_event;
409 410
	int err = -1;

411
	comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
412 413 414
	if (comm_event == NULL)
		goto out;

415
	mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
416 417
	if (mmap_event == NULL)
		goto out_free_comm;
418

419 420 421
	if (machine__is_default_guest(machine))
		return 0;

422 423 424
	snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
	proc = opendir(proc_path);

425 426
	if (proc == NULL)
		goto out_free_mmap;
427 428 429 430 431 432 433

	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;
434 435 436 437 438
		/*
 		 * 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,
439
					   process, tool, machine, mmap_data);
440 441
	}

442
	err = 0;
443
	closedir(proc);
444 445 446 447 448 449
out_free_mmap:
	free(mmap_event);
out_free_comm:
	free(comm_event);
out:
	return err;
450
}
451

452 453 454 455 456
struct process_symbol_args {
	const char *name;
	u64	   start;
};

457
static int find_symbol_cb(void *arg, const char *name, char type,
458
			  u64 start)
459 460 461
{
	struct process_symbol_args *args = arg;

462 463 464 465 466 467
	/*
	 * 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))
468 469 470 471 472 473
		return 0;

	args->start = start;
	return 1;
}

474 475 476 477 478 479 480 481 482 483 484
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;
}

485
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
486
				       perf_event__handler_t process,
487
				       struct machine *machine)
488 489
{
	size_t size;
490
	const char *mmap_name;
491 492
	char name_buff[PATH_MAX];
	struct map *map;
493
	struct kmap *kmap;
494
	int err;
495 496 497 498 499
	/*
	 * 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.
	 */
500
	union perf_event *event = zalloc((sizeof(event->mmap) +
501
					  machine->id_hdr_size));
502 503 504 505 506
	if (event == NULL) {
		pr_debug("Not enough memory synthesizing mmap event "
			 "for kernel modules\n");
		return -1;
	}
507

508
	mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
509
	if (machine__is_host(machine)) {
510 511 512 513
		/*
		 * kernel uses PERF_RECORD_MISC_USER for user space maps,
		 * see kernel/perf_event.c __perf_event_mmap
		 */
514
		event->header.misc = PERF_RECORD_MISC_KERNEL;
515
	} else {
516
		event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
517
	}
518

519
	map = machine->vmlinux_maps[MAP__FUNCTION];
520
	kmap = map__kmap(map);
521
	size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
522
			"%s%s", mmap_name, kmap->ref_reloc_sym->name) + 1;
523
	size = PERF_ALIGN(size, sizeof(u64));
524 525
	event->mmap.header.type = PERF_RECORD_MMAP;
	event->mmap.header.size = (sizeof(event->mmap) -
526
			(sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
527
	event->mmap.pgoff = kmap->ref_reloc_sym->addr;
528 529 530 531
	event->mmap.start = map->start;
	event->mmap.len   = map->end - event->mmap.start;
	event->mmap.pid   = machine->pid;

532
	err = process(tool, event, &synth_sample, machine);
533 534 535
	free(event);

	return err;
536 537
}

538 539 540 541 542
size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
{
	return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid);
}

543
int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
544
			     union perf_event *event,
545
			     struct perf_sample *sample,
546
			     struct machine *machine)
547
{
548
	return machine__process_comm_event(machine, event, sample);
549 550
}

551
int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
552
			     union perf_event *event,
553
			     struct perf_sample *sample,
554
			     struct machine *machine)
555
{
556
	return machine__process_lost_event(machine, event, sample);
557
}
558

559 560
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
{
561
	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
562
		       event->mmap.pid, event->mmap.tid, event->mmap.start,
563 564 565
		       event->mmap.len, event->mmap.pgoff,
		       (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
		       event->mmap.filename);
566 567
}

568 569 570
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
{
	return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
571
			   " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n",
572 573 574 575
		       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,
576
		       (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
577 578 579
		       event->mmap2.filename);
}

580
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
581
			     union perf_event *event,
582
			     struct perf_sample *sample,
583
			     struct machine *machine)
584
{
585
	return machine__process_mmap_event(machine, event, sample);
586 587
}

588 589
int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
			     union perf_event *event,
590
			     struct perf_sample *sample,
591 592
			     struct machine *machine)
{
593
	return machine__process_mmap2_event(machine, event, sample);
594 595
}

596 597 598 599 600 601 602
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);
}

603
int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
604
			     union perf_event *event,
605
			     struct perf_sample *sample,
606
			     struct machine *machine)
607
{
608
	return machine__process_fork_event(machine, event, sample);
609
}
610

611 612
int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
			     union perf_event *event,
613
			     struct perf_sample *sample,
614 615
			     struct machine *machine)
{
616
	return machine__process_exit_event(machine, event, sample);
617 618
}

619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
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;
635 636 637
	case PERF_RECORD_MMAP2:
		ret += perf_event__fprintf_mmap2(event, fp);
		break;
638 639 640 641 642 643 644
	default:
		ret += fprintf(fp, "\n");
	}

	return ret;
}

645 646
int perf_event__process(struct perf_tool *tool __maybe_unused,
			union perf_event *event,
647
			struct perf_sample *sample,
648
			struct machine *machine)
649
{
650
	return machine__process_event(machine, event, sample);
651 652
}

653
void thread__find_addr_map(struct thread *thread,
654 655
			   struct machine *machine, u8 cpumode,
			   enum map_type type, u64 addr,
656
			   struct addr_location *al)
657
{
658
	struct map_groups *mg = &thread->mg;
659
	bool load_map = false;
660

661
	al->machine = machine;
662
	al->thread = thread;
663
	al->addr = addr;
664 665
	al->cpumode = cpumode;
	al->filtered = false;
666

667 668 669 670 671
	if (machine == NULL) {
		al->map = NULL;
		return;
	}

672
	if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
673
		al->level = 'k';
674
		mg = &machine->kmaps;
675
		load_map = true;
676
	} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
677
		al->level = '.';
678 679
	} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
		al->level = 'g';
680
		mg = &machine->kmaps;
681
		load_map = true;
682 683
	} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
		al->level = 'u';
684
	} else {
685
		al->level = 'H';
686
		al->map = NULL;
687 688 689 690 691 692 693 694 695 696

		if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
			cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
			!perf_guest)
			al->filtered = true;
		if ((cpumode == PERF_RECORD_MISC_USER ||
			cpumode == PERF_RECORD_MISC_KERNEL) &&
			!perf_host)
			al->filtered = true;

697 698 699
		return;
	}
try_again:
700
	al->map = map_groups__find(mg, type, al->addr);
701 702 703 704 705 706 707 708 709 710
	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.
		 */
711
		if ((long long)al->addr < 0 &&
712
		    cpumode == PERF_RECORD_MISC_USER &&
713 714
		    machine && mg != &machine->kmaps) {
			mg = &machine->kmaps;
715 716
			goto try_again;
		}
717 718 719 720 721 722
	} else {
		/*
		 * Kernel maps might be changed when loading symbols so loading
		 * must be done prior to using kernel maps.
		 */
		if (load_map)
723
			map__load(al->map, machine->symbol_filter);
724
		al->addr = al->map->map_ip(al->map, al->addr);
725
	}
726 727
}

728 729
void thread__find_addr_location(struct thread *thread, struct machine *machine,
				u8 cpumode, enum map_type type, u64 addr,
730
				struct addr_location *al)
731
{
732
	thread__find_addr_map(thread, machine, cpumode, type, addr, al);
733
	if (al->map != NULL)
734 735
		al->sym = map__find_symbol(al->map, al->addr,
					   machine->symbol_filter);
736 737
	else
		al->sym = NULL;
738 739
}

740
int perf_event__preprocess_sample(const union perf_event *event,
741
				  struct machine *machine,
742
				  struct addr_location *al,
743
				  struct perf_sample *sample)
744
{
745
	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
746 747
	struct thread *thread = machine__findnew_thread(machine, sample->pid,
							sample->pid);
748

749 750 751
	if (thread == NULL)
		return -1;

752
	if (thread__is_filtered(thread))
753 754
		goto out_filtered;

755
	dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
756
	/*
757
	 * Have we already created the kernel maps for this machine?
758 759 760 761 762 763
	 *
	 * 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 &&
764 765
	    machine->vmlinux_maps[MAP__FUNCTION] == NULL)
		machine__create_kernel_maps(machine);
766

767
	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
768
			      sample->ip, al);
769 770 771
	dump_printf(" ...... dso: %s\n",
		    al->map ? al->map->dso->long_name :
			al->level == 'H' ? "[hypervisor]" : "<not found>");
772
	al->sym = NULL;
773
	al->cpu = sample->cpu;
774 775

	if (al->map) {
776 777
		struct dso *dso = al->map->dso;

778
		if (symbol_conf.dso_list &&
779 780 781 782 783
		    (!dso || !(strlist__has_entry(symbol_conf.dso_list,
						  dso->short_name) ||
			       (dso->short_name != dso->long_name &&
				strlist__has_entry(symbol_conf.dso_list,
						   dso->long_name)))))
784 785
			goto out_filtered;

786 787
		al->sym = map__find_symbol(al->map, al->addr,
					   machine->symbol_filter);
788
	}
789

790 791 792
	if (symbol_conf.sym_list &&
		(!al->sym || !strlist__has_entry(symbol_conf.sym_list,
						al->sym->name)))
793 794 795 796 797 798
		goto out_filtered;

	return 0;

out_filtered:
	al->filtered = true;
799 800
	return 0;
}