From d38c8fb27f7f94d81ec546bff6c306e21f949d0e Mon Sep 17 00:00:00 2001 From: Aldo Mazzeo Date: Thu, 7 Mar 2019 02:05:26 +0100 Subject: [PATCH] Don't duplicate a uc_mem_map_ptr'd memory region when splitting it (#1028) (#1030) --- uc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/uc.c b/uc.c index 56166cce..11399017 100644 --- a/uc.c +++ b/uc.c @@ -801,6 +801,8 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres uint32_t perms; uint64_t begin, end, chunk_end; size_t l_size, m_size, r_size; + RAMBlock *block = NULL; + bool prealloc = false; chunk_end = address + size; @@ -817,10 +819,27 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres // impossible case return false; - backup = copy_region(uc, mr); - if (backup == NULL) + QTAILQ_FOREACH(block, &uc->ram_list.blocks, next) { + if (block->offset <= mr->addr && block->length >= (mr->end - mr->addr)) { + break; + } + } + + if (block == NULL) return false; + // RAM_PREALLOC is not defined outside exec.c and I didn't feel like + // moving it + prealloc = !!(block->flags & 1); + + if (block->flags & 1) { + backup = block->host; + } else { + backup = copy_region(uc, mr); + if (backup == NULL) + return false; + } + // save the essential information required for the split before mr gets deleted perms = mr->perms; begin = mr->addr; @@ -853,31 +872,48 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres // allocation just failed so no guarantee that we can recover the original // allocation at this point if (l_size > 0) { - if (uc_mem_map(uc, begin, l_size, perms) != UC_ERR_OK) - goto error; - if (uc_mem_write(uc, begin, backup, l_size) != UC_ERR_OK) - goto error; + if (!prealloc) { + if (uc_mem_map(uc, begin, l_size, perms) != UC_ERR_OK) + goto error; + if (uc_mem_write(uc, begin, backup, l_size) != UC_ERR_OK) + goto error; + } else { + if (uc_mem_map_ptr(uc, begin, l_size, perms, backup) != UC_ERR_OK) + goto error; + } } if (m_size > 0 && !do_delete) { - if (uc_mem_map(uc, address, m_size, perms) != UC_ERR_OK) - goto error; - if (uc_mem_write(uc, address, backup + l_size, m_size) != UC_ERR_OK) - goto error; + if (!prealloc) { + if (uc_mem_map(uc, address, m_size, perms) != UC_ERR_OK) + goto error; + if (uc_mem_write(uc, address, backup + l_size, m_size) != UC_ERR_OK) + goto error; + } else { + if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != UC_ERR_OK) + goto error; + } } if (r_size > 0) { - if (uc_mem_map(uc, chunk_end, r_size, perms) != UC_ERR_OK) - goto error; - if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) - goto error; + if (!prealloc) { + if (uc_mem_map(uc, chunk_end, r_size, perms) != UC_ERR_OK) + goto error; + if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) + goto error; + } else { + if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, backup + l_size + m_size) != UC_ERR_OK) + goto error; + } } - free(backup); + if (!prealloc) + free(backup); return true; error: - free(backup); + if (!prealloc) + free(backup); return false; }