mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-06-19 17:37:49 +00:00
Merge branch 'fix/self_modifying' of https://github.com/rhelmot/unicorn into rhelmot-fix/self_modifying
This commit is contained in:
commit
69d976375e
|
@ -240,6 +240,7 @@ struct uc_struct {
|
||||||
int thumb; // thumb mode for ARM
|
int thumb; // thumb mode for ARM
|
||||||
// full TCG cache leads to middle-block break in the last translation?
|
// full TCG cache leads to middle-block break in the last translation?
|
||||||
bool block_full;
|
bool block_full;
|
||||||
|
int size_arg; // what tcg arg slot do we need to update with the size of the block?
|
||||||
MemoryRegion **mapped_blocks;
|
MemoryRegion **mapped_blocks;
|
||||||
uint32_t mapped_block_count;
|
uint32_t mapped_block_count;
|
||||||
uint32_t mapped_block_cache_index;
|
uint32_t mapped_block_cache_index;
|
||||||
|
|
|
@ -11115,7 +11115,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
|
||||||
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
||||||
// save block address to see if we need to patch block size later
|
// save block address to see if we need to patch block size later
|
||||||
env->uc->block_addr = pc_start;
|
env->uc->block_addr = pc_start;
|
||||||
|
env->uc->size_arg = tcg_ctx->gen_opparam_buf - tcg_ctx->gen_opparam_ptr + 1;
|
||||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
||||||
|
} else {
|
||||||
|
env->uc->size_arg = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
|
|
|
@ -11233,7 +11233,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
|
||||||
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
||||||
// save block address to see if we need to patch block size later
|
// save block address to see if we need to patch block size later
|
||||||
env->uc->block_addr = pc_start;
|
env->uc->block_addr = pc_start;
|
||||||
|
env->uc->size_arg = tcg_ctx->gen_opparam_buf - tcg_ctx->gen_opparam_ptr + 1;
|
||||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
||||||
|
} else {
|
||||||
|
env->uc->size_arg = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
|
|
|
@ -8388,15 +8388,17 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op,
|
||||||
dc->is_jmp = DISAS_NEXT;
|
dc->is_jmp = DISAS_NEXT;
|
||||||
lj = -1;
|
lj = -1;
|
||||||
max_insns = tb->cflags & CF_COUNT_MASK;
|
max_insns = tb->cflags & CF_COUNT_MASK;
|
||||||
if (max_insns <= 1)
|
if (max_insns == 0)
|
||||||
max_insns = CF_COUNT_MASK;
|
max_insns = CF_COUNT_MASK;
|
||||||
|
|
||||||
// Unicorn: trace this block on request
|
// Unicorn: trace this block on request
|
||||||
// Only hook this block if it is not broken from previous translation due to
|
// Only hook this block if the previous block was not truncated due to space
|
||||||
// full translation cache
|
|
||||||
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
||||||
env->uc->block_addr = pc_start;
|
env->uc->block_addr = pc_start;
|
||||||
|
env->uc->size_arg = tcg_ctx->gen_opparam_buf - tcg_ctx->gen_opparam_ptr + 1;
|
||||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
||||||
|
} else {
|
||||||
|
env->uc->size_arg = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
|
|
|
@ -3109,7 +3109,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
|
||||||
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
||||||
// save block address to see if we need to patch block size later
|
// save block address to see if we need to patch block size later
|
||||||
env->uc->block_addr = pc_start;
|
env->uc->block_addr = pc_start;
|
||||||
|
env->uc->size_arg = tcg_ctx->gen_opparam_buf - tcg_ctx->gen_opparam_ptr + 1;
|
||||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
||||||
|
} else {
|
||||||
|
env->uc->size_arg = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
|
|
|
@ -19217,7 +19217,10 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
||||||
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
||||||
// save block address to see if we need to patch block size later
|
// save block address to see if we need to patch block size later
|
||||||
env->uc->block_addr = pc_start;
|
env->uc->block_addr = pc_start;
|
||||||
|
env->uc->size_arg = tcg_ctx->gen_opparam_buf - tcg_ctx->gen_opparam_ptr + 1;
|
||||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
||||||
|
} else {
|
||||||
|
env->uc->size_arg = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
|
|
|
@ -5421,6 +5421,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
|
||||||
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) {
|
||||||
// save block address to see if we need to patch block size later
|
// save block address to see if we need to patch block size later
|
||||||
env->uc->block_addr = pc_start;
|
env->uc->block_addr = pc_start;
|
||||||
|
env->uc->size_arg = tcg_ctx->gen_opparam_buf - tcg_ctx->gen_opparam_ptr + 1;
|
||||||
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,12 +179,12 @@ static int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_s
|
||||||
|
|
||||||
gen_intermediate_code(env, tb);
|
gen_intermediate_code(env, tb);
|
||||||
|
|
||||||
// Unicorn: when tracing block, patch 1st operand for block size
|
// Unicorn: when tracing block, patch block size operand for callback
|
||||||
if (env->uc->block_addr == tb->pc && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, tb->pc)) {
|
if (env->uc->size_arg != -1 && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, tb->pc)) {
|
||||||
if (env->uc->block_full) // block size is unknown
|
if (env->uc->block_full) // block size is unknown
|
||||||
*(s->gen_opparam_buf + 1) = 0;
|
*(s->gen_opparam_buf + env->uc->size_arg) = 0;
|
||||||
else
|
else
|
||||||
*(s->gen_opparam_buf + 1) = tb->size;
|
*(s->gen_opparam_buf + env->uc->size_arg) = tb->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate machine code */
|
/* generate machine code */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
||||||
printf("hook_block(…)\n");
|
printf("hook_block(%p, %lx, %d, %p)\n", uc, address, size, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
BIN
tests/regress/x86_self_modifying.elf
Executable file
BIN
tests/regress/x86_self_modifying.elf
Executable file
Binary file not shown.
37
tests/regress/x86_self_modifying.py
Executable file
37
tests/regress/x86_self_modifying.py
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
from unicorn import *
|
||||||
|
from unicorn.x86_const import *
|
||||||
|
from struct import pack
|
||||||
|
|
||||||
|
import os
|
||||||
|
import regress
|
||||||
|
|
||||||
|
CODE_ADDR = 0x08048000
|
||||||
|
STACK_ADDR = 0x2000000
|
||||||
|
CODE = open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'x86_self_modifying.elf')).read()
|
||||||
|
CODE_SIZE = len(CODE) + (0x1000 - len(CODE)%0x1000)
|
||||||
|
STACK_SIZE = 0x8000
|
||||||
|
|
||||||
|
ENTRY_POINT = 0x8048074
|
||||||
|
|
||||||
|
def hook_intr(uc, intno, data):
|
||||||
|
uc.emu_stop()
|
||||||
|
|
||||||
|
class SelfModifying(regress.RegressTest):
|
||||||
|
def test_self_modifying(self):
|
||||||
|
uc = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||||
|
|
||||||
|
uc.mem_map(CODE_ADDR, CODE_SIZE, 5)
|
||||||
|
uc.mem_map(STACK_ADDR, STACK_SIZE, 7)
|
||||||
|
uc.mem_write(CODE_ADDR, CODE)
|
||||||
|
uc.reg_write(UC_X86_REG_ESP, STACK_ADDR + STACK_SIZE)
|
||||||
|
|
||||||
|
uc.hook_add(UC_HOOK_INTR, hook_intr)
|
||||||
|
|
||||||
|
uc.emu_start(ENTRY_POINT, -1)
|
||||||
|
|
||||||
|
retcode = uc.reg_read(UC_X86_REG_EBX)
|
||||||
|
self.assertEqual(retcode, 65)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
regress.main()
|
51
tests/regress/x86_self_modifying.s
Normal file
51
tests/regress/x86_self_modifying.s
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
mov ebp, esp
|
||||||
|
sub ebp, 0x4000
|
||||||
|
mov edx, ebp
|
||||||
|
|
||||||
|
lea esi, [self_modifying]
|
||||||
|
mov edi, ebp
|
||||||
|
mov ecx, 0x2d
|
||||||
|
call memcpy
|
||||||
|
add ebp, 0x2d
|
||||||
|
xor ebx, ebx
|
||||||
|
call edx
|
||||||
|
|
||||||
|
mov eax, 1
|
||||||
|
int 0x80
|
||||||
|
|
||||||
|
memcpy:
|
||||||
|
cmp ecx, 0
|
||||||
|
je _end
|
||||||
|
dec ecx
|
||||||
|
mov al, byte ptr [esi+ecx]
|
||||||
|
mov byte ptr [edi+ecx], al
|
||||||
|
jmp memcpy
|
||||||
|
|
||||||
|
_end:
|
||||||
|
ret
|
||||||
|
|
||||||
|
self_modifying:
|
||||||
|
inc ebx
|
||||||
|
call $+5
|
||||||
|
pop esi
|
||||||
|
dec byte ptr [esi+11]
|
||||||
|
xor edx, edx
|
||||||
|
sub esi, 6
|
||||||
|
_loop_start:
|
||||||
|
cmp edx, 5
|
||||||
|
jz _loop_end
|
||||||
|
|
||||||
|
mov edi, ebp
|
||||||
|
mov ecx, 0x2d
|
||||||
|
lea eax, [memcpy]
|
||||||
|
call eax
|
||||||
|
inc edx
|
||||||
|
add ebp, 0x2d
|
||||||
|
mov byte ptr [ebp], 0xc3
|
||||||
|
jmp _loop_start
|
||||||
|
|
||||||
|
_loop_end:
|
Loading…
Reference in a new issue