{"id":18535807,"url":"https://github.com/daniel5151/gdb-optional-step-bug","last_synced_at":"2025-04-09T15:32:52.163Z","repository":{"id":44933985,"uuid":"415702709","full_name":"daniel5151/gdb-optional-step-bug","owner":"daniel5151","description":"GDB client doesn't respect optional single-step support on certain target architectures","archived":false,"fork":false,"pushed_at":"2025-02-23T23:46:23.000Z","size":24,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-24T08:54:41.010Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daniel5151.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-10T21:18:36.000Z","updated_at":"2025-02-23T23:46:27.000Z","dependencies_parsed_at":"2022-09-04T15:24:38.911Z","dependency_job_id":null,"html_url":"https://github.com/daniel5151/gdb-optional-step-bug","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daniel5151%2Fgdb-optional-step-bug","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daniel5151%2Fgdb-optional-step-bug/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daniel5151%2Fgdb-optional-step-bug/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daniel5151%2Fgdb-optional-step-bug/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daniel5151","download_url":"https://codeload.github.com/daniel5151/gdb-optional-step-bug/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248058203,"owners_count":21040718,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T19:27:49.930Z","updated_at":"2025-04-09T15:32:52.157Z","avatar_url":"https://github.com/daniel5151.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GDB optional single-step bug repro\n\nThis repo exhibits the behavior reported at https://sourceware.org/bugzilla/show_bug.cgi?id=28440\n\n## The Bug\n\nOn certain architectures, the GDB client doesn't respect `vCont?` responses that don't report support for single-stepping (i.e: via `;s;S`), and will _unconditionally_ send single-step resume packets. This can lead to very Bad Things happening when targets encounter unexpected single-step packets, ranging from silently ignoring the request, to failing to parse the `vCont` packet the request is encapsulated in.\n\n## This Repo\n\nThis repo includes a few basic GDB remote targets, implemented using [`gdbstub`](https://github.com/daniel5151/gdbstub), a Rust library that implements the server-side of the GDB Remote Serial Protocol.\n\nThese are incredibly barebones \"dummy\" remote targets, whereby they present a memory space entirely filled with `NOP` instructions, and use dummy values when reporting register values.\n\n## Running\n\nUse the provided `check_vcont.sh` script to verify how `vCont?` is handled by\nyour version of GDB (use `$GDB` to configure the path):\n\n```\n$ GDB=gdb-multiarch ./check_vcont.sh armv4t mips i386:x86-64 aarch64\nGNU gdb (GDB) 15.2 for x86_64-pc-linux-gnu\n ===================== [armv4t] =====================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C#26\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;c:p1.-1#0f\n\n=================== [armv4t (SS)] ===================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C;s;S#62\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n\n ===================== [mips] =====================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C#26\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;c:p1.-1#0f\n\n=================== [mips (SS)] ===================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C;s;S#62\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;c:p1.-1#0f\n\n ===================== [i386:x86-64] =====================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C#26\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n ERROR gdbstub::stub::core_impl::resume   \u003e GDB client sent resume action not reported by `vCont?`\n\n=================== [i386:x86-64 (SS)] ===================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C;s;S#62\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n\n ===================== [aarch64] =====================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C#26\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n ERROR gdbstub::stub::core_impl::resume   \u003e GDB client sent resume action not reported by `vCont?`\n\n=================== [aarch64 (SS)] ===================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C;s;S#62\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n```\n\nHowever, when using a GDB version compiled for bare-metal targets:\n\n```\n$ GDB=arm-none-eabi-gdb ./check_vcont.sh armv4t mips\nGNU gdb (GDB) 15.2 for arm-none-eabi\n ===================== [armv4t] =====================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C#26\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n ERROR gdbstub::stub::core_impl::resume   \u003e GDB client sent resume action not reported by `vCont?`\n\n=================== [armv4t (SS)] ===================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C;s;S#62\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n\n ===================== [mips] =====================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C#26\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n ERROR gdbstub::stub::core_impl::resume   \u003e GDB client sent resume action not reported by `vCont?`\n\n=================== [mips (SS)] ===================\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont?#49\n TRACE gdbstub::protocol::response_writer \u003e --\u003e $vCont;c;C;s;S#62\n TRACE gdbstub::protocol::recv_packet     \u003e \u003c-- $vCont;s:p1.1;c:p1.-1#f7\n```\n\n### Running Manually\n\nYou can test any architecture supported by GDB's `set architecture` command when connecting to the stub, such as:\n\n- `armv4t`: ARMv4T\n- `mips`: MIPS\n- `i386:x86-64`: X86_64\n- `aarch64`: AArch64\n\nBy passing the `--single-step` flag, support can be added to the target. For\nexample:\n\n```bash\n# enable trace logs for the `gdbstub` library, dumping send/recv'd packets to stderr\nexport RUST_LOG=trace\n\n# run the stub with trace logging enabled + single-step support\ncargo run -- --single-step\n# run the stub with trace logging enabled, *without* single-step support\ncargo run --\n```\n\nThe GDB client can connect to these targets over TCP loopback. i.e:\n\n```\n(gdb) set architecture armv4t\n(gdb) target remote :9001\n```\n\nSee the `try_stepi.gdb` script for more commands.\n\n## Observations\n\nWhen using GDB for x86_64-pc-linux-gnu:\n\n|        | `--single-step` (`vCont;c;C;s;S`) | (no support) (`vCont;c;C`) |\n|:------:|:---------------------------------:|:--------------------------:|\n| `armv4t` |          `vCont;c:p1.-1`          |   `vCont;s:p1.1;c:p1.-1`   |\n| `mips` |          `vCont;c:p1.-1`          |       `vCont;c:p1.-1`      |\n| `i386:x86-64` |       `vCont;s:p1.1;c:p1.-1`      |   `vCont;s:p1.1;c:p1.-1`   |\n| `aarch64` |       `vCont;s:p1.1;c:p1.-1`      |   `vCont;s:p1.1;c:p1.-1`   |\n\nWhen using GDB for bare-metal targets (e.g. arm-none-eabi-gdb):\n\n|        | `--single-step` (`vCont;c;C;s;S`) | (no support) (`vCont;c;C`) |\n|:------:|:---------------------------------:|:--------------------------:|\n| `armv4t` |          `vCont;s:p1.1;c:p1.-1`          |   `vCont;s:p1.1;c:p1.-1`   |\n| `mips` |          `vCont;s:p1.1;c:p1.-1`          |   `vCont;s:p1.1;c:p1.-1`   |\n\n- The armv4t example works as expected.\n  - If `--single-step` is not provided, the GDB stub reports `vCont;c;C`, and the GDB client responds with `vCont;c:p1.-1`. If `--single-step` is provided, the GDB stub reports `vCont;c;C;s;S`, and the GDB client responds with with `vCont;s:p1.1;c:p1.-1`.\n  - This matches the spec.\n- Both x86_64 and aarch64 examples do _not_ work as expected.\n  - If `--single-step` is not provided, the GDB stub reports `vCont;c;C`, and the GDB client nonetheless responds with `vCont;s:p1.1;c:p1.-1`! This results in an internal `gdbstub` error, and the example terminates.\n  - If `--single-step` is provided, both work correctly by sending `vCont;s:p1.1;c:p1.-1`.\n- The MIPS example is interesting.\n  - Regardless if `--single-step` was provided, the GDB client will _never_ send a `vCont;s:pX.X` packet!\n  - While this isn't strictly an \"error\", it isn't nonetheless weird that the GDB client doesn't attempt to use the target's \"native\" single step feature.\n- However, when using bare-metal GDB versions (e.g. arm-none-eabi-gdb):\n  - Both armv4t and MIPS targets unconditionally receive single-step packets (`vCont;s:p1.1;c:p1.-1`), regardless of their reported capabilities.\n  - This suggests the issue may be more prevalent in bare-metal GDB variants.\n\n## Expected behaviors\n\n- The GDB client should not send `s` resumption packets when the `vCont?` response doesn't include support for `s`, regardless of architecture or GDB variant\n- The GDB client should use the `s` resumption packet when `vCont?` includes support for `s`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaniel5151%2Fgdb-optional-step-bug","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaniel5151%2Fgdb-optional-step-bug","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaniel5151%2Fgdb-optional-step-bug/lists"}