diff --git a/src/custommem.c b/src/custommem.c index af8dcdef2f..ac6de222f0 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -2911,33 +2911,19 @@ void* find31bitBlockNearHint(void* hint_, size_t size, uintptr_t mask) { // first, check if program break as changed catchup_brk_protection(); - uint32_t prot; uintptr_t hint = (uintptr_t)hint_; if(hint_upper) upper = 0x100000000LL; if(!mask) mask = 0xffff; - while(cur=size) - return (void*)cur; - } - // granularity 0x10000 - cur = (bend+mask)&~mask; - } + if(rb_find_free_range(mapallmem, cur, upper, size, mask, &cur)) + return (void*)cur; if(hint_) return NULL; cur = (uintptr_t)LOWEST; - while(cur<(uintptr_t)hint) { - if(!rb_get_end(mapallmem, cur, &prot, &bend)) { - if(bend-cur>=size) - return (void*)cur; - } - // granularity 0x10000 - cur = (bend+mask)&~mask; - } + if(rb_find_free_range(mapallmem, cur, hint, size, mask, &cur)) + return (void*)cur; return NULL; } @@ -2962,19 +2948,11 @@ void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask) { // first, check if program break as changed catchup_brk_protection(); - uint32_t prot; if(hint=size) - return (void*)cur; - } - // granularity 0x10000 - cur = (bend+mask)&~mask; - } + if(rb_find_free_range(mapallmem, cur, 0x800000000000LL, size, mask, &cur)) + return (void*)cur; return NULL; } void* find47bitBlockElf(size_t size, int mainbin, uintptr_t mask) diff --git a/src/include/rbtree.h b/src/include/rbtree.h index cb0d14d52f..18572076c2 100644 --- a/src/include/rbtree.h +++ b/src/include/rbtree.h @@ -66,6 +66,7 @@ #ifndef RBTREE_H #define RBTREE_H +#include #include typedef struct rbtree rbtree_t; @@ -136,6 +137,20 @@ int rb_get_end(rbtree_t* tree, uintptr_t addr, uint32_t* val, uintptr_t* end); */ int rb_get_end_64(rbtree_t* tree, uintptr_t addr, uint64_t* val, uintptr_t* end); +/** + * rb_find_free_range() - Finds the first suitably aligned free address range. + * @tree: Tree containing the occupied address ranges. + * @start: Inclusive lower bound for the search. + * @upper: Exclusive upper bound for the search. + * @size: Required size of the free range. + * @align_mask: Alignment mask applied after occupied ranges are skipped. + * @result: Pointer receiving the start of the first matching range. + * + * This function performs one tree descent followed by an in-order traversal. + * Return: 1 if a matching range was found, otherwise 0. + */ +int rb_find_free_range(rbtree_t* tree, uintptr_t start, uintptr_t upper, size_t size, uintptr_t align_mask, uintptr_t* result); + /** * rb_set() - Set an address range in a red-black tree. * @tree: Pointer to the red-black tree where the address range will be set. diff --git a/src/tools/rbtree.c b/src/tools/rbtree.c index 98b64b2d3d..e03eede399 100644 --- a/src/tools/rbtree.c +++ b/src/tools/rbtree.c @@ -633,6 +633,46 @@ int rb_get_end_64(rbtree_t* tree, uintptr_t addr, uint64_t* val, uintptr_t* end) return 0; } +int rb_find_free_range(rbtree_t* tree, uintptr_t start, uintptr_t upper, size_t size, uintptr_t align_mask, uintptr_t* result) +{ + if (!tree || !result || start >= upper || size > upper - start) + return 0; + + uintptr_t cur = start; + rbnode *node = tree->root, *next = NULL; + + while (node) { + if (node->end <= cur) { + node = node->right; + } else { + next = node; + node = node->left; + } + } + + node = next; + while (node && cur < upper) { + if (node->start >= upper) + break; + if (cur < node->start && size <= node->start - cur) { + *result = cur; + return 1; + } + if (cur < node->end) { + if (node->end >= upper) + return 0; + cur = (node->end + align_mask) & ~align_mask; + } + node = succ_node(node); + } + + if (cur < upper && size <= upper - cur) { + *result = cur; + return 1; + } + return 0; +} + int rb_set_64(rbtree_t *tree, uintptr_t start, uintptr_t end, uint64_t data) { // printf("rb_set( "); rbtree_print(tree); printf(" , 0x%lx, 0x%lx, %hhu);\n", start, end, data); fflush(stdout); dynarec_log(LOG_DEBUG, "set %s: 0x%lx, 0x%lx, 0x%x\n", tree->name, start, end, data);