about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-11-05 13:17:50 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-11-05 13:17:50 +0100
commit9c120168593c9565780c365aef0f511f3e692d61 (patch)
tree9c9a94ca40d11fdeb32d574b26ac51264bcfd8db /src
parente6943c8a9dad781aa5e1caf7c0cd59041e3c29f8 (diff)
downloadbox64-9c120168593c9565780c365aef0f511f3e692d61.tar.gz
box64-9c120168593c9565780c365aef0f511f3e692d61.zip
Better way to track mapped memory
Diffstat (limited to 'src')
-rw-r--r--src/custommem.c94
-rw-r--r--src/elfs/elfloader.c6
-rw-r--r--src/include/custommem.h3
-rw-r--r--src/tools/bridge.c2
4 files changed, 62 insertions, 43 deletions
diff --git a/src/custommem.c b/src/custommem.c
index dbbd223c..b4bdde6c 100644
--- a/src/custommem.c
+++ b/src/custommem.c
@@ -93,7 +93,8 @@ typedef struct mapmem_s {
     struct mapmem_s *next;
 } mapmem_t;
 
-static mapmem_t *mapmem = NULL;
+static mapmem_t *mapallmem = NULL;
+static mapmem_t *mmapmem = NULL;
 
 typedef struct blocklist_s {
     void*               block;
@@ -1069,7 +1070,6 @@ void protectDB(uintptr_t addr, uintptr_t size)
             prot = native_lock_xchg_b(&block[i&0xffff], PROT_WAIT);
         } while(prot==PROT_WAIT);
         uint32_t dyn = prot&PROT_DYN;
-        uint32_t mapped = prot&PROT_MMAP;
         if(!prot)
             prot = PROT_READ | PROT_WRITE | PROT_EXEC;      // comes from malloc & co, so should not be able to execute
         prot&=~PROT_CUSTOM;
@@ -1077,9 +1077,9 @@ void protectDB(uintptr_t addr, uintptr_t size)
             if(prot&PROT_WRITE) {
                 if(!dyn) 
                     mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
-                prot |= mapped|PROT_DYNAREC;
+                prot |= PROT_DYNAREC;
             } else 
-                prot |= mapped|PROT_DYNAREC_R;
+                prot |= PROT_DYNAREC_R;
         }
         native_lock_storeb(&block[i&0xffff], prot);
     }
@@ -1110,7 +1110,7 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
                     prot&=~PROT_DYN;
                     if(mark)
                         cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
-                    mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP);
+                    mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
                 } else if(prot&PROT_DYNAREC_R)
                     prot &= ~PROT_CUSTOM;
             }
@@ -1147,7 +1147,7 @@ int isprotectedDB(uintptr_t addr, size_t size)
 
 #endif
 
-void printMapMem()
+void printMapMem(mapmem_t* mapmem)
 {
     mapmem_t* m = mapmem;
     while(m) {
@@ -1156,10 +1156,12 @@ void printMapMem()
     }
 }
 
-void addMapMem(uintptr_t begin, uintptr_t end)
+void addMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
 {
     if(!mapmem)
         return;
+    if(begin<box64_pagesize)
+        begin = box64_pagesize;
     begin &=~(box64_pagesize-1);
     end = (end&~(box64_pagesize-1))+(box64_pagesize-1); // full page
     // sanitize values
@@ -1195,10 +1197,12 @@ void addMapMem(uintptr_t begin, uintptr_t end)
     }
     // all done!
 }
-void removeMapMem(uintptr_t begin, uintptr_t end)
+void removeMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
 {
     if(!mapmem)
         return;
+    if(begin<box64_pagesize)
+        begin = box64_pagesize;
     begin &=~(box64_pagesize-1);
     end = (end&~(box64_pagesize-1))+(box64_pagesize-1); // full page
     // sanitize values
@@ -1249,7 +1253,7 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
     if(end>=(1LL<<(48-MEMPROT_SHIFT)))
         end = (1LL<<(48-MEMPROT_SHIFT))-1;
     mutex_lock(&mutex_prot);
-    addMapMem(addr, addr+size-1);
+    addMapMem(mapallmem, addr, addr+size-1);
     UNLOCK_DYNAREC();
     uintptr_t bidx = ~1LL;
     uint8_t *block = NULL;
@@ -1260,7 +1264,6 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
         }
         GET_PROT_WAIT(old_prot, i&0xffff);
         uint32_t dyn=(old_prot&PROT_DYN);
-        uint32_t mapped=(old_prot&PROT_MMAP);
         if(!(dyn&PROT_NOPROT)) {
             if(dyn && (prot&PROT_WRITE)) {   // need to remove the write protection from this block
                 dyn = PROT_DYNAREC;
@@ -1269,7 +1272,7 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
                 dyn = PROT_DYNAREC_R;
             }
         }
-        SET_PROT(i&0xffff, prot|dyn|mapped);
+        SET_PROT(i&0xffff, prot|dyn);
     }
     UNLOCK_NODYNAREC();
 }
@@ -1281,7 +1284,7 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
     if(end>=(1LL<<(48-MEMPROT_SHIFT)))
         end = (1LL<<(48-MEMPROT_SHIFT))-1;
     mutex_lock(&mutex_prot);
-    addMapMem(addr, addr+size-1);
+    addMapMem(mapallmem, addr, addr+size-1);
     UNLOCK_DYNAREC();
     for (uintptr_t i=(idx>>16); i<=(end>>16); ++i) {
         uint8_t* block = getProtBlock(i, prot?1:0);
@@ -1297,11 +1300,14 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
 
 void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
 {
+    mutex_lock(&mutex_prot);
+    addMapMem(mmapmem, addr, addr+size-1);
+    mutex_unlock(&mutex_prot);
     if(prot)
-        setProtection(addr, size, prot|PROT_MMAP);
+        setProtection(addr, size, prot);
     else {
         mutex_lock(&mutex_prot);
-        addMapMem(addr, addr+size-1);
+        addMapMem(mapallmem, addr, addr+size-1);
         mutex_unlock(&mutex_prot);
     }
 }
@@ -1327,7 +1333,7 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
     if(end>=(1LL<<(48-MEMPROT_SHIFT)))
         end = (1LL<<(48-MEMPROT_SHIFT))-1;
     mutex_lock(&mutex_prot);
-    addMapMem(addr, addr+size-1);
+    addMapMem(mapallmem, addr, addr+size-1);
     mutex_unlock(&mutex_prot);
     // don't need to add precise tracking probably
 }
@@ -1436,7 +1442,8 @@ void freeProtection(uintptr_t addr, size_t size)
     if(end>=(1LL<<(48-MEMPROT_SHIFT)))
         end = (1LL<<(48-MEMPROT_SHIFT))-1;
     mutex_lock(&mutex_prot);
-    removeMapMem(addr, addr+size-1);
+    removeMapMem(mapallmem, addr, addr+size-1);
+    removeMapMem(mmapmem, addr, addr+size-1);
     UNLOCK_DYNAREC();
     for (uintptr_t i=idx; i<=end; ++i) {
         const uint32_t key = (i>>16);
@@ -1503,19 +1510,23 @@ uint32_t getProtection(uintptr_t addr)
     uint8_t *block = getProtBlock(idx>>16, 0);
     GET_PROT(ret, idx&0xffff);
     UNLOCK_NODYNAREC();
-    return ret&~PROT_MMAP;
+    return ret;
 }
 
 int getMmapped(uintptr_t addr)
 {
-    if(addr>=(1LL<<48))
-        return 0;
-    LOCK_NODYNAREC();
-    const uintptr_t idx = (addr>>MEMPROT_SHIFT);
-    uint8_t *block = getProtBlock(idx>>16, 0);
-    GET_PROT(ret, idx&0xffff);
-    UNLOCK_NODYNAREC();
-    return (ret&PROT_MMAP)?1:0;
+    mapmem_t* m = mmapmem;
+    if(addr<box64_pagesize) return 0;
+    while(m) {
+        uintptr_t begin = m->begin;
+        uintptr_t end = m->end;
+        if(addr>=begin && addr<=end)
+            return 1;
+        if(addr<begin)
+            return 0;
+        m = m->next;
+    }
+    return 0;
 }
 
 #define LOWEST (void*)0x10000
@@ -1523,7 +1534,7 @@ int getMmapped(uintptr_t addr)
 
 void* find31bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
 {
-    mapmem_t* m = mapmem;
+    mapmem_t* m = mapallmem;
     uintptr_t h = (uintptr_t)hint;
     if(hint<LOWEST) hint = LOWEST;
     if(!mask) mask = 0xffff;
@@ -1559,7 +1570,7 @@ void* find47bitBlock(size_t size)
 }
 void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
 {
-    mapmem_t* m = mapmem;
+    mapmem_t* m = mapallmem;
     uintptr_t h = (uintptr_t)hint;
     if(hint<LOWEST) hint = LOWEST;
     if(!mask) mask = 0xffff;
@@ -1596,7 +1607,7 @@ void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask)
 
 int isBlockFree(void* hint, size_t size)
 {
-    mapmem_t* m = mapmem;
+    mapmem_t* m = mapallmem;
     uintptr_t h = (uintptr_t)hint;
     if(h>0x800000000000LL)
         return 0;   // no tracking there
@@ -1679,7 +1690,7 @@ void reserveHighMem()
     #endif
         return; // don't reserve by default
     intptr_t cur = 1LL<<47;
-    mapmem_t* m = mapmem;
+    mapmem_t* m = mapallmem;
     while(m && (m->end<cur)) {
         m = m->next;
     }
@@ -1697,7 +1708,7 @@ void reserveHighMem()
         cur = m->end + 1;
         m = m->next;
         if(addr)
-            addMapMem(addr, end);
+            addMapMem(mapallmem, addr, end);
     }
 }
 
@@ -1732,12 +1743,16 @@ void init_custommem_helper(box64context_t* ctx)
     lockaddress = kh_init(lockaddress);
 #endif
     pthread_atfork(NULL, NULL, atfork_child_custommem);
-    // init mapmem list
-    mapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
-    mapmem->begin = 0x0;
-    mapmem->end = (uintptr_t)LOWEST - 1;
+    // init mapallmem list
+    mapallmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
+    mapallmem->begin = 0x0;
+    mapallmem->end = (uintptr_t)LOWEST - 1;
     loadProtectionFromMap();
     reserveHighMem();
+    // init mmapmem list
+    mmapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
+    mmapmem->begin = 0x0;
+    mmapmem->end = (uintptr_t)box64_pagesize - 1;
     // check if PageSize is correctly defined
     if(box64_pagesize != (1<<MEMPROT_SHIFT)) {
         printf_log(LOG_NONE, "Error: PageSize configuration is wrong: configured with %d, but got %zd\n", 1<<MEMPROT_SHIFT, box64_pagesize);
@@ -1849,9 +1864,14 @@ void fini_custommem_helper(box64context_t *ctx)
     pthread_mutex_destroy(&mutex_prot);
     pthread_mutex_destroy(&mutex_blocks);
     #endif
-    while(mapmem) {
-        mapmem_t *tmp = mapmem;
-        mapmem = mapmem->next;
+    while(mapallmem) {
+        mapmem_t *tmp = mapallmem;
+        mapallmem = mapallmem->next;
+        box_free(tmp);
+    }
+    while(mmapmem) {
+        mapmem_t *tmp = mmapmem;
+        mmapmem = mmapmem->next;
         box_free(tmp);
     }
 }
diff --git a/src/elfs/elfloader.c b/src/elfs/elfloader.c
index 7cc4ec12..0e9feb75 100644
--- a/src/elfs/elfloader.c
+++ b/src/elfs/elfloader.c
@@ -216,7 +216,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
     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);
+    setProtection((uintptr_t)image, head->memsz, 0);
 
     head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
     head->tlsbase = AddTLSPartition(context, head->tlssize);
@@ -260,7 +260,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
                     try_mmap = 0;
                     printf_log(log_level, "Mapping failed, using regular mmap+read");
                 } else {
-                    setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot);
+                    setProtection((uintptr_t)p, head->multiblocks[n].asize, prot);
                     head->multiblocks[n].p = p;
 
                 }
@@ -285,7 +285,7 @@ int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
                     }
                     return 1;
                 }
-                setProtection_mmap((uintptr_t)p, head->multiblocks[n].asize, prot);
+                setProtection((uintptr_t)p, head->multiblocks[n].asize, prot);
                 head->multiblocks[n].p = p;
                 if(e->p_filesz) {
                     fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET);
diff --git a/src/include/custommem.h b/src/include/custommem.h
index 4fbdae6d..76157123 100644
--- a/src/include/custommem.h
+++ b/src/include/custommem.h
@@ -71,9 +71,8 @@ uintptr_t getJumpAddress64(uintptr_t addr);
 #define PROT_DYNAREC    0x80
 #define PROT_DYNAREC_R  0x40
 #define PROT_NOPROT     0x20
-#define PROT_MMAP       0x10
 #define PROT_DYN        (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
-#define PROT_CUSTOM     (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP | PROT_NOPROT)
+#define PROT_CUSTOM     (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
 #define PROT_WAIT       0xFF
 
 void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
diff --git a/src/tools/bridge.c b/src/tools/bridge.c
index f86998a5..d009021d 100644
--- a/src/tools/bridge.c
+++ b/src/tools/bridge.c
@@ -60,7 +60,7 @@ brick_t* NewBrick(void* old)
         printf_log(LOG_NONE, "Warning, cannot allocate 0x%lx aligned bytes for bridge, will probably crash later\n", NBRICK*sizeof(onebridge_t));
     }
     #ifdef DYNAREC
-    setProtection((uintptr_t)ptr, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NOPROT | PROT_MMAP);
+    setProtection((uintptr_t)ptr, NBRICK * sizeof(onebridge_t), PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NOPROT);
     #endif
     dynarec_log(LOG_INFO, "New Bridge brick at %p (size 0x%zx)\n", ptr, NBRICK*sizeof(onebridge_t));
     ret->b = ptr;