Don't duplicate a uc_mem_map_ptr'd memory region when splitting it (#1028) (#1030)

This commit is contained in:
Aldo Mazzeo 2019-03-07 02:05:26 +01:00 committed by Nguyen Anh Quynh
parent d6d4131873
commit d38c8fb27f

68
uc.c
View File

@ -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;
}