Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    • Switch to GitLab Next
  • Sign in / Register
  • QEMU QEMU
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 609
    • Issues 609
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Container Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Insights
    • Issue
    • Repository
  • External wiki
    • External wiki
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • QEMU
  • QEMUQEMU
  • Issues
  • #245
Closed
Open
Created May 09, 2021 by Philippe Mathieu-Daudé@philmdReporter

watchpoints might not properly stop execution at the right address

This bug has been copied automatically from: https://bugs.launchpad.net/qemu/+bug/1792659
Reported by 'Ramiro Polla' on 2018-09-15 :

This bug has been tested with the latest development tree
(19b599f7664b2ebfd0f405fb79c14dd241557452).

I am using qemu-system-i386 with the gdbserver stub. I set a watchpoint on
some address. When the watchpoint is hit, it will be reported by gdb, but
it might happen that eip points to the wrong address (execution has not
properly stopped when the watchpoint was hit).

The setup I used to reproduce it is quite complex, but I believe I have
found the cause of the bug, so I will describe that.

The check_watchpoint() function sets cflags_next_tb in order to force the
execution of only one instruction, and then exits the current tb. It then
expects to be called again after that one instruction is executed, the
watchpoint is hit and it is reported to gdb.

The problem is that another interrupt might have been generated around the
same time as the watchpoint. If the interrupt changes eip and execution
goes on in another address, the value of cflags_next_tb will be spoiled.
When we come back from the interrupt to the address where the watchpoint
is hit, it is possible that a tb with multiple instructions is been
executed, and therefore eip points to the wrong address, ahead of where it
should be.

In my case, the order is as follows:
* i8259 generates an IRQ
  - cpu->interrupt_request contains both CPU_INTERRUPT_TGT_EXT_1 and
CPU_INTERRUPT_HARD
* cpu_handle_interrupt() -> x86_cpu_exec_interrupt() is called
  - it deals with CPU_INTERRUPT_TGT_EXT_1
  - execution continues
* I am exactly at the instruction where the watchpoint is hit.
  - check_watchpoint() is called and cflags_next_tb is set to force the
execution of only one instruction.
  - execution breaks out of the loop with siglongjmp()
* cpu_handle_interrupt() -> x86_cpu_exec_interrupt() is called
  - it deals with the IRQ. eip is changed and cflags_next_tb is spoiled
  - execution continues at the IRQ

[...]
* The kernel finishes dealing with the IRQ

* I am back at the instruction where the watchpoint is hit.
  - A tb is created and executed with two instructions instead of one
  - eip is now ahead of the instruction that hit the watchpoint
* cpu_handle_interrupt() is called
  - it deals with CPU_INTERRUPT_DEBUG
  - the watchpoint is reported by gdb, but with the wrong eip.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking