qilingframework / qiling

A True Instrumentable Binary Emulation Framework
https://qiling.io
GNU General Public License v2.0
5.12k stars 743 forks source link

Qdb not working for Cortex-M mcu emulation due to missing CPSR register #1262

Open ckudera opened 2 years ago

ckudera commented 2 years ago

Describe the bug Qdb requires the CPSR register for context rendering and branch prediction. However, reg_map in cortex_m_const.py doesn't contain a mapping for the CPSR register which leads to an AttributeError.

Sample Code (tested with current dev branch)

from qiling.core import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.mcu.stm32f4 import stm32f411

def test_mcu_gpio_stm32f411():
    ql = Qiling(["hello_gpioA.hex"], archtype="cortex_m", ostype="mcu", env=stm32f411, verbose=QL_VERBOSE.OFF)

    ql.hw.create("usart2").watch()
    ql.hw.create("rcc").watch()
    ql.hw.create("gpioa").watch()

    ql.hw.gpioa.hook_set(5, lambda: print("LED light up"))
    ql.hw.gpioa.hook_reset(5, lambda: print("LED light off"))

    ql.debugger = "qdb"

    ql.run(count=10000)

if __name__ == "__main__":
    test_mcu_gpio_stm32f411()

Results in:

Traceback (most recent call last):
  File "/mnt/data/Temp/a/emulation/stm32f411_gpio_hook.py", line 22, in <module>
    test_mcu_gpio_stm32f411()
  File "/mnt/data/Temp/a/emulation/stm32f411_gpio_hook.py", line 18, in test_mcu_gpio_stm32f411
    ql.run(count=10000)
  File "/mnt/data/Temp/a/emulation/qiling/core.py", line 575, in run
    debugger = debugger(self)
  File "/mnt/data/Temp/a/emulation/qiling/debugger/qdb/qdb.py", line 46, in __init__
    self.dbg_hook(init_hook)
  File "/mnt/data/Temp/a/emulation/qiling/debugger/qdb/qdb.py", line 93, in dbg_hook
    self.do_context()
  File "/mnt/data/Temp/a/emulation/qiling/debugger/qdb/qdb.py", line 384, in do_context
    self.render.context_reg(self._saved_reg_dump)
  File "/mnt/data/Temp/a/emulation/qiling/debugger/qdb/render/render.py", line 44, in wrapper
    context_dumper(*args, **kwargs)
  File "/mnt/data/Temp/a/emulation/qiling/debugger/qdb/render/render_arm.py", line 34, in context_reg
    self.print_mode_info(self.ql.arch.regs.cpsr)
  File "/mnt/data/Temp/a/emulation/qiling/arch/register.py", line 42, in __getattr__
    return super().__getattribute__(name)
AttributeError: 'QlRegisterManager' object has no attribute 'cpsr'

Expected behavior Qdb should be executed without an AttributeError.

Additional context A dirty solution is to add "cpsr": UC_ARM_REG_CPSR, to reg_map in cortex_m_const.py. Although this allows Qdb to run, the solution is messy because the CPSR register is not present in ARMv6-M and ARMv7-M processors (source). My suggested solution would be to extend ARM debugging by differentiating between different ARM architecture profiles (Cortex-M vs Cortex-A vs Cortex-R). Profiles which do not implement the CPSR register need to be treated differently.

ucgJhe commented 2 years ago

adapt the dirty fix for now, probably refactor it after we introduce cortex-A or cortex-R

elicn commented 2 years ago

I opened a new feature request for that: #1264

elicn commented 1 year ago

@ucgJhe, wasn't it fixed in a recent PR of yours?

ucgJhe commented 1 year ago

@elicn yes think so, @ckudera please check out to lastest dev branch to see if this issue been fixed

ckudera commented 1 year ago

@ucgJhe Sorry, missed that one. However, unfortunately, it's not fixed. I tested it against the current dev branch and version 1.4.5.

~/Temp/qiling_issue > python main.py
─────────────────────────────────────── [ REGISTERS ] ───────────────────────────────────────
r0: 0x00000000      r1: 0x00000000      r2: 0x00000000      
r3: 0x00000000      r4: 0x00000000      r5: 0x00000000      
r6: 0x00000000      r7: 0x00000000      r8: 0x00000000      
r9: 0x00000000      sp: 0x20020000      lr: 0xffffffff      
pc: 0x08000788      sl: 0x00000000      ip: 0x00000000      
fp: 0x00000000      xpsr: 0x40000000    control: 0x00000000     
primask: 0x00000000     faultmask: 0x00000000   basepri: 0x00000000     

Traceback (most recent call last):
  File "/mnt/data/Temp/qiling_issue/main.py", line 22, in <module>
    test_mcu_gpio_stm32f411()
  File "/mnt/data/Temp/qiling_issue/main.py", line 18, in test_mcu_gpio_stm32f411
    ql.run(count=10000)
  File "/mnt/data/Temp/qiling_issue/qiling/core.py", line 575, in run
    debugger = debugger(self)
  File "/mnt/data/Temp/qiling_issue/qiling/debugger/qdb/qdb.py", line 48, in __init__
    self.dbg_hook(init_hook)
  File "/mnt/data/Temp/qiling_issue/qiling/debugger/qdb/qdb.py", line 91, in dbg_hook
    self.do_context()
  File "/mnt/data/Temp/qiling_issue/qiling/debugger/qdb/qdb.py", line 381, in do_context
    self.render.context_reg(self._saved_reg_dump)
  File "/mnt/data/Temp/qiling_issue/qiling/debugger/qdb/render/render.py", line 44, in wrapper
    context_dumper(*args, **kwargs)
  File "/mnt/data/Temp/qiling_issue/qiling/debugger/qdb/render/render_arm.py", line 75, in context_reg
    self.print_mode_info(self.ql.arch.regs.cpsr)
  File "/mnt/data/Temp/qiling_issue/qiling/arch/register.py", line 42, in __getattr__
    return super().__getattribute__(name)
AttributeError: 'QlRegisterManager' object has no attribute 'cpsr'

I attached sample.zip for easier replicability.

elicn commented 1 year ago

Thanks. I beleive CPSR shouldn't been used in ContextRenderCORTEX_M, since it does not exist on Cortex-M. @ucgJhe, can you take a look and see whether this line should be there?