about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c17
-rw-r--r--src/elfs/elfloader.c313
-rw-r--r--src/elfs/elfloader_private.h21
-rw-r--r--src/include/custommem.h1
-rw-r--r--src/include/elfloader.h5
-rw-r--r--src/librarian/library.c60
-rw-r--r--src/main.c21
-rw-r--r--src/wrapped/wrappedlibc.c12
8 files changed, 159 insertions, 291 deletions
diff --git a/src/custommem.c b/src/custommem.c
index 51359bd4..b85b2257 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -85,6 +85,7 @@ static uint64_t  memprot_allocated = 0, memprot_max_allocated = 0;
 #endif
 static memprot_t memprot[1<<MEMPROT_SIZE0];    // x86_64 mem is 48bits, page is 12bits, so memory is tracked as [20][16][page protection]
 static uint8_t   memprot_default[MEMPROT_SIZE];
+static int have48bits = 0;
 static int inited = 0;
 
 typedef struct mapmem_s {
@@ -1410,6 +1411,8 @@ void loadProtectionFromMap()
         if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
             int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
             allocProtection(s, e-s, prot);
+            if(s>0x7fff00000000LL)
+                have48bits = 1;
         }
     }
     fclose(f);
@@ -1570,6 +1573,20 @@ void* find47bitBlockNearHint(void* hint, size_t size)
     }
     return NULL;
 }
+void* find47bitBlockElf(size_t size, int mainbin)
+{
+    static void* startingpoint = NULL;
+    if(!startingpoint) {
+        startingpoint = (void*)(have48bits?0x7fff00000000LL:0x7f00000000LL);
+    }
+    void* mainaddr = (void*)0x100000000LL;
+    void* ret = find47bitBlockNearHint(mainbin?mainaddr:startingpoint, size);
+    if(!ret)
+        ret = find32bitBlock(size);
+    if(!mainbin)
+        startingpoint = (void*)(((uintptr_t)startingpoint+size+0x1000000LL)&~0xffffffLL);
+    return ret;
+}
 
 int isBlockFree(void* hint, size_t size)
 {
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 818d7d5f..a7d6e5b3 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -69,6 +69,9 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
     h->globaldefver = NewDefaultVersion();
     h->weakdefver = NewDefaultVersion();
     h->refcnt = 1;
+
+    h->file = f;
+    h->fileno = fileno(f);
     
     return h;
 }
@@ -100,6 +103,8 @@ void FreeElfHeader(elfheader_t** head)
 
     box_free(h->name);
     box_free(h->path);
+    if(h->file)
+        fclose(h->file);
     box_free(h);
 
     *head = NULL;
@@ -169,201 +174,112 @@ const char* ElfPath(elfheader_t* head)
         return NULL;
     return head->path;
 }
-int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
+int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
 {
     uintptr_t offs = 0;
+    loadProtectionFromMap();
     if(!head->vaddr && box64_load_addr) {
         offs = (uintptr_t)find47bitBlockNearHint((void*)box64_load_addr, head->memsz);
         box64_load_addr += head->memsz;
         box64_load_addr = (box64_load_addr+0x10ffffffLL)&~0xffffffLL;
     }
     int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG;
-    if(!offs)
-        offs = head->vaddr;
-    if(head->vaddr) {
-        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->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t));
-        head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
-        head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
-        // 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 && head->PHEntries[i].p_flags) {
-                Elf64_Phdr * e = &head->PHEntries[i];
-                uintptr_t bstart = e->p_vaddr;
-                uint64_t bsize = e->p_memsz;
-                uintptr_t balign = e->p_align;
-                if (balign) balign = balign-1; else balign = 1;
-                if(balign<4095) balign = 4095;
-                uintptr_t bend = (bstart + bsize + balign)&(~balign);
-                bstart &= ~balign;
-                int ok = 0;
-                for (int j=0; !ok && j<n; ++j) {
-                    uintptr_t start = head->multiblock_offs[j];
-                    uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j];
-                    start &= ~balign;
-                    if( (head->e_type == ET_DYN) ||
-                        (((bstart>=start) && (bstart<=end+0x1000)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
-                    {
-                        // merge
-                        ok = 1;
-                        if(bstart<start)
-                            head->multiblock_offs[j] = bstart;
-                        head->multiblock_size[j] = ((bend>end)?bend:end) - head->multiblock_offs[j];
-                        --head->multiblock_n;
-                    }
-                }
-                if(!ok) {
-                    head->multiblock_offs[n] = bstart;
-                    head->multiblock_size[n] = bend - head->multiblock_offs[n];
-                    ++n;
-                }
-            }
-        head->multiblock_n = n; // might be less in fact
-        for (int i=0; i<head->multiblock_n; ++i) {
-            printf_log(log_level, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
-            void* p = mmap((void*)head->multiblock_offs[i], head->multiblock_size[i]
-                , PROT_READ | PROT_WRITE | PROT_EXEC
-                , MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/
-                , -1, 0);
-            if(p==MAP_FAILED) {
-                printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name);
-                return 1;
-            }
-            if(head->multiblock_offs[i] &&( p!=(void*)head->multiblock_offs[i])) {
-                if((head->e_type!=ET_DYN)) {
-                    printf_log(LOG_NONE, "Error, memory map (@%p 0x%zx/0x%zx) for elf \"%s\" allocated @%p\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name, p);
-                    return 1;
-                } else {
-                    printf_log(LOG_INFO, "Allocated memory is not at hinted %p but %p (size %lx) \"%s\"\n", (void*)head->multiblock_offs[i], p, head->multiblock_size[i], head->name);
-                    // need to adjust vaddr!
-                    for (size_t j=0; j<head->numPHEntries; ++j) 
-                        if(head->PHEntries[j].p_type == PT_LOAD) {
-                            Elf64_Phdr * e = &head->PHEntries[j];
-                            if(e->p_vaddr>=head->multiblock_offs[j] && e->p_vaddr<(head->multiblock_offs[j]+head->multiblock_size[j])) {
-                                e->p_vaddr = e->p_vaddr - head->multiblock_offs[j] + (uintptr_t)p;
-                                if(!head->delta) head->delta = (intptr_t)p - (intptr_t)head->multiblock_offs[j];
-                            }
-                        }
-                }
-            }
-            setProtection((uintptr_t)p, head->multiblock_size[i], PROT_READ | PROT_WRITE | PROT_EXEC);
-            head->multiblock[i] = p;
-            if(p<(void*)head->memory)
-                head->memory = (char*)p;
-        }
-    } else {
-        // vaddr is 0, load everything has a One block
-        uintptr_t old_offs = offs;
-        if(!offs /*&& box64_wine*/)
-            offs = (uintptr_t)find47bitBlock(head->memsz); // limit to 47bits...
-        printf_log(log_level, "Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
-        void* p = mmap((void*)offs, head->memsz
-            , PROT_READ | PROT_WRITE | PROT_EXEC
-            , MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
-            , -1, 0);
-        if(offs &&!old_offs && p!=MAP_FAILED && offs!=(uintptr_t)p) {
-            // try again
-            munmap(p, head->memsz);
-            loadProtectionFromMap();
-            offs = (uintptr_t)find47bitBlock(head->memsz);
-            printf_log(log_level, "New, try. Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
-            p = mmap((void*)offs, head->memsz
-                , PROT_READ | PROT_WRITE | PROT_EXEC
-                , MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
-                , -1, 0);
-        }
-        if(p==MAP_FAILED) {
-            printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name);
-            return 1;
-        }
-        if(offs && (p!=(void*)offs) && (head->e_type!=ET_DYN)) {
-            printf_log(LOG_NONE, "Error, memory map (@%p 0x%zx/0x%zx) for elf \"%s\" allocated @%p\n", (void*)offs, head->memsz, head->align, head->name, p);
-            return 1;
-        }
-        setProtection((uintptr_t)p, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
-        head->memory = p;
-        memset(p, 0, head->memsz);
-        head->delta = (intptr_t)p - (intptr_t)head->vaddr;
-        printf_log(log_level, "Got %p (delta=%p)\n", p, (void*)head->delta);
-
-        head->multiblock_n = 1;
-        head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t));
-        head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
-        head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
-        head->multiblock_size[0] = head->memsz;
-        head->multiblock_offs[0] = (uintptr_t)p;
-        head->multiblock[0] = p;
-    }
+    if(!offs && !head->vaddr)
+        offs = (uintptr_t)find47bitBlockElf(head->memsz, mainbin); // limit to 47bits...
 
-    head->tlsbase = AddTLSPartition(context, head->tlssize);
-
-    return 0;
-}
-
-void FreeElfMemory(elfheader_t* head)
-{
-    if(head->multiblock_n) {
-        for(int i=0; i<head->multiblock_n; ++i) {
-#ifdef DYNAREC
-            dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
-            if(box64_dynarec) {
-                cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
-                freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
-            }
-#endif
-            munmap(head->multiblock[i], head->multiblock_size[i]);
-        }
-        box_free(head->multiblock);
-        box_free(head->multiblock_size);
-        box_free(head->multiblock_offs);
-    }
-}
+    head->delta = offs;
+    printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name);
 
