mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 11:35:32 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
065fd60d4c
|
@ -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:
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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
32
regress/fpu_mem_write.py
Executable 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
2
regress/memmap_segfault2.py
Normal file → Executable 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)
|
||||||
|
|
|
@ -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 "=========================="
|
||||||
|
|
|
@ -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
17
uc.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue