diff options
Diffstat (limited to 'tools/perf/util/map.c')
| -rw-r--r-- | tools/perf/util/map.c | 122 |
1 files changed, 120 insertions, 2 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 39cd2d0faff6..25c571f4cba6 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -32,6 +32,93 @@ static inline int is_no_dso_memory(const char *filename) | |||
| 32 | !strcmp(filename, "[heap]"); | 32 | !strcmp(filename, "[heap]"); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | static inline int is_android_lib(const char *filename) | ||
| 36 | { | ||
| 37 | return !strncmp(filename, "/data/app-lib", 13) || | ||
| 38 | !strncmp(filename, "/system/lib", 11); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline bool replace_android_lib(const char *filename, char *newfilename) | ||
| 42 | { | ||
| 43 | const char *libname; | ||
| 44 | char *app_abi; | ||
| 45 | size_t app_abi_length, new_length; | ||
| 46 | size_t lib_length = 0; | ||
| 47 | |||
| 48 | libname = strrchr(filename, '/'); | ||
| 49 | if (libname) | ||
| 50 | lib_length = strlen(libname); | ||
| 51 | |||
| 52 | app_abi = getenv("APP_ABI"); | ||
| 53 | if (!app_abi) | ||
| 54 | return false; | ||
| 55 | |||
| 56 | app_abi_length = strlen(app_abi); | ||
| 57 | |||
| 58 | if (!strncmp(filename, "/data/app-lib", 13)) { | ||
| 59 | char *apk_path; | ||
| 60 | |||
| 61 | if (!app_abi_length) | ||
| 62 | return false; | ||
| 63 | |||
| 64 | new_length = 7 + app_abi_length + lib_length; | ||
| 65 | |||
| 66 | apk_path = getenv("APK_PATH"); | ||
| 67 | if (apk_path) { | ||
| 68 | new_length += strlen(apk_path) + 1; | ||
| 69 | if (new_length > PATH_MAX) | ||
| 70 | return false; | ||
| 71 | snprintf(newfilename, new_length, | ||
| 72 | "%s/libs/%s/%s", apk_path, app_abi, libname); | ||
| 73 | } else { | ||
| 74 | if (new_length > PATH_MAX) | ||
| 75 | return false; | ||
| 76 | snprintf(newfilename, new_length, | ||
| 77 | "libs/%s/%s", app_abi, libname); | ||
| 78 | } | ||
| 79 | return true; | ||
| 80 | } | ||
| 81 | |||
| 82 | if (!strncmp(filename, "/system/lib/", 11)) { | ||
| 83 | char *ndk, *app; | ||
| 84 | const char *arch; | ||
| 85 | size_t ndk_length; | ||
| 86 | size_t app_length; | ||
| 87 | |||
| 88 | ndk = getenv("NDK_ROOT"); | ||
| 89 | app = getenv("APP_PLATFORM"); | ||
| 90 | |||
| 91 | if (!(ndk && app)) | ||
| 92 | return false; | ||
| 93 | |||
| 94 | ndk_length = strlen(ndk); | ||
| 95 | app_length = strlen(app); | ||
| 96 | |||
| 97 | if (!(ndk_length && app_length && app_abi_length)) | ||
| 98 | return false; | ||
| 99 | |||
| 100 | arch = !strncmp(app_abi, "arm", 3) ? "arm" : | ||
| 101 | !strncmp(app_abi, "mips", 4) ? "mips" : | ||
| 102 | !strncmp(app_abi, "x86", 3) ? "x86" : NULL; | ||
| 103 | |||
| 104 | if (!arch) | ||
| 105 | return false; | ||
| 106 | |||
| 107 | new_length = 27 + ndk_length + | ||
| 108 | app_length + lib_length | ||
| 109 | + strlen(arch); | ||
| 110 | |||
| 111 | if (new_length > PATH_MAX) | ||
| 112 | return false; | ||
| 113 | snprintf(newfilename, new_length, | ||
| 114 | "%s/platforms/%s/arch-%s/usr/lib/%s", | ||
| 115 | ndk, app, arch, libname); | ||
| 116 | |||
| 117 | return true; | ||
| 118 | } | ||
| 119 | return false; | ||
| 120 | } | ||
| 121 | |||
| 35 | void map__init(struct map *map, enum map_type type, | 122 | void map__init(struct map *map, enum map_type type, |
| 36 | u64 start, u64 end, u64 pgoff, struct dso *dso) | 123 | u64 start, u64 end, u64 pgoff, struct dso *dso) |
| 37 | { | 124 | { |
| @@ -51,7 +138,7 @@ void map__init(struct map *map, enum map_type type, | |||
| 51 | 138 | ||
| 52 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 139 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
| 53 | u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, | 140 | u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, |
| 54 | u64 ino_gen, char *filename, | 141 | u64 ino_gen, u32 prot, u32 flags, char *filename, |
| 55 | enum map_type type) | 142 | enum map_type type) |
| 56 | { | 143 | { |
| 57 | struct map *map = malloc(sizeof(*map)); | 144 | struct map *map = malloc(sizeof(*map)); |
| @@ -59,8 +146,9 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
| 59 | if (map != NULL) { | 146 | if (map != NULL) { |
| 60 | char newfilename[PATH_MAX]; | 147 | char newfilename[PATH_MAX]; |
| 61 | struct dso *dso; | 148 | struct dso *dso; |
| 62 | int anon, no_dso, vdso; | 149 | int anon, no_dso, vdso, android; |
| 63 | 150 | ||
| 151 | android = is_android_lib(filename); | ||
| 64 | anon = is_anon_memory(filename); | 152 | anon = is_anon_memory(filename); |
| 65 | vdso = is_vdso_map(filename); | 153 | vdso = is_vdso_map(filename); |
| 66 | no_dso = is_no_dso_memory(filename); | 154 | no_dso = is_no_dso_memory(filename); |
| @@ -69,12 +157,19 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
| 69 | map->min = d_min; | 157 | map->min = d_min; |
| 70 | map->ino = ino; | 158 | map->ino = ino; |
| 71 | map->ino_generation = ino_gen; | 159 | map->ino_generation = ino_gen; |
| 160 | map->prot = prot; | ||
| 161 | map->flags = flags; | ||
| 72 | 162 | ||
| 73 | if ((anon || no_dso) && type == MAP__FUNCTION) { | 163 | if ((anon || no_dso) && type == MAP__FUNCTION) { |
| 74 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); | 164 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); |
| 75 | filename = newfilename; | 165 | filename = newfilename; |
| 76 | } | 166 | } |
| 77 | 167 | ||
| 168 | if (android) { | ||
| 169 | if (replace_android_lib(filename, newfilename)) | ||
| 170 | filename = newfilename; | ||
| 171 | } | ||
| 172 | |||
| 78 | if (vdso) { | 173 | if (vdso) { |
| 79 | pgoff = 0; | 174 | pgoff = 0; |
| 80 | dso = vdso__dso_findnew(dsos__list); | 175 | dso = vdso__dso_findnew(dsos__list); |
| @@ -323,6 +418,7 @@ void map_groups__init(struct map_groups *mg) | |||
| 323 | INIT_LIST_HEAD(&mg->removed_maps[i]); | 418 | INIT_LIST_HEAD(&mg->removed_maps[i]); |
| 324 | } | 419 | } |
| 325 | mg->machine = NULL; | 420 | mg->machine = NULL; |
| 421 | mg->refcnt = 1; | ||
| 326 | } | 422 | } |
| 327 | 423 | ||
| 328 | static void maps__delete(struct rb_root *maps) | 424 | static void maps__delete(struct rb_root *maps) |
| @@ -358,6 +454,28 @@ void map_groups__exit(struct map_groups *mg) | |||
| 358 | } | 454 | } |
| 359 | } | 455 | } |
| 360 | 456 | ||
| 457 | struct map_groups *map_groups__new(void) | ||
| 458 | { | ||
| 459 | struct map_groups *mg = malloc(sizeof(*mg)); | ||
| 460 | |||
| 461 | if (mg != NULL) | ||
| 462 | map_groups__init(mg); | ||
| 463 | |||
| 464 | return mg; | ||
| 465 | } | ||
| 466 | |||
| 467 | void map_groups__delete(struct map_groups *mg) | ||
| 468 | { | ||
| 469 | map_groups__exit(mg); | ||
| 470 | free(mg); | ||
| 471 | } | ||
| 472 | |||
| 473 | void map_groups__put(struct map_groups *mg) | ||
| 474 | { | ||
| 475 | if (--mg->refcnt == 0) | ||
| 476 | map_groups__delete(mg); | ||
| 477 | } | ||
| 478 | |||
| 361 | void map_groups__flush(struct map_groups *mg) | 479 | void map_groups__flush(struct map_groups *mg) |
| 362 | { | 480 | { |
| 363 | int type; | 481 | int type; |