-int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
-{
+    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
+    head->memory = (char*)0xffffffffffffffff;
+    int n = 0;
     for (size_t i=0; i<head->numPHEntries; ++i) {
         if(head->PHEntries[i].p_type == PT_LOAD) {
             Elf64_Phdr * e = &head->PHEntries[i];
-            char* dest = (char*)e->p_paddr + head->delta;
-            printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz);
-            void* p = (void*)-1;
-            if(e->p_memsz==e->p_filesz && !(e->p_align&(box64_pagesize-1))) {
-                printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
-                p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
+
+            head->multiblocks[n].flags = e->p_flags;
+            head->multiblocks[n].offs = e->p_offset;
+            head->multiblocks[n].paddr = e->p_paddr + offs;
+            head->multiblocks[n].size = e->p_filesz;
+            head->multiblocks[n].align = e->p_align;
+            // check if alignment is correct
+            uintptr_t balign = head->multiblocks[n].align-1;
+            if(balign<(box64_pagesize-1)) balign = (box64_pagesize-1);
+            head->multiblocks[n].asize = e->p_memsz+(head->multiblocks[n].paddr&balign);
+            int try_mmap = 1;
+            if(e->p_offset&balign)
+                try_mmap = 0;
+            if(e->p_memsz-e->p_filesz>balign)
+                try_mmap = 0;
+            if(head->multiblocks[n].asize != head->multiblocks[n].size)
+                try_mmap = 0;
+            if(!e->p_flags)
+                try_mmap = 0;
+            uint8_t prot = e->p_flags?(PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0)):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,
+                    head->fileno,
+                    e->p_offset
+                );
+                if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) {
+                    try_mmap = 0;
+                    printf_log(log_level, "Mapping failed, using regular mmap+read");
+                } else {
+                    setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot);
+                    head->multiblocks[n].p = p;
+
+                }
             }
-            if(p!=dest) {
-                printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
-                fseeko64(f, e->p_offset, SEEK_SET);
-                if(e->p_filesz) {
-                    if(fread(dest, e->p_filesz, 1, f)!=1) {
-                        printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%zd)\n", i, e->p_filesz);
-                        return 1;
-                    }
+            if(!try_mmap) {
+                uintptr_t paddr = head->multiblocks[n].paddr&~balign;
+                printf_log(log_level, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblocks[n].asize, (void*)paddr, head->name);
+                void* p = mmap64(
+                    (void*)paddr,
+                    head->multiblocks[n].asize,
+                    prot,
+                    MAP_PRIVATE|MAP_ANONYMOUS|(e->p_flags?MAP_NORESERVE:0),
+                    -1,
+                    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);
+                    return 1;
+                }
+                setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot);
+                fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET);
+                if(fread((void*)head->multiblocks[n].paddr, head->multiblocks[n].size, 1, head->file)!=1) {
+                    printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name);
+                    return 1;
                 }
             }
 #ifdef DYNAREC
             if(box64_dynarec && (e->p_flags & PF_X)) {
-                dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
-                addDBFromAddressRange((uintptr_t)dest, e->p_memsz);
+                dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", head->multiblocks[n].p, (void*)head->multiblocks[n].asize);
+                addDBFromAddressRange((uintptr_t)head->multiblocks[n].p, head->multiblocks[n].asize);
             }
 #endif
