Skip to content

Commit

Permalink
src: find .text section using dl_iterate_phdr
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
2 people authored and targos committed Apr 28, 2020
1 parent fd2486e commit 2f976d7
Showing 1 changed file with 57 additions and 63 deletions.
120 changes: 57 additions & 63 deletions src/large_pages/node_large_page.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
#include "util.h"
#include "uv.h"

#include <fcntl.h> // _O_RDWR
#if defined(__linux__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <link.h>
#endif
#include <sys/types.h>
#include <sys/mman.h>
#if defined(__FreeBSD__)
Expand All @@ -38,19 +43,17 @@
#elif defined(__APPLE__)
#include <mach/vm_map.h>
#endif
#include <unistd.h> // readlink
#include <unistd.h> // getpid

#include <climits> // PATH_MAX
#include <clocale>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

// The functions in this file map the text segment of node into 2M pages.
Expand Down Expand Up @@ -110,72 +113,63 @@ 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;
};

#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<dl_iterate_params*>(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;
#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<uintptr_t>(&__node_text_start);
dl_iterate_params dl_params = {
0, 0, reinterpret_cast<uintptr_t>(&__node_text_start)
};
uintptr_t lpstub_start = reinterpret_cast<uintptr_t>(&__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<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;
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;

if (dl_params.start < dl_params.end) {
char* from = reinterpret_cast<char*>(hugepage_align_up(dl_params.start));
char* to = reinterpret_cast<char*>(hugepage_align_down(dl_params.end));
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;
}
}
}
}

ifs.close();
#elif defined(__FreeBSD__)
std::string exename;
{
Expand Down Expand Up @@ -289,7 +283,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);
Expand Down

0 comments on commit 2f976d7

Please sign in to comment.