unicorn icon indicating copy to clipboard operation
unicorn copied to clipboard

UC_HOOK_MEM_READ only triggered once (x86 64 emulated on mac M1)

Open stevielavern opened this issue 1 year ago • 10 comments

Hello,

Description

I'm facing a strange issue where my UC_HOOK_MEM_READ is only called the first time a memory read is encountered. All subsequent reads do not trigger the callback.

Setup

  • Unicorn commit d4b92485
  • Host: Mac M1 running macOS 14 (Sonoma)
  • Emulated code: x86 64

Unicorn has been compiled as per recommendations in the documentation. Unicorn python bindings were installed in a fresh python venv.

Test case

from unicorn import *
from unicorn.x86_const import *

# mov rax, [0x10000]
# mov [0x10000], rax
code = b"\x48\xa1\x00\x00\x01\x00\x00\x00\x00\x00\x48\xa3\x00\x00\x01\x00\x00\x00\x00\x00"*10

# callback for tracing memory access (READ ony)
def hook_mem_access(uc, access, address, size, value, user_data):
    if access == UC_MEM_READ:
        print(f">>> Memory is being READ at {address:#x}, data size = {size}")
    else:
        print(f">>> Memory is being WRITE at {address:#x}, data size = {size}")

def test_x86_64_mem_read():
    print("Emulate x86 64-bit code")
    try:
    
        mu = Uc(UC_ARCH_X86, UC_MODE_64)
        mu.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, hook_mem_access)

        mu.mem_map(0x10000, 1024*8)
        mu.mem_write(0x10000, b"\xaa"*8)

        # write machine code to be emulated to memory
        mu.mem_map(0, 0x1000)
        mu.mem_write(0, code)


        # emulate machine code in infinite time
        mu.emu_start(0, len(code))

    except UcError as e:
        print("ERROR: %s" % e)


if __name__ == '__main__':
    test_x86_64_mem_read()

Test case output

Emulate x86 64-bit code
>>> Memory is being READ at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8
>>> Memory is being WRITE at 0x10000, data size = 8

As can be seen above, hook_mem_access is only called once for READ while it is expected to be called 10 times. Strangely, this does not affect writes.

stevielavern avatar Nov 15 '23 11:11 stevielavern

I meet the same problem on M2 pro. I test arm64 arch

TinyNiko avatar Dec 19 '23 07:12 TinyNiko

Verified the read operations are inlined. Arm64 backend tends to inline read/write operations.

See: https://github.com/unicorn-engine/unicorn/wiki/FAQ#memory-hooks-are-skipped

1200003E0: F4 03 10 32                orr    w20, wzr, #0x10000
1200003E4: 60 06 7E A9                ldp    x0, x1, [x19, #-0x20]
1200003E8: 00 18 54 8A                and    x0, x0, x20, lsr #6
1200003EC: 21 00 00 8B                add    x1, x1, x0
1200003F0: 20 00 40 F9                ldr    x0, [x1]  # <--- Optimized as a single instruction, x1 = 0x100000

wtdcode avatar Dec 25 '23 12:12 wtdcode

Same problem here, M2 :(

lwerdna avatar Mar 12 '24 20:03 lwerdna

I'm emulating UC_ARCH_ARM/UC_CPU_ARM_CORTEX_M4 and on Mac M1 host, and I'm not seeing UC_MEM_READ events. Is there a way to overcome this limitation, e.g. recompile the lib with the TCG inlining disabled? I'm trying to emulate peripherals and things needs to take action on read events.

keroblabs avatar Apr 06 '24 15:04 keroblabs

you may try this, not tested full functionalities , since I only need the address and value of reads. https://github.com/saicao/unicorn/commit/026f4c447e944cd855fd0d44fea52ac31bc3a372 @keroblabs

saicao avatar Apr 12 '24 03:04 saicao

@saicao Would you like to submit a PR for that?


From: SAI @.> Sent: Friday, April 12, 2024 11:23:13 AM To: unicorn-engine/unicorn @.> Cc: lazymio @.>; Comment @.> Subject: Re: [unicorn-engine/unicorn] UC_HOOK_MEM_READ only triggered once (x86 64 emulated on mac M1) (Issue #1908)

you may try this, not tested full functionalities , since I only need the address and value of reads. @.***https://github.com/saicao/unicorn/commit/026f4c447e944cd855fd0d44fea52ac31bc3a372 @keroblabshttps://github.com/keroblabs

― Reply to this email directly, view it on GitHubhttps://github.com/unicorn-engine/unicorn/issues/1908#issuecomment-2050896270, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AHJULO4YKUHK5KBRAGYLUUTY45HSDAVCNFSM6AAAAAA7MLCXI6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANJQHA4TMMRXGA. You are receiving this because you commented.Message ID: @.***>

wtdcode avatar Apr 12 '24 03:04 wtdcode

@saicao Awesome! I applied the patch locally, rebuilt the lib and now all read events are coming through.

keroblabs avatar Apr 12 '24 13:04 keroblabs

I meet the same problem,the platform is android arm64 with c code and the target arch is arm64. I try the patch of saicao ,but not solve my problem. Is anyone solve this problem? @wtdcode

Gavin0210 avatar Aug 02 '24 06:08 Gavin0210

I try dev branch ,but the problem is still exist.

Gavin0210 avatar Aug 02 '24 06:08 Gavin0210