Skip to content

Commit c00ce7b

Browse files
Gabriel Schulhofbnoordhuis
authored andcommittedMar 24, 2020
src: find .text section using dl_iterate_phdr
Use `dl_iterate_phdr(3)` to find the mapping containing `__node_text_start` instead of parsing `/proc/self/maps`. Signed-off-by: Gabriel Schulhof <[email protected]> Co-Authored-By: Ben Noordhuis <[email protected]> PR-URL: #32244 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: David Carlier <[email protected]>
1 parent df1d4f7 commit c00ce7b

File tree

1 file changed

+57
-63
lines changed

1 file changed

+57
-63
lines changed
 

‎src/large_pages/node_large_page.cc

+57-63
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@
2929
#include "util.h"
3030
#include "uv.h"
3131

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
3338
#include <sys/types.h>
3439
#include <sys/mman.h>
3540
#if defined(__FreeBSD__)
@@ -38,19 +43,17 @@
3843
#elif defined(__APPLE__)
3944
#include <mach/vm_map.h>
4045
#endif
41-
#include <unistd.h> // readlink
46+
#include <unistd.h> // getpid
4247

4348
#include <climits> // PATH_MAX
4449
#include <clocale>
4550
#include <csignal>
46-
#include <cstdio>
4751
#include <cstdlib>
4852
#include <cstdint>
4953
#include <cstring>
5054
#include <string>
5155
#include <fstream>
5256
#include <iostream>
53-
#include <sstream>
5457
#include <vector>
5558

5659
// 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) {
110113
return ((addr) & ~((hps) - 1));
111114
}
112115

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__)
117144

118145
struct text_region FindNodeTextRegion() {
119146
struct text_region nregion;
120147
nregion.found_text_region = false;
121148
#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+
};
129152
uintptr_t lpstub_start = reinterpret_cast<uintptr_t>(&__start_lpstub);
130153

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+
}
176172
}
177-
178-
ifs.close();
179173
#elif defined(__FreeBSD__)
180174
std::string exename;
181175
{
@@ -289,7 +283,7 @@ bool IsTransparentHugePagesEnabled() {
289283
return always == "[always]" || madvise == "[madvise]";
290284
}
291285
#elif defined(__FreeBSD__)
292-
static bool IsSuperPagesEnabled() {
286+
bool IsSuperPagesEnabled() {
293287
// It is enabled by default on amd64.
294288
unsigned int super_pages = 0;
295289
size_t super_pages_length = sizeof(super_pages);

0 commit comments

Comments
 (0)