Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Chris Eagle 2015-08-25 20:51:54 -07:00
commit 065fd60d4c
9 changed files with 147 additions and 16 deletions

View File

@ -7,10 +7,10 @@ Linux, *BSD & Solaris. We also show steps to cross-compile for Microsoft Windows
Unicorn requires few dependent packages as followings Unicorn requires few dependent packages as followings
- For Mac OS X, "pkg-config" is needed. - For Mac OS X, "pkg-config" and "glib" are needed.
Brew users can install "pkg-config" with: Brew users can install "pkg-config" and "glib" with:
$ brew install pkg-config $ brew install pkg-config glib
- For Linux, glib2-dev is needed. - For Linux, glib2-dev is needed.
Ubuntu/Debian users can install this with: Ubuntu/Debian users can install this with:

View File

@ -13,6 +13,7 @@ X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], e
X86_CODE64 = b"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" X86_CODE64 = b"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59"
X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
X86_CODE64_SYSCALL = '\x0f\x05' # SYSCALL X86_CODE64_SYSCALL = '\x0f\x05' # SYSCALL
X86_CODE16 = '\x00\x00' # add byte ptr [bx + si], al
# memory address where emulation starts # memory address where emulation starts
ADDRESS = 0x1000000 ADDRESS = 0x1000000
@ -437,6 +438,36 @@ def test_x86_64_syscall():
print("ERROR: %s" % e) print("ERROR: %s" % e)
def test_x86_16():
print("Emulate x86 16-bit code")
try:
# Initialize emulator in X86-16bit mode
mu = Uc(UC_ARCH_X86, UC_MODE_16)
# map 8KB memory for this emulation
mu.mem_map(0, 8 * 1024)
# set CPU registers
mu.reg_write(UC_X86_REG_EAX, 7)
mu.reg_write(UC_X86_REG_EBX, 5)
mu.reg_write(UC_X86_REG_ESI, 6)
# write machine code to be emulated to memory
mu.mem_write(0, X86_CODE16)
# emulate machine code in infinite time
mu.emu_start(0, len(X86_CODE16))
# now print out some registers
print(">>> Emulation done. Below is the CPU context")
tmp = mu.mem_read(11, 1)
print("[0x%x] = 0x%x" %(11, tmp[0]))
except UcError as e:
print("ERROR: %s" % e)
if __name__ == '__main__': if __name__ == '__main__':
test_i386() test_i386()
print("=" * 20) print("=" * 20)
@ -451,3 +482,5 @@ if __name__ == '__main__':
test_x86_64() test_x86_64()
print("=" * 20) print("=" * 20)
test_x86_64_syscall() test_x86_64_syscall()
print("=" * 20)
test_x86_16()

View File

@ -390,9 +390,9 @@ uc_err uc_hook_del(uch handle, uch *h2);
@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 will be round down to 8KB boundary This address must be aligned to 4KB, or this will return with UC_ERR_MAP error.
@size: size of the new memory region to be mapped in. This will be round up to @size: size of the new memory region to be mapped in.
the next 8KB boundary. This size must be multiple of 4KB, or this will return with UC_ERR_MAP 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).

View File

@ -19169,9 +19169,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
int num_insns; int num_insns;
int max_insns; int max_insns;
int insn_bytes; int insn_bytes;
int is_slot; int is_slot = 0;
TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGContext *tcg_ctx = env->uc->tcg_ctx;
TCGArg *save_opparam_ptr; TCGArg *save_opparam_ptr = NULL;
if (search_pc) if (search_pc)
qemu_log("search pc %d\n", search_pc); qemu_log("search pc %d\n", search_pc);

32
regress/fpu_mem_write.py Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/python
from unicorn import *
from unicorn.x86_const import *
ESP = 0x2000
PAGE_SIZE = 1 * 1024 * 1024
# fstcw [esp]
# pop ecx
CODE = b'\x9B\xD9\x3C\x24\x59'
def mem_reader(addr, size):
tmp = mu.mem_read(addr, size)
for i in tmp:
print(" 0x%x" % i),
print("")
def hook_mem_write(uc, access, address, size, value, user_data):
print("mem WRITE: 0x%x, data size = %u, data value = 0x%x" % (address, size, value))
return True
mu = Uc(UC_ARCH_X86, UC_MODE_32)
mu.mem_map(0, PAGE_SIZE)
mu.mem_write(0, CODE)
mu.reg_write(UC_X86_REG_ESP, ESP)
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write)
mu.emu_start(0x0, 0, 0, 2)
esp = mu.reg_read(UC_X86_REG_ESP)
print("value at ESP [0x%X]: " % esp)
mem_reader(esp, 10)

2
regress/memmap_segfault2.py Normal file → Executable file
View File