-
-            // zero'd difference between filesz and memsz
-            /*if(e->p_filesz != e->p_memsz)
-                memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/    //block is already 0'd at creation
+            if((uintptr_t)head->memory>(uintptr_t)head->multiblocks[n].p)
+                head->memory = (char*)head->multiblocks[n].p;
+            ++n;
         }
         if(head->PHEntries[i].p_type == PT_TLS) {
             Elf64_Phdr * e = &head->PHEntries[i];
             char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase);
             printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
             if(e->p_filesz) {
-                fseeko64(f, e->p_offset, SEEK_SET);
-                if(fread(dest, e->p_filesz, 1, f)!=1) {
+                fseeko64(head->file, e->p_offset, SEEK_SET);
+                if(fread(dest, e->p_filesz, 1, head->file)!=1) {
                     printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz);
                     return 1;
                 }
@@ -373,9 +289,31 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
                 memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
         }
     }
+
+    // can close the elf file now!
+    fclose(head->file);
+    head->file = NULL;
+    head->fileno = -1;
+
     return 0;
 }
 
+void FreeElfMemory(elfheader_t* head)
+{
+    if(head->multiblock_n) {
+        for(int i=0; i<head->multiblock_n; ++i) {
+#ifdef DYNAREC
+            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);
+        }
+        box_free(head->multiblocks);
+    }
+}
+
 int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
 {
     if(!verneeded || !head)
@@ -393,39 +331,6 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne
     return 1;
 }
 
-int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
-{
-    (void)context;
-
-    for (size_t i=0; i<head->numPHEntries; ++i) {
-        if(head->PHEntries[i].p_type == PT_LOAD) {
-            Elf64_Phdr * e = &head->PHEntries[i];
-            char* dest = (char*)e->p_paddr + head->delta;
-            printf_log(LOG_DEBUG, "Re-loading block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
-            int ret = fseeko64(f, e->p_offset, SEEK_SET);
-            if(ret==-1) {printf_log(LOG_NONE, "Fail to (re)seek PT_LOAD part #%zu (offset=%ld, errno=%d/%s)\n", i, e->p_offset, errno, strerror(errno)); return 1;}
-            #ifdef DYNAREC
-            cleanDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
-            #endif
-            uint32_t page_offset = (uintptr_t)dest & (box64_pagesize - 1);
-            mprotect(dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
-            setProtection((uintptr_t)dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
-            if(e->p_filesz) {
-                ssize_t r = -1;
-                if((r=fread(dest, e->p_filesz, 1, f))!=1) {
-                    printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%zu (dest=%p, size=%zd, return=%zd, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f)));
-                    return 1;
-                }
-            }
-            // zero'd difference between filesz and memsz
-            if(e->p_filesz != e->p_memsz)
-                memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
-        }
-    }
-    // TLS data are just a copy, no need to re-load it
-    return 0;
-}
-
 int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername)
 {
     if(!h)
@@ -1444,8 +1349,8 @@ int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
     if(!h)
         return 0;
     for(int i=0; i<h->multiblock_n; ++i) {
-        uintptr_t base = h->multiblock_offs[i];
-        uintptr_t end = h->multiblock_offs[i] + h->multiblock_size[i] - 1;
+        uintptr_t base = h->multiblocks[i].paddr;
+        uintptr_t end = h->multiblocks[i].paddr + h->multiblocks[i].size - 1;
         if(addr>=base && addr<=end)
             return 1;
         
diff --git a/src/elfs/elfloader_private.h b/src/elfs/elfloader_private.h
index d2bc2559..b80c87db 100644
--- a/src/elfs/elfloader_private.h
+++ b/src/elfs/elfloader_private.h
@@ -9,7 +9,17 @@ typedef struct kh_defaultversion_s kh_defaultversion_t;
 #include <elf.h>
 #include "elfloader.h"
 
-struct elfheader_s {
+typedef struct multiblock_s {
+    void*       p;
+    uintptr_t   offs;
+    uintptr_t   paddr;
+    uintptr_t   align;
+    uint64_t    size;
+    uint64_t    asize;
+    uint8_t     flags;
+} multiblock_t;
+
+typedef struct elfheader_s {
     char*       name;
     char*       path;   // Resolved path to file
     char*       soname; // soname of the elf
@@ -90,20 +100,21 @@ struct elfheader_s {
     int         malloc_hook_2;  // this elf hook malloc, hacking it
 
     char*       memory;     // char* and not void* to allow math on memory pointer
-    void**      multiblock;
-    uintptr_t*  multiblock_offs;
-    uint64_t*   multiblock_size;
+    multiblock_t*  multiblocks;
     int         multiblock_n;
 
     library_t   *lib;       // attached lib (exept on main elf)
     needed_libs_t* needed;
 
+    FILE*       file;
+    int         fileno;
+
     kh_mapsymbols_t   *mapsymbols;
     kh_mapsymbols_t   *weaksymbols;
     kh_mapsymbols_t   *localsymbols;
     kh_defaultversion_t *globaldefver;  // the global default version for symbols (the XXX@@vvvv of symbols)
     kh_defaultversion_t *weakdefver;    // the weak default version for symbols (the XXX@@vvvv of symbols)
-};
+} elfheader_t;
 
 #define R_X86_64_NONE           0       /* No reloc */
 #define R_X86_64_64             1       /* Direct 64 bit  */
