unicorn-engine / unicorn

Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
http://www.unicorn-engine.org
GNU General Public License v2.0
7.53k stars 1.33k forks source link

why unicorn stopped in advance? #1846

Open HyperSine opened 1 year ago

HyperSine commented 1 year ago

Hi, considering the following code:

import unicorn

def code_trace(uc: unicorn.Uc, address, size, user_data):
    # print('code_trace: 0x{:016x}'.format(address))
    pass

def page_fault(uc: unicorn.Uc, type, address, size, value, user_data) -> bool:
    uc.mem_map(0x400000, 0x2000)
    uc.mem_write(0x400000, b'\x90' * 0x2000)  # fill with NOPs
    return True

uc = unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_64)

uc.hook_add(unicorn.UC_HOOK_MEM_FETCH_UNMAPPED, page_fault, None, 0x400000, 0x400000)
uc.hook_add(unicorn.UC_HOOK_CODE, code_trace, None)   # if i remove this line, everything works as expected.

try:
    uc.emu_start(0x400000, 0x403000)
except Exception as e:
    print(e)
    print('rip = 0x{:016x}'.format(uc.reg_read(unicorn.x86_const.UC_X86_REG_RIP)))

The code runs and prints:

Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)
rip = 0x0000000000401f48

which seems unicorn stopped at 0x401f48. But the address 0x401f48 is still in mapped memory range [0x400000, 0x402000). Why unicorn stopped in advance? And if I remove UC_HOOK_CODE hook, it prints

Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)
rip = 0x0000000000402000

which seems unicorn didn't stop in advance. The strange behavior confused me. Is there a bug here?

wtdcode commented 1 year ago

Oh I see, looks like a bug indeed. Needs investigating.