From ad877e6af059c77980675a914c41a0d8a4d43a21 Mon Sep 17 00:00:00 2001 From: Chris Eagle Date: Tue, 1 Sep 2015 13:40:19 -0700 Subject: [PATCH] Add error value UC_ERR_INVAL and rename UC_ERR_OOM to UC_ERR_NOMEM to provide more error specificity --- include/unicorn/unicorn.h | 28 ++++++++++---------- uc.c | 54 ++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 9a39c8a6..cbac0506 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -104,7 +104,7 @@ typedef enum uc_mode { // These are values returned by uc_errno() typedef enum uc_err { 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_HANDLE, // Invalid handle 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_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_INVAL, // Inavalid argument provided to uc_xxx function (See specific function API) } uc_err; @@ -405,15 +406,15 @@ typedef enum uc_prot { @handle: handle returned by uc_open() @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. - 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. 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 - for detailed error). + @return UC_ERR_OK on success, UC_ERR_NOMEM if no memory is available to satisfy the + request, or other value on failure (refer to uc_err enum for detailed error). */ UNICORN_EXPORT 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() @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. - 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. 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 - for detailed error). + @return UC_ERR_OK on success, UC_ERR_HANDLE for an invalid handle, UC_ERR_INVAL + for invalid perms or unaligned address or size, UC_ERR_NOMEM if entire region + is not mapped. */ UNICORN_EXPORT 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() @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. - 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 for detailed error). diff --git a/uc.c b/uc.c index 177c8cf3..32a9af70 100644 --- a/uc.c +++ b/uc.c @@ -68,8 +68,8 @@ const char *uc_strerror(uc_err code) return "Unknown error code"; case UC_ERR_OK: return "OK (UC_ERR_OK)"; - case UC_ERR_OOM: - return "Out of memory (UC_ERR_OOM)"; + case UC_ERR_NOMEM: + return "No memory available or memory not present (UC_ERR_NOMEM)"; case UC_ERR_ARCH: return "Invalid/unsupported architecture(UC_ERR_ARCH)"; 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)"; case 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)); if (!uc) { // memory insufficient - return UC_ERR_OOM; + return UC_ERR_NOMEM; } 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); if (i == 0) - return UC_ERR_OOM; // FIXME + return UC_ERR_NOMEM; // FIXME *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); if (i == 0) - return UC_ERR_OOM; // FIXME + return UC_ERR_NOMEM; // FIXME *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) // invalid memory mapping - return UC_ERR_MAP; + return UC_ERR_INVAL; // address must be aligned to uc->target_page_size if ((address & uc->target_page_align) != 0) - return UC_ERR_MAP; + return UC_ERR_INVAL; // size must be multiple of uc->target_page_size if ((size & uc->target_page_align) != 0) - return UC_ERR_MAP; + return UC_ERR_INVAL; // check for only valid permissions 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 regions = (MemoryRegion**)realloc(uc->mapped_blocks, sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR)); if (regions == NULL) { - return UC_ERR_OOM; + return UC_ERR_NOMEM; } 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; if (size == 0) - // invalid memory mapping - return UC_ERR_MAP; + // trivial case, no change + return UC_ERR_OK; // address must be aligned to uc->target_page_size if ((address & uc->target_page_align) != 0) - return UC_ERR_MAP; + return UC_ERR_INVAL; // size must be multiple of uc->target_page_size if ((size & uc->target_page_align) != 0) - return UC_ERR_MAP; + return UC_ERR_INVAL; // check for only valid permissions if ((perms & ~UC_PROT_ALL) != 0) - return UC_ERR_MAP; + return UC_ERR_INVAL; //check that user's entire requested block is mapped 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 //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); len = MIN(size - count, mr->end - addr); if (!split_region(handle, mr, addr, len, false)) - return UC_ERR_MAP; + return UC_ERR_NOMEM; count += 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); if (mr == NULL) { //this should never happern if splitting succeeded - return UC_ERR_MAP; + return UC_ERR_NOMEM; } } //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 if ((address & uc->target_page_align) != 0) - return UC_ERR_MAP; + return UC_ERR_INVAL; // size must be multiple of uc->target_page_size 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 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 //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); len = MIN(size - count, mr->end - address); if (!split_region(handle, mr, address, len, true)) - return UC_ERR_MAP; + return UC_ERR_NOMEM; count += 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; return UC_ERR_OK; } 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; return UC_ERR_OK; } 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; return UC_ERR_OK; } else - return UC_ERR_OOM; + return UC_ERR_NOMEM; case UC_X86_INS_IN: // FIXME: only one event handler at the same time 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; return UC_ERR_OK; } else - return UC_ERR_OOM; + return UC_ERR_NOMEM; case UC_X86_INS_SYSCALL: case UC_X86_INS_SYSENTER: // 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; return UC_ERR_OK; } else - return UC_ERR_OOM; + return UC_ERR_NOMEM; } break; }