about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-11-04 09:09:55 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-11-04 09:09:55 +0100
commitf0d5e9d01ef74346da13f88f7d1b6678980e622b (patch)
tree0636c68df9bb7a5ba2c8d82a7e5158764f04c76c /src
parentbe05309e51e1df36dd1aec67e6421eb7dcf0e9c9 (diff)
downloadbox64-f0d5e9d01ef74346da13f88f7d1b6678980e622b.tar.gz
box64-f0d5e9d01ef74346da13f88f7d1b6678980e622b.zip
[ELFLOADER] More changes to elf memory managment
Diffstat (limited to 'src')
-rw-r--r--src/elfs/elfloader.c37
-rw-r--r--src/elfs/elfloader_private.h1
2 files changed, 30 insertions, 8 deletions
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 4917c628..7cc4ec12 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -197,16 +197,34 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
     if(!offs && !head->vaddr)
         offs = (uintptr_t)find47bitBlockElf(head->memsz, mainbin, max_align); // limit to 47bits...
 
+    // prereserve the whole elf image, without populating
+    void* image = mmap64((void*)(head->vaddr?head->vaddr:offs), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+    if(image!=MAP_FAILED && !head->vaddr && image!=(void*)offs) {
+        offs = (uintptr_t)image;
+        printf_log(LOG_INFO, "Mamp64 for (@%p 0x%zx) for elf \"%s\" returned %p instead", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image);
+    }
+    if(image==MAP_FAILED || image!=(void*)(head->vaddr?head->vaddr:offs)) {
+        printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx) for elf \"%s\"", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name);
+        if(image==MAP_FAILED) {
+            printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno));
+        } else {
+            printf_log(LOG_NONE, " got %p\n", image);
+        }
+        return 1;
+    }
     head->delta = offs;
     printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name);
 
+    head->image = image;
+    setProtection_mmap((uintptr_t)image, head->memsz, 0);
+
     head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
     head->tlsbase = AddTLSPartition(context, head->tlssize);
     // and now, create all individual blocks
     head->memory = (char*)0xffffffffffffffff;
     int n = 0;
     for (size_t i=0; i<head->numPHEntries; ++i) {
-        if(head->PHEntries[i].p_type == PT_LOAD) {
+        if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
             Elf64_Phdr * e = &head->PHEntries[i];
 
             head->multiblocks[n].flags = e->p_flags;
@@ -225,16 +243,16 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
                 try_mmap = 0;
             if(head->multiblocks[n].asize != head->multiblocks[n].size)
                 try_mmap = 0;
-            if(!e->p_flags || !e->p_filesz)
+            if(!e->p_filesz)
                 try_mmap = 0;
-            uint8_t prot = e->p_flags?(PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0)):0;
+            uint8_t prot = PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0);
             if(try_mmap) {
                 printf_log(log_level, "Mmaping 0x%lx memory @%p for Elf \"%s\"\n", head->multiblocks[n].size, (void*)head->multiblocks[n].paddr, head->name);
                 void* p = mmap64(
                     (void*)head->multiblocks[n].paddr, 
                     head->multiblocks[n].asize, 
                     prot,
-                    MAP_PRIVATE,
+                    MAP_PRIVATE|MAP_FIXED,
                     head->fileno,
                     e->p_offset
                 );
@@ -254,7 +272,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
                     (void*)paddr,
                     head->multiblocks[n].asize,
                     prot,
-                    MAP_PRIVATE|MAP_ANONYMOUS|(e->p_flags?MAP_NORESERVE:0),
+                    MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
                     -1,
                     0
                 );
@@ -315,17 +333,20 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
 void FreeElfMemory(elfheader_t* head)
 {
     if(head->multiblock_n) {
-        for(int i=0; i<head->multiblock_n; ++i) {
 #ifdef DYNAREC
+        for(int i=0; i<head->multiblock_n; ++i) {
             dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
             if(box64_dynarec)
                 cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].size, 1);
-#endif
-            munmap(head->multiblocks[i].p, head->multiblocks[i].asize);
             freeProtection((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize);
         }
+#endif
         box_free(head->multiblocks);
     }
+    // we only need to free the overall mmap, no need to free individual part as they are inside the big one
+    if(head->image && head->memsz)
+        munmap(head->image, head->memsz);
+    freeProtection((uintptr_t)head->image, head->memsz);
 }
 
 int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h
index b80c87db..ed151b39 100644
--- a/src/elfs/elfloader_private.h
+++ b/src/elfs/elfloader_private.h
@@ -49,6 +49,7 @@ typedef struct elfheader_s {
     uint32_t    flags;
 
     intptr_t    delta;  // should be 0
+    void*       image;
 
     uintptr_t   entrypoint;
     uintptr_t   initentry;