Add error value UC_ERR_INVAL and rename UC_ERR_OOM to UC_ERR_NOMEM to provide more error specificity
This commit is contained in:
@ -104,7 +104,7 @@ typedef enum uc_mode {
|
|||||||
// These are values returned by uc_errno()
|
// These are values returned by uc_errno()
|
||||||
typedef enum uc_err {
|
typedef enum uc_err {
|
||||||
UC_ERR_OK = 0, // No error: everything was fine
|
UC_ERR_OK = 0, // No error: everything was fine
|
||||||
UC_ERR_OOM, // Out-Of-Memory error: uc_open(), uc_emulate()
|
UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate()
|
||||||
UC_ERR_ARCH, // Unsupported architecture: uc_open()
|
UC_ERR_ARCH, // Unsupported architecture: uc_open()
|
||||||
UC_ERR_HANDLE, // Invalid handle
|
UC_ERR_HANDLE, // Invalid handle
|
||||||
UC_ERR_UCH, // Invalid handle (uch)
|
UC_ERR_UCH, // Invalid handle (uch)
|
||||||
@ -119,6 +119,7 @@ typedef enum uc_err {
|
|||||||
UC_ERR_WRITE_PROT, // Quit emulation due to UC_PROT_WRITE violation: uc_emu_start()
|
UC_ERR_WRITE_PROT, // Quit emulation due to UC_PROT_WRITE violation: uc_emu_start()
|
||||||
UC_ERR_READ_PROT, // Quit emulation due to UC_PROT_READ violation: uc_emu_start()
|
UC_ERR_READ_PROT, // Quit emulation due to UC_PROT_READ violation: uc_emu_start()
|
||||||
UC_ERR_EXEC_PROT, // Quit emulation due to UC_PROT_EXEC violation: uc_emu_start()
|
UC_ERR_EXEC_PROT, // Quit emulation due to UC_PROT_EXEC violation: uc_emu_start()
|
||||||
|
UC_ERR_INVAL, // Inavalid argument provided to uc_xxx function (See specific function API)
|
||||||
} uc_err;
|
} uc_err;
|
||||||
|
|
||||||
|
|
||||||
@ -405,15 +406,15 @@ typedef enum uc_prot {
|
|||||||
|
|
||||||
@handle: handle returned by uc_open()
|
@handle: handle returned by uc_open()
|
||||||
@address: starting address of the new memory region to be mapped in.
|
@address: starting address of the new memory region to be mapped in.
|
||||||
This address must be aligned to 4KB, or this will return with UC_ERR_MAP error.
|
This address must be aligned to 4KB, or this will return with UC_ERR_INVAL error.
|
||||||
@size: size of the new memory region to be mapped in.
|
@size: size of the new memory region to be mapped in.
|
||||||
This size must be multiple of 4KB, or this will return with UC_ERR_MAP error.
|
This size must be multiple of 4KB, or this will return with UC_ERR_INVAL error.
|
||||||
@perms: Permissions for the newly mapped region.
|
@perms: Permissions for the newly mapped region.
|
||||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||||
or this will return with UC_ERR_MAP error.
|
or this will return with UC_ERR_INVAL error.
|
||||||
|
|
||||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
@return UC_ERR_OK on success, UC_ERR_NOMEM if no memory is available to satisfy the
|
||||||
for detailed error).
|
request, or other value on failure (refer to uc_err enum for detailed error).
|
||||||
*/
|
*/
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms);
|
uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms);
|
||||||
@ -424,15 +425,16 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms);
|
|||||||
|
|
||||||
@handle: handle returned by uc_open()
|
@handle: handle returned by uc_open()
|
||||||
@address: starting address of the memory region to be modified.
|
@address: starting address of the memory region to be modified.
|
||||||
This address must be aligned to 4KB, or this will return with UC_ERR_MAP error.
|
This address must be aligned to 4KB, or this will return with UC_ERR_INVAL error.
|
||||||
@size: size of the memory region to be modified.
|
@size: size of the memory region to be modified.
|
||||||
This size must be multiple of 4KB, or this will return with UC_ERR_MAP error.
|
This size must be multiple of 4KB, or this will return with UC_ERR_INVAL error.
|
||||||
@perms: New permissions for the mapped region.
|
@perms: New permissions for the mapped region.
|
||||||
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC,
|
||||||
or this will return with UC_ERR_MAP error.
|
or this will return with UC_ERR_INVAL error.
|
||||||
|
|
||||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
@return UC_ERR_OK on success, UC_ERR_HANDLE for an invalid handle, UC_ERR_INVAL
|
||||||
for detailed error).
|
for invalid perms or unaligned address or size, UC_ERR_NOMEM if entire region
|
||||||
|
is not mapped.
|
||||||
*/
|
*/
|
||||||
UNICORN_EXPORT
|
UNICORN_EXPORT
|
||||||
uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms);
|
uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms);
|
||||||
@ -443,9 +445,9 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms)
|
|||||||
|
|
||||||
@handle: handle returned by uc_open()
|
@handle: handle returned by uc_open()
|
||||||
@address: starting address of the memory region to be unmapped.
|
@address: starting address of the memory region to be unmapped.
|
||||||
This address must be aligned to 4KB, or this will return with UC_ERR_MAP error.
|
This address must be aligned to 4KB, or this will return with UC_ERR_INVAL error.
|
||||||
@size: size of the memory region to be modified.
|
@size: size of the memory region to be modified.
|
||||||
This size must be multiple of 4KB, or this will return with UC_ERR_MAP error.
|
This size must be multiple of 4KB, or this will return with UC_ERR_INVAL error.
|
||||||
|
|
||||||
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
@return UC_ERR_OK on success, or other value on failure (refer to uc_err enum
|
||||||
for detailed error).
|
for detailed error).
|
||||||
|
54
uc.c
54
uc.c
@ -68,8 +68,8 @@ const char *uc_strerror(uc_err code)
|
|||||||
return "Unknown error code";
|
return "Unknown error code";
|
||||||
case UC_ERR_OK:
|
case UC_ERR_OK:
|
||||||
return "OK (UC_ERR_OK)";
|
return "OK (UC_ERR_OK)";
|
||||||
case UC_ERR_OOM:
|
case UC_ERR_NOMEM:
|
||||||
return "Out of memory (UC_ERR_OOM)";
|
return "No memory available or memory not present (UC_ERR_NOMEM)";
|
||||||
case UC_ERR_ARCH:
|
case UC_ERR_ARCH:
|
||||||
return "Invalid/unsupported architecture(UC_ERR_ARCH)";
|
return "Invalid/unsupported architecture(UC_ERR_ARCH)";
|
||||||
case UC_ERR_HANDLE:
|
case UC_ERR_HANDLE:
|
||||||
@ -98,6 +98,8 @@ const char *uc_strerror(uc_err code)
|
|||||||
return "Read from non-readable memory (UC_ERR_READ_PROT)";
|
return "Read from non-readable memory (UC_ERR_READ_PROT)";
|
||||||
case UC_ERR_EXEC_PROT:
|
case UC_ERR_EXEC_PROT:
|
||||||
return "Fetch from non-executable memory (UC_ERR_EXEC_PROT)";
|
return "Fetch from non-executable memory (UC_ERR_EXEC_PROT)";
|
||||||
|
case UC_ERR_INVAL:
|
||||||
|
return "Invalid argumet (UC_ERR_INVAL)";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +145,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uch *handle)
|
|||||||
uc = calloc(1, sizeof(*uc));
|
uc = calloc(1, sizeof(*uc));
|
||||||
if (!uc) {
|
if (!uc) {
|
||||||
// memory insufficient
|
// memory insufficient
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
uc->errnum = UC_ERR_OK;
|
uc->errnum = UC_ERR_OK;
|
||||||
@ -590,7 +592,7 @@ static int _hook_code(uch handle, int type, uint64_t begin, uint64_t end,
|
|||||||
|
|
||||||
i = hook_add(handle, type, begin, end, callback, user_data);
|
i = hook_add(handle, type, begin, end, callback, user_data);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return UC_ERR_OOM; // FIXME
|
return UC_ERR_NOMEM; // FIXME
|
||||||
|
|
||||||
*h2 = i;
|
*h2 = i;
|
||||||
|
|
||||||
@ -606,7 +608,7 @@ static uc_err _hook_mem_access(uch handle, uc_mem_type type,
|
|||||||
|
|
||||||
i = hook_add(handle, type, begin, end, callback, user_data);
|
i = hook_add(handle, type, begin, end, callback, user_data);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return UC_ERR_OOM; // FIXME
|
return UC_ERR_NOMEM; // FIXME
|
||||||
|
|
||||||
*h2 = i;
|
*h2 = i;
|
||||||
|
|
||||||
@ -625,24 +627,24 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size, uint32_t perms)
|
|||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
// invalid memory mapping
|
// invalid memory mapping
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
// address must be aligned to uc->target_page_size
|
// address must be aligned to uc->target_page_size
|
||||||
if ((address & uc->target_page_align) != 0)
|
if ((address & uc->target_page_align) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
// size must be multiple of uc->target_page_size
|
// size must be multiple of uc->target_page_size
|
||||||
if ((size & uc->target_page_align) != 0)
|
if ((size & uc->target_page_align) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
// check for only valid permissions
|
// check for only valid permissions
|
||||||
if ((perms & ~UC_PROT_ALL) != 0)
|
if ((perms & ~UC_PROT_ALL) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow
|
if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow
|
||||||
regions = (MemoryRegion**)realloc(uc->mapped_blocks, sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR));
|
regions = (MemoryRegion**)realloc(uc->mapped_blocks, sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR));
|
||||||
if (regions == NULL) {
|
if (regions == NULL) {
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
uc->mapped_blocks = regions;
|
uc->mapped_blocks = regions;
|
||||||
}
|
}
|
||||||
@ -768,24 +770,24 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms)
|
|||||||
return UC_ERR_UCH;
|
return UC_ERR_UCH;
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
// invalid memory mapping
|
// trivial case, no change
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_OK;
|
||||||
|
|
||||||
// address must be aligned to uc->target_page_size
|
// address must be aligned to uc->target_page_size
|
||||||
if ((address & uc->target_page_align) != 0)
|
if ((address & uc->target_page_align) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
// size must be multiple of uc->target_page_size
|
// size must be multiple of uc->target_page_size
|
||||||
if ((size & uc->target_page_align) != 0)
|
if ((size & uc->target_page_align) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
// check for only valid permissions
|
// check for only valid permissions
|
||||||
if ((perms & ~UC_PROT_ALL) != 0)
|
if ((perms & ~UC_PROT_ALL) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
//check that user's entire requested block is mapped
|
//check that user's entire requested block is mapped
|
||||||
if (!check_mem_area(uc, address, size))
|
if (!check_mem_area(uc, address, size))
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_NOMEM;
|
||||||
|
|
||||||
//Now we know entire region is mapped, so change permissions
|
//Now we know entire region is mapped, so change permissions
|
||||||
//If request exactly matches a region we don't need to split
|
//If request exactly matches a region we don't need to split
|
||||||
@ -798,7 +800,7 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms)
|
|||||||
MemoryRegion *mr = memory_mapping(uc, addr);
|
MemoryRegion *mr = memory_mapping(uc, addr);
|
||||||
len = MIN(size - count, mr->end - addr);
|
len = MIN(size - count, mr->end - addr);
|
||||||
if (!split_region(handle, mr, addr, len, false))
|
if (!split_region(handle, mr, addr, len, false))
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_NOMEM;
|
||||||
count += len;
|
count += len;
|
||||||
addr += len;
|
addr += len;
|
||||||
}
|
}
|
||||||
@ -806,7 +808,7 @@ uc_err uc_mem_protect(uch handle, uint64_t address, size_t size, uint32_t perms)
|
|||||||
mr = memory_mapping(uc, address);
|
mr = memory_mapping(uc, address);
|
||||||
if (mr == NULL) {
|
if (mr == NULL) {
|
||||||
//this should never happern if splitting succeeded
|
//this should never happern if splitting succeeded
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//regions exactly matches an existing region just change perms
|
//regions exactly matches an existing region just change perms
|
||||||
@ -833,7 +835,7 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size)
|
|||||||
|
|
||||||
// address must be aligned to uc->target_page_size
|
// address must be aligned to uc->target_page_size
|
||||||
if ((address & uc->target_page_align) != 0)
|
if ((address & uc->target_page_align) != 0)
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_INVAL;
|
||||||
|
|
||||||
// size must be multiple of uc->target_page_size
|
// size must be multiple of uc->target_page_size
|
||||||
if ((size & uc->target_page_align) != 0)
|
if ((size & uc->target_page_align) != 0)
|
||||||
@ -841,7 +843,7 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size)
|
|||||||
|
|
||||||
//check that user's entire requested block is mapped
|
//check that user's entire requested block is mapped
|
||||||
if (!check_mem_area(uc, address, size))
|
if (!check_mem_area(uc, address, size))
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_NOMEM;
|
||||||
|
|
||||||
//Now we know entire region is mapped, so begin the delete
|
//Now we know entire region is mapped, so begin the delete
|
||||||
//check trivial case first
|
//check trivial case first
|
||||||
@ -866,7 +868,7 @@ uc_err uc_mem_unmap(uch handle, uint64_t address, size_t size)
|
|||||||
MemoryRegion *mr = memory_mapping(uc, address);
|
MemoryRegion *mr = memory_mapping(uc, address);
|
||||||
len = MIN(size - count, mr->end - address);
|
len = MIN(size - count, mr->end - address);
|
||||||
if (!split_region(handle, mr, address, len, true))
|
if (!split_region(handle, mr, address, len, true))
|
||||||
return UC_ERR_MAP;
|
return UC_ERR_NOMEM;
|
||||||
count += len;
|
count += len;
|
||||||
address += len;
|
address += len;
|
||||||
}
|
}
|
||||||
@ -902,7 +904,7 @@ static uc_err _hook_mem_invalid(struct uc_struct* uc, uc_cb_eventmem_t callback,
|
|||||||
uc->hook_mem_idx = i;
|
uc->hook_mem_idx = i;
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else
|
} else
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -921,7 +923,7 @@ static uc_err _hook_intr(struct uc_struct* uc, void *callback,
|
|||||||
uc->hook_intr_idx = i;
|
uc->hook_intr_idx = i;
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else
|
} else
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -945,7 +947,7 @@ static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callb
|
|||||||
uc->hook_out_idx = i;
|
uc->hook_out_idx = i;
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else
|
} else
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
case UC_X86_INS_IN:
|
case UC_X86_INS_IN:
|
||||||
// FIXME: only one event handler at the same time
|
// FIXME: only one event handler at the same time
|
||||||
i = hook_find_new(uc);
|
i = hook_find_new(uc);
|
||||||
@ -956,7 +958,7 @@ static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callb
|
|||||||
uc->hook_in_idx = i;
|
uc->hook_in_idx = i;
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else
|
} else
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
case UC_X86_INS_SYSCALL:
|
case UC_X86_INS_SYSCALL:
|
||||||
case UC_X86_INS_SYSENTER:
|
case UC_X86_INS_SYSENTER:
|
||||||
// FIXME: only one event handler at the same time
|
// FIXME: only one event handler at the same time
|
||||||
@ -968,7 +970,7 @@ static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callb
|
|||||||
uc->hook_syscall_idx = i;
|
uc->hook_syscall_idx = i;
|
||||||
return UC_ERR_OK;
|
return UC_ERR_OK;
|
||||||
} else
|
} else
|
||||||
return UC_ERR_OOM;
|
return UC_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user