From 31c03a2f0f51e400729d43468bc184675a1a9ab7 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Thu, 12 Mar 2020 21:02:46 -0700 Subject: [PATCH 1/6] 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 --- src/large_pages/node_large_page.cc | 103 ++++++++++++----------------- 1 file changed, 44 insertions(+), 59 deletions(-) diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index 31d85c1734a63c..689305e23c249e 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -29,7 +29,9 @@ #include "util.h" #include "uv.h" -#include // _O_RDWR +#if defined(__linux__) +#include +#endif #include #include #if defined(__FreeBSD__) @@ -38,12 +40,11 @@ #elif defined(__APPLE__) #include #endif -#include // readlink +#include // getpid #include // PATH_MAX #include #include -#include #include #include #include @@ -110,72 +111,56 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) { return ((addr) & ~((hps) - 1)); } -// The format of the maps file is the following -// address perms offset dev inode pathname -// 00400000-00452000 r-xp 00000000 08:02 173521 /usr/bin/dbus-daemon -// This is also handling the case where the first line is not the binary. +struct dl_iterate_params { + uintptr_t start; + uintptr_t end; + uintptr_t reference_sym; +}; struct text_region FindNodeTextRegion() { struct text_region nregion; nregion.found_text_region = false; #if defined(__linux__) - std::ifstream ifs; - std::string map_line; - std::string permission; - std::string dev; - char dash; - uintptr_t start, end, offset, inode; - uintptr_t node_text_start = reinterpret_cast(&__node_text_start); + dl_iterate_params dl_params = { + 0, 0, reinterpret_cast(&__node_text_start) + }; uintptr_t lpstub_start = reinterpret_cast(&__start_lpstub); - ifs.open("/proc/self/maps"); - if (!ifs) { - PrintWarning("could not open /proc/self/maps"); - return nregion; - } - - while (std::getline(ifs, map_line)) { - std::istringstream iss(map_line); - iss >> std::hex >> start; - iss >> dash; - iss >> std::hex >> end; - iss >> permission; - iss >> offset; - iss >> dev; - iss >> inode; - - if (inode == 0) - continue; - - std::string pathname; - iss >> pathname; - - if (permission != "r-xp") - continue; - - if (node_text_start < start || node_text_start >= end) - continue; - - start = node_text_start; - if (lpstub_start > start && lpstub_start <= end) - end = lpstub_start; - - char* from = reinterpret_cast(hugepage_align_up(start)); - char* to = reinterpret_cast(hugepage_align_down(end)); - - if (from >= to) - break; + if (dl_iterate_phdr([](struct dl_phdr_info* info, size_t, void* data) -> int { + if (info->dlpi_name[0] == 0) { + for (int idx = 0; idx < info->dlpi_phnum; idx++) { + const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; + if (phdr->p_type == PT_LOAD && phdr->p_flags & PF_X) { + auto dl_params = reinterpret_cast(data); + uintptr_t start = info->dlpi_addr + phdr->p_vaddr; + uintptr_t end = start + phdr->p_memsz; + + if (dl_params->reference_sym >= start && + dl_params->reference_sym <= end) { + dl_params->start = start; + dl_params->end = end; + return 1; + } + } + } + } + return 0; + }, &dl_params) == 1) { + dl_params.start = dl_params.reference_sym; + if (lpstub_start > dl_params.start && lpstub_start <= dl_params.end) + dl_params.end = lpstub_start; - size_t size = to - from; - nregion.found_text_region = true; - nregion.from = from; - nregion.to = to; - nregion.total_hugepages = size / hps; + if (dl_params.start < dl_params.end) { + char* from = reinterpret_cast(hugepage_align_up(dl_params.start)); + char* to = reinterpret_cast(hugepage_align_down(dl_params.end)); - break; + size_t size = to - from; + nregion.found_text_region = true; + nregion.from = from; + nregion.to = to; + nregion.total_hugepages = size / hps; + } } - - ifs.close(); #elif defined(__FreeBSD__) std::string exename; { From f6531aa47c81e0b5b7ad710e56c067677a827a06 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 13 Mar 2020 08:41:50 -0700 Subject: [PATCH 2/6] Update src/large_pages/node_large_page.cc Co-Authored-By: Ben Noordhuis --- src/large_pages/node_large_page.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index 689305e23c249e..593b993e9b456d 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -130,7 +130,7 @@ struct text_region FindNodeTextRegion() { if (info->dlpi_name[0] == 0) { for (int idx = 0; idx < info->dlpi_phnum; idx++) { const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; - if (phdr->p_type == PT_LOAD && phdr->p_flags & PF_X) { + if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { auto dl_params = reinterpret_cast(data); uintptr_t start = info->dlpi_addr + phdr->p_vaddr; uintptr_t end = start + phdr->p_memsz; From 5932d05f0f5ddb81dd53f96948357fcf20b6ea4c Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 13 Mar 2020 08:42:03 -0700 Subject: [PATCH 3/6] Update src/large_pages/node_large_page.cc Co-Authored-By: Ben Noordhuis --- src/large_pages/node_large_page.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index 593b993e9b456d..fc79b3d82a1243 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -131,7 +131,7 @@ struct text_region FindNodeTextRegion() { for (int idx = 0; idx < info->dlpi_phnum; idx++) { const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { - auto dl_params = reinterpret_cast(data); + auto dl_params = static_cast(data); uintptr_t start = info->dlpi_addr + phdr->p_vaddr; uintptr_t end = start + phdr->p_memsz; From 617e6018b17362d8403e10154d3945b2cd88b9f4 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 13 Mar 2020 10:31:12 -0700 Subject: [PATCH 4/6] address review comments --- src/large_pages/node_large_page.cc | 48 ++++++++++++++++-------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index fc79b3d82a1243..1878c24704b568 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -30,6 +30,7 @@ #include "uv.h" #if defined(__linux__) +#define _GNU_SOURCE #include #endif #include @@ -51,7 +52,6 @@ #include #include #include -#include #include // The functions in this file map the text segment of node into 2M pages. @@ -117,6 +117,29 @@ struct dl_iterate_params { uintptr_t reference_sym; }; +#if defined(__linux__) +int FindMapping(struct dl_phdr_info* info, size_t, void* data) { + if (info->dlpi_name[0] == 0) { + for (int idx = 0; idx < info->dlpi_phnum; idx++) { + const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; + if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { + auto dl_params = static_cast(data); + uintptr_t start = info->dlpi_addr + phdr->p_vaddr; + uintptr_t end = start + phdr->p_memsz; + + if (dl_params->reference_sym >= start && + dl_params->reference_sym <= end) { + dl_params->start = start; + dl_params->end = end; + return 1; + } + } + } + } + return 0; +} +#endif // defined(__linux__) + struct text_region FindNodeTextRegion() { struct text_region nregion; nregion.found_text_region = false; @@ -126,26 +149,7 @@ struct text_region FindNodeTextRegion() { }; uintptr_t lpstub_start = reinterpret_cast(&__start_lpstub); - if (dl_iterate_phdr([](struct dl_phdr_info* info, size_t, void* data) -> int { - if (info->dlpi_name[0] == 0) { - for (int idx = 0; idx < info->dlpi_phnum; idx++) { - const ElfW(Phdr)* phdr = &info->dlpi_phdr[idx]; - if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) { - auto dl_params = static_cast(data); - uintptr_t start = info->dlpi_addr + phdr->p_vaddr; - uintptr_t end = start + phdr->p_memsz; - - if (dl_params->reference_sym >= start && - dl_params->reference_sym <= end) { - dl_params->start = start; - dl_params->end = end; - return 1; - } - } - } - } - return 0; - }, &dl_params) == 1) { + if (dl_iterate_phdr(FindMapping, &dl_params) == 1) { dl_params.start = dl_params.reference_sym; if (lpstub_start > dl_params.start && lpstub_start <= dl_params.end) dl_params.end = lpstub_start; @@ -274,7 +278,7 @@ bool IsTransparentHugePagesEnabled() { return always == "[always]" || madvise == "[madvise]"; } #elif defined(__FreeBSD__) -static bool IsSuperPagesEnabled() { +bool IsSuperPagesEnabled() { // It is enabled by default on amd64. unsigned int super_pages = 0; size_t super_pages_length = sizeof(super_pages); From ba539ef530a4caa4c07d115fe5ed29f61bed37f7 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 13 Mar 2020 11:01:55 -0700 Subject: [PATCH 5/6] introduce additional sanity checks on the range --- src/large_pages/node_large_page.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index 1878c24704b568..a15cf0b6184ed1 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -157,12 +157,15 @@ struct text_region FindNodeTextRegion() { if (dl_params.start < dl_params.end) { char* from = reinterpret_cast(hugepage_align_up(dl_params.start)); char* to = reinterpret_cast(hugepage_align_down(dl_params.end)); - - size_t size = to - from; - nregion.found_text_region = true; - nregion.from = from; - nregion.to = to; - nregion.total_hugepages = size / hps; + if (from < to) { + size_t pagecount = (to - from) / hps; + if (pagecount > 0) { + nregion.found_text_region = true; + nregion.from = from; + nregion.to = to; + nregion.total_hugepages = pagecount; + } + } } } #elif defined(__FreeBSD__) From 2d6be5e752e71af7f72bf47f45ad249911df0e1a Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Fri, 13 Mar 2020 13:15:16 -0700 Subject: [PATCH 6/6] ensure _GNU_SOURCE is defined instead of defining it unconditionally --- src/large_pages/node_large_page.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/large_pages/node_large_page.cc b/src/large_pages/node_large_page.cc index a15cf0b6184ed1..e3972f52559399 100644 --- a/src/large_pages/node_large_page.cc +++ b/src/large_pages/node_large_page.cc @@ -30,7 +30,9 @@ #include "uv.h" #if defined(__linux__) +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #endif #include