diff options
Diffstat (limited to 'tools/perf/util/map.c')
-rw-r--r-- | tools/perf/util/map.c | 116 |
1 files changed, 85 insertions, 31 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index e672f2fef65b..3a7eb6ec0eec 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -17,16 +17,6 @@ static inline int is_anon_memory(const char *filename) | |||
17 | return strcmp(filename, "//anon") == 0; | 17 | return strcmp(filename, "//anon") == 0; |
18 | } | 18 | } |
19 | 19 | ||
20 | static int strcommon(const char *pathname, char *cwd, int cwdlen) | ||
21 | { | ||
22 | int n = 0; | ||
23 | |||
24 | while (n < cwdlen && pathname[n] == cwd[n]) | ||
25 | ++n; | ||
26 | |||
27 | return n; | ||
28 | } | ||
29 | |||
30 | void map__init(struct map *self, enum map_type type, | 20 | void map__init(struct map *self, enum map_type type, |
31 | u64 start, u64 end, u64 pgoff, struct dso *dso) | 21 | u64 start, u64 end, u64 pgoff, struct dso *dso) |
32 | { | 22 | { |
@@ -39,11 +29,12 @@ void map__init(struct map *self, enum map_type type, | |||
39 | self->unmap_ip = map__unmap_ip; | 29 | self->unmap_ip = map__unmap_ip; |
40 | RB_CLEAR_NODE(&self->rb_node); | 30 | RB_CLEAR_NODE(&self->rb_node); |
41 | self->groups = NULL; | 31 | self->groups = NULL; |
32 | self->referenced = false; | ||
42 | } | 33 | } |
43 | 34 | ||
44 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 35 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
45 | u64 pgoff, u32 pid, char *filename, | 36 | u64 pgoff, u32 pid, char *filename, |
46 | enum map_type type, char *cwd, int cwdlen) | 37 | enum map_type type) |
47 | { | 38 | { |
48 | struct map *self = malloc(sizeof(*self)); | 39 | struct map *self = malloc(sizeof(*self)); |
49 | 40 | ||
@@ -52,16 +43,6 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
52 | struct dso *dso; | 43 | struct dso *dso; |
53 | int anon; | 44 | int anon; |
54 | 45 | ||
55 | if (cwd) { | ||
56 | int n = strcommon(filename, cwd, cwdlen); | ||
57 | |||
58 | if (n == cwdlen) { | ||
59 | snprintf(newfilename, sizeof(newfilename), | ||
60 | ".%s", filename + n); | ||
61 | filename = newfilename; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | anon = is_anon_memory(filename); | 46 | anon = is_anon_memory(filename); |
66 | 47 | ||
67 | if (anon) { | 48 | if (anon) { |
@@ -248,6 +229,39 @@ void map_groups__init(struct map_groups *self) | |||
248 | self->machine = NULL; | 229 | self->machine = NULL; |
249 | } | 230 | } |
250 | 231 | ||
232 | static void maps__delete(struct rb_root *self) | ||
233 | { | ||
234 | struct rb_node *next = rb_first(self); | ||
235 | |||
236 | while (next) { | ||
237 | struct map *pos = rb_entry(next, struct map, rb_node); | ||
238 | |||
239 | next = rb_next(&pos->rb_node); | ||
240 | rb_erase(&pos->rb_node, self); | ||
241 | map__delete(pos); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | static void maps__delete_removed(struct list_head *self) | ||
246 | { | ||
247 | struct map *pos, *n; | ||
248 | |||
249 | list_for_each_entry_safe(pos, n, self, node) { | ||
250 | list_del(&pos->node); | ||
251 | map__delete(pos); | ||
252 | } | ||
253 | } | ||
254 | |||
255 | void map_groups__exit(struct map_groups *self) | ||
256 | { | ||
257 | int i; | ||
258 | |||
259 | for (i = 0; i < MAP__NR_TYPES; ++i) { | ||
260 | maps__delete(&self->maps[i]); | ||
261 | maps__delete_removed(&self->removed_maps[i]); | ||
262 | } | ||
263 | } | ||
264 | |||
251 | void map_groups__flush(struct map_groups *self) | 265 | void map_groups__flush(struct map_groups *self) |
252 | { | 266 | { |
253 | int type; | 267 | int type; |
@@ -374,6 +388,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
374 | { | 388 | { |
375 | struct rb_root *root = &self->maps[map->type]; | 389 | struct rb_root *root = &self->maps[map->type]; |
376 | struct rb_node *next = rb_first(root); | 390 | struct rb_node *next = rb_first(root); |
391 | int err = 0; | ||
377 | 392 | ||
378 | while (next) { | 393 | while (next) { |
379 | struct map *pos = rb_entry(next, struct map, rb_node); | 394 | struct map *pos = rb_entry(next, struct map, rb_node); |
@@ -390,20 +405,16 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
390 | 405 | ||
391 | rb_erase(&pos->rb_node, root); | 406 | rb_erase(&pos->rb_node, root); |
392 | /* | 407 | /* |
393 | * We may have references to this map, for instance in some | ||
394 | * hist_entry instances, so just move them to a separate | ||
395 | * list. | ||
396 | */ | ||
397 | list_add_tail(&pos->node, &self->removed_maps[map->type]); | ||
398 | /* | ||
399 | * Now check if we need to create new maps for areas not | 408 | * Now check if we need to create new maps for areas not |
400 | * overlapped by the new map: | 409 | * overlapped by the new map: |
401 | */ | 410 | */ |
402 | if (map->start > pos->start) { | 411 | if (map->start > pos->start) { |
403 | struct map *before = map__clone(pos); | 412 | struct map *before = map__clone(pos); |
404 | 413 | ||
405 | if (before == NULL) | 414 | if (before == NULL) { |
406 | return -ENOMEM; | 415 | err = -ENOMEM; |
416 | goto move_map; | ||
417 | } | ||
407 | 418 | ||
408 | before->end = map->start - 1; | 419 | before->end = map->start - 1; |
409 | map_groups__insert(self, before); | 420 | map_groups__insert(self, before); |
@@ -414,14 +425,27 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, | |||
414 | if (map->end < pos->end) { | 425 | if (map->end < pos->end) { |
415 | struct map *after = map__clone(pos); | 426 | struct map *after = map__clone(pos); |
416 | 427 | ||
417 | if (after == NULL) | 428 | if (after == NULL) { |
418 | return -ENOMEM; | 429 | err = -ENOMEM; |
430 | goto move_map; | ||
431 | } | ||
419 | 432 | ||
420 | after->start = map->end + 1; | 433 | after->start = map->end + 1; |
421 | map_groups__insert(self, after); | 434 | map_groups__insert(self, after); |
422 | if (verbose >= 2) | 435 | if (verbose >= 2) |
423 | map__fprintf(after, fp); | 436 | map__fprintf(after, fp); |
424 | } | 437 | } |
438 | move_map: | ||
439 | /* | ||
440 | * If we have references, just move them to a separate list. | ||
441 | */ | ||
442 | if (pos->referenced) | ||
443 | list_add_tail(&pos->node, &self->removed_maps[map->type]); | ||
444 | else | ||
445 | map__delete(pos); | ||
446 | |||
447 | if (err) | ||
448 | return err; | ||
425 | } | 449 | } |
426 | 450 | ||
427 | return 0; | 451 | return 0; |
@@ -493,6 +517,11 @@ void maps__insert(struct rb_root *maps, struct map *map) | |||
493 | rb_insert_color(&map->rb_node, maps); | 517 | rb_insert_color(&map->rb_node, maps); |
494 | } | 518 | } |
495 | 519 | ||
520 | void maps__remove(struct rb_root *self, struct map *map) | ||
521 | { | ||
522 | rb_erase(&map->rb_node, self); | ||
523 | } | ||
524 | |||
496 | struct map *maps__find(struct rb_root *maps, u64 ip) | 525 | struct map *maps__find(struct rb_root *maps, u64 ip) |
497 | { | 526 | { |
498 | struct rb_node **p = &maps->rb_node; | 527 | struct rb_node **p = &maps->rb_node; |
@@ -526,6 +555,31 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid) | |||
526 | return self->root_dir == NULL ? -ENOMEM : 0; | 555 | return self->root_dir == NULL ? -ENOMEM : 0; |
527 | } | 556 | } |
528 | 557 | ||
558 | static void dsos__delete(struct list_head *self) | ||
559 | { | ||
560 | struct dso *pos, *n; | ||
561 | |||
562 | list_for_each_entry_safe(pos, n, self, node) { | ||
563 | list_del(&pos->node); | ||
564 | dso__delete(pos); | ||
565 | } | ||
566 | } | ||
567 | |||
568 | void machine__exit(struct machine *self) | ||
569 | { | ||
570 | map_groups__exit(&self->kmaps); | ||
571 | dsos__delete(&self->user_dsos); | ||
572 | dsos__delete(&self->kernel_dsos); | ||
573 | free(self->root_dir); | ||
574 | self->root_dir = NULL; | ||
575 | } | ||
576 | |||
577 | void machine__delete(struct machine *self) | ||
578 | { | ||
579 | machine__exit(self); | ||
580 | free(self); | ||
581 | } | ||
582 | |||
529 | struct machine *machines__add(struct rb_root *self, pid_t pid, | 583 | struct machine *machines__add(struct rb_root *self, pid_t pid, |
530 | const char *root_dir) | 584 | const char *root_dir) |
531 | { | 585 | { |