qiling icon indicating copy to clipboard operation
qiling copied to clipboard

Creating a Cortex M Linux Qiling instance causes `AttributeError`.

Open LukeSerne opened this issue 3 years ago • 4 comments

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'

LukeSerne avatar Aug 27 '22 10:08 LukeSerne

@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.

elicn avatar Aug 30 '22 14:08 elicn

@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.

Not sure, probably depends on the underlying cpu model.

wtdcode avatar Aug 31 '22 12:08 wtdcode

@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.

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.

LukeSerne avatar Sep 02 '22 13:09 LukeSerne

@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?

LukeSerne avatar Sep 15 '22 14:09 LukeSerne