|
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