diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
commit | a292241cccb7e20e8b997a9a44177e7c98141859 (patch) | |
tree | a0b0bb95e7dce3233a2d8b203f9e326cdec7a00e /tools/perf/util/machine.c | |
parent | d49cb7aeebb974713f9f7ab2991352d3050b095b (diff) | |
parent | 68807a0c2015cb40df4869e16651f0ce5cc14d52 (diff) |
Merge branch 'next' into for-linus
Prepare input updates for 3.16.
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r-- | tools/perf/util/machine.c | 95 |
1 files changed, 44 insertions, 51 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index c872991e0f65..27c2a5efe450 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -327,9 +327,10 @@ struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, | |||
327 | return __machine__findnew_thread(machine, pid, tid, true); | 327 | return __machine__findnew_thread(machine, pid, tid, true); |
328 | } | 328 | } |
329 | 329 | ||
330 | struct thread *machine__find_thread(struct machine *machine, pid_t tid) | 330 | struct thread *machine__find_thread(struct machine *machine, pid_t pid, |
331 | pid_t tid) | ||
331 | { | 332 | { |
332 | return __machine__findnew_thread(machine, 0, tid, false); | 333 | return __machine__findnew_thread(machine, pid, tid, false); |
333 | } | 334 | } |
334 | 335 | ||
335 | int machine__process_comm_event(struct machine *machine, union perf_event *event, | 336 | int machine__process_comm_event(struct machine *machine, union perf_event *event, |
@@ -716,7 +717,7 @@ static char *get_kernel_version(const char *root_dir) | |||
716 | } | 717 | } |
717 | 718 | ||
718 | static int map_groups__set_modules_path_dir(struct map_groups *mg, | 719 | static int map_groups__set_modules_path_dir(struct map_groups *mg, |
719 | const char *dir_name) | 720 | const char *dir_name, int depth) |
720 | { | 721 | { |
721 | struct dirent *dent; | 722 | struct dirent *dent; |
722 | DIR *dir = opendir(dir_name); | 723 | DIR *dir = opendir(dir_name); |
@@ -741,7 +742,15 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg, | |||
741 | !strcmp(dent->d_name, "..")) | 742 | !strcmp(dent->d_name, "..")) |
742 | continue; | 743 | continue; |
743 | 744 | ||
744 | ret = map_groups__set_modules_path_dir(mg, path); | 745 | /* Do not follow top-level source and build symlinks */ |
746 | if (depth == 0) { | ||
747 | if (!strcmp(dent->d_name, "source") || | ||
748 | !strcmp(dent->d_name, "build")) | ||
749 | continue; | ||
750 | } | ||
751 | |||
752 | ret = map_groups__set_modules_path_dir(mg, path, | ||
753 | depth + 1); | ||
745 | if (ret < 0) | 754 | if (ret < 0) |
746 | goto out; | 755 | goto out; |
747 | } else { | 756 | } else { |
@@ -785,11 +794,11 @@ static int machine__set_modules_path(struct machine *machine) | |||
785 | if (!version) | 794 | if (!version) |
786 | return -1; | 795 | return -1; |
787 | 796 | ||
788 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", | 797 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s", |
789 | machine->root_dir, version); | 798 | machine->root_dir, version); |
790 | free(version); | 799 | free(version); |
791 | 800 | ||
792 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); | 801 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); |
793 | } | 802 | } |
794 | 803 | ||
795 | static int machine__create_module(void *arg, const char *name, u64 start) | 804 | static int machine__create_module(void *arg, const char *name, u64 start) |
@@ -1026,7 +1035,7 @@ int machine__process_mmap2_event(struct machine *machine, | |||
1026 | } | 1035 | } |
1027 | 1036 | ||
1028 | thread = machine__findnew_thread(machine, event->mmap2.pid, | 1037 | thread = machine__findnew_thread(machine, event->mmap2.pid, |
1029 | event->mmap2.pid); | 1038 | event->mmap2.tid); |
1030 | if (thread == NULL) | 1039 | if (thread == NULL) |
1031 | goto out_problem; | 1040 | goto out_problem; |
1032 | 1041 | ||
@@ -1074,7 +1083,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
1074 | } | 1083 | } |
1075 | 1084 | ||
1076 | thread = machine__findnew_thread(machine, event->mmap.pid, | 1085 | thread = machine__findnew_thread(machine, event->mmap.pid, |
1077 | event->mmap.pid); | 1086 | event->mmap.tid); |
1078 | if (thread == NULL) | 1087 | if (thread == NULL) |
1079 | goto out_problem; | 1088 | goto out_problem; |
1080 | 1089 | ||
@@ -1114,7 +1123,9 @@ static void machine__remove_thread(struct machine *machine, struct thread *th) | |||
1114 | int machine__process_fork_event(struct machine *machine, union perf_event *event, | 1123 | int machine__process_fork_event(struct machine *machine, union perf_event *event, |
1115 | struct perf_sample *sample) | 1124 | struct perf_sample *sample) |
1116 | { | 1125 | { |
1117 | struct thread *thread = machine__find_thread(machine, event->fork.tid); | 1126 | struct thread *thread = machine__find_thread(machine, |
1127 | event->fork.pid, | ||
1128 | event->fork.tid); | ||
1118 | struct thread *parent = machine__findnew_thread(machine, | 1129 | struct thread *parent = machine__findnew_thread(machine, |
1119 | event->fork.ppid, | 1130 | event->fork.ppid, |
1120 | event->fork.ptid); | 1131 | event->fork.ptid); |
@@ -1140,7 +1151,9 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event | |||
1140 | int machine__process_exit_event(struct machine *machine, union perf_event *event, | 1151 | int machine__process_exit_event(struct machine *machine, union perf_event *event, |
1141 | struct perf_sample *sample __maybe_unused) | 1152 | struct perf_sample *sample __maybe_unused) |
1142 | { | 1153 | { |
1143 | struct thread *thread = machine__find_thread(machine, event->fork.tid); | 1154 | struct thread *thread = machine__find_thread(machine, |
1155 | event->fork.pid, | ||
1156 | event->fork.tid); | ||
1144 | 1157 | ||
1145 | if (dump_trace) | 1158 | if (dump_trace) |
1146 | perf_event__fprintf_task(event, stdout); | 1159 | perf_event__fprintf_task(event, stdout); |
@@ -1184,39 +1197,22 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex) | |||
1184 | return 0; | 1197 | return 0; |
1185 | } | 1198 | } |
1186 | 1199 | ||
1187 | static const u8 cpumodes[] = { | ||
1188 | PERF_RECORD_MISC_USER, | ||
1189 | PERF_RECORD_MISC_KERNEL, | ||
1190 | PERF_RECORD_MISC_GUEST_USER, | ||
1191 | PERF_RECORD_MISC_GUEST_KERNEL | ||
1192 | }; | ||
1193 | #define NCPUMODES (sizeof(cpumodes)/sizeof(u8)) | ||
1194 | |||
1195 | static void ip__resolve_ams(struct machine *machine, struct thread *thread, | 1200 | static void ip__resolve_ams(struct machine *machine, struct thread *thread, |
1196 | struct addr_map_symbol *ams, | 1201 | struct addr_map_symbol *ams, |
1197 | u64 ip) | 1202 | u64 ip) |
1198 | { | 1203 | { |
1199 | struct addr_location al; | 1204 | struct addr_location al; |
1200 | size_t i; | ||
1201 | u8 m; | ||
1202 | 1205 | ||
1203 | memset(&al, 0, sizeof(al)); | 1206 | memset(&al, 0, sizeof(al)); |
1207 | /* | ||
1208 | * We cannot use the header.misc hint to determine whether a | ||
1209 | * branch stack address is user, kernel, guest, hypervisor. | ||
1210 | * Branches may straddle the kernel/user/hypervisor boundaries. | ||
1211 | * Thus, we have to try consecutively until we find a match | ||
1212 | * or else, the symbol is unknown | ||
1213 | */ | ||
1214 | thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al); | ||
1204 | 1215 | ||
1205 | for (i = 0; i < NCPUMODES; i++) { | ||
1206 | m = cpumodes[i]; | ||
1207 | /* | ||
1208 | * We cannot use the header.misc hint to determine whether a | ||
1209 | * branch stack address is user, kernel, guest, hypervisor. | ||
1210 | * Branches may straddle the kernel/user/hypervisor boundaries. | ||
1211 | * Thus, we have to try consecutively until we find a match | ||
1212 | * or else, the symbol is unknown | ||
1213 | */ | ||
1214 | thread__find_addr_location(thread, machine, m, MAP__FUNCTION, | ||
1215 | ip, &al); | ||
1216 | if (al.sym) | ||
1217 | goto found; | ||
1218 | } | ||
1219 | found: | ||
1220 | ams->addr = ip; | 1216 | ams->addr = ip; |
1221 | ams->al_addr = al.addr; | 1217 | ams->al_addr = al.addr; |
1222 | ams->sym = al.sym; | 1218 | ams->sym = al.sym; |
@@ -1238,37 +1234,35 @@ static void ip__resolve_data(struct machine *machine, struct thread *thread, | |||
1238 | ams->map = al.map; | 1234 | ams->map = al.map; |
1239 | } | 1235 | } |
1240 | 1236 | ||
1241 | struct mem_info *machine__resolve_mem(struct machine *machine, | 1237 | struct mem_info *sample__resolve_mem(struct perf_sample *sample, |
1242 | struct thread *thr, | 1238 | struct addr_location *al) |
1243 | struct perf_sample *sample, | ||
1244 | u8 cpumode) | ||
1245 | { | 1239 | { |
1246 | struct mem_info *mi = zalloc(sizeof(*mi)); | 1240 | struct mem_info *mi = zalloc(sizeof(*mi)); |
1247 | 1241 | ||
1248 | if (!mi) | 1242 | if (!mi) |
1249 | return NULL; | 1243 | return NULL; |
1250 | 1244 | ||
1251 | ip__resolve_ams(machine, thr, &mi->iaddr, sample->ip); | 1245 | ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip); |
1252 | ip__resolve_data(machine, thr, cpumode, &mi->daddr, sample->addr); | 1246 | ip__resolve_data(al->machine, al->thread, al->cpumode, |
1247 | &mi->daddr, sample->addr); | ||
1253 | mi->data_src.val = sample->data_src; | 1248 | mi->data_src.val = sample->data_src; |
1254 | 1249 | ||
1255 | return mi; | 1250 | return mi; |
1256 | } | 1251 | } |
1257 | 1252 | ||
1258 | struct branch_info *machine__resolve_bstack(struct machine *machine, | 1253 | struct branch_info *sample__resolve_bstack(struct perf_sample *sample, |
1259 | struct thread *thr, | 1254 | struct addr_location *al) |
1260 | struct branch_stack *bs) | ||
1261 | { | 1255 | { |
1262 | struct branch_info *bi; | ||
1263 | unsigned int i; | 1256 | unsigned int i; |
1257 | const struct branch_stack *bs = sample->branch_stack; | ||
1258 | struct branch_info *bi = calloc(bs->nr, sizeof(struct branch_info)); | ||
1264 | 1259 | ||
1265 | bi = calloc(bs->nr, sizeof(struct branch_info)); | ||
1266 | if (!bi) | 1260 | if (!bi) |
1267 | return NULL; | 1261 | return NULL; |
1268 | 1262 | ||
1269 | for (i = 0; i < bs->nr; i++) { | 1263 | for (i = 0; i < bs->nr; i++) { |
1270 | ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to); | 1264 | ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to); |
1271 | ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from); | 1265 | ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from); |
1272 | bi[i].flags = bs->entries[i].flags; | 1266 | bi[i].flags = bs->entries[i].flags; |
1273 | } | 1267 | } |
1274 | return bi; | 1268 | return bi; |
@@ -1326,7 +1320,7 @@ static int machine__resolve_callchain_sample(struct machine *machine, | |||
1326 | continue; | 1320 | continue; |
1327 | } | 1321 | } |
1328 | 1322 | ||
1329 | al.filtered = false; | 1323 | al.filtered = 0; |
1330 | thread__find_addr_location(thread, machine, cpumode, | 1324 | thread__find_addr_location(thread, machine, cpumode, |
1331 | MAP__FUNCTION, ip, &al); | 1325 | MAP__FUNCTION, ip, &al); |
1332 | if (al.sym != NULL) { | 1326 | if (al.sym != NULL) { |
@@ -1385,8 +1379,7 @@ int machine__resolve_callchain(struct machine *machine, | |||
1385 | return 0; | 1379 | return 0; |
1386 | 1380 | ||
1387 | return unwind__get_entries(unwind_entry, &callchain_cursor, machine, | 1381 | return unwind__get_entries(unwind_entry, &callchain_cursor, machine, |
1388 | thread, evsel->attr.sample_regs_user, | 1382 | thread, sample, max_stack); |
1389 | sample, max_stack); | ||
1390 | 1383 | ||
1391 | } | 1384 | } |
1392 | 1385 | ||