diff options
| author | Michael Lentine <mlentine@google.com> | 2014-05-20 05:48:50 -0400 |
|---|---|---|
| committer | Jiri Olsa <jolsa@kernel.org> | 2014-05-21 09:03:25 -0400 |
| commit | eca8183699964579ca8a0b8d116bd1f4da0136f7 (patch) | |
| tree | 078bfe88e5c3fbe397c9ca0d4d8ab2e0ff63979d /tools/perf | |
| parent | 21cfc5e10395eba795c0610cf3cf7f0a4f6f33ff (diff) | |
perf tools: Add automatic remapping of Android libraries
This patch automatically adjusts the path of MMAP records
associated with Android system libraries.
The Android system is organized with system libraries found in
/system/lib and user libraries in /data/app-lib. On the host system
(not running Android), system libraries can be found in the downloaded
NDK directory under ${NDK_ROOT}/platforms/${APP_PLATFORM}/arch-${ARCH}/usr/lib
and the user libraries are installed under libs/${APP_ABI} within
the apk build directory. This patch makes running the reporting
tools possible on the host system using the libraries from the NDK.
Signed-off-by: Michael Lentine <mlentine@google.com>
Reviewed-by: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1400579330-5043-3-git-send-email-eranian@google.com
[ fixed 'space required before the open parenthesis' checkpatch.pl errors ]
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/util/map.c | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ba5f5c0c838b..8ccbb32eda25 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 | { |
| @@ -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); |
| @@ -75,6 +163,11 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
| 75 | filename = newfilename; | 163 | filename = newfilename; |
| 76 | } | 164 | } |
| 77 | 165 | ||
| 166 | if (android) { | ||
| 167 | if (replace_android_lib(filename, newfilename)) | ||
| 168 | filename = newfilename; | ||
| 169 | } | ||
| 170 | |||
| 78 | if (vdso) { | 171 | if (vdso) { |
| 79 | pgoff = 0; | 172 | pgoff = 0; |
| 80 | dso = vdso__dso_findnew(dsos__list); | 173 | dso = vdso__dso_findnew(dsos__list); |
