17d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng/* ANDROID_CHANGE_BEGIN */ 27d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#ifdef __APPLE__ 37d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#include "include/linux/types.h" 47d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#else 5097a574687b429a2f8ab7988308c7edb828156b6Andrew Hsieh/* Suppress kernel-name space pollution in <linux/types.h> below */ 6097a574687b429a2f8ab7988308c7edb828156b6Andrew Hsieh#include <features.h> 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <linux/types.h> 87d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#endif 97d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng/* ANDROID_CHANGE_END */ 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "event.h" 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "debug.h" 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "session.h" 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "sort.h" 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "string.h" 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "strlist.h" 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "thread.h" 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "thread_map.h" 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char *perf_event__names[] = { 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [0] = "TOTAL", 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_MMAP] = "MMAP", 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_LOST] = "LOST", 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_COMM] = "COMM", 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_EXIT] = "EXIT", 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_THROTTLE] = "THROTTLE", 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_FORK] = "FORK", 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_READ] = "READ", 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_SAMPLE] = "SAMPLE", 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_HEADER_ATTR] = "ATTR", 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengconst char *perf_event__name(unsigned int id) 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (id >= ARRAY_SIZE(perf_event__names)) 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return "INVALID"; 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!perf_event__names[id]) 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return "UNKNOWN"; 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return perf_event__names[id]; 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct perf_sample synth_sample = { 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .pid = -1, 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .tid = -1, 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .time = -1, 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .stream_id = -1, 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .cpu = -1, 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng .period = 1, 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int full, perf_event__handler_t process, 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char filename[PATH_MAX]; 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char bf[BUFSIZ]; 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *fp; 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t size = 0; 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng DIR *tasks; 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dirent dirent, *next; 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid_t tgid = 0; 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fp = fopen(filename, "r"); 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fp == NULL) { 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_race: 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * We raced with a task exiting - just return: 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("couldn't open %s\n", filename); 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(&event->comm, 0, sizeof(event->comm)); 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (!event->comm.comm[0] || !event->comm.pid) { 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fgets(bf, sizeof(bf), fp) == NULL) { 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_warning("couldn't get COMM and pgid, malformed %s\n", filename); 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (memcmp(bf, "Name:", 5) == 0) { 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *name = bf + 5; 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*name && isspace(*name)) 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++name; 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = strlen(name) - 1; 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memcpy(event->comm.comm, name, size++); 93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (memcmp(bf, "Tgid:", 5) == 0) { 94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *tgids = bf + 5; 95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (*tgids && isspace(*tgids)) 96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++tgids; 97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tgid = event->comm.pid = atoi(tgids); 98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->comm.header.type = PERF_RECORD_COMM; 102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_BEGIN */ 1037d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#if defined(__BIONIC__) || defined(__APPLE__) 104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = KERNEL_ALIGN(size, sizeof(u64)); 105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = ALIGN(size, sizeof(u64)); 107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_END */ 109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(event->comm.comm + size, 0, session->id_hdr_size); 110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->comm.header.size = (sizeof(event->comm) - 111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (sizeof(event->comm.comm) - size) + 112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng session->id_hdr_size); 113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!full) { 114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->comm.tid = pid; 115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process(event, &synth_sample, session); 117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng tasks = opendir(filename); 123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tasks == NULL) 124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_race; 125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (!readdir_r(tasks, &dirent, &next) && next) { 127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *end; 128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid = strtol(dirent.d_name, &end, 10); 129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*end) 130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->comm.tid = pid; 133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process(event, &synth_sample, session); 135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng closedir(tasks); 138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fclose(fp); 140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return tgid; 142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int perf_event__synthesize_mmap_events(union perf_event *event, 145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid_t pid, pid_t tgid, 146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__handler_t process, 147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char filename[PATH_MAX]; 150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng FILE *fp; 151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); 153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fp = fopen(filename, "r"); 155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fp == NULL) { 156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * We raced with a task exiting - just return: 158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("couldn't open %s\n", filename); 160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.type = PERF_RECORD_MMAP; 164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c 166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.misc = PERF_RECORD_MISC_USER; 168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (1) { 170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char bf[BUFSIZ], *pbf = bf; 171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int n; 172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t size; 173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (fgets(bf, sizeof(bf), fp) == NULL) 174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng n = hex2u64(pbf, &event->mmap.start); 178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (n < 0) 179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pbf += n + 1; 181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng n = hex2u64(pbf, &event->mmap.len); 182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (n < 0) 183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pbf += n + 3; 185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*pbf == 'x') { /* vm_exec */ 186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *execname = strchr(bf, '/'); 187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* Catch VDSO */ 189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (execname == NULL) 190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng execname = strstr(bf, "[vdso]"); 191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (execname == NULL) 193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pbf += 3; 196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng n = hex2u64(pbf, &event->mmap.pgoff); 197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = strlen(execname); 199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng execname[size - 1] = '\0'; /* Remove \n */ 200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memcpy(event->mmap.filename, execname, size); 201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_BEGIN */ 2027d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#if defined(__BIONIC__) || defined(__APPLE__) 203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = KERNEL_ALIGN(size, sizeof(u64)); 204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = ALIGN(size, sizeof(u64)); 206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_END */ 208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.len -= event->mmap.start; 209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.size = (sizeof(event->mmap) - 210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (sizeof(event->mmap.filename) - size)); 211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(event->mmap.filename + size, 0, session->id_hdr_size); 212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.size += session->id_hdr_size; 213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pid = tgid; 214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.tid = pid; 215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process(event, &synth_sample, session); 217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng fclose(fp); 221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__synthesize_modules(perf_event__handler_t process, 225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session, 226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine) 227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct rb_node *nd; 229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map_groups *kmaps = &machine->kmaps; 230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng union perf_event *event = zalloc((sizeof(event->mmap) + 231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng session->id_hdr_size)); 232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (event == NULL) { 233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Not enough memory synthesizing mmap event " 234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "for kernel modules\n"); 235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.type = PERF_RECORD_MMAP; 239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * kernel uses 0 for user space maps, see kernel/perf_event.c 242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * __perf_event_mmap 243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__is_host(machine)) 245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.misc = PERF_RECORD_MISC_KERNEL; 246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng nd; nd = rb_next(nd)) { 251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t size; 252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *pos = rb_entry(nd, struct map, rb_node); 253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (pos->dso->kernel) 255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_BEGIN */ 2587d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#if defined(__BIONIC__) || defined(__APPLE__) 259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = KERNEL_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_END */ 264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.type = PERF_RECORD_MMAP; 265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.size = (sizeof(event->mmap) - 266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (sizeof(event->mmap.filename) - size)); 267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memset(event->mmap.filename + size, 0, session->id_hdr_size); 268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.size += session->id_hdr_size; 269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.start = pos->start; 270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.len = pos->end - pos->start; 271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pid = machine->pid; 272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng memcpy(event->mmap.filename, pos->dso->long_name, 274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pos->dso->long_name_len + 1); 275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process(event, &synth_sample, session); 276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(event); 279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int __event__synthesize_thread(union perf_event *comm_event, 283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng union perf_event *mmap_event, 284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid_t pid, perf_event__handler_t process, 285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, 288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng session); 289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (tgid == -1) 290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, 292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process, session); 293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__synthesize_thread_map(struct thread_map *threads, 296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__handler_t process, 297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 298e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 299e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng union perf_event *comm_event, *mmap_event; 300e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err = -1, thread; 301e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 302e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 303e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (comm_event == NULL) 304e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 305e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 306e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 307e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (mmap_event == NULL) 308e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_free_comm; 309e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 310e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = 0; 311e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng for (thread = 0; thread < threads->nr; ++thread) { 312e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (__event__synthesize_thread(comm_event, mmap_event, 313e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng threads->map[thread], 314e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process, session)) { 315e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = -1; 316e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 317e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 318e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 319e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(mmap_event); 320e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_free_comm: 321e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(comm_event); 322e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 323e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 324e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 325e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 326e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__synthesize_threads(perf_event__handler_t process, 327e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 328e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 329e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng DIR *proc; 330e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dirent dirent, *next; 331e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng union perf_event *comm_event, *mmap_event; 332e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err = -1; 333e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 334e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 335e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (comm_event == NULL) 336e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out; 337e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 338e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 339e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (mmap_event == NULL) 340e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_free_comm; 341e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 342e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng proc = opendir("/proc"); 343e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (proc == NULL) 344e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_free_mmap; 345e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 346e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng while (!readdir_r(proc, &dirent, &next) && next) { 347e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *end; 348e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pid_t pid = strtol(dirent.d_name, &end, 10); 349e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 350e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (*end) /* only interested in proper numerical dirents */ 351e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng continue; 352e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 353e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng __event__synthesize_thread(comm_event, mmap_event, pid, 354e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng process, session); 355e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 356e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 357e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng closedir(proc); 358e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = 0; 359e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_free_mmap: 360e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(mmap_event); 361e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_free_comm: 362e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(comm_event); 363e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout: 364e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 365e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 366e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 367e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct process_symbol_args { 368e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *name; 369e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 start; 370e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 371e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 372e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int find_symbol_cb(void *arg, const char *name, char type, 373e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u64 start, u64 end __used) 374e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 375e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct process_symbol_args *args = arg; 376e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 377e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 378e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Must be a function or at least an alias, as in PARISC64, where "_text" is 379e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * an 'A' to the same address as "_stext". 380e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 381e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!(symbol_type__is_a(type, MAP__FUNCTION) || 382e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng type == 'A') || strcmp(name, args->name)) 383e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 384e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 385e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng args->start = start; 386e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 1; 387e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 388e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 389e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 390e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session, 391e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine, 392e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *symbol_name) 393e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 394e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t size; 395e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *filename, *mmap_name; 396e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char path[PATH_MAX]; 397e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char name_buff[PATH_MAX]; 398e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 399e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int err; 400e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 401e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * We should get this from /sys/kernel/sections/.text, but till that is 402e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * available use this, and after it is use this as a fallback for older 403e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * kernels. 404e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 405e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct process_symbol_args args = { .name = symbol_name, }; 406e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng union perf_event *event = zalloc((sizeof(event->mmap) + 407e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng session->id_hdr_size)); 408e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (event == NULL) { 409e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_debug("Not enough memory synthesizing mmap event " 410e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "for kernel modules\n"); 411e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 412e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 413e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 414e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 415e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__is_host(machine)) { 416e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 417e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * kernel uses PERF_RECORD_MISC_USER for user space maps, 418e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * see kernel/perf_event.c __perf_event_mmap 419e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 420e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.misc = PERF_RECORD_MISC_KERNEL; 421e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng filename = "/proc/kallsyms"; 422e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 423e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 424e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__is_default_guest(machine)) 425e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng filename = (char *) symbol_conf.default_guest_kallsyms; 426e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else { 427e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sprintf(path, "%s/proc/kallsyms", machine->root_dir); 428e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng filename = path; 429e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 430e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 431e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 432e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) 433e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -ENOENT; 434e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 435e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map = machine->vmlinux_maps[MAP__FUNCTION]; 436e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = snprintf(event->mmap.filename, sizeof(event->mmap.filename), 437e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "%s%s", mmap_name, symbol_name) + 1; 438e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_BEGIN */ 4397d82a4640abdcc3ffbd89c7971a11e4ac7953b7fBen Cheng#if defined(__BIONIC__) || defined(__APPLE__) 440e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = KERNEL_ALIGN(size, sizeof(u64)); 441e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#else 442e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size = ALIGN(size, sizeof(u64)); 443e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif 444e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* ANDROID_CHANGE_END */ 445e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.type = PERF_RECORD_MMAP; 446e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.header.size = (sizeof(event->mmap) - 447e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (sizeof(event->mmap.filename) - size) + session->id_hdr_size); 448e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pgoff = args.start; 449e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.start = map->start; 450e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.len = map->end - event->mmap.start; 451e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pid = machine->pid; 452e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 453e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng err = process(event, &synth_sample, session); 454e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng free(event); 455e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 456e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return err; 457e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 458e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 459e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__process_comm(union perf_event *event, 460e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_sample *sample __used, 461e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 462e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 463e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread = perf_session__findnew(session, event->comm.tid); 464e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 465e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); 466e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 467e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 468e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 469e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 470e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 471e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 472e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 473e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 474e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 475e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__process_lost(union perf_event *event, 476e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_sample *sample __used, 477e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 478e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 479e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 480e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->lost.id, event->lost.lost); 481e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng session->hists.stats.total_lost += event->lost.lost; 482e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 483e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 484e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 485e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void perf_event__set_kernel_mmap_len(union perf_event *event, 486e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map **maps) 487e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 488e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng maps[MAP__FUNCTION]->start = event->mmap.start; 489e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len; 490e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 491e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Be a bit paranoid here, some perf.data file came with 492e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * a zero sized synthesized MMAP event for the kernel. 493e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 494e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (maps[MAP__FUNCTION]->end == 0) 495e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng maps[MAP__FUNCTION]->end = ~0ULL; 496e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 497e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 498e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int perf_event__process_kernel_mmap(union perf_event *event, 499e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 500e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 501e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 502e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char kmmap_prefix[PATH_MAX]; 503e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine; 504e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum dso_kernel_type kernel_type; 505e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng bool is_kernel_mmap; 506e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 507e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = perf_session__findnew_machine(session, event->mmap.pid); 508e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!machine) { 509e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng pr_err("Can't find id %d's machine\n", event->mmap.pid); 510e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 511e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 512e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 513e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); 514e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__is_host(machine)) 515e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng kernel_type = DSO_TYPE_KERNEL; 516e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 517e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng kernel_type = DSO_TYPE_GUEST_KERNEL; 518e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 519e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng is_kernel_mmap = memcmp(event->mmap.filename, 520e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng kmmap_prefix, 521e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlen(kmmap_prefix)) == 0; 522e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (event->mmap.filename[0] == '/' || 523e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 524e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 525e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char short_module_name[1024]; 526e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *name, *dot; 527e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 528e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (event->mmap.filename[0] == '/') { 529e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng name = strrchr(event->mmap.filename, '/'); 530e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (name == NULL) 531e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 532e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 533e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ++name; /* skip / */ 534e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dot = strrchr(name, '.'); 535e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (dot == NULL) 536e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 537e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng snprintf(short_module_name, sizeof(short_module_name), 538e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng "[%.*s]", (int)(dot - name), name); 539e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strxfrchar(short_module_name, '-', '_'); 540e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 541e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strcpy(short_module_name, event->mmap.filename); 542e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 543e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map = machine__new_module(machine, event->mmap.start, 544e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.filename); 545e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map == NULL) 546e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 547e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 548e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng name = strdup(short_module_name); 549e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (name == NULL) 550e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 551e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 552e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map->dso->short_name = name; 553e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map->dso->sname_alloc = 1; 554e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map->end = map->start + event->mmap.len; 555e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (is_kernel_mmap) { 556e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng const char *symbol_name = (event->mmap.filename + 557e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlen(kmmap_prefix)); 558e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 559e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Should be there already, from the build-id table in 560e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * the header. 561e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 562e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, 563e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng kmmap_prefix); 564e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (kernel == NULL) 565e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 566e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 567e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng kernel->kernel = kernel_type; 568e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (__machine__create_kernel_maps(machine, kernel) < 0) 569e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 570e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 571e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); 572e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 573e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 574e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Avoid using a zero address (kptr_restrict) for the ref reloc 575e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * symbol. Effectively having zero here means that at record 576e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * time /proc/sys/kernel/kptr_restrict was non zero. 577e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 578e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (event->mmap.pgoff != 0) { 579e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 580e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_name, 581e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pgoff); 582e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 583e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 584e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine__is_default_guest(machine)) { 585e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 586e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * preload dso of guest kernel and modules 587e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 588e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], 589e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng NULL); 590e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 591e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 592e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 593e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_problem: 594e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 595e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 596e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 597e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__process_mmap(union perf_event *event, 598e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_sample *sample __used, 599e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 600e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 601e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine; 602e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread; 603e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map *map; 604e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 605e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng int ret = 0; 606e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 607e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 608e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pid, event->mmap.tid, event->mmap.start, 609e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.len, event->mmap.pgoff, event->mmap.filename); 610e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 611e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 612e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpumode == PERF_RECORD_MISC_KERNEL) { 613e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng ret = perf_event__process_kernel_mmap(event, session); 614e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (ret < 0) 615e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 616e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 617e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 618e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 619e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = perf_session__find_host_machine(session); 620e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine == NULL) 621e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 622e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng thread = perf_session__findnew(session, event->mmap.pid); 623e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (thread == NULL) 624e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 625e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng map = map__new(&machine->user_dsos, event->mmap.start, 626e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.len, event->mmap.pgoff, 627e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->mmap.pid, event->mmap.filename, 628e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng MAP__FUNCTION); 629e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (map == NULL) 630e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_problem; 631e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 632e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng thread__insert_map(thread, map); 633e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 634e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 635e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_problem: 636e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); 637e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 638e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 639e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 640e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__process_task(union perf_event *event, 641e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_sample *sample __used, 642e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 643e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 644e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread = perf_session__findnew(session, event->fork.tid); 645e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *parent = perf_session__findnew(session, event->fork.ptid); 646e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 647e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 648e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->fork.ppid, event->fork.ptid); 649e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 650e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (event->header.type == PERF_RECORD_EXIT) { 651e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_session__remove_thread(session, thread); 652e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 653e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 654e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 655e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (thread == NULL || parent == NULL || 656e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng thread__fork(thread, parent) < 0) { 657e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 658e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 659e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 660e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 661e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 662e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 663e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 664e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__process(union perf_event *event, struct perf_sample *sample, 665e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session) 666e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 667e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng switch (event->header.type) { 668e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case PERF_RECORD_COMM: 669e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__process_comm(event, sample, session); 670e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 671e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case PERF_RECORD_MMAP: 672e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__process_mmap(event, sample, session); 673e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 674e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case PERF_RECORD_FORK: 675e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case PERF_RECORD_EXIT: 676e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__process_task(event, sample, session); 677e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 678e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng case PERF_RECORD_LOST: 679e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng perf_event__process_lost(event, sample, session); 680e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng default: 681e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng break; 682e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 683e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 684e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 685e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 686e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 687e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid thread__find_addr_map(struct thread *self, 688e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session, u8 cpumode, 689e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type, pid_t pid, u64 addr, 690e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct addr_location *al) 691e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 692e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct map_groups *mg = &self->mg; 693e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct machine *machine = NULL; 694e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 695e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->thread = self; 696e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->addr = addr; 697e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->cpumode = cpumode; 698e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->filtered = false; 699e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 700e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 701e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->level = 'k'; 702e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = perf_session__find_host_machine(session); 703e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine == NULL) { 704e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map = NULL; 705e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 706e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 707e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mg = &machine->kmaps; 708e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 709e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->level = '.'; 710e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = perf_session__find_host_machine(session); 711e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 712e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->level = 'g'; 713e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine = perf_session__find_machine(session, pid); 714e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (machine == NULL) { 715e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map = NULL; 716e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 717e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 718e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mg = &machine->kmaps; 719e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else { 720e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 721e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 'u' means guest os user space. 722e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * TODO: We don't support guest user space. Might support late. 723e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 724e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) 725e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->level = 'u'; 726e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 727e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->level = 'H'; 728e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map = NULL; 729e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 730e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((cpumode == PERF_RECORD_MISC_GUEST_USER || 731e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && 732e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !perf_guest) 733e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->filtered = true; 734e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((cpumode == PERF_RECORD_MISC_USER || 735e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpumode == PERF_RECORD_MISC_KERNEL) && 736e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !perf_host) 737e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->filtered = true; 738e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 739e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return; 740e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 741e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengtry_again: 742e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map = map_groups__find(mg, type, al->addr); 743e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (al->map == NULL) { 744e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 745e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * If this is outside of all known maps, and is a negative 746e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * address, try to look it up in the kernel dso, as it might be 747e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * a vsyscall or vdso (which executes in user-mode). 748e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 749e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * XXX This is nasty, we should have a symbol list in the 750e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * "[vdso]" dso, but for now lets use the old trick of looking 751e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * in the whole kernel symbol list. 752e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 753e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if ((long long)al->addr < 0 && 754e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng cpumode == PERF_RECORD_MISC_USER && 755e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine && mg != &machine->kmaps) { 756e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng mg = &machine->kmaps; 757e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto try_again; 758e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 759e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } else 760e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->addr = al->map->map_ip(al->map, al->addr); 761e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 762e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 763e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengvoid thread__find_addr_location(struct thread *self, 764e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session, u8 cpumode, 765e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng enum map_type type, pid_t pid, u64 addr, 766e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct addr_location *al, 767e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_filter_t filter) 768e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 769e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng thread__find_addr_map(self, session, cpumode, type, pid, addr, al); 770e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (al->map != NULL) 771e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->sym = map__find_symbol(al->map, al->addr, filter); 772e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng else 773e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->sym = NULL; 774e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 775e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 776e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint perf_event__preprocess_sample(const union perf_event *event, 777e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_session *session, 778e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct addr_location *al, 779e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct perf_sample *sample, 780e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng symbol_filter_t filter) 781e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{ 782e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 783e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng struct thread *thread = perf_session__findnew(session, event->ip.pid); 784e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 785e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (thread == NULL) 786e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return -1; 787e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 788e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (symbol_conf.comm_list && 789e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !strlist__has_entry(symbol_conf.comm_list, thread->comm)) 790e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_filtered; 791e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 792e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 793e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng /* 794e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Have we already created the kernel maps for the host machine? 795e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 796e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * This should have happened earlier, when we processed the kernel MMAP 797e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * events, but for older perf.data files there was no such thing, so do 798e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * it now. 799e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 800e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (cpumode == PERF_RECORD_MISC_KERNEL && 801e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) 802e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng machine__create_kernel_maps(&session->host_machine); 803e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 804e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 805e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng event->ip.pid, event->ip.ip, al); 806e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng dump_printf(" ...... dso: %s\n", 807e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map ? al->map->dso->long_name : 808e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->level == 'H' ? "[hypervisor]" : "<not found>"); 809e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->sym = NULL; 810e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->cpu = sample->cpu; 811e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 812e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (al->map) { 813e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (symbol_conf.dso_list && 814e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (!al->map || !al->map->dso || 815e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !(strlist__has_entry(symbol_conf.dso_list, 816e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map->dso->short_name) || 817e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng (al->map->dso->short_name != al->map->dso->long_name && 818e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strlist__has_entry(symbol_conf.dso_list, 819e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->map->dso->long_name))))) 820e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_filtered; 821e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 822e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->sym = map__find_symbol(al->map, al->addr, filter); 823e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng } 824e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 825e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (symbol_conf.sym_list && al->sym && 826e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) 827e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng goto out_filtered; 828e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 829e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 830e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 831e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengout_filtered: 832e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng al->filtered = true; 833e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return 0; 834e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 835