Skip to content

gdb: send library events during module load - #320

Merged
williballenthin merged 2 commits into
masterfrom
issue-319-gdb-library-events
Aug 28, 2026
Merged

gdb: send library events during module load#320
williballenthin merged 2 commits into
masterfrom
issue-319-gdb-library-events

Conversation

@williballenthin

@williballenthin williballenthin commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Closes #319

When a module is mapped at runtime (for example by LoadLibrary), the gdb stub requests a stop and replies with the library stop reason (T05thread:1;library:;). Clients such as IDA then re-read qXfer:libraries:read, diff the list against what they knew, and fire LIB_LOADED events, so runtime-loaded DLLs appear in the Modules window without a manual refresh. This matches Windows gdbserver semantics: the LoadLibrary handler completes fully (module mapped, PEB updated, return value written) before unicorn halts, and the client resumes on its own unless the user chose to suspend on library load.

Changes

  • WindowsEmulator gains module_change_listeners, notified after load_image appends to emu.modules (the single mutation point for the module list). Listener errors are logged, never propagated into emulation.
  • GdbServer registers a listener for the session lifetime (added on client connect, removed in close()). A module change sets _library_list_changed and requests a stop through the existing _request_stop machinery.
  • _stop_reply appends library:; from that flag alone and clears it, so the field can coalesce with another pending stop reason (a breakpoint reached in the same instruction) or with a dependency chain that maps several DLLs before the halt. One stop covers them all, because the client diffs the full list.
  • Reading the flag rather than the stop kind also keeps a repeated ? query from re-reporting an event the client already handled.
  • No qSupported change: the library stop reason is not gated by a feature string, and qXfer:libraries:read+ is already advertised.

FreeLibrary does not unmap, so unload events cannot occur. The mechanism is direction-agnostic (clients diff the full list), so LIB_UNLOADED works if module removal is implemented later. doc/gdb.md records both the new stop reason and this limitation.

Testing

  • tests/test_gdb_compat.py: a module change requests a library stop and its reply carries library:;; the flag piggybacks on a breakpoint stop reply and is reported once; the listener is removed when the session closes.
  • tests/test_gdb.py: end-to-end subprocess test that maps a module mid-run through a code hook, asserts the T05...library:; stop reply, finds the new DLL in the re-fetched library XML, and confirms the next stop does not repeat the event. Suppressing the notification makes this test time out, so it is not vacuous.
  • Full suite: 181 passed, 26 skipped. The 3 failures are pre-existing and come from the uninitialized tests/capa-testfiles submodule.

🤖 Generated with Claude Code

When a module is mapped at runtime (e.g. LoadLibrary), the stub now
requests a stop and replies with the "library" stop reason
(T05thread:1;library:;). Clients such as IDA then re-read
qXfer:libraries:read, diff the list, and fire LIB_LOADED events.

- WindowsEmulator gains module_change_listeners, notified after
  load_image appends to emu.modules (the single mutation point)
- GdbServer registers a listener for the session lifetime; module
  changes set a flag and request a stop via the existing
  _request_stop machinery
- If a stop is already pending or the target is stopped, the flag
  makes the next stop reply carry library:; instead; it clears once
  reported
- No qSupported change needed: the library stop reason is not gated
  by a feature string

FreeLibrary remains a no-op so unload events cannot occur yet; the
mechanism is direction-agnostic since clients diff the full list.

Closes #319
@google-cla

google-cla Bot commented Aug 28, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Drive the `library:;` stop-reply field only from the module-change flag.
Keeping the `kind == "library"` check as a second source repeated the
event on every later `?` query, because `_stop_reason` still held the
library stop.

Access `module_change_listeners` directly, matching how the server
reaches every other emulator attribute.
@williballenthin
williballenthin force-pushed the issue-319-gdb-library-events branch from a5d1c28 to 680e733 Compare August 28, 2026 13:02
@williballenthin
williballenthin merged commit 9e6af61 into master Aug 28, 2026
10 checks passed
@williballenthin
williballenthin deleted the issue-319-gdb-library-events branch August 28, 2026 13:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gdb: send library events during module load/unload

1 participant