diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-11-01 20:17:37 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-11-01 20:17:37 +0100 |
| commit | 52811e2ec2cab55775b9f878d80c0a626f0045ca (patch) | |
| tree | 15e9b3d588d4f5dfa3e62b2bc923521f12db023e /src | |
| parent | 107738f0f27493677c05fc7a8217aca7b673b5c9 (diff) | |
| download | box64-52811e2ec2cab55775b9f878d80c0a626f0045ca.tar.gz box64-52811e2ec2cab55775b9f878d80c0a626f0045ca.zip | |
[ELFLOADER] Fixed loading of elf with huge alignment
Diffstat (limited to 'src')
| -rw-r--r-- | src/custommem.c | 24 | ||||
| -rw-r--r-- | src/elfs/elfloader.c | 29 | ||||
| -rw-r--r-- | src/include/custommem.h | 6 | ||||
| -rw-r--r-- | src/wrapped/wrappedlibc.c | 6 |
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); |