GDB + SVD
If you debug embedded inferiors with GDB you might want to check the state of some register of some peripheral. You can do this by hand by just reading the memory where the register is mapped. This includes consulting the data sheet to get the address which is pretty slow if you need to do this often.
There is a GDB plugin called PyCortexMDebug, which enables you to read or write registers, show descriptions and list peripherals of micro controllers. The peripheral and register information are loaded from a System View Description file (SVD) You can find many svd files from different vendors in this repository: cmsis-svd.
Unfortunately the plugin only worked if your inferior is written in C/C++ because the method of actually reading/writing memory uses c-style type casts. This doesn’t work if you debug a rust inferior like I did. GDBs python API provides methods to directly read or write a specific address in the inferiors memory. So let’s use them: https://github.com/wose/PyCortexMDebug
A pull request will be made after I tested it a little more.
After the plugin installation you can add something like the following to your
.gdbinit
of your project to activate the plugin and load a specific svd file.
source gdb.py svd_load STM32F103xx.svd
gdb.py
is the one which is part of PyCortexMDebug. You’ll have to specify the
path where you’ve put it or copy it next to your .gdbinit
.
After connecting to your target you can use the svd
command:
>>> svd Available Peripherals: FSMC: Flexible static memory controller PWR: Power control RCC: Reset and clock control GPIOA: General purpose I/O GPIOB: General purpose I/O GPIOC: General purpose I/O GPIOD: General purpose I/O GPIOE: General purpose I/O GPIOF: General purpose I/O GPIOG: General purpose I/O AFIO: Alternate function I/O EXTI: EXTI DMA1: DMA controller DMA2: DMA controller SDIO: Secure digital input/output interface RTC: Real time clock BKP: Backup registers IWDG: Independent watchdog WWDG: Window watchdog TIM1: Advanced timer TIM8: Advanced timer TIM2: General purpose timer TIM3: General purpose timer TIM4: General purpose timer TIM5: General purpose timer TIM9: General purpose timer TIM12: General purpose timer TIM10: General purpose timer TIM11: General purpose timer TIM13: General purpose timer TIM14: General purpose timer TIM6: Basic timer TIM7: Basic timer I2C1: Inter integrated circuit I2C2: Inter integrated circuit SPI1: Serial peripheral interface SPI2: Serial peripheral interface SPI3: Serial peripheral interface USART1: Universal synchronous asynchronous receiver transmitter USART2: Universal synchronous asynchronous receiver transmitter USART3: Universal synchronous asynchronous receiver transmitter ADC1: Analog to digital converter ADC2: Analog to digital converter ADC3: Analog to digital converter CAN: Controller area network DAC: Digital to analog converter DBG: Debug support UART4: Universal asynchronous receiver transmitter UART5: Universal asynchronous receiver transmitter CRC: CRC calculation unit FLASH: FLASH >>> svd/x I2C1 Registers in I2C1: CR1: 0x00000001 Control register 1 CR2: 0x00000018 Control register 2 OAR1: 0x00000000 Own address register 1 OAR2: 0x00000000 Own address register 2 DR: 0x000000B0 Data register SR1: 0x00000001 Status register 1 SR2: 0x00000003 Status register 2 CCR: 0x00000078 Clock control register TRISE: 0x00000019 TRISE register >>> svd I2C1 SR1 Fields in SR1 of peripheral I2C1: SMBALERT: 0 SMBus alert TIMEOUT: 0 Timeout or Tlow error PECERR: 0 PEC Error in reception OVR: 0 Overrun/Underrun AF: 0 Acknowledge failure ARLO: 0 Arbitration lost (master mode) BERR: 0 Bus error TxE: 0 Data register empty (transmitters) RxNE: 0 Data register not empty (receivers) STOPF: 0 Stop detection (slave mode) ADD10: 0 10-bit header sent (Master mode) BTF: 0 Byte transfer finished ADDR: 0 Address sent (master mode)/matched (slave mode) SB: 1 Start bit (Master mode)