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.33k stars 1.31k forks source link

UC_ERR_INSN_INVALID on x86 popcnt #1880

Closed captainGeech42 closed 9 months ago

captainGeech42 commented 9 months ago

I'm getting an invalid instruction exception when executing the below code. Capstone properly recognizes and disassembles those opcodes, so I'm not sure why Unicorn doesn't recognize it.

import binascii

from unicorn import *
from unicorn.x86_const import *

# popcnt bx, word ptr [esp - 0x4c]
code = binascii.unhexlify("66f30fb85c24b4")

mu = Uc(UC_ARCH_X86, UC_MODE_32)
# stack
mu.mem_map(0x1000, 0x1000)
mu.reg_write(UC_X86_REG_ESP, 0x1080)

# code
mu.mem_map(0x3000,0x1000)
mu.mem_write(0x3000, code)

def hook(mu, addr, size, user_data):
    print(f"addr={hex(addr)}, size={hex(size)}")

mu.hook_add(UC_HOOK_CODE, hook)
mu.emu_start(0x3000, 0x3000+len(code), count=1)

Output:

$ python uc_bug_repro.py
addr=0x3000, size=0xf1f1f1f1
Traceback (most recent call last):
  File ".../uc_bug_repro.py", line 22, in <module>
    mu.emu_start(0x3000, 0x3000+len(code), count=1)
  File ".../python3.10/site-packages/unicorn/unicorn.py", line 547, in emu_start
    raise UcError(status)
unicorn.unicorn.UcError: Invalid instruction (UC_ERR_INSN_INVALID)

I'm running the latest pypi version on macOS

$ python -m pip freeze | egrep ^unicorn
unicorn==2.0.1.post1
wtdcode commented 9 months ago

This works:

import binascii

from unicorn import *
from unicorn.x86_const import *

# popcnt bx, word ptr [esp - 0x4c]
code = binascii.unhexlify("66f30fb85c24b4")

mu = Uc(UC_ARCH_X86, UC_MODE_32)
mu.ctl_set_cpu_model(UC_CPU_X86_EPYC_ROME) # <-- This line
# stack
mu.mem_map(0x1000, 0x1000)
mu.reg_write(UC_X86_REG_ESP, 0x1080)

# code
mu.mem_map(0x3000,0x1000)
mu.mem_write(0x3000, code)

def hook(mu, addr, size, user_data):
    print(f"addr={hex(addr)}, size={hex(size)}")

mu.hook_add(UC_HOOK_CODE, hook)
mu.emu_start(0x3000, 0x3000+len(code), count=1)

Reading: https://github.com/unicorn-engine/unicorn/wiki/FAQ#emulating-some-instructions-gives-an-error-like-invalid-instruction-what-should-i-do

captainGeech42 commented 9 months ago

thank you for the code+reference @wtdcode , that works on my end as well!