aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/machine.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r--tools/perf/util/machine.c180
1 files changed, 105 insertions, 75 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6188d2876a71..84cdb072ac83 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -40,12 +40,29 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
40 return -ENOMEM; 40 return -ENOMEM;
41 41
42 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 42 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
43 thread__set_comm(thread, comm); 43 thread__set_comm(thread, comm, 0);
44 } 44 }
45 45
46 return 0; 46 return 0;
47} 47}
48 48
49struct machine *machine__new_host(void)
50{
51 struct machine *machine = malloc(sizeof(*machine));
52
53 if (machine != NULL) {
54 machine__init(machine, "", HOST_KERNEL_ID);
55
56 if (machine__create_kernel_maps(machine) < 0)
57 goto out_delete;
58 }
59
60 return machine;
61out_delete:
62 free(machine);
63 return NULL;
64}
65
49static void dsos__delete(struct list_head *dsos) 66static void dsos__delete(struct list_head *dsos)
50{ 67{
51 struct dso *pos, *n; 68 struct dso *pos, *n;
@@ -314,7 +331,8 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid)
314 return __machine__findnew_thread(machine, 0, tid, false); 331 return __machine__findnew_thread(machine, 0, tid, false);
315} 332}
316 333
317int machine__process_comm_event(struct machine *machine, union perf_event *event) 334int machine__process_comm_event(struct machine *machine, union perf_event *event,
335 struct perf_sample *sample)
318{ 336{
319 struct thread *thread = machine__findnew_thread(machine, 337 struct thread *thread = machine__findnew_thread(machine,
320 event->comm.pid, 338 event->comm.pid,
@@ -323,7 +341,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
323 if (dump_trace) 341 if (dump_trace)
324 perf_event__fprintf_comm(event, stdout); 342 perf_event__fprintf_comm(event, stdout);
325 343
326 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 344 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
327 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 345 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
328 return -1; 346 return -1;
329 } 347 }
@@ -332,7 +350,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
332} 350}
333 351
334int machine__process_lost_event(struct machine *machine __maybe_unused, 352int machine__process_lost_event(struct machine *machine __maybe_unused,
335 union perf_event *event) 353 union perf_event *event, struct perf_sample *sample __maybe_unused)
336{ 354{
337 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 355 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
338 event->lost.id, event->lost.lost); 356 event->lost.id, event->lost.lost);
@@ -776,75 +794,44 @@ static int machine__set_modules_path(struct machine *machine)
776 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 794 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
777} 795}
778 796
779static int machine__create_modules(struct machine *machine) 797static int machine__create_module(void *arg, const char *name, u64 start)
780{ 798{
781 char *line = NULL; 799 struct machine *machine = arg;
782 size_t n;
783 FILE *file;
784 struct map *map; 800 struct map *map;
801
802 map = machine__new_module(machine, start, name);
803 if (map == NULL)
804 return -1;
805
806 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
807
808 return 0;
809}
810
811static int machine__create_modules(struct machine *machine)
812{
785 const char *modules; 813 const char *modules;
786 char path[PATH_MAX]; 814 char path[PATH_MAX];
787 815
788 if (machine__is_default_guest(machine)) 816 if (machine__is_default_guest(machine)) {
789 modules = symbol_conf.default_guest_modules; 817 modules = symbol_conf.default_guest_modules;
790 else { 818 } else {
791 sprintf(path, "%s/proc/modules", machine->root_dir); 819 snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);
792 modules = path; 820 modules = path;
793 } 821 }
794 822
795 if (symbol__restricted_filename(modules, "/proc/modules")) 823 if (symbol__restricted_filename(modules, "/proc/modules"))
796 return -1; 824 return -1;
797 825
798 file = fopen(modules, "r"); 826 if (modules__parse(modules, machine, machine__create_module))
799 if (file == NULL)
800 return -1; 827 return -1;
801 828
802 while (!feof(file)) { 829 if (!machine__set_modules_path(machine))
803 char name[PATH_MAX]; 830 return 0;
804 u64 start;
805 char *sep;
806 int line_len;
807
808 line_len = getline(&line, &n, file);
809 if (line_len < 0)
810 break;
811
812 if (!line)
813 goto out_failure;
814
815 line[--line_len] = '\0'; /* \n */
816
817 sep = strrchr(line, 'x');
818 if (sep == NULL)
819 continue;
820
821 hex2u64(sep + 1, &start);
822
823 sep = strchr(line, ' ');
824 if (sep == NULL)
825 continue;
826
827 *sep = '\0';
828
829 snprintf(name, sizeof(name), "[%s]", line);
830 map = machine__new_module(machine, start, name);
831 if (map == NULL)
832 goto out_delete_line;
833 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
834 }
835 831
836 free(line); 832 pr_debug("Problems setting modules path maps, continuing anyway...\n");
837 fclose(file);
838 833
839 if (machine__set_modules_path(machine) < 0) {
840 pr_debug("Problems setting modules path maps, continuing anyway...\n");
841 }
842 return 0; 834 return 0;
843
844out_delete_line:
845 free(line);
846out_failure:
847 return -1;
848} 835}
849 836
850int machine__create_kernel_maps(struct machine *machine) 837int machine__create_kernel_maps(struct machine *machine)
@@ -998,7 +985,8 @@ out_problem:
998} 985}
999 986
1000int machine__process_mmap2_event(struct machine *machine, 987int machine__process_mmap2_event(struct machine *machine,
1001 union perf_event *event) 988 union perf_event *event,
989 struct perf_sample *sample __maybe_unused)
1002{ 990{
1003 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 991 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1004 struct thread *thread; 992 struct thread *thread;
@@ -1045,7 +1033,8 @@ out_problem:
1045 return 0; 1033 return 0;
1046} 1034}
1047 1035
1048int machine__process_mmap_event(struct machine *machine, union perf_event *event) 1036int machine__process_mmap_event(struct machine *machine, union perf_event *event,
1037 struct perf_sample *sample __maybe_unused)
1049{ 1038{
1050 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1039 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1051 struct thread *thread; 1040 struct thread *thread;
@@ -1102,7 +1091,8 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)
1102 list_add_tail(&th->node, &machine->dead_threads); 1091 list_add_tail(&th->node, &machine->dead_threads);
1103} 1092}
1104 1093
1105int machine__process_fork_event(struct machine *machine, union perf_event *event) 1094int machine__process_fork_event(struct machine *machine, union perf_event *event,
1095 struct perf_sample *sample)
1106{ 1096{
1107 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1097 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1108 struct thread *parent = machine__findnew_thread(machine, 1098 struct thread *parent = machine__findnew_thread(machine,
@@ -1119,7 +1109,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1119 perf_event__fprintf_task(event, stdout); 1109 perf_event__fprintf_task(event, stdout);
1120 1110
1121 if (thread == NULL || parent == NULL || 1111 if (thread == NULL || parent == NULL ||
1122 thread__fork(thread, parent) < 0) { 1112 thread__fork(thread, parent, sample->time) < 0) {
1123 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 1113 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1124 return -1; 1114 return -1;
1125 } 1115 }
@@ -1127,8 +1117,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1127 return 0; 1117 return 0;
1128} 1118}
1129 1119
1130int machine__process_exit_event(struct machine *machine __maybe_unused, 1120int machine__process_exit_event(struct machine *machine, union perf_event *event,
1131 union perf_event *event) 1121 struct perf_sample *sample __maybe_unused)
1132{ 1122{
1133 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1123 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1134 1124
@@ -1141,23 +1131,24 @@ int machine__process_exit_event(struct machine *machine __maybe_unused,
1141 return 0; 1131 return 0;
1142} 1132}
1143 1133
1144int machine__process_event(struct machine *machine, union perf_event *event) 1134int machine__process_event(struct machine *machine, union perf_event *event,
1135 struct perf_sample *sample)
1145{ 1136{
1146 int ret; 1137 int ret;
1147 1138
1148 switch (event->header.type) { 1139 switch (event->header.type) {
1149 case PERF_RECORD_COMM: 1140 case PERF_RECORD_COMM:
1150 ret = machine__process_comm_event(machine, event); break; 1141 ret = machine__process_comm_event(machine, event, sample); break;
1151 case PERF_RECORD_MMAP: 1142 case PERF_RECORD_MMAP:
1152 ret = machine__process_mmap_event(machine, event); break; 1143 ret = machine__process_mmap_event(machine, event, sample); break;
1153 case PERF_RECORD_MMAP2: 1144 case PERF_RECORD_MMAP2:
1154 ret = machine__process_mmap2_event(machine, event); break; 1145 ret = machine__process_mmap2_event(machine, event, sample); break;
1155 case PERF_RECORD_FORK: 1146 case PERF_RECORD_FORK:
1156 ret = machine__process_fork_event(machine, event); break; 1147 ret = machine__process_fork_event(machine, event, sample); break;
1157 case PERF_RECORD_EXIT: 1148 case PERF_RECORD_EXIT:
1158 ret = machine__process_exit_event(machine, event); break; 1149 ret = machine__process_exit_event(machine, event, sample); break;
1159 case PERF_RECORD_LOST: 1150 case PERF_RECORD_LOST:
1160 ret = machine__process_lost_event(machine, event); break; 1151 ret = machine__process_lost_event(machine, event, sample); break;
1161 default: 1152 default:
1162 ret = -1; 1153 ret = -1;
1163 break; 1154 break;
@@ -1267,10 +1258,12 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1267 struct thread *thread, 1258 struct thread *thread,
1268 struct ip_callchain *chain, 1259 struct ip_callchain *chain,
1269 struct symbol **parent, 1260 struct symbol **parent,
1270 struct addr_location *root_al) 1261 struct addr_location *root_al,
1262 int max_stack)
1271{ 1263{
1272 u8 cpumode = PERF_RECORD_MISC_USER; 1264 u8 cpumode = PERF_RECORD_MISC_USER;
1273 unsigned int i; 1265 int chain_nr = min(max_stack, (int)chain->nr);
1266 int i;
1274 int err; 1267 int err;
1275 1268
1276 callchain_cursor_reset(&callchain_cursor); 1269 callchain_cursor_reset(&callchain_cursor);
@@ -1280,7 +1273,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1280 return 0; 1273 return 0;
1281 } 1274 }
1282 1275
1283 for (i = 0; i < chain->nr; i++) { 1276 for (i = 0; i < chain_nr; i++) {
1284 u64 ip; 1277 u64 ip;
1285 struct addr_location al; 1278 struct addr_location al;
1286 1279
@@ -1352,12 +1345,14 @@ int machine__resolve_callchain(struct machine *machine,
1352 struct thread *thread, 1345 struct thread *thread,
1353 struct perf_sample *sample, 1346 struct perf_sample *sample,
1354 struct symbol **parent, 1347 struct symbol **parent,
1355 struct addr_location *root_al) 1348 struct addr_location *root_al,
1349 int max_stack)
1356{ 1350{
1357 int ret; 1351 int ret;
1358 1352
1359 ret = machine__resolve_callchain_sample(machine, thread, 1353 ret = machine__resolve_callchain_sample(machine, thread,
1360 sample->callchain, parent, root_al); 1354 sample->callchain, parent,
1355 root_al, max_stack);
1361 if (ret) 1356 if (ret)
1362 return ret; 1357 return ret;
1363 1358
@@ -1373,6 +1368,41 @@ int machine__resolve_callchain(struct machine *machine,
1373 1368
1374 return unwind__get_entries(unwind_entry, &callchain_cursor, machine, 1369 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
1375 thread, evsel->attr.sample_regs_user, 1370 thread, evsel->attr.sample_regs_user,
1376 sample); 1371 sample, max_stack);
1377 1372
1378} 1373}
1374
1375int machine__for_each_thread(struct machine *machine,
1376 int (*fn)(struct thread *thread, void *p),
1377 void *priv)
1378{
1379 struct rb_node *nd;
1380 struct thread *thread;
1381 int rc = 0;
1382
1383 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
1384 thread = rb_entry(nd, struct thread, rb_node);
1385 rc = fn(thread, priv);
1386 if (rc != 0)
1387 return rc;
1388 }
1389
1390 list_for_each_entry(thread, &machine->dead_threads, node) {
1391 rc = fn(thread, priv);
1392 if (rc != 0)
1393 return rc;
1394 }
1395 return rc;
1396}
1397
1398int __machine__synthesize_threads(struct machine *machine, struct perf_tool *tool,
1399 struct target *target, struct thread_map *threads,
1400 perf_event__handler_t process, bool data_mmap)
1401{
1402 if (target__has_task(target))
1403 return perf_event__synthesize_thread_map(tool, threads, process, machine, data_mmap);
1404 else if (target__has_cpu(target))
1405 return perf_event__synthesize_threads(tool, process, machine, data_mmap);
1406 /* command specified */
1407 return 0;
1408}