diff --git a/src/include/custommem.h b/src/include/custommem.h
index 31b3f30e..ffd20af6 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -96,6 +96,7 @@ void* find32bitBlock(size_t size);
 void* find31bitBlockNearHint(void* hint, size_t size);
 void* find47bitBlock(size_t size);
 void* find47bitBlockNearHint(void* hint, size_t size);
+void* find47bitBlockElf(size_t size, int mainbin);
 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/include/elfloader.h b/src/include/elfloader.h
index d9d7f152..bc09ad31 100644
--- a/src/include/elfloader.h
+++ b/src/include/elfloader.h
@@ -14,6 +14,7 @@ typedef struct kh_defaultversion_s kh_defaultversion_t;
 typedef struct dynablock_s dynablock_t;
 #endif
 
+// Open an elfheader. Transfert control of f to elfheader also!
 elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
 void FreeElfHeader(elfheader_t** head);
 const char* ElfName(elfheader_t* head);
@@ -22,11 +23,9 @@ void ElfAttachLib(elfheader_t* head, library_t* lib);
 
 // return 0 if OK
 int CalcLoadAddr(elfheader_t* head);
-int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin);
+int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin);
 void FreeElfMemory(elfheader_t* head);
-int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
 int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded);
-int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
 int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
 int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
 void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
diff --git a/src/librarian/library.c b/src/librarian/library.c
index a64ea596..896c6d0d 100644
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -261,25 +261,15 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t*
         if(CalcLoadAddr(elf_header)) {
             printf_log(LOG_NONE, "Error: reading elf header of %s\n", libname);
             FreeElfHeader(&elf_header);
-            fclose(f);
             return 0;
         }
