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

PR-URL: nodejs#31547
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
  • Loading branch information
bnoordhuis authored and Gabriel Schulhof committed Apr 9, 2020
1 parent d8bdf4e commit ccadc89
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 68 deletions.
3 changes: 2 additions & 1 deletion node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,8 @@
],
}],
[ 'OS in "linux freebsd mac" and '
'target_arch=="x64"', {
'target_arch=="x64" and '
'node_target_type=="executable"', {
'defines': [ 'NODE_ENABLE_LARGE_CODE_PAGES=1' ],
'sources': [
'src/large_pages/node_large_page.cc',
Expand Down
16 changes: 0 additions & 16 deletions node.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -317,22 +317,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.

83 changes: 45 additions & 38 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,12 @@ int MapStaticCodeToLargePages() {
return -1;
}

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

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

bool IsLargePagesEnabled() {
Expand Down

0 comments on commit ccadc89

Please sign in to comment.