3030#include " util.h"
3131#include " uv.h"
3232
33+ #if defined(__linux__) || defined(__FreeBSD__)
34+ #include < string.h>
3335#if defined(__linux__)
3436#ifndef _GNU_SOURCE
3537#define _GNU_SOURCE
36- #endif
38+ #endif // ifndef _GNU_SOURCE
39+ #endif // defined(__linux__)
3740#include < link.h>
38- #endif
41+ #endif // defined(__linux__) || defined(__FreeBSD__)
42+
3943#include < sys/types.h>
4044#include < sys/mman.h>
4145#if defined(__FreeBSD__)
7377// Use madvise with MADV_HUGEPAGE to use Anonymous 2M Pages
7478// If successful copy the code there and unmap the original region.
7579
76- #if defined(__linux__)
80+ #if defined(__linux__) || defined(__FreeBSD__)
7781extern " C" {
7882// This symbol must be declared weak because this file becomes part of all
7983// Node.js targets (like node_mksnapshot, node_mkcodecache, and cctest) and
8084// those files do not supply the symbol.
8185extern char __attribute__ ((weak)) __node_text_start;
8286extern char __start_lpstub;
8387} // extern "C"
84- #endif // defined(__linux__)
88+ #endif // defined(__linux__) || defined(__FreeBSD__)
8589
8690#endif // defined(NODE_ENABLE_LARGE_CODE_PAGES) && NODE_ENABLE_LARGE_CODE_PAGES
8791namespace node {
@@ -121,19 +125,26 @@ inline uintptr_t hugepage_align_down(uintptr_t addr) {
121125 return ((addr) & ~((hps) - 1 ));
122126}
123127
128+ #if defined(__linux__) || defined(__FreeBSD__)
129+ #if defined(__FreeBSD__)
130+ #ifndef ElfW
131+ #define ElfW (name ) Elf_##name
132+ #endif // ifndef ElfW
133+ #endif // defined(__FreeBSD__)
134+
124135struct dl_iterate_params {
125136 uintptr_t start;
126137 uintptr_t end;
127138 uintptr_t reference_sym;
139+ std::string exename;
128140};
129141
130- #if defined(__linux__)
131142int FindMapping (struct dl_phdr_info * info, size_t , void * data) {
132- if (info->dlpi_name [0 ] == 0 ) {
143+ auto dl_params = static_cast <dl_iterate_params*>(data);
144+ if (dl_params->exename == std::string (info->dlpi_name )) {
133145 for (int idx = 0 ; idx < info->dlpi_phnum ; idx++) {
134146 const ElfW (Phdr)* phdr = &info->dlpi_phdr [idx];
135147 if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) {
136- auto dl_params = static_cast <dl_iterate_params*>(data);
137148 uintptr_t start = info->dlpi_addr + phdr->p_vaddr ;
138149 uintptr_t end = start + phdr->p_memsz ;
139150
@@ -148,17 +159,30 @@ int FindMapping(struct dl_phdr_info* info, size_t, void* data) {
148159 }
149160 return 0 ;
150161}
151- #endif // defined(__linux__)
162+ #endif // defined(__linux__) || defined(__FreeBSD__)
152163
153164struct text_region FindNodeTextRegion () {
154165 struct text_region nregion;
155166 nregion.found_text_region = false ;
156- #if defined(__linux__)
167+ #if defined(__linux__) || defined(__FreeBSD__)
157168 dl_iterate_params dl_params = {
158- 0 , 0 , reinterpret_cast <uintptr_t >(&__node_text_start)
169+ 0 , 0 , reinterpret_cast <uintptr_t >(&__node_text_start), " "
159170 };
160171 uintptr_t lpstub_start = reinterpret_cast <uintptr_t >(&__start_lpstub);
161172
173+ #if defined(__FreeBSD__)
174+ // On FreeBSD we need the name of the binary, because `dl_iterate_phdr` does
175+ // not pass in an empty string as the `dlpi_name` of the binary but rather its
176+ // absolute path.
177+ {
178+ char selfexe[PATH_MAX];
179+ size_t count = sizeof (selfexe);
180+ if (uv_exepath (selfexe, &count))
181+ return nregion;
182+ dl_params.exename = std::string (selfexe, count);
183+ }
184+ #endif // defined(__FreeBSD__)
185+
162186 if (dl_iterate_phdr (FindMapping, &dl_params) == 1 ) {
163187 Debug (" Hugepages info: start: %p - sym: %p - end: %p\n " ,
164188 reinterpret_cast <void *>(dl_params.start ),
@@ -187,62 +211,6 @@ struct text_region FindNodeTextRegion() {
187211 }
188212 }
189213 }
190- #elif defined(__FreeBSD__)
191- std::string exename;
192- {
193- char selfexe[PATH_MAX];
194- size_t count = sizeof (selfexe);
195- if (uv_exepath (selfexe, &count))
196- return nregion;
197-
198- exename = std::string (selfexe, count);
199- }
200-
201- size_t numpg;
202- int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid ()};
203- const size_t miblen = arraysize (mib);
204- if (sysctl (mib, miblen, nullptr , &numpg, nullptr , 0 ) == -1 ) {
205- return nregion;
206- }
207-
208- // Enough for struct kinfo_vmentry.
209- numpg = numpg * 4 / 3 ;
210- auto alg = std::vector<char >(numpg);
211-
212- if (sysctl (mib, miblen, alg.data (), &numpg, nullptr , 0 ) == -1 ) {
213- return nregion;
214- }
215-
216- char * start = alg.data ();
217- char * end = start + numpg;
218-
219- while (start < end) {
220- kinfo_vmentry* entry = reinterpret_cast <kinfo_vmentry*>(start);
221- const size_t cursz = entry->kve_structsize ;
222- if (cursz == 0 ) {
223- break ;
224- }
225-
226- if (entry->kve_path [0 ] == ' \0 ' ) {
227- continue ;
228- }
229- bool excmapping = ((entry->kve_protection & KVME_PROT_READ) &&
230- (entry->kve_protection & KVME_PROT_EXEC));
231-
232- if (!strcmp (exename.c_str (), entry->kve_path ) && excmapping) {
233- char * estart =
234- reinterpret_cast <char *>(hugepage_align_up (entry->kve_start ));
235- char * eend =
236- reinterpret_cast <char *>(hugepage_align_down (entry->kve_end ));
237- size_t size = eend - estart;
238- nregion.found_text_region = true ;
239- nregion.from = estart;
240- nregion.to = eend;
241- nregion.total_hugepages = size / hps;
242- break ;
243- }
244- start += cursz;
245- }
246214#elif defined(__APPLE__)
247215 struct vm_region_submap_info_64 map;
248216 mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
@@ -349,13 +317,11 @@ MoveTextRegionToLargePages(const text_region& r) {
349317 PrintSystemError (errno);
350318 });
351319
352- #if !defined (__FreeBSD__)
353320 // Allocate temporary region and back up the code we will re-map.
354321 nmem = mmap (nullptr , size,
355322 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1 , 0 );
356323 if (nmem == MAP_FAILED) goto fail;
357324 memcpy (nmem, r.from , size);
358- #endif
359325
360326#if defined(__linux__)
361327// We already know the original page is r-xp
@@ -374,6 +340,7 @@ MoveTextRegionToLargePages(const text_region& r) {
374340 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED |
375341 MAP_ALIGNED_SUPER, -1 , 0 );
376342 if (tmem == MAP_FAILED) goto fail;
343+ memcpy (start, nmem, size);
377344#elif defined(__APPLE__)
378345 // There is not enough room to reserve the mapping close
379346 // to the region address so we content to give a hint
@@ -420,11 +387,6 @@ int MapStaticCodeToLargePages() {
420387 if (r.found_text_region == false )
421388 return ENOENT;
422389
423- #if defined(__FreeBSD__)
424- if (r.from < reinterpret_cast <void *>(&MoveTextRegionToLargePages))
425- return -1 ;
426- #endif
427-
428390 return MoveTextRegionToLargePages (r);
429391#else
430392 return ENOTSUP;
0 commit comments