Skip to content

Cortex-M Vector Table Offset Register not used during mcu emulation #1548

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
antcpl opened this issue Mar 18, 2025 · 1 comment
Open

Cortex-M Vector Table Offset Register not used during mcu emulation #1548

antcpl opened this issue Mar 18, 2025 · 1 comment
Labels
os mcu MCU emulation related

Comments

@antcpl
Copy link

antcpl commented Mar 18, 2025

Describe the bug
When emulating an mcu based on the cortex-m, Qiling never uses the value stored in the Vector Table Offset Register. This register is used to indicate an offset for the base address of the vector table. This produces a bug when emulating a firmware that is using this register to indicate an offset to use its vector table. In my case the vector table is used in the firmware to fetch interrupt handler, the bug makes the firmware trying to fetch interrupt handlers from wrong address.

Sample Code

ql = Qiling(["./toto.elf"],
                archtype=QL_ARCH.CORTEX_M, ostype=QL_OS.MCU, env=stm32f103, verbose=QL_VERBOSE.DISABLED)

    ql.hw.create('scb')
    ql.hw.create('gpioa')
    ql.hw.create('usart2').watch()
    ql.hw.create('rcc')
    ql.hw.create('afio')
    ql.hw.create('exti')
    ql.hw.create('gpioc')

    ql.hw.show_info()

    ql.hw.usart2.send("totototo".encode())

    ql.run(count=1000000)

Expected behavior
Just take into account the value present in the register.

Additional context
Tested on the dev branch.
This register is laying in the SCB part of the CPU memory, as shown in the code above once scb hardware added to the emulation, the memory is perfectly handled, read and write to it works fine (checked by using DISASM debug log).

Suggested correction
For me this was problematic when the firmware uses interruption so here is how I corrected the problem. It has been tested and worked perfectly but I'm not sure this is the right place to implement this correction plus I've hardcoded the address which is very ugly.
In qiling/arch/cortex_m.py in interrupt_handler function :

def interrupt_handler(self, ql: Qiling, intno: int):
        basepri = self.regs.basepri & 0xf0

        if basepri and basepri <= ql.hw.nvic.get_priority(intno):
            return

        if intno > IRQ.HARD_FAULT and (self.regs.primask & 0x1):
            return

        if intno != IRQ.NMI and (self.regs.faultmask & 0x1):
            return

        if ql.verbose >= QL_VERBOSE.DISASM:
            ql.log.debug(f'Handle the intno: {intno}')

        with QlInterruptContext(ql):
            isr = intno + 16
            offset = isr * 4
            
            # ============= personnal modifications ============= 
            #Here qiling doesn't care about the SCB_VTOR which is not normal for the cortex M 
            SCB_VTOR = int.from_bytes(ql.mem.read(0xe000ed08,4), byteorder='little')

            entry = ql.mem.read_ptr(offset + SCB_VTOR)
            # ======================================= 

            exc_return = 0xFFFFFFFD if self.using_psp() else 0xFFFFFFF9

            self.regs.write('ipsr', isr)
            self.regs.write('pc', entry)
            self.regs.write('lr', exc_return)

            ql.log.debug(hex(self.effective_pc))

            self.uc.emu_start(self.effective_pc, 0, 0, 0xffffff)
@elicn
Copy link
Member

elicn commented Mar 18, 2025

Maybe a profile configuration would make sense here, but I am not sure.
Tagging @cla7aye15I4nd for awareness.

In the meantime, you might want to replace the int.from_bytes + ql.mem.read with just ql.mem.read_ptr

@elicn elicn added the os mcu MCU emulation related label Mar 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
os mcu MCU emulation related
Projects
None yet
Development

No branches or pull requests

2 participants