Creating a Cortex M Linux Qiling instance causes `AttributeError`.
Describe the bug
Creating a Cortex M Qiling instance with a Linux ostype causes an AttributeError.
Sample Code
import qiling
qiling.Qiling(code=b"\0", archtype=qiling.const.QL_ARCH.CORTEX_M, ostype='linux')
Expected behavior No error.
Result
Traceback (most recent call last):
File "test.py", line 2, in <module>
qiling.Qiling(code=b"\0", archtype=qiling.const.QL_ARCH.CORTEX_M, ostype='linux')
File "~/.local/lib/python3.8/site-packages/qiling/core.py", line 179, in __init__
self._os = select_os(ostype)(self)
File "~/.local/lib/python3.8/site-packages/qiling/os/linux/linux.py", line 48, in __init__
self.load()
File "~/.local/lib/python3.8/site-packages/qiling/os/linux/linux.py", line 56, in load
self.ql.arch.enable_vfp()
File "~/.local/lib/python3.8/site-packages/qiling/arch/arm.py", line 104, in enable_vfp
self.regs.c1_c0_2 = self.regs.c1_c0_2 | (0b11 << 20) | (0b11 << 22)
File "~/.local/lib/python3.8/site-packages/qiling/arch/register.py", line 41, in __getattr__
return super().__getattribute__(name)
AttributeError: 'QlRegisterManager' object has no attribute 'c1_c0_2'
@wtdcode, the enable_vfp method is called whenever the arch is recognized as ARM.
Should QlArchCORTEX_M have this method (inherited from QlArchARM)? If not, we can have Cortex M nullify its method.
@wtdcode, the
enable_vfpmethod is called whenever the arch is recognized as ARM. ShouldQlArchCORTEX_Mhave this method (inherited fromQlArchARM)? If not, we can have Cortex M nullify its method.
Not sure, probably depends on the underlying cpu model.
@wtdcode, the
enable_vfpmethod is called whenever the arch is recognized as ARM. ShouldQlArchCORTEX_Mhave this method (inherited fromQlArchARM)? If not, we can have Cortex M nullify its method.
Removing the enable_vfp call results in no error when creating the qiling object, but instead, Unicorn thows an UC_ERR_INSN_INVALID error when trying to execute some code.
For example, consider the bytecode 80 b5 00 af 00 f0 3e fe. The below script:
import qiling
ql = qiling.Qiling(code=bytes.fromhex("80 b5 00 af 00 f0 3e fe"), archtype=qiling.const.QL_ARCH.CORTEX_M, ostype="linux")
ql.run()
Gives as output:
[x] CPU Context:
[x] r0 : 0x0
[x] r1 : 0x0
[x] r2 : 0x0
[x] r3 : 0x0
[x] r4 : 0x0
[x] r5 : 0x0
[x] r6 : 0x0
[x] r7 : 0x0
[x] r8 : 0x0
[x] r9 : 0x0
[x] r10 : 0x0
[x] r11 : 0x0
[x] r12 : 0x0
[x] sp : 0x11ff000
[x] lr : 0x0
[x] pc : 0x11ff000
[x] msp : 0x11ff000
[x] psp : 0x0
[x] xpsr : 0x40000000
[x] apsr : 0x40000000
[x] ipsr : 0x0
[x] epsr : 0x0
[x] primask : 0x0
[x] faultmask : 0x0
[x] basepri : 0x0
[x] control : 0x0
[x] xpsr_nzcvqg : 0x0
[x] Hexdump:
[x] 80 b5 00 af 00 f0 3e fe
[x] Disassembly:
[=] 011ff000 [[shellcode_stack] + 0x1ff000] 80 b5 push {r7, lr}
[=] 011ff002 [[shellcode_stack] + 0x1ff002] 00 af add r7, sp, #0
[=] 011ff004 [[shellcode_stack] + 0x1ff004] 00 f0 3e fe bl #0x11ffc84
[=] 011ff008 [[shellcode_stack] + 0x1ff008] 00 00 movs r0, r0
[=] 011ff00a [[shellcode_stack] + 0x1ff00a] 00 00 movs r0, r0
[=] 011ff00c [[shellcode_stack] + 0x1ff00c] 00 00 movs r0, r0
[=] 011ff00e [[shellcode_stack] + 0x1ff00e] 00 00 movs r0, r0
[=] 011ff010 [[shellcode_stack] + 0x1ff010] 00 00 movs r0, r0
[=] 011ff012 [[shellcode_stack] + 0x1ff012] 00 00 movs r0, r0
[=] 011ff014 [[shellcode_stack] + 0x1ff014] 00 00 movs r0, r0
[=] 011ff016 [[shellcode_stack] + 0x1ff016] 00 00 movs r0, r0
[=] 011ff018 [[shellcode_stack] + 0x1ff018] 00 00 movs r0, r0
[=] 011ff01a [[shellcode_stack] + 0x1ff01a] 00 00 movs r0, r0
[=] 011ff01c [[shellcode_stack] + 0x1ff01c] 00 00 movs r0, r0
[=] 011ff01e [[shellcode_stack] + 0x1ff01e] 00 00 movs r0, r0
[=] 011ff020 [[shellcode_stack] + 0x1ff020] 00 00 movs r0, r0
[=] 011ff022 [[shellcode_stack] + 0x1ff022] 00 00 movs r0, r0
[=] 011ff024 [[shellcode_stack] + 0x1ff024] 00 00 movs r0, r0
[=] 011ff026 [[shellcode_stack] + 0x1ff026] 00 00 movs r0, r0
[=] 011ff028 [[shellcode_stack] + 0x1ff028] 00 00 movs r0, r0
[=] 011ff02a [[shellcode_stack] + 0x1ff02a] 00 00 movs r0, r0
[=] 011ff02c [[shellcode_stack] + 0x1ff02c] 00 00 movs r0, r0
[=] 011ff02e [[shellcode_stack] + 0x1ff02e] 00 00 movs r0, r0
[=] 011ff030 [[shellcode_stack] + 0x1ff030] 00 00 movs r0, r0
[=] 011ff032 [[shellcode_stack] + 0x1ff032] 00 00 movs r0, r0
[=] 011ff034 [[shellcode_stack] + 0x1ff034] 00 00 movs r0, r0
[=] 011ff036 [[shellcode_stack] + 0x1ff036] 00 00 movs r0, r0
[=] 011ff038 [[shellcode_stack] + 0x1ff038] 00 00 movs r0, r0
[=] 011ff03a [[shellcode_stack] + 0x1ff03a] 00 00 movs r0, r0
[=] 011ff03c [[shellcode_stack] + 0x1ff03c] 00 00 movs r0, r0
[=] 011ff03e [[shellcode_stack] + 0x1ff03e] 00 00 movs r0, r0
[x] PC = 0x011ff000
[x] Memory map:
[x] Start End Perm Label Image
[x] 0001000000 - 0001a00000 rwx [shellcode_stack]
[x] 00ffff0000 - 00ffff1000 rwx [arm_traps]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "~/.local/lib/python3.8/site-packages/qiling/core.py", line 573, in run
self.os.run()
File "~/.local/lib/python3.8/site-packages/qiling/os/linux/linux.py", line 141, in run
self.ql.emu_start(self.entry_point, (self.entry_point + len(self.ql.code)), self.ql.timeout, self.ql.count)
File "~/.local/lib/python3.8/site-packages/qiling/core.py", line 706, in emu_start
self.uc.emu_start(begin, end, timeout, count)
File "~/.local/lib/python3.8/site-packages/unicorn/unicorn.py", line 525, in emu_start
raise UcError(status)
unicorn.unicorn.UcError: Invalid instruction (UC_ERR_INSN_INVALID)
This output shows that qiling can correctly disassemble the bytecode, but unicorn cannot.
@elicn @wtdcode Are there any updates on this issue? Do you know what the cause of the issue is and how it should be fixed?