Merge remote-tracking branch 'h33p/master' into dev
This is for binary search optmization on memory blocks.
This commit is contained in:
commit
489b072fc3
@ -1,5 +1,25 @@
|
||||
#include "unicorn_test.h"
|
||||
|
||||
static void test_map_correct() {
|
||||
uc_engine* uc;
|
||||
|
||||
OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc));
|
||||
OK(uc_mem_map (uc, 0x40000, 0x1000 * 16, UC_PROT_ALL));
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_map_wrapping() {
|
||||
uc_engine* uc;
|
||||
|
||||
OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc));
|
||||
uc_assert_err(UC_ERR_ARG, uc_mem_map (uc, (~0ll - 0x4000) & ~0xfff, 0x8000, UC_PROT_ALL));
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{ "test_map_correct", test_map_correct },
|
||||
{ "test_map_wrapping", test_map_wrapping },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
};
|
||||
|
73
uc.c
73
uc.c
@ -765,26 +765,52 @@ uc_err uc_emu_stop(uc_engine *uc)
|
||||
return UC_ERR_OK;
|
||||
}
|
||||
|
||||
// return target index where a memory region at the address exists, or could be inserted
|
||||
//
|
||||
// address either is inside the mapping at the returned index, or is in free space before
|
||||
// the next mapping.
|
||||
//
|
||||
// if there is overlap, between regions, ending address will be higher than the starting
|
||||
// address of the mapping at returned index
|
||||
static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) {
|
||||
int left, right, mid;
|
||||
MemoryRegion *mapping;
|
||||
|
||||
left = 0;
|
||||
right = uc->mapped_block_count;
|
||||
|
||||
while (left < right) {
|
||||
mid = left + (right - left) / 2;
|
||||
|
||||
mapping = uc->mapped_blocks[mid];
|
||||
|
||||
if (mapping->end - 1 < address) {
|
||||
left = mid + 1;
|
||||
} else if (mapping->addr > address) {
|
||||
right = mid;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
// find if a memory range overlaps with existing mapped regions
|
||||
static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size)
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t end = begin + size - 1;
|
||||
|
||||
for(i = 0; i < uc->mapped_block_count; i++) {
|
||||
// begin address falls inside this region?
|
||||
if (begin >= uc->mapped_blocks[i]->addr && begin <= uc->mapped_blocks[i]->end - 1) {
|
||||
return true;
|
||||
}
|
||||
// end address falls inside this region?
|
||||
if (end >= uc->mapped_blocks[i]->addr && end <= uc->mapped_blocks[i]->end - 1) {
|
||||
return true;
|
||||
}
|
||||
// this region falls totally inside this range?
|
||||
if (begin < uc->mapped_blocks[i]->addr && end > uc->mapped_blocks[i]->end - 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
i = bsearch_mapped_blocks(uc, begin);
|
||||
|
||||
// is this the highest region with no possible overlap?
|
||||
if (i >= uc->mapped_block_count)
|
||||
return false;
|
||||
|
||||
// end address overlaps this region?
|
||||
if (end >= uc->mapped_blocks[i]->addr)
|
||||
return true;
|
||||
|
||||
// not found
|
||||
return false;
|
||||
@ -794,6 +820,7 @@ static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size)
|
||||
static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, MemoryRegion *block)
|
||||
{
|
||||
MemoryRegion **regions;
|
||||
int pos;
|
||||
|
||||
if (block == NULL) {
|
||||
return UC_ERR_NOMEM;
|
||||
@ -808,7 +835,12 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per
|
||||
uc->mapped_blocks = regions;
|
||||
}
|
||||
|
||||
uc->mapped_blocks[uc->mapped_block_count] = block;
|
||||
pos = bsearch_mapped_blocks(uc, block->addr);
|
||||
|
||||
// shift the array right to give space for the new pointer
|
||||
memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], sizeof(MemoryRegion*) * (uc->mapped_block_count - pos));
|
||||
|
||||
uc->mapped_blocks[pos] = block;
|
||||
uc->mapped_block_count++;
|
||||
|
||||
return UC_ERR_OK;
|
||||
@ -1225,13 +1257,10 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address)
|
||||
return uc->mapped_blocks[i];
|
||||
}
|
||||
|
||||
for(i = 0; i < uc->mapped_block_count; i++) {
|
||||
if (address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1) {
|
||||
// cache this index for the next query
|
||||
uc->mapped_block_cache_index = i;
|
||||
return uc->mapped_blocks[i];
|
||||
}
|
||||
}
|
||||
i = bsearch_mapped_blocks(uc, address);
|
||||
|
||||
if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1)
|
||||
return uc->mapped_blocks[i];
|
||||
|
||||
// not found
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user