-        // allocate memory
-        if(AllocElfMemory(context, elf_header, 0)) {
-            printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", libname);
+        // allocate and load elf
+        if(AllocLoadElfMemory(context, elf_header, 0)) {
+            printf_log(LOG_NONE, "Error: loading for elf %s\n", libname);
             FreeElfHeader(&elf_header);
-            fclose(f);
-            return 0;
-        }
-        // Load elf into memory
-        if(LoadElfMemory(f, context, elf_header)) {
-            printf_log(LOG_NONE, "Error: loading in memory elf %s\n", libname);
-            FreeElfHeader(&elf_header);
-            fclose(f);
             return 0;
         }
         // can close the file now
-        fclose(f);
         if(verneeded && !isElfHasNeededVer(elf_header, lib->name, verneeded)) {
             // incompatible, discard and continue the search
             FreeElfHeader(&elf_header);
@@ -488,50 +478,6 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x64emu_t*
     return 0;
 }
 
-int ReloadLibrary(library_t* lib, x64emu_t* emu)
-{
-    if(lib->type==LIB_EMULATED) {
-        elfheader_t *elf_header = lib->e.elf;
-        // reload image in memory and re-run the mapping
-        char libname[MAX_PATH];
-        strcpy(libname, lib->path);
-        int found = FileExist(libname, IS_FILE);
-        if(!found && !strchr(lib->path, '/'))
-            for(int i=0; i<my_context->box64_ld_lib.size; ++i)
-            {
-                strcpy(libname, my_context->box64_ld_lib.paths[i]);
-                strcat(libname, lib->path);
-                if(FileExist(libname, IS_FILE))
-                    break;
-            }
-        if(!FileExist(libname, IS_FILE)) {
-            printf_log(LOG_NONE, "Error: open file to re-load elf %s\n", libname);
-            return 1;   // failed to reload...
-        }
-        FILE *f = fopen(libname, "rb");
-        if(!f) {
-            printf_log(LOG_NONE, "Error: cannot open file to re-load elf %s (errno=%d/%s)\n", libname, errno, strerror(errno));
-            return 1;   // failed to reload...
-        }
-        if(ReloadElfMemory(f, my_context, elf_header)) {
-            printf_log(LOG_NONE, "Error: re-loading in memory elf %s\n", libname);
-            fclose(f);
-            return 1;
-        }
-        // can close the file now
-        fclose(f);
-        // should bindnow be store in a per/library basis?
-        if(RelocateElf(my_context->maplib, lib->maplib, 0, elf_header)) {
-            printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", lib->name);
-            return 1;
-        }
-        RelocateElfPlt(my_context->maplib, lib->maplib, 0, elf_header);
-        // init (will use PltRelocator... because some other libs are not yet resolved)
-        RunElfInit(elf_header, emu);
-    }
-    return 0;
-}
-
 int FiniLibrary(library_t* lib, x64emu_t* emu)
 {
     switch (lib->type) {
diff --git a/src/main.c b/src/main.c
index eb185c66..0d0a61cf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1728,32 +1728,21 @@ int main(int argc, const char **argv, char **env) {
 
     if(CalcLoadAddr(elf_header)) {
         printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->fullpath);
-        fclose(f);
-        free_contextargv();
-        FreeBox64Context(&my_context);
-        FreeCollection(&ld_preload);
-        return -1;
-    }
-    // allocate memory
-    if(AllocElfMemory(my_context, elf_header, 1)) {
-        printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->fullpath);
-        fclose(f);
+        FreeElfHeader(&elf_header);
         free_contextargv();
         FreeBox64Context(&my_context);
         FreeCollection(&ld_preload);
         return -1;
     }
-    // Load elf into memory
-    if(LoadElfMemory(f, my_context, elf_header)) {
-        printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->fullpath);
-        fclose(f);
+    // allocate memory and load elf
+    if(AllocLoadElfMemory(my_context, elf_header, 1)) {
+        printf_log(LOG_NONE, "Error: loading elf %s\n", my_context->fullpath);
+        FreeElfHeader(&elf_header);
         free_contextargv();
         FreeBox64Context(&my_context);
         FreeCollection(&ld_preload);
         return -1;
     }
-    // can close the file now
-    fclose(f);
     if(ElfCheckIfUseTCMallocMinimal(elf_header)) {
         if(!box64_tcmalloc_minimal) {
             // need to reload with tcmalloc_minimal as a LD_PRELOAD!
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index b9ed9c42..ce284a8d 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -2556,7 +2556,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
     (void)emu;
     if(prot&PROT_WRITE)
         prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on i386
-    if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) => ", addr, length, prot, flags, fd, offset);}
+    if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mmap64(%p, %lu, 0x%x, 0x%x, %d, %ld) => ", addr, length, prot, flags, fd, offset);}
     int new_flags = flags;
     #ifndef NOALIGN
     void* old_addr = addr;
@@ -2598,7 +2598,7 @@ EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot
         errno = EEXIST;
         return MAP_FAILED;
     }
-    if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "%p\n", ret);}
+    if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);}
     #ifdef DYNAREC
     if(box64_dynarec && ret!=MAP_FAILED) {
         /*if(flags&0x100000 && addr!=ret)
@@ -2623,9 +2623,9 @@ EXPORT void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot,
 EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr)
 {
     (void)emu;
-    if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "mremap(%p, %lu, %lu, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);}
+    if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mremap(%p, %lu, %lu, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);}
     void* ret = mremap(old_addr, old_size, new_size, flags, new_addr);
-    if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "%p\n", ret);}
+    if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);}
     if(ret!=(void*)-1) {
         uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM;
         if(ret==old_addr) {
@@ -2673,7 +2673,7 @@ EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t ne
 EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
 {
     (void)emu;
-    if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "munmap(%p, %lu)\n", addr, length);}
+    if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "munmap(%p, %lu)\n", addr, length);}
     int ret = munmap(addr, length);
     #ifdef DYNAREC
     if(!ret && box64_dynarec && length) {
@@ -2689,7 +2689,7 @@ EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
 EXPORT int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot)
 {
     (void)emu;
-    if(box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "mprotect(%p, %lu, 0x%x)\n", addr, len, prot);}
+    if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mprotect(%p, %lu, 0x%x)\n", addr, len, prot);}
     if(prot&PROT_WRITE)
         prot|=PROT_READ;    // PROT_READ is implicit with PROT_WRITE on x86_64
     int ret = mprotect(addr, len, prot);