Skip to content

Commit

Permalink
src: use __executable_start for linux hugepages
Browse files Browse the repository at this point in the history
`__executable_start` is provided by GNU's and LLVM's default linker
scripts, obviating the need to plug in a custom linker script.

The problem with our bespoke linker script is that it works with ld.bfd
but not ld.gold and cannot easily be ported because the latter linker
doesn't understand the `INSERT BEFORE` directive.

The /proc/self/maps scanner is updated to account for the fact that
there are a number of sections between `&__executable_start` and
the start of the .text section.

Fortunately, those sections are all mapped into the same memory segment
so we only need to look at the next line to find the start of our text
segment.

Fixes: nodejs#31520
  • Loading branch information
bnoordhuis committed Jan 28, 2020
1 parent 7b7e7bd commit cbf276f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 68 deletions.
16 changes: 0 additions & 16 deletions node.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -306,22 +306,6 @@
'ldflags': [ '-Wl,-z,relro',
'-Wl,-z,now' ]
}],
[ 'OS=="linux" and '
'target_arch=="x64" and '
'llvm_version=="0.0"', {
'ldflags': [
'-Wl,-T',
'<!(echo "$(pwd)/src/large_pages/ld.implicit.script")',
]
}],
[ 'OS=="linux" and '
'target_arch=="x64" and '
'llvm_version!="0.0"', {
'ldflags': [
'-Wl,-T',
'<!(echo "$(pwd)/src/large_pages/ld.implicit.script.lld")',
]
}],
[ 'node_use_openssl=="true"', {
'defines': [ 'HAVE_OPENSSL=1' ],
'conditions': [
Expand Down
10 changes: 0 additions & 10 deletions src/large_pages/ld.implicit.script

This file was deleted.

3 changes: 0 additions & 3 deletions src/large_pages/ld.implicit.script.lld

This file was deleted.

80 changes: 41 additions & 39 deletions src/large_pages/node_large_page.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@
// Use madvise with MADV_HUGEPAGE to use Anonymous 2M Pages
// If successful copy the code there and unmap the original region.

extern char __nodetext;
#if defined(__linux__)
extern "C" {
extern char __executable_start;
} // extern "C"
#endif // defined(__linux__)

namespace node {

Expand Down Expand Up @@ -116,17 +120,6 @@ static struct text_region FindNodeTextRegion() {
return nregion;
}

std::string exename;
{
char selfexe[PATH_MAX];

size_t size = sizeof(selfexe);
if (uv_exepath(selfexe, &size))
return nregion;

exename = std::string(selfexe, size);
}

while (std::getline(ifs, map_line)) {
std::istringstream iss(map_line);
iss >> std::hex >> start;
Expand All @@ -136,26 +129,42 @@ static struct text_region FindNodeTextRegion() {
iss >> offset;
iss >> dev;
iss >> inode;
if (inode != 0) {
std::string pathname;
iss >> pathname;
if (pathname == exename && permission == "r-xp") {
uintptr_t ntext = reinterpret_cast<uintptr_t>(&__nodetext);
if (ntext >= start && ntext < end) {
char* from = reinterpret_cast<char*>(hugepage_align_up(ntext));
char* to = reinterpret_cast<char*>(hugepage_align_down(end));

if (from < to) {
size_t size = to - from;
nregion.found_text_region = true;
nregion.from = from;
nregion.to = to;
nregion.total_hugepages = size / hps;
}
break;
}
}
}

if (inode == 0)
continue;

std::string pathname;
iss >> pathname;

if (start != reinterpret_cast<uintptr_t>(&__executable_start))
continue;

// The next line is our .text section.
if (!std::getline(ifs, map_line))
break;

iss = std::istringstream(map_line);
iss >> std::hex >> start;
iss >> dash;
iss >> std::hex >> end;
iss >> permission;

if (permission != "r-xp")
break;

char* from = reinterpret_cast<char*>(hugepage_align_up(start));
char* to = reinterpret_cast<char*>(hugepage_align_down(end));

if (from >= to)
break;

size_t size = to - from;
nregion.found_text_region = true;
nregion.from = from;
nregion.to = to;
nregion.total_hugepages = size / hps;

break;
}

ifs.close();
Expand Down Expand Up @@ -408,14 +417,7 @@ int MapStaticCodeToLargePages() {
return -1;
}

#if defined(__linux__) || defined(__FreeBSD__)
if (r.from > reinterpret_cast<void*>(&MoveTextRegionToLargePages))
return MoveTextRegionToLargePages(r);

return -1;
#elif defined(__APPLE__)
return MoveTextRegionToLargePages(r);
#endif
}

bool IsLargePagesEnabled() {
Expand Down

0 comments on commit cbf276f

Please sign in to comment.