-
-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linux ELF does not load correctly if page size is not 4KB #31
Comments
For Windows, this hack seems to work: diff --git a/blink/map.c b/blink/map.c
index a14c120..f8274f2 100644
--- a/blink/map.c
+++ b/blink/map.c
@@ -20,6 +20,10 @@
#include <string.h>
#include <unistd.h>
+#ifdef __CYGWIN__
+#include <windows.h>
+#endif
+
#include "blink/assert.h"
#include "blink/log.h"
#include "blink/macros.h"
@@ -32,6 +36,12 @@ long GetSystemPageSize(void) {
// "pages" in Emscripten only refer to the granularity the memory
// buffer can be grown at but does not affect functions like mmap.
return 4096;
+#endif
+#ifdef __CYGWIN__
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ unassert(IS2POW(si.dwPageSize));
+ return si.dwPageSize;
#endif
long z;
unassert((z = sysconf(_SC_PAGESIZE)) > 0);
@@ -47,6 +57,17 @@ void *Mmap(void *addr, //
off_t offset, //
const char *owner) {
void *res = mmap(addr, length, prot, flags, fd, offset);
+#if __CYGWIN__
+ if (res == MAP_FAILED && (flags & MAP_FIXED) && fd == -1) {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ void* nearest_addr = (void*)ROUNDDOWN((u64)addr,
+ (u64)si.dwAllocationGranularity);
+ size_t new_length = length + (u64)addr - (u64)nearest_addr;
+ res = mmap(nearest_addr, new_length, prot, flags, fd, offset);
+ unassert(mprotect(nearest_addr, new_length - length, PROT_NONE));
+ }
+#endif
#if LOG_MEM
char szbuf[16];
FormatSize(szbuf, length, 1024); This hack aligns the base address to the nearest allocatable address. This might leak some bytes, but because JIT (the only ones using For other purposes other than This hack still does not address the loader's problem though. And after reading your loader code for a while, I seem to understand what it does, step-by-step, but I do not understand why. Many ELF tutorials that I learned from take all the program headers, calculate a start and end address, allocate all pages at the same time before copying the data, and handles page permissions through |
When this hack is applied, the log changes to:
Note that I'm running |
The problem with doing that is it'll cause a page fault on every single page in the program image. Our loader code is complicated because it loads the program image into memory without copying it. This is important when loading programs like GCC CC1 which might have a ~33mb binary. Only a small number of those pages in the program image will ever be touched. So using our technique, they'll never become resident memory. |
I recommend enabling these: Lines 17 to 18 in 8ae81a2
|
Closing this, the sample mentioned in the issue works with the latest code from |
This comment noted that when the page size is not 64KB, the loader just "forgets" to copy the data onto memory.
This problem was discovered in the first versions of
blink
on Emscripten before a hack hardcoding the page size to 4096 is enabled.However, on Cygwin, this problem appears again:
While Windows can use 4096-byte page sizes for
mprotect
and stuff, it can only allocate pages with 64kb granularity.The text was updated successfully, but these errors were encountered: