Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARM32 Cortex A9 MRRC instruction UC_ERR_INSN_INVALID #1954

Open
TobalJackson opened this issue May 6, 2024 · 5 comments
Open

ARM32 Cortex A9 MRRC instruction UC_ERR_INSN_INVALID #1954

TobalJackson opened this issue May 6, 2024 · 5 comments

Comments

@TobalJackson
Copy link

Hello,
I've come across an issue with unicorn treating the following instruction as invalid:

mrrc p15, 0x1, r1, r0, cr15

the arm documentation describes this instruction as reading a coprocessor register into 2 normal registers: https://developer.arm.com/documentation/dui0489/h/arm-and-thumb-instructions/mrc--mrc2--mrrc-and-mrrc2

Below is an example script which demonstrates this behavior:

#!/usr/bin/env python3
from pwn import *
from unicorn import *
from unicorn.arm_const import *

context.arch = 'arm'
context.endian = 'little'

error = asm("mrrc p15, 0x1, r1, r0, cr15")
errbytes = disasm(error)

print(unicorn.__version__)
print(error)
print(errbytes)

mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
# mu.ctl_set_cpu_model(UC_CPU_ARM_CORTEX_A15) #tried with A7, A8, A9, A15, and
# MAX with same result
mu.ctl_set_cpu_model(UC_CPU_ARM_CORTEX_A9)
mu.mem_map(0, 2 * 1024 * 1024)

mu.mem_write(0x1000, error)

def dump_regs(mu):
    regs = {"r0": UC_ARM_REG_R0,
            "r1": UC_ARM_REG_R1,
            "r2": UC_ARM_REG_R2,
            "r3": UC_ARM_REG_R3,
            "r4": UC_ARM_REG_R4,
            "r5": UC_ARM_REG_R5,
            "r6": UC_ARM_REG_R6,
            "r7": UC_ARM_REG_R7,
            "r8": UC_ARM_REG_R8,
            "r9": UC_ARM_REG_R9,
            "r10": UC_ARM_REG_R10,
            "r11": UC_ARM_REG_R11,
            "r12": UC_ARM_REG_R12,
            "sp": UC_ARM_REG_SP,
            "lr": UC_ARM_REG_LR,
            "pc": UC_ARM_REG_PC,
            "CPSR": UC_ARM_REG_CPSR
            }
    regs_out = {}
    for reg in regs:
        regs_out[reg] = mu.reg_read(regs[reg])
    for reg in regs_out:
        print("{}: {}".format(reg, hex(regs_out[reg])))
    return regs_out

try:
    mu.emu_start(0x1000, 0x1010)
except Exception as e:
    print(e)
    regs = dump_regs(mu)
    inst = mu.mem_read(regs['pc'], 4)
    print(inst)

And the output:

-> % ./error.py
2.0.1
b'\x1f\x1fP\xec'
   0:   ec501f1f        mrrc    15, 1, r1, r0, cr15
Invalid instruction (UC_ERR_INSN_INVALID)
r0: 0x0
r1: 0x0
r2: 0x0
r3: 0x0
r4: 0x0
r5: 0x0
r6: 0x0
r7: 0x0
r8: 0x0
r9: 0x0
r10: 0x0
r11: 0x0
r12: 0x0
sp: 0x0
lr: 0x0
pc: 0x1000
CPSR: 0x400001d3
bytearray(b'\x1f\x1fP\xec')

Please let me know if you'd like additional information,
Thank you

@TobalJackson
Copy link
Author

I just built the dev branch (2.0.2 - c39e802) and re-ran, but received the same error.

@wtdcode
Copy link
Member

wtdcode commented May 7, 2024

Thanks for the reproduction, I will have a look.

@vlasta-labsky
Copy link

I think it is correctly reported as invalid instruction and therefore not a bug.
MRRC variant is supposed to be 64bit access to coprocessor that implements 64bit registers.
P15 on Cortex-A is "System Control Coprocessor" and all its registers are 32bit wide.
Correct instruction for accessing P15 coprocessor is MRC (32bit access)
something like this MRC p15, 0, r0, c1, c0, 0

Please refer to Cortex-A documentation https://developer.arm.com/documentation/den0013/d/ARM-Processor-Modes-and-Registers/Registers/Coprocessor-15

@TobalJackson
Copy link
Author

I did some digging on this subject, and it seems that ARMv7-A added something calle LPAE (Large Physical Address Extension) to support >4GB of ram. In doing so, it seems like there are one or more 64-bit coprocessor registers that were added:

The Large Physical Address Extension, Virtualization Extensions, and the optional Generic Timer introduce a small number of 64-bit control registers.

From https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/Virtual-Memory-System-Architecture--VMSA-/About-the-control-registers-for-VMSA/About-system-control-register-accesses?lang=en#BEIHGCFD

@vlasta-labsky
Copy link

Yes there are 64bit registers with LPAE (TTBR0 TTBR1 and PAR).
https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/Virtual-Memory-System-Architecture--VMSA-/About-the-control-registers-for-VMSA/Effect-of-the-LPAE-and-Virtualization-Extensions-on-the-system-control-registers?lang=en

If I change the architecture to Cortex-A15 and try for example PAR register
mrrc p15, 0, r1, r0, c7
it works as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants