|
29 | 29 | #include "util.h" |
30 | 30 | #include "uv.h" |
31 | 31 |
|
32 | | -#include <fcntl.h> // _O_RDWR |
| 32 | +#if defined(__linux__) |
| 33 | +#ifndef _GNU_SOURCE |
| 34 | +#define _GNU_SOURCE |
| 35 | +#endif |
| 36 | +#include <link.h> |
| 37 | +#endif |
33 | 38 | #include <sys/types.h> |
34 | 39 | #include <sys/mman.h> |
35 | 40 | #if defined(__FreeBSD__) |
|
38 | 43 | #elif defined(__APPLE__) |
39 | 44 | #include <mach/vm_map.h> |
40 | 45 | #endif |
41 | | -#include <unistd.h> // readlink |
| 46 | +#include <unistd.h> // getpid |
42 | 47 |
|
43 | 48 | #include <climits> // PATH_MAX |
44 | 49 | #include <clocale> |
45 | 50 | #include <csignal> |
46 | | -#include <cstdio> |
47 | 51 | #include <cstdlib> |
48 | 52 | #include <cstdint> |
49 | 53 | #include <cstring> |
50 | 54 | #include <string> |
51 | 55 | #include <fstream> |
52 | 56 | #include <iostream> |
53 | | -#include <sstream> |
54 | 57 | #include <vector> |
55 | 58 |
|
56 | 59 | // The functions in this file map the text segment of node into 2M pages. |
@@ -110,72 +113,63 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) { |
110 | 113 | return ((addr) & ~((hps) - 1)); |
111 | 114 | } |
112 | 115 |
|
113 | | -// The format of the maps file is the following |
114 | | -// address perms offset dev inode pathname |
115 | | -// 00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon |
116 | | -// This is also handling the case where the first line is not the binary. |
| 116 | +struct dl_iterate_params { |
| 117 | + uintptr_t start; |
| 118 | + uintptr_t end; |
| 119 | + uintptr_t reference_sym; |
| 120 | +}; |
| 121 | + |
| 122 | +#if defined(__linux__) |
| 123 | +int FindMapping(struct dl_phdr_info* info, size_t, void* data) { |
| 124 | + if (info->dlpi_name[0] == 0) { |
| 125 | + for (int idx = 0; idx < info->dlpi_phnum; idx++) { |
| 126 | + const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; |
| 127 | + if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { |
| 128 | + auto dl_params = static_cast<dl_iterate_params*>(data); |
| 129 | + uintptr_t start = info->dlpi_addr + phdr->p_vaddr; |
| 130 | + uintptr_t end = start + phdr->p_memsz; |
| 131 | + |
| 132 | + if (dl_params->reference_sym >= start && |
| 133 | + dl_params->reference_sym <= end) { |
| 134 | + dl_params->start = start; |
| 135 | + dl_params->end = end; |
| 136 | + return 1; |
| 137 | + } |
| 138 | + } |
| 139 | + } |
| 140 | + } |
| 141 | + return 0; |
| 142 | +} |
| 143 | +#endif // defined(__linux__) |
117 | 144 |
|
118 | 145 | struct text_region FindNodeTextRegion() { |
119 | 146 | struct text_region nregion; |
120 | 147 | nregion.found_text_region = false; |
121 | 148 | #if defined(__linux__) |
122 | | - std::ifstream ifs; |
123 | | - std::string map_line; |
124 | | - std::string permission; |
125 | | - std::string dev; |
126 | | - char dash; |
127 | | - uintptr_t start, end, offset, inode; |
128 | | - uintptr_t node_text_start = reinterpret_cast<uintptr_t>(&__node_text_start); |
| 149 | + dl_iterate_params dl_params = { |
| 150 | + 0, 0, reinterpret_cast<uintptr_t>(&__node_text_start) |
| 151 | + }; |
129 | 152 | uintptr_t lpstub_start = reinterpret_cast<uintptr_t>(&__start_lpstub); |
130 | 153 |
|
131 | | - ifs.open("/proc/self/maps"); |
132 | | - if (!ifs) { |
133 | | - PrintWarning("could not open /proc/self/maps"); |
134 | | - return nregion; |
135 | | - } |
136 | | - |
137 | | - while (std::getline(ifs, map_line)) { |
138 | | - std::istringstream iss(map_line); |
139 | | - iss >> std::hex >> start; |
140 | | - iss >> dash; |
141 | | - iss >> std::hex >> end; |
142 | | - iss >> permission; |
143 | | - iss >> offset; |
144 | | - iss >> dev; |
145 | | - iss >> inode; |
146 | | - |
147 | | - if (inode == 0) |
148 | | - continue; |
149 | | - |
150 | | - std::string pathname; |
151 | | - iss >> pathname; |
152 | | - |
153 | | - if (permission != "r-xp") |
154 | | - continue; |
155 | | - |
156 | | - if (node_text_start < start || node_text_start >= end) |
157 | | - continue; |
158 | | - |
159 | | - start = node_text_start; |
160 | | - if (lpstub_start > start && lpstub_start <= end) |
161 | | - end = lpstub_start; |
162 | | - |
163 | | - char* from = reinterpret_cast<char*>(hugepage_align_up(start)); |
164 | | - char* to = reinterpret_cast<char*>(hugepage_align_down(end)); |
165 | | - |
166 | | - if (from >= to) |
167 | | - break; |
168 | | - |
169 | | - size_t size = to - from; |
170 | | - nregion.found_text_region = true; |
171 | | - nregion.from = from; |
172 | | - nregion.to = to; |
173 | | - nregion.total_hugepages = size / hps; |
174 | | - |
175 | | - break; |
| 154 | + if (dl_iterate_phdr(FindMapping, &dl_params) == 1) { |
| 155 | + dl_params.start = dl_params.reference_sym; |
| 156 | + if (lpstub_start > dl_params.start && lpstub_start <= dl_params.end) |
| 157 | + dl_params.end = lpstub_start; |
| 158 | + |
| 159 | + if (dl_params.start < dl_params.end) { |
| 160 | + char* from = reinterpret_cast<char*>(hugepage_align_up(dl_params.start)); |
| 161 | + char* to = reinterpret_cast<char*>(hugepage_align_down(dl_params.end)); |
| 162 | + if (from < to) { |
| 163 | + size_t pagecount = (to - from) / hps; |
| 164 | + if (pagecount > 0) { |
| 165 | + nregion.found_text_region = true; |
| 166 | + nregion.from = from; |
| 167 | + nregion.to = to; |
| 168 | + nregion.total_hugepages = pagecount; |
| 169 | + } |
| 170 | + } |
| 171 | + } |
176 | 172 | } |
177 | | - |
178 | | - ifs.close(); |
179 | 173 | #elif defined(__FreeBSD__) |
180 | 174 | std::string exename; |
181 | 175 | { |
@@ -289,7 +283,7 @@ bool IsTransparentHugePagesEnabled() { |
289 | 283 | return always == "[always]" || madvise == "[madvise]"; |
290 | 284 | } |
291 | 285 | #elif defined(__FreeBSD__) |
292 | | -static bool IsSuperPagesEnabled() { |
| 286 | +bool IsSuperPagesEnabled() { |
293 | 287 | // It is enabled by default on amd64. |
294 | 288 | unsigned int super_pages = 0; |
295 | 289 | size_t super_pages_length = sizeof(super_pages); |
|
0 commit comments