@ -1,3 +1,5 @@
#!/usr/bin/python
from unicorn import * from unicorn import *
uc = Uc(UC_ARCH_X86, UC_MODE_32) uc = Uc(UC_ARCH_X86, UC_MODE_32)
uc.mem_map(0x0000, 0x2000) uc.mem_map(0x0000, 0x2000)

View File

@ -15,6 +15,8 @@ if test -e $DIR/sample_x86; then
$DIR/sample_x86 -32 $DIR/sample_x86 -32
echo "==========================" echo "=========================="
$DIR/sample_x86 -64 $DIR/sample_x86 -64
echo "=========================="
$DIR/sample_x86 -16
fi fi
if test -e $DIR/sample_arm; then if test -e $DIR/sample_arm; then
echo "==========================" echo "=========================="

View File

@ -24,7 +24,8 @@
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash //#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash
//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" //#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9"
#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" //\xc3" #define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59"
#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al
// memory address where emulation starts // memory address where emulation starts
#define ADDRESS 0x1000000 #define ADDRESS 0x1000000
@ -672,6 +673,58 @@ static void test_x86_64(void)
uc_close(&handle); uc_close(&handle);
} }
static void test_x86_16(void)
{
uch handle;
uc_err err;
uint8_t tmp;
int32_t eax = 7;
int32_t ebx = 5;
int32_t esi = 6;
printf("Emulate x86 16-bit code\n");
// Initialize emulator in X86-16bit mode
err = uc_open(UC_ARCH_X86, UC_MODE_16, &handle);
if (err) {
printf("Failed on uc_open() with error returned: %u\n", err);
return;
}
// map 8KB memory for this emulation
uc_mem_map(handle, 0, 8 * 1024);
// write machine code to be emulated to memory
if (uc_mem_write(handle, 0, (uint8_t *)X86_CODE16, sizeof(X86_CODE64) - 1)) {
printf("Failed to write emulation code to memory, quit!\n");
return;
}
// initialize machine registers
uc_reg_write(handle, UC_X86_REG_EAX, &eax);
uc_reg_write(handle, UC_X86_REG_EBX, &ebx);
uc_reg_write(handle, UC_X86_REG_ESI, &esi);
// emulate machine code in infinite time (last param = 0), or when
// finishing all the code.
err = uc_emu_start(handle, 0, sizeof(X86_CODE16) - 1, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
}
// now print out some registers
printf(">>> Emulation done. Below is the CPU context\n");
// read from memory
if (!uc_mem_read(handle, 11, &tmp, 1))
printf(">>> Read 1 bytes from [0x%x] = 0x%x\n", 11, tmp);
else
printf(">>> Failed to read 1 bytes from [0x%x]\n", 11);
uc_close(&handle);
}
int main(int argc, char **argv, char **envp) int main(int argc, char **argv, char **envp)
{ {
if (argc == 2) { if (argc == 2) {
@ -689,6 +742,10 @@ int main(int argc, char **argv, char **envp)
test_x86_64(); test_x86_64();
} }
if (!strcmp(argv[1], "-16")) {
test_x86_16();
}
// test memleak // test memleak
if (!strcmp(argv[1], "-0")) { if (!strcmp(argv[1], "-0")) {
while(1) { while(1) {
@ -697,7 +754,7 @@ int main(int argc, char **argv, char **envp)
} }
} }
} else { } else {
printf("Syntax: %s <-32|-64>\n", argv[0]); printf("Syntax: %s <-16|-32|-64>\n", argv[0]);
} }
return 0; return 0;

17
uc.c
View File

@ -535,7 +535,6 @@ UNICORN_EXPORT
uc_err uc_mem_map(uch handle, uint64_t address, size_t size) uc_err uc_mem_map(uch handle, uint64_t address, size_t size)
{ {
struct uc_struct* uc = (struct uc_struct *)handle; struct uc_struct* uc = (struct uc_struct *)handle;
size_t s;
if (handle == 0) if (handle == 0)
// invalid handle // invalid handle
@ -545,11 +544,17 @@ uc_err uc_mem_map(uch handle, uint64_t address, size_t size)
// invalid memory mapping // invalid memory mapping
return UC_ERR_MAP; return UC_ERR_MAP;
// align to 8KB boundary // address must be aligned to 4KB
map_begin[map_count] = address & (~ (8*1024 - 1)); if ((address & (4*1024 - 1)) != 0)
s = (size + 8*1024 - 1) & (~ (8*1024 - 1)); return UC_ERR_MAP;
map_end[map_count] = s + map_begin[map_count];
uc->memory_map(uc, map_begin[map_count], s); // size must be multiple of 4KB
if ((size & (4*1024 - 1)) != 0)
return UC_ERR_MAP;
map_begin[map_count] = address;
map_end[map_count] = size + map_begin[map_count];
uc->memory_map(uc, map_begin[map_count], size);
map_count++; map_count++;
return UC_ERR_OK; return UC_ERR_OK;