Skip to content

Commit

Permalink
src: start the .text section with an asm symbol
Browse files Browse the repository at this point in the history
We create an object file in assembly which introduces the symbol
`__node_text_start` into the .text section and place the resulting
object file as the first file the linker encounters. We do this to
ensure that we can recognize the boundaries of the .text section when
attempting to establish the address range to map to large pages.

Additionally, we rename the section containing the remapping code from
`.lpstub` to `lpstub` so as to take advantage of the linker's feature
whereby it inserts the symbol `__start_lpstub` when the section's name
can be rendered as a valid C variable. We need this symbol in order to
avoid self-mapping the remapping code to large pages, because doing so
would cause the process to crash.

Backport-PR-URL: #32092
PR-URL: #31981
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
Signed-off-by: Gabriel Schulhof <gabriel.schulhof@intel.com>
  • Loading branch information
Gabriel Schulhof authored and targos committed Apr 28, 2020
1 parent 809d8b5 commit 178c682
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 14 deletions.
20 changes: 20 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,19 @@
},

'targets': [
{
'target_name': 'node_text_start',
'type': 'none',
'conditions': [
[ 'OS=="linux" and '
'target_arch=="x64"', {
'type': 'static_library',
'sources': [
'src/large_pages/node_text_start.S'
]
}],
]
},
{
'target_name': '<(node_core_target_name)',
'type': 'executable',
Expand Down Expand Up @@ -496,6 +509,13 @@
'src/node_snapshot_stub.cc'
],
}],
[ 'OS=="linux" and '
'target_arch=="x64"', {
'dependencies': [ 'node_text_start' ],
'ldflags+': [
'<(PRODUCT_DIR)/obj.target/node_text_start/src/large_pages/node_text_start.o'
]
}],
],
}, # node_core_target_name
{
Expand Down
28 changes: 14 additions & 14 deletions src/large_pages/node_large_page.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@

#if defined(__linux__)
extern "C" {
extern char __executable_start;
// This symbol must be declared weak because this file becomes part of all
// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and
// those files do not supply the symbol.
extern char __attribute__((weak)) __node_text_start;
extern char __start_lpstub;
} // extern "C"
#endif // defined(__linux__)

Expand Down Expand Up @@ -121,6 +125,8 @@ struct text_region FindNodeTextRegion() {
std::string dev;
char dash;
uintptr_t start, end, offset, inode;
uintptr_t node_text_start = reinterpret_cast<uintptr_t>(&__node_text_start);
uintptr_t lpstub_start = reinterpret_cast<uintptr_t>(&__start_lpstub);

ifs.open("/proc/self/maps");
if (!ifs) {
Expand All @@ -144,21 +150,15 @@ struct text_region FindNodeTextRegion() {
std::string pathname;
iss >> pathname;

if (start != reinterpret_cast<uintptr_t>(&__executable_start))
if (permission != "r-xp")
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 (node_text_start < start || node_text_start >= end)
continue;

if (permission != "r-xp")
break;
start = node_text_start;
if (lpstub_start > start && lpstub_start <= end)
end = lpstub_start;

char* from = reinterpret_cast<char*>(hugepage_align_up(start));
char* to = reinterpret_cast<char*>(hugepage_align_down(end));
Expand Down Expand Up @@ -318,7 +318,7 @@ static bool IsSuperPagesEnabled() {
// d. If successful copy the code there and unmap the original region
int
#if !defined(__APPLE__)
__attribute__((__section__(".lpstub")))
__attribute__((__section__("lpstub")))
#else
__attribute__((__section__("__TEXT,__lpstub")))
#endif
Expand Down
5 changes: 5 additions & 0 deletions src/large_pages/node_text_start.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.text
.align 0x2000
.global __node_text_start
.hidden __node_text_start
__node_text_start:

0 comments on commit 178c682

Please sign in to comment.