|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "shared-libraries.h" |
|
6 |
|
7 #define PATH_MAX_TOSTRING(x) #x |
|
8 #define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x) |
|
9 #include <stdlib.h> |
|
10 #include <stdio.h> |
|
11 #include <string.h> |
|
12 #include <limits.h> |
|
13 #include <unistd.h> |
|
14 #include <fstream> |
|
15 #include "platform.h" |
|
16 #include "shared-libraries.h" |
|
17 |
|
18 #if !defined(MOZ_WIDGET_GONK) |
|
19 // TODO fix me with proper include |
|
20 #include "nsDebug.h" |
|
21 #ifdef ANDROID |
|
22 #include "ElfLoader.h" // dl_phdr_info |
|
23 #else |
|
24 #include <link.h> // dl_phdr_info |
|
25 #endif |
|
26 #include <features.h> |
|
27 #include <dlfcn.h> |
|
28 #include <sys/types.h> |
|
29 |
|
30 #ifdef ANDROID |
|
31 extern "C" __attribute__((weak)) |
|
32 int dl_iterate_phdr( |
|
33 int (*callback) (struct dl_phdr_info *info, |
|
34 size_t size, void *data), |
|
35 void *data); |
|
36 #endif |
|
37 |
|
38 int dl_iterate_callback(struct dl_phdr_info *dl_info, size_t size, void *data) |
|
39 { |
|
40 SharedLibraryInfo& info = *reinterpret_cast<SharedLibraryInfo*>(data); |
|
41 |
|
42 if (dl_info->dlpi_phnum <= 0) |
|
43 return 0; |
|
44 |
|
45 unsigned long libStart = -1; |
|
46 unsigned long libEnd = 0; |
|
47 |
|
48 for (size_t i = 0; i < dl_info->dlpi_phnum; i++) { |
|
49 if (dl_info->dlpi_phdr[i].p_type != PT_LOAD) { |
|
50 continue; |
|
51 } |
|
52 unsigned long start = dl_info->dlpi_addr + dl_info->dlpi_phdr[i].p_vaddr; |
|
53 unsigned long end = start + dl_info->dlpi_phdr[i].p_memsz; |
|
54 if (start < libStart) |
|
55 libStart = start; |
|
56 if (end > libEnd) |
|
57 libEnd = end; |
|
58 } |
|
59 SharedLibrary shlib(libStart, libEnd, 0, "", dl_info->dlpi_name); |
|
60 info.AddSharedLibrary(shlib); |
|
61 |
|
62 return 0; |
|
63 } |
|
64 #endif |
|
65 |
|
66 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() |
|
67 { |
|
68 SharedLibraryInfo info; |
|
69 |
|
70 #if !defined(MOZ_WIDGET_GONK) |
|
71 dl_iterate_phdr(dl_iterate_callback, &info); |
|
72 #ifndef ANDROID |
|
73 return info; |
|
74 #endif |
|
75 #endif |
|
76 |
|
77 pid_t pid = getpid(); |
|
78 char path[PATH_MAX]; |
|
79 snprintf(path, PATH_MAX, "/proc/%d/maps", pid); |
|
80 std::ifstream maps(path); |
|
81 std::string line; |
|
82 int count = 0; |
|
83 while (std::getline(maps, line)) { |
|
84 int ret; |
|
85 //XXX: needs input sanitizing |
|
86 unsigned long start; |
|
87 unsigned long end; |
|
88 char perm[6] = ""; |
|
89 unsigned long offset; |
|
90 char name[PATH_MAX] = ""; |
|
91 ret = sscanf(line.c_str(), |
|
92 "%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n", |
|
93 &start, &end, perm, &offset, name); |
|
94 if (!strchr(perm, 'x')) { |
|
95 // Ignore non executable entries |
|
96 continue; |
|
97 } |
|
98 if (ret != 5 && ret != 4) { |
|
99 LOG("Get maps line failed"); |
|
100 continue; |
|
101 } |
|
102 #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) |
|
103 // Use proc/pid/maps to get the dalvik-jit section since it has |
|
104 // no associated phdrs |
|
105 if (strcmp(name, "/dev/ashmem/dalvik-jit-code-cache") != 0) |
|
106 continue; |
|
107 #else |
|
108 if (strcmp(perm, "r-xp") != 0) { |
|
109 // Ignore entries that are writable and/or shared. |
|
110 // At least one graphics driver uses short-lived "rwxs" mappings |
|
111 // (see bug 926734 comment 5), so just checking for 'x' isn't enough. |
|
112 continue; |
|
113 } |
|
114 #endif |
|
115 SharedLibrary shlib(start, end, offset, "", name); |
|
116 info.AddSharedLibrary(shlib); |
|
117 if (count > 10000) { |
|
118 LOG("Get maps failed"); |
|
119 break; |
|
120 } |
|
121 count++; |
|
122 } |
|
123 return info; |
|
124 } |