about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-11-01 20:17:37 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-11-01 20:17:37 +0100
commit52811e2ec2cab55775b9f878d80c0a626f0045ca (patch)
tree15e9b3d588d4f5dfa3e62b2bc923521f12db023e /src
parent107738f0f27493677c05fc7a8217aca7b673b5c9 (diff)
downloadbox64-52811e2ec2cab55775b9f878d80c0a626f0045ca.tar.gz
box64-52811e2ec2cab55775b9f878d80c0a626f0045ca.zip
[ELFLOADER] Fixed loading of elf with huge alignment
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c24
-rw-r--r--src/elfs/elfloader.c29
-rw-r--r--src/include/custommem.h6
-rw-r--r--src/wrapped/wrappedlibc.c6
4 files changed, 40 insertions, 25 deletions
diff --git a/src/custommem.c b/src/custommem.c
index f72b83e4..dbbd223c 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -1521,11 +1521,12 @@ int getMmapped(uintptr_t addr)
 #define LOWEST (void*)0x10000
 #define MEDIUM (void*)0x40000000
 
-void* find31bitBlockNearHint(void* hint, size_t size)
+void* find31bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
 {
     mapmem_t* m = mapmem;
     uintptr_t h = (uintptr_t)hint;
     if(hint<LOWEST) hint = LOWEST;
+    if(!mask) mask = 0xffff;
     while(m && m->end<0x80000000LL) {
         // granularity 0x10000
         uintptr_t addr = m->end+1;
@@ -1533,7 +1534,7 @@ void* find31bitBlockNearHint(void* hint, size_t size)
         // check hint and available size
         if(addr<=h && end>=h && end-h+1>=size)
             return hint;
-        uintptr_t aaddr = (addr+0xffff)&~0xffff;
+        uintptr_t aaddr = (addr+mask)&~mask;
         if(aaddr>=h && end>aaddr && end-aaddr+1>=size)
             return (void*)aaddr;
         m = m->next;
@@ -1543,24 +1544,25 @@ void* find31bitBlockNearHint(void* hint, size_t size)
 
 void* find32bitBlock(size_t size)
 {
-    void* ret = find31bitBlockNearHint(MEDIUM, size);
+    void* ret = find31bitBlockNearHint(MEDIUM, size, 0);
     if(ret)
         return ret;
-    ret = find31bitBlockNearHint(LOWEST, size);
+    ret = find31bitBlockNearHint(LOWEST, size, 0);
     return ret?ret:find47bitBlock(size);
 }
 void* find47bitBlock(size_t size)
 {
-    void* ret = find47bitBlockNearHint((void*)0x100000000LL, size);
+    void* ret = find47bitBlockNearHint((void*)0x100000000LL, size, 0);
     if(!ret)
         ret = find32bitBlock(size);
     return ret;
 }
-void* find47bitBlockNearHint(void* hint, size_t size)
+void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
 {
     mapmem_t* m = mapmem;
     uintptr_t h = (uintptr_t)hint;
     if(hint<LOWEST) hint = LOWEST;
+    if(!mask) mask = 0xffff;
     while(m && m->end<0x800000000000LL) {
         // granularity 0x10000
         uintptr_t addr = m->end+1;
@@ -1568,23 +1570,25 @@ void* find47bitBlockNearHint(void* hint, size_t size)
         // check hint and available size
         if(addr<=h && end>=h && end-h+1>=size)
             return hint;
-        uintptr_t aaddr = (addr+0xffff)&~0xffff;
+        uintptr_t aaddr = (addr+mask)&~mask;
         if(aaddr>=h && end>aaddr && end-aaddr+1>=size)
             return (void*)aaddr;
         m = m->next;
     }
     return NULL;
 }
-void* find47bitBlockElf(size_t size, int mainbin)
+void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask)
 {
     static void* startingpoint = NULL;
     if(!startingpoint) {
         startingpoint = (void*)(have48bits?0x7fff00000000LL:0x7f00000000LL);
     }
     void* mainaddr = (void*)0x100000000LL;
-    void* ret = find47bitBlockNearHint(mainbin?mainaddr:startingpoint, size);
+    void* ret = find47bitBlockNearHint(mainbin?mainaddr:startingpoint, size, mask);
     if(!ret)
-        ret = find32bitBlock(size);
+        ret = find31bitBlockNearHint(MEDIUM, size, mask);
+    if(!ret)
+        ret = find31bitBlockNearHint(LOWEST, size, mask);
     if(!mainbin)
         startingpoint = (void*)(((uintptr_t)startingpoint+size+0x1000000LL)&~0xffffffLL);
     return ret;
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index d6fe2efb..9af62f39 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -178,22 +178,28 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
 {
     uintptr_t offs = 0;
     loadProtectionFromMap();
+    int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG;
+
+    head->multiblock_n = 0; // count PHEntrie with LOAD
+    uintptr_t max_align = (box64_pagesize-1);
+    for (size_t i=0; i<head->numPHEntries; ++i) 
+        if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
+            if(max_align < head->PHEntries[i].p_align-1)
+                max_align = head->PHEntries[i].p_align-1;
+            ++head->multiblock_n;
+        }
+
     if(!head->vaddr && box64_load_addr) {
-        offs = (uintptr_t)find47bitBlockNearHint((void*)box64_load_addr, head->memsz);
-        box64_load_addr += head->memsz;
+        offs = (uintptr_t)find47bitBlockNearHint((void*)((box64_load_addr+max_align)&~max_align), head->memsz, max_align);
+        box64_load_addr = offs + head->memsz;
         box64_load_addr = (box64_load_addr+0x10ffffffLL)&~0xffffffLL;
     }
-    int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG;
     if(!offs && !head->vaddr)
-        offs = (uintptr_t)find47bitBlockElf(head->memsz, mainbin); // limit to 47bits...
+        offs = (uintptr_t)find47bitBlockElf(head->memsz, mainbin, max_align); // limit to 47bits...
 
     head->delta = offs;
     printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name);
 
-    head->multiblock_n = 0; // count PHEntrie with LOAD
-    for (size_t i=0; i<head->numPHEntries; ++i) 
-        if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
-            ++head->multiblock_n;
     head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
     head->tlsbase = AddTLSPartition(context, head->tlssize);
     // and now, create all individual blocks
@@ -253,7 +259,12 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
                     0
                 );
                 if(p==MAP_FAILED || p!=(void*)paddr) {
-                    printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name);
+                    printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, head->multiblocks[n].asize, balign, head->name);
+                    if(p==MAP_FAILED) {
+                        printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno));
+                    } else {
+                        printf_log(LOG_NONE, " got %p\n", p);
+                    }
                     return 1;
                 }
                 setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot);
diff --git a/src/include/custommem.h b/src/include/custommem.h
index ffd20af6..4fbdae6d 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -93,10 +93,10 @@ int AreaInHotPage(uintptr_t start, uintptr_t end);
 void AddHotPage(uintptr_t addr);
 #endif
 void* find32bitBlock(size_t size);
-void* find31bitBlockNearHint(void* hint, size_t size);
+void* find31bitBlockNearHint(void* hint, size_t size, uintptr_t mask);
 void* find47bitBlock(size_t size);
-void* find47bitBlockNearHint(void* hint, size_t size);
-void* find47bitBlockElf(size_t size, int mainbin);
+void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask); // mask can be 0 for default one (0xffff)
+void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask);
 int isBlockFree(void* hint, size_t size);
 
 // unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index cee5fecd..ff6ed7ce 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2563,7 +2563,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
     new_flags&=~MAP_32BIT;   // remove MAP_32BIT
     if(flags&MAP_32BIT) {
         // MAP_32BIT only exist on x86_64!
-        addr = find31bitBlockNearHint(addr, length);
+        addr = find31bitBlockNearHint(addr, length, 0);
     } else if (box64_wine || 1) {   // other mmap should be restricted to 47bits
         if(!addr)
             addr = find47bitBlock(length);
@@ -2576,7 +2576,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
         printf_log(LOG_DEBUG, "Warning, mmap on 32bits didn't worked, ask %p, got %p ", addr, ret);
         munmap(ret, length);
         loadProtectionFromMap();    // reload map, because something went wrong previously
-        addr = find31bitBlockNearHint(old_addr, length); // is this the best way?
+        addr = find31bitBlockNearHint(old_addr, length, 0); // is this the best way?
         new_flags = (addr && isBlockFree(addr, length) )? (new_flags|MAP_FIXED) : new_flags;
         if(new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE)==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
         ret = mmap64(addr, length, prot, new_flags, fd, offset);
@@ -2586,7 +2586,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
         printf_log(LOG_DEBUG, "Warning, mmap on 47bits didn't worked, ask %p, got %p ", addr, ret);
         munmap(ret, length);
         loadProtectionFromMap();    // reload map, because something went wrong previously
-        addr = find47bitBlockNearHint(old_addr, length); // is this the best way?
+        addr = find47bitBlockNearHint(old_addr, length, 0); // is this the best way?
         new_flags = (addr && isBlockFree(addr, length)) ? (new_flags|MAP_FIXED) : new_flags;
         if(new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE)==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
         ret = mmap64(addr, length, prot, new_flags, fd, offset);