qilingframework / qilingframework/qiling

GDB debugging STM32f1xx stops execution after interrupt

Open
#1,276 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

gdbserver
Dominant language
Python
Stars
6.1k
Forks
798
Avg merge
1d 1h
Merged PRs (30d)
9

Description

[ disclaimer: to get below code to work I copied the gdb target XML files of 'arm' to 'qiling/debugger/gdb/xml/cortex_m' and put back the 'setup_remap' function in 'hw/hw.py' (STM32 uses aliased memory). The former might have something to do with this? ]

I'm using -dev of today (+/- 1hr ago) to do remote GDB debugging on an STM32f10x target. Attaching works, GDB stops at the entry point but then when I just let the firmware continue 'c', an interrupt 0x2 is caught and directly afterwards my script stops execution.

    ql = Qiling(["firmware.hex"], archtype="cortex_m", env=stm32f105,verbose=QL_VERBOSE.DEBUG)
    ql.hw.create('rcc')
    ql.hw.create('flash interface')
    ql.hw.create('exti')
    ql.hw.create('usart1')
    ql.hw.create('gpioa')
    ql.hw.create('afio')
    ql.hw.create('spi2')
    ql.hw.create('dma1').watch()
    ql.debugger = True
    ql.run()

I'd expect either GDB to intercept the interrupt OR it just being handled internally by the firmware as it does when running without the debugger (without 'ql.debugger = True' the firmware just runs normally).

However, the debugger appears to think the target exited as no exception is raised, and then throws an Exception due to the MCU not having an exit code:

[+]     Received interrupt: 0x2
Traceback (most recent call last):
...
  File "/home/user/.local/lib/python3.10/site-packages/qiling/core.py", line 586, in run
    debugger.run()
  File "/home/user/.local/lib/python3.10/site-packages/qiling/debugger/gdb/gdb.py", line 767, in run
    reply = handler(subcmd.decode(ENCODING))
  File "/home/user/.local/lib/python3.10/site-packages/qiling/debugger/gdb/gdb.py", line 655, in handle_v
    return handle_c('')
  File "/home/user/.local/lib/python3.10/site-packages/qiling/debugger/gdb/gdb.py", line 243, in handle_c
    reply = f'W{self.ql.os.exit_code:02x}'
AttributeError: 'QlOsMcu' object has no attribute 'exit_code'

I tried letting the handle_c method run 'self.gdb.resume_emu()' in a loop, but then the interrupt is just looping and the firmware gets stuck. Wasn't able to find the code responsible for dropping out of the emulator loop when an interrupt is raised in debug mode versus non-debug mode. In any case the interrupt shouldn't be interpreted as the target exiting. I'd prefer the interrupt handler is simply called within the firmware as normal without dropping to the debugger; I can always put a bp on the handler address if needed.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in qiling/debugger/gdb/gdb.py, tracing run(), handle_c(), and the interrupt path after the reported Received interrupt message. Review qiling/debugger/gdb/xml/cortex_m and the setup_remap context in hw/hw.py. Done means an STM32 interrupt can be handled by the firmware during GDB execution without being treated as target exit or requiring an MCU exit_code.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools, embedded-iot, reverse-engineering
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.