Skip to content

Rework process attaching - #199

Open
jonathanzetier wants to merge 1 commit into
daniel5151:dev/0.8from
jonathanzetier:rework-current-pid
Open

Rework process attaching#199
jonathanzetier wants to merge 1 commit into
daniel5151:dev/0.8from
jonathanzetier:rework-current-pid

Conversation

@jonathanzetier

@jonathanzetier jonathanzetier commented May 10, 2026

Copy link
Copy Markdown

This removes the need for the CurrentActivePid trait. As discussed in the issue tracker for #124 (multiprocess support), we're willing to trade a needless usize in targets that don't need it for simpler multiprocess support.

Description

As discussed #124 (comment) and #124 (comment), we're doing away with the CurrentActivePid trait.

The total size reported by the bloat checker surprisingly reported a total size decrease of 7 bytes, but less surprisingly the .text section increased about 150 bytes, and the relro_padding section decreased slightly more than 150 bytes (likely for 8-byte padding reasons).

API Stability

  • This PR does not require a breaking API change

This is going into v0.8, which is already breaking the API.

Checklist

  • Documentation
    • Ensured any public-facing rustdoc formatting looks good (via cargo doc)
    • [N/A] (if appropriate) Added feature to "Debugging Features" in README.md
  • Validation
    • [N/A] Included output of running examples/armv4t with RUST_LOG=trace + any relevant GDB output under the "Validation" section below
    • Included output of running ./example_no_std/check_size.sh before/after changes under the "Validation" section below
  • If implementing a new protocol extension IDET
    • [N/A] Included a basic sample implementation in examples/armv4t
    • [N/A] IDET can be optimized out (confirmed via ./example_no_std/check_size.sh)
    • OR implementation requires introducing non-optional binary bloat (please elaborate under "Description")
  • If upstreaming an Arch implementation
    • [ N/A] I have tested this code in my project, and to the best of my knowledge, it is working as intended.

Validation

GDB output
$ gdb-multiarch --ex 'target extended-remote 127.0.0.1:9001'
Remote debugging using 127.0.0.1:9001
Reading /test.elf from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /test.elf from remote target...
Reading symbols from target:/test.elf...
Reading /test.elf from remote target...
Reading symbols from target:/test.elf...
main () at test.c:1
1	test.c: No such file or directory.
(gdb) attach 123
A program is being debugged already.  Kill it? (y or n) y
Attaching to program: target:/test.elf, process 123
`target:/test.elf' has disappeared; keeping its symbols.
Reading /test.elf from remote target...
Reading symbols from target:/test.elf...
main () at test.c:1
1	in test.c
(gdb)
TRACE log
$ RUST_LOG=trace cargo run --example armv4t
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/examples/armv4t`
loading section ".text" into memory from [0x55550000..0x55550078]
Setting PC to 0x55550000
Waiting for a GDB connection on "127.0.0.1:9001"...
Debugger connected from 127.0.0.1:39588
 TRACE gdbstub::protocol::recv_packet > <-- +
 TRACE gdbstub::protocol::recv_packet > <-- $qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+;memory-tagging+;xmlRegisters=i386#77
 TRACE gdbstub::protocol::response_writer > --> $PacketSize=1000;vContSupported+;multiprocess+;QStartNoAckMode+;fork-events+;vfork-events+;vforkdone-events+;exec-events+;ReverseContinue+;ReverseStep+;QDisableRandomization+;QEnvironmentHexEncoded+;QEnvironmentUnset+;QEnvironmentReset+;QStartupWithShell+;QSetWorkingDir+;swbreak+;hwbreak+;QTBuffer:size+;TracepointSource+;QCatchSyscalls+;qXfer:features:read+;qXfer:memory-map:read+;qXfer:exec-file:read+;qXfer:auxv:read+;qXfer:libraries-svr4:read+;qXfer:libraries:read+#5f
 TRACE gdbstub::protocol::recv_packet     > <-- +
 TRACE gdbstub::protocol::recv_packet     > <-- $vMustReplyEmpty#3a
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("vMustReplyEmpty")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- +
 TRACE gdbstub::protocol::recv_packet     > <-- $QStartNoAckMode#b0
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- +
 TRACE gdbstub::protocol::recv_packet     > <-- $!#21
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $Hgp0.0#ad
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:0,ffb#79
 TRACE gdbstub::protocol::response_writer > --> $m<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
    <architecture>armv4t</architecture>
    <feature name="org.gnu.gdb.arm.core">
        <vector id="padding" type="uint32" count="25"/>

        <reg name="r0" bitsize="32" type="uint32"/>
        <reg name="r1" bitsize="32" type="uint32"/>
        <reg name="r2" bitsize="32" type="uint32"/>
        <reg name="r3" bitsize="32" type="uint32"/>
        <reg name="r4" bitsize="32" type="uint32"/>
        <reg name="r5" bitsize="32" type="uint32"/>
        <reg name="r6" bitsize="32" type="uint32"/>
        <reg name="r7" bitsize="32" type="uint32"/>
        <reg name="r8" bitsize="32" type="uint32"/>
        <reg name="r9" bitsize="32" type="uint32"/>
        <reg name="r10" bitsize="32" type="uint32"/>
        <reg name="r11" bitsize="32" type="uint32"/>
        <reg name="r12" bitsize="32" type="uint32"/>
        <reg name="sp" bitsize="32" type="data_ptr"/>
        <reg name="lr" bitsize="32"/>
        <reg name="pc" bitsize="32" type="code_ptr"/>

        <!--
            For some reason, my version of `gdb-multiarch` doesn't seem to
            respect "regnum", and will not parse this custom target.xml unless I
            manually include the padding bytes in the target description.

            On the bright side, AFAIK, there aren't all that many architectures
            that use padding bytes. Heck, the only reason armv4t uses padding is
            for historical reasons (see comment below).

            Odds are if you're defining your own custom arch, you won't run into
            this issue, since you can just lay out all the registers in the
            correct order.
        -->
        <reg name="padding" type="padding" bitsize="32"/>

        <!-- The CPSR is register 25, rather than register 16, because
        the FPA registers historically were placed between the PC
        and the CPSR in the "g" packet. -->
        <reg name="cpsr" bitsize="32" regnum="25"/>
    </feature>
    <xi:include href="extra.xml"/>
</target>#08
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:80d,ffb#15
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:extra.xml:0,ffb#16
 TRACE gdbstub::protocol::response_writer > --> $m<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<feature name="custom-armv4t-extension">
    <!--
        maps to a simple scratch register within the emulator. the GDB
        client can read the register using `p }custom` and set it using
        `set }custom=1337`
    -->
    <reg name="custom" bitsize="32" type="uint32"/>

    <!--
        pseudo-register that return the current time when read.

        notably, i've set up the target to NOT send this register as part of
        the regular register list, which means that GDB will fetch/update
        this register via the 'p' and 'P' packets respectively
    -->
    <reg name="time" bitsize="32" type="uint32"/>

    <!--
        pseudo-register that is always unavailable.

        it is supposed to be reported as 'x'-ed bytes in replies to 'p' packets
        and shown by the GDB client as "<unavailable>".
    -->
    <reg name="unavailable" bitsize="32" type="uint32"/>
</feature>#e9
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:extra.xml:3c5,ffb#b1
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:auxv:read::0,ffb#d8
 TRACE gdbstub::protocol::response_writer > --> $m#b9
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:auxv:read::8,ffb#e0
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qTStatus#49
 TRACE gdbstub::protocol::response_writer > --> $T0;tframes:00#4b
 TRACE gdbstub::protocol::recv_packet     > <-- $qTfV#81
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $?#3f
 TRACE gdbstub::protocol::response_writer > --> $T05thread:p01.01;#06
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp01.01#cd
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qAttached:1#fa
GDB queried if it was attached to a process with PID 1
 TRACE gdbstub::protocol::response_writer > --> $1#31
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:1:0,ffb#b7
 TRACE gdbstub::protocol::response_writer > --> $m/test.elf#c1
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:1:9,ffb#c0
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:setfs:0#bf
 TRACE gdbstub::protocol::response_writer > --> $F0#76
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:open:6a7573742070726f62696e67,0,1c0#ed
 TRACE gdbstub::protocol::response_writer > --> $F-1,02#32
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:setfs:1#c0
 TRACE gdbstub::protocol::response_writer > --> $F0#76
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:open:2f746573742e656c66,0,0#1e
 TRACE gdbstub::protocol::response_writer > --> $F00#a6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:open:2f746573742e656c66,0,0#1e
 TRACE gdbstub::protocol::response_writer > --> $F00#a6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $qSymbol::#5b
 INFO  gdbstub::stub::core_impl           > Unknown command: Ok("qSymbol::")
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:1:0,ffb#b7
 TRACE gdbstub::protocol::response_writer > --> $m/test.elf#c1
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:1:9,ffb#c0
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $Hc-1#09
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $qOffsets#4b
 TRACE gdbstub::protocol::response_writer > --> $Text=00;Data=00;Bss=00#94
 TRACE gdbstub::protocol::recv_packet     > <-- $g#67
 TRACE gdbstub::protocol::response_writer > --> $00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000107856341200005555xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1000000078563412#db
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:libraries-svr4:read::0,ffb#8d
 TRACE gdbstub::protocol::response_writer > --> $m<library-list-svr4 version="1.0" main-lm="0x4">
    <library name="/test.elf" lm="0x8" l_addr="0" l_ld="0" lmid="0x14"/>
</library-list-svr4>#25
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:libraries-svr4:read::8d,ffb#f9
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:auxv:read::0,ffb#d8
 TRACE gdbstub::protocol::response_writer > --> $m#b9
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:auxv:read::8,ffb#e0
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:open:2f746573742e656c66,0,0#1e
 TRACE gdbstub::protocol::response_writer > --> $F00#a6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp01.01#cd
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:memory-map:read::0,ffb#18
 TRACE gdbstub::protocol::response_writer > --> $m<?xml version="1.0"?>
<!DOCTYPE memory-map
    PUBLIC "+//IDN gnu.org//DTD GDB Memory Map V1.0//EN"
            "http://sourceware.org/gdb/gdb-memory-map.dtd">
<memory-map>
    <memory type="ram" start="0x00000000" length="0x10000000"/>
    <memory type="ram" start="0x12340000" length="0x10000"/>
    <memory type="flash" start="0x55550000" length="0x10000000">
        <property name="blocksize">0x1000</property>
    </memory>
</memory-map>#f4
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:memory-map:read::1bb,ffb#dd
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,2#5f
 TRACE gdbstub::protocol::response_writer > --> $04b0#f6
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,2#5f
 TRACE gdbstub::protocol::response_writer > --> $04b0#f6
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $qTStatus#49
 TRACE gdbstub::protocol::response_writer > --> $T0;tframes:00#4b
 TRACE gdbstub::protocol::recv_packet     > <-- $qTfP#7b
 TRACE gdbstub::protocol::response_writer > --> $#00
 TRACE gdbstub::protocol::recv_packet     > <-- $vKill;1#6e
GDB sent a kill request for pid Some(1)
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:close:0#b0
 TRACE gdbstub::protocol::response_writer > --> $F0#76
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,102fc#1b
 TRACE gdbstub::protocol::response_writer > --> $F0474;UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#3c
 TRACE gdbstub::protocol::recv_packet     > <-- $vAttach;7b#9f
GDB attached to a process with PID 123
 TRACE gdbstub::protocol::response_writer > --> $T05thread:p7b.01;#3e
 TRACE gdbstub::protocol::recv_packet     > <-- $Hgp0.0#ad
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:7b:0,ffb#1f
 TRACE gdbstub::protocol::response_writer > --> $m/test.elf#c1
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:7b:9,ffb#28
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qC#b4
 TRACE gdbstub::protocol::response_writer > --> $QCp7b.01#2c
 TRACE gdbstub::protocol::recv_packet     > <-- $Hgp7b.1#17
 TRACE gdbstub::protocol::response_writer > --> $OK#9a
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:0,ffb#79
 TRACE gdbstub::protocol::response_writer > --> $m<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
    <architecture>armv4t</architecture>
    <feature name="org.gnu.gdb.arm.core">
        <vector id="padding" type="uint32" count="25"/>

        <reg name="r0" bitsize="32" type="uint32"/>
        <reg name="r1" bitsize="32" type="uint32"/>
        <reg name="r2" bitsize="32" type="uint32"/>
        <reg name="r3" bitsize="32" type="uint32"/>
        <reg name="r4" bitsize="32" type="uint32"/>
        <reg name="r5" bitsize="32" type="uint32"/>
        <reg name="r6" bitsize="32" type="uint32"/>
        <reg name="r7" bitsize="32" type="uint32"/>
        <reg name="r8" bitsize="32" type="uint32"/>
        <reg name="r9" bitsize="32" type="uint32"/>
        <reg name="r10" bitsize="32" type="uint32"/>
        <reg name="r11" bitsize="32" type="uint32"/>
        <reg name="r12" bitsize="32" type="uint32"/>
        <reg name="sp" bitsize="32" type="data_ptr"/>
        <reg name="lr" bitsize="32"/>
        <reg name="pc" bitsize="32" type="code_ptr"/>

        <!--
            For some reason, my version of `gdb-multiarch` doesn't seem to
            respect "regnum", and will not parse this custom target.xml unless I
            manually include the padding bytes in the target description.

            On the bright side, AFAIK, there aren't all that many architectures
            that use padding bytes. Heck, the only reason armv4t uses padding is
            for historical reasons (see comment below).

            Odds are if you're defining your own custom arch, you won't run into
            this issue, since you can just lay out all the registers in the
            correct order.
        -->
        <reg name="padding" type="padding" bitsize="32"/>

        <!-- The CPSR is register 25, rather than register 16, because
        the FPA registers historically were placed between the PC
        and the CPSR in the "g" packet. -->
        <reg name="cpsr" bitsize="32" regnum="25"/>
    </feature>
    <xi:include href="extra.xml"/>
</target>#08
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:target.xml:80d,ffb#15
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:extra.xml:0,ffb#16
 TRACE gdbstub::protocol::response_writer > --> $m<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<feature name="custom-armv4t-extension">
    <!--
        maps to a simple scratch register within the emulator. the GDB
        client can read the register using `p }custom` and set it using
        `set }custom=1337`
    -->
    <reg name="custom" bitsize="32" type="uint32"/>

    <!--
        pseudo-register that return the current time when read.

        notably, i've set up the target to NOT send this register as part of
        the regular register list, which means that GDB will fetch/update
        this register via the 'p' and 'P' packets respectively
    -->
    <reg name="time" bitsize="32" type="uint32"/>

    <!--
        pseudo-register that is always unavailable.

        it is supposed to be reported as 'x'-ed bytes in replies to 'p' packets
        and shown by the GDB client as "<unavailable>".
    -->
    <reg name="unavailable" bitsize="32" type="uint32"/>
</feature>#e9
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:features:read:extra.xml:3c5,ffb#b1
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:7b:0,ffb#1f
 TRACE gdbstub::protocol::response_writer > --> $m/test.elf#c1
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:exec-file:read:7b:9,ffb#28
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $g#67
 TRACE gdbstub::protocol::response_writer > --> $00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000107856341200005555xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1000000078563412#db
 TRACE gdbstub::protocol::recv_packet     > <-- $qOffsets#4b
 TRACE gdbstub::protocol::response_writer > --> $Text=00;Data=00;Bss=00#94
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:libraries-svr4:read::0,ffb#8d
 TRACE gdbstub::protocol::response_writer > --> $m<library-list-svr4 version="1.0" main-lm="0x4">
    <library name="/test.elf" lm="0x8" l_addr="0" l_ld="0" lmid="0x14"/>
</library-list-svr4>#25
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:libraries-svr4:read::8d,ffb#f9
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:auxv:read::0,ffb#d8
 TRACE gdbstub::protocol::response_writer > --> $m#b9
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:auxv:read::8,ffb#e0
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:setfs:7b#28
 TRACE gdbstub::protocol::response_writer > --> $F0#76
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:open:2f746573742e656c66,0,0#1e
 TRACE gdbstub::protocol::response_writer > --> $F00#a6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,0#ef
UUUUxx#eabstub::protocol::response_writer > --> $F1000;ELF(UU4@4 (
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10540#b9
 TRACE gdbstub::protocol::response_writer > --> $F0230;UxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#d6
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,34#26
 TRACE gdbstub::protocol::response_writer > --> $F1000;UUUUxx#83
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,104b2#e8
 TRACE gdbstub::protocol::response_writer > --> $F02be;.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#e2
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:pread:0,1000,10078#bf
 TRACE gdbstub::protocol::response_writer > --> $F06f8;s
                                                        .UUx�oUUx�ox	o�ty	o�l4UU0i	o�pint%
                                                                                                      :
                                                                                                       ;
                                                                                                        9
                                                                                                         I@�B:
                                                                                                              ;
                                                                                                               9
                                                                                                                I
                                                                                                                 }

                                                                                                                  >
test.c                                                                                                            UUx[�
      UU	gKLgiJ
                      /%ef
                          jtest.cGNU C11 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] -mfloat-abi=soft -marm -march=armv4t -g -O0 -std=c11mainGCC: (15:9-2019-q4-0ubuntu1) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599]A)aeabi4T  �
                                                                                                                                                                                                                                                                 ����|
UUxB�B
B�UUxUU
�UU
   xUU�xUUxUU+xUU7UUx<xUUIxUUWUUtest.c}a__DATA_START__end__DATA_END____BSS_END__main__TEXT_END____BSS_START____TEXT_START__.symtab.strtab.shstrtab.text.bss.debug_info.debug_abbrev.debug_aranges.debug_line.debug_str.comment.ARM.attributes.debug_frameUxxUUx&xw2�U@D Od_[0��f0HYop�}
�0�P
	Lf��#9d
 TRACE gdbstub::protocol::recv_packet     > <-- $vFile:fstat:0#bc
 TRACE gdbstub::protocol::response_writer > --> $F40;p#26
 TRACE gdbstub::protocol::recv_packet     > <-- $qfThreadInfo#bb
 TRACE gdbstub::protocol::response_writer > --> $mp7b.01#05
 TRACE gdbstub::protocol::recv_packet     > <-- $qsThreadInfo#c8
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:memory-map:read::0,ffb#18
 TRACE gdbstub::protocol::response_writer > --> $m<?xml version="1.0"?>
<!DOCTYPE memory-map
    PUBLIC "+//IDN gnu.org//DTD GDB Memory Map V1.0//EN"
            "http://sourceware.org/gdb/gdb-memory-map.dtd">
<memory-map>
    <memory type="ram" start="0x00000000" length="0x10000000"/>
    <memory type="ram" start="0x12340000" length="0x10000"/>
    <memory type="flash" start="0x55550000" length="0x10000000">
        <property name="blocksize">0x1000</property>
    </memory>
</memory-map>#f4
 TRACE gdbstub::protocol::recv_packet     > <-- $qXfer:memory-map:read::1bb,ffb#dd
 TRACE gdbstub::protocol::response_writer > --> $l#6c
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,2#5f
 TRACE gdbstub::protocol::response_writer > --> $04b0#f6
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,2#5f
 TRACE gdbstub::protocol::response_writer > --> $04b0#f6
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
 TRACE gdbstub::protocol::recv_packet     > <-- $m55550000,4#61
 TRACE gdbstub::protocol::response_writer > --> $04b02de5#26
Before/After `./example_no_std/check_size.sh` output

Before

File  .text    Size          Crate Name
2.4%  70.3%  8.7KiB      [Unknown] main
0.1%   2.9%    372B        gdbstub gdbstub::protocol::commands::breakpoint::BasicBreakpoint::from_slice
0.1%   2.3%    295B        gdbstub <gdbstub::protocol::common::thread_id::ThreadId as core::convert::TryFrom<&[u8]>>::try_from
0.1%   2.2%    278B        gdbstub gdbstub::protocol::packet::PacketBuf::new
0.1%   2.2%    275B        gdbstub gdbstub::protocol::common::hex::decode_hex_buf
0.1%   1.7%    218B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write
0.1%   1.6%    206B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_specific_thread_id
0.0%   1.1%    143B           core core::iter::traits::iterator::Iterator::nth
0.0%   1.0%    132B        gdbstub gdbstub::protocol::common::hex::decode_hex
0.0%   1.0%    131B        gdbstub gdbstub::protocol::common::hex::decode_hex
0.0%   1.0%    124B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::inner_write
0.0%   0.9%    110B        gdbstub gdbstub::protocol::common::hex::decode_hex
0.0%   0.9%    109B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_num
0.0%   0.8%    107B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_num
0.0%   0.8%    106B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::flush
0.0%   0.8%    106B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::read_addrs
0.0%   0.8%    104B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_hex
0.0%   0.7%     93B           core <core::iter::adapters::skip::Skip<I> as core::iter::traits::iterator::Iterator>::next
0.0%   0.7%     92B        gdbstub <gdbstub::protocol::common::thread_id::IdKind as core::convert::TryFrom<&[u8]>>::try_from
0.0%   0.7%     87B           core <core::slice::iter::SplitMut<T,P> as core::iter::traits::iterator::Iterator>::next
0.0%   0.5%     67B   gdbstub_arch <gdbstub_arch::arm::reg::arm_core::ArmCoreRegs as gdbstub::arch::Registers>::gdb_deserialize
0.0%   0.5%     65B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::write_registers
0.0%   0.5%     65B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::read_registers
0.0%   0.5%     65B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::write_addrs
0.0%   0.4%     50B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadResume>::resume
0.0%   0.4%     50B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadResume>::set_resume_action_continue
0.0%   0.4%     50B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadResume>::clear_resume_actions
0.0%   0.3%     44B  gdbstub_nostd gdbstub_nostd::print_str::print_str
0.0%   0.3%     38B      [Unknown] _start
0.0%   0.0%      6B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::breakpoints::SwBreakpoint>::add_sw_breakpoint
3.5% 100.0% 12.4KiB                .text section size, the file size is 357.2KiB
target/release/gdbstub-nostd  :
section               size    addr
.interp                 28     680
.note.ABI-tag           32     708
.note.gnu.build-id      36     740
.dynsym                384     776
.gnu.version            32    1160
.gnu.version_r          64    1192
.gnu.hash               28    1256
.dynstr                215    1284
.rela.dyn              432    1504
.rela.plt               24    1936
.rodata                881    1968
.eh_frame_hdr          252    2852
.eh_frame             1256    3104
.text                12737    8464
.init                   27   21204
.fini                   13   21232
.plt                    32   21248
.fini_array              8   25376
.init_array              8   25384
.dynamic               432   25392
.got                   120   25824
.got.plt                32   25944
.relro_padding        2696   25976
.tm_clone_table          0   30072
.data                    8   30072
.bss                     1   30080
.comment               184       0
Total                19962

After

File  .text    Size          Crate Name
2.5%  70.7%  8.9KiB      [Unknown] main
0.1%   2.9%    372B        gdbstub gdbstub::protocol::commands::breakpoint::BasicBreakpoint::from_slice
0.1%   2.3%    295B        gdbstub <gdbstub::protocol::common::thread_id::ThreadId as core::convert::TryFrom<&[u8]>>::try_from
0.1%   2.2%    278B        gdbstub gdbstub::protocol::packet::PacketBuf::new
0.1%   2.1%    275B        gdbstub gdbstub::protocol::common::hex::decode_hex_buf
0.1%   1.7%    218B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write
0.1%   1.6%    206B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_specific_thread_id
0.0%   1.1%    143B           core core::iter::traits::iterator::Iterator::nth
0.0%   1.0%    132B        gdbstub gdbstub::protocol::common::hex::decode_hex
0.0%   1.0%    131B        gdbstub gdbstub::protocol::common::hex::decode_hex
0.0%   1.0%    124B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::inner_write
0.0%   0.9%    110B        gdbstub gdbstub::protocol::common::hex::decode_hex
0.0%   0.8%    109B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_num
0.0%   0.8%    107B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_num
0.0%   0.8%    106B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::flush
0.0%   0.8%    106B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::read_addrs
0.0%   0.8%    104B        gdbstub gdbstub::protocol::response_writer::ResponseWriter<C>::write_hex
0.0%   0.7%     93B           core <core::iter::adapters::skip::Skip<I> as core::iter::traits::iterator::Iterator>::next
0.0%   0.7%     92B        gdbstub <gdbstub::protocol::common::thread_id::IdKind as core::convert::TryFrom<&[u8]>>::try_from
0.0%   0.7%     87B           core <core::slice::iter::SplitMut<T,P> as core::iter::traits::iterator::Iterator>::next
0.0%   0.5%     67B   gdbstub_arch <gdbstub_arch::arm::reg::arm_core::ArmCoreRegs as gdbstub::arch::Registers>::gdb_deserialize
0.0%   0.5%     65B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::write_registers
0.0%   0.5%     65B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::read_registers
0.0%   0.5%     65B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadBase>::write_addrs
0.0%   0.4%     50B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadResume>::resume
0.0%   0.4%     50B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadResume>::set_resume_action_continue
0.0%   0.4%     50B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::base::multithread::MultiThreadResume>::clear_resume_actions
0.0%   0.3%     44B  gdbstub_nostd gdbstub_nostd::print_str::print_str
0.0%   0.3%     38B      [Unknown] _start
0.0%   0.0%      6B gdbstub_nostd? <gdbstub_nostd::gdb::DummyTarget as gdbstub::target::ext::breakpoints::SwBreakpoint>::add_sw_breakpoint
3.5% 100.0% 12.6KiB                .text section size, the file size is 355.8KiB
target/release/gdbstub-nostd  :
section               size    addr
.interp                 28     680
.note.ABI-tag           32     708
.note.gnu.build-id      36     740
.dynsym                384     776
.gnu.version            32    1160
.gnu.version_r          64    1192
.gnu.hash               28    1256
.dynstr                215    1284
.rela.dyn              432    1504
.rela.plt               24    1936
.rodata                881    1968
.eh_frame_hdr          252    2852
.eh_frame             1256    3104
.text                12890    8464
.init                   27   21356
.fini                   13   21384
.plt                    32   21408
.fini_array              8   25536
.init_array              8   25544
.dynamic               432   25552
.got                   120   25984
.got.plt                32   26104
.relro_padding        2536   26136
.tm_clone_table          0   30232
.data                    8   30232
.bss                     1   30240
.comment               184       0
Total                19955

@jonathanzetier

jonathanzetier commented May 10, 2026

Copy link
Copy Markdown
Author

...In the original description I mistakenly said that the armv4t examples don't have attach, and was informed by github's CI tests that in fact, it does, whoops! That's what I get for pushing early in the morning. It should be resolved now.

As a meta-note, have you considered something like pre-commit and/or pre-push hooks? I've gotten used to them (perhaps too used to them, as seen above), it's an easy way to make sure that you don't forget a certain test/check, and there's the easy escape hatch of --no-verify to commit/push WIP.

Anyways, I figure this might be a good time/place to address the issue of the report_reasonable_stop_reason with attach (which might provide a model for how we rework the other uses of report_reasonable_stop_reason), and wanted to solicit your opinion on how to go about doing this. One idea is to have attach return a T::Tid, and send that back as a stop reply...but this makes it impossible/unergonomic to do useful things like include register state, or reply with a message saying the process just died.

Did you want to go through with the new GdbStubStateMachine::Attached state proposed in #124 (comment)? I'm not as familiar with this part of the codebase (but should get more familiar with it sooner or later...non-stop mode is something my organization would like to help add to gdbstub as well), but it seems like you'd need both AttachedIdle and AttachedRunning states, since a stub might be running an attached process, or it might have an attached process and be waiting, and this could lead to a combinatorial explosion that would be hard to manage.

This removes the need for the `CurrentActivePid` trait.  As discussed in
the issue tracker for daniel5151#124 (multiprocess support), we're willing to
trade a needless `usize` in targets that don't need it for simpler
multiprocess support.
@daniel5151

daniel5151 commented May 11, 2026

Copy link
Copy Markdown
Owner

FYI, I prob won't be able to take a look here until ~Wednesday (got a bit of a hectic week). Apologies!

EDIT: Looking like this weekend at this point. I'm traveling cross-country at the moment, but should hopefully have some free time ~Sat / Sun.

@daniel5151 daniel5151 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that previous threads were discussing the notion of current_tid, but now that I've had a chance to page back in context about this code... it's not going to be as simple as adding a new field. fortunately, I think the recent T::Tid + IsValidTid rework stuff has laid a solid foundation for generically handling pid tracking across the 3 classes of targets we have today.

notably, with the current design, it seems pretty easy to "desync" the pid being tracked in this independent new type vs. in the other current_*_tid types (and ofc, having the same info in two places is unfortunate to begin with)

lmk if this feedback makes sense!

Comment thread src/stub/core_impl.rs
_connection: PhantomData<C>,

// The most recently attached PID
current_active_pid: Pid,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, IIRC, there's not real notion of "active" thread-id in the GDB RSP. The only firm concepts are the currently "selected" thread-id for memory operations, and resume operations.

as such, adding a new type here doesn't seem right. rather, I think the IsValidTid trait will need to grow some new methods for generically setting / getting the pid component of T::Tid.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a few places in the protocol that mention the notion of a "current thread":

  • The qC RSP message is described as this (annoyingly, this is entire thing, and there is no elaboration on what "current" means anywhere else...I know I already complained about this, but it doesn't make it any less annoying)

Return the current thread ID.

  • The documentation for qXfer:exec-file:read includes this:

If the annex part is empty the remote stub should return the filename corresponding to the currently executing process.

  • If a client doesn't support multiprocess extensions, it sends us thread IDs without a process ID, so there needs to be some notion of what process it's referring to; the process would be the "current" process (ie the attached process), which would combine to make the "current" thread.

Unless I'm misreading these, it seems like there's a need to represent the current process/thread somewhere; would you rather close this PR and keep on representing it in the target implementations like they were before this PR?

I do worry that handling it in the targets could be potentially confusing for multiprocess target implementations, who also have to keep track of what the "current" PID is, along with all their "attached" PIDs; like what does it really mean to have a "current" thread when you're keeping track of 3 separate processes that are all running at the same time?


Extending the IsValidTid trait to return the pid component seems like it would have to interact with the stub somehow to get this current pid for multithreaded stubs, since the client can still attach to an arbitrary process; we can't just return FAKE_PID...it would probably be more useful as a method of the stub, where the IsValidTid trait would return None if there was no pid component, and the stub could provide a current pid.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the GDB RSP docs definitely have some annoying ambiguities... sigh.

Inferring the correct behavior typically requires playing around with the code, and maybe cross-referencing with the upstream implementation in the GDB source code (i.e: in remote.c).

Unless I'm misreading these, it seems like there's a need to represent the current process/thread somewhere;

Well yes, of course. I'm not saying we shouldn't track it.

What I'm saying is that the correct place to track this info is in current_{mem,resume}_tid, which can only be done by extending T::Tid to properly track pids.

Or, in other words, to refine my initial comment - the terms "active" thread-id and "selected" thread-id are one and the same, and should be tracked via the same bit of storage.

Again, this all goes back to the fact that you really shouldn't be thinking about pids and tids as separate concepts for the vast majority of the GDB RSP.

Outside of a few narrow packets (e.g: attach, run), the only thing that ever really matters is a specific tuple of (pid, tid) (AKA, what the GDB RSP calls a thread-id). That's the thing that should be tracked via current_{mem,resume}_tid, that's the thing that will be passed to Target IDETs via the tid: T::Tid param, etc...

When you think about it that way, it should be very clear why a separate current_active_pid: Pid type doesn't really make sense. You're splitting out an indivisible aspect of the thread-id data type into its own field.

I do worry that handling it in the targets could be potentially confusing for multiprocess target implementations, who also have to keep track of what the "current" PID is, along with all their "attached" PIDs; like what does it really mean to have a "current" thread when you're keeping track of 3 separate processes that are all running at the same time?

The notion of the selected/active thread-id is something that should never leak out of the gdbstub implementation itself. And indeed, if you look, you'll find that qC doesn't even correspond to an IDET.

Indeed, not leaking "current active thread" semantics is is one of gdbstubs major ergonomic wins over trying to roll your own stub code!

From the target's perspective, there is no such thing as a 'Current PID'. The target is essentially just a set of stateless functions that say 'Read memory from PID X, Thread Y'. The only entity that needs to know which PID is 'current' is gdbstub, so it knows which numbers to pass into those functions.

It will only ever be asked to operate on specific thread-ids (i.e: (pid, tid) tuples), or all tids in a single pid (via some of the resume APIs). Sure, there are some APIs that will ask the target to do something related to a specific pid (i.e: attach), but it's only when the Target affirmatively responds to those packets (via a stop reason) that gdbstub checks to see what (pid, tid) is being reported as part of the stop response, and then updates its internal active-pid tracking.

Or, another example (not related to attach): when the GDB client wants to switch contexts, it sends an Hg (set general thread) or Hc (set continue thread) packet. gdbstub intercepts these and exclusively uses them to update its internal current_{mem,resume}_tid state. The target implementation never sees these H packets directly, and it never needs to maintain a concept of a 'selected' thread.

Instead, when a subsequent packet arrives that relies on this context (like a memory read m or a register read g), gdbstub automatically grabs that stored state and passes the fully-resolved (pid, tid) directly into the relevant Target trait method. Keeping that boundary strict is exactly why we want to avoid leaking a current_active_pid or similar state into the target traits.

Extending the IsValidTid trait to return the pid component seems like it would have to interact with the stub somehow to get this current pid for multithreaded stubs, since the client can still attach to an arbitrary process

Hopefully you can now see why this isn't really accurate. IsValidTid doesn't need to 'interact' with the stub to get the PID because the stub is the one that constructs the T::Tid and gives it to the trait in the first place. The trait simply acts as the storage container for that tuple.

i.e: when the client attaches to an arbitrary process, gdbstub will pass that request through to the state machine, and when the request is acknowledged by the Target with a corresponding stop-reason on attach, gdbstub will update its internal tracking to reflect the newly selected thread-id.


Does this all make a bit more sense now? Do you see why IsValidTid will need to be tweaked to also track pid handling?

wrt. handling the FAKE_PID codepaths - look at how I reworked gdbstub's code in #198 to report an error in cases where a single-threaded target (i.e: where T::Tid = ()) somehow runs into a situation where the GDB client is requesting something that isn't SINGLE_THREAD_TID. That same style of handling should be easy to do wrt. FAKE_PID when T::Tid is () or Tid in the single/multi-thread use cases, while transparently converting to/from (tid, pid) in the new multi-process use-cases.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a lot in there; I was already familiar with how tids (and one day, pids) get to the target method, but just to make sure I understood the actionable parts of your response, it's basically:

  1. We don't need the current_active_pid field of the GdbStubImpl (how this this PR does it) or the CurrentActivePid trait (what v0.8 currently does), because it should be tracked in current_{mem,resume}_tid
  2. We need to expand the IsValidTid to get the pid, and it would look something like this:
impl IsValidTid for () {
    def get_pid(&self) -> Pid {
        crate::FAKE_PID
    }

    ...
}

impl IsValidTid for Tid {
    def get_pid(&self) -> Pid {
        crate::FAKE_PID
    }

    ...
}

// Multiprocess name/representation in my local branch
impl IsValidTid for ExtendedThreadId {
    def get_pid(&self) -> Pid {
        self.pid
    }

    ...
}

If I'm mischaracterizing this, please ignore everything after this line and correct me!


I enthusiastically agree that this covers almost everything in the protocol, but I don't see how this handles a response to a qC packet. The client can still attach to any pid in the multithreaded (or even single threaded) case, but if the only candidates we can store that attached pid are in current_mem_tid/current_resume_tid, there's literally nowhere the value of the pid can go. When we use the above implementation for the return value of qC, we return FAKE_PID, and the gdb client crashes after a vAttach followed by a qC, with an assertion failure because the process portion of qC doesn't match the process it originally attached to (at least that's what versions 12.1, and IIRC 17.1, of the gdb client do).

Maybe there's a different path that fixes all of these? Currently the stub unconditionally reports it supports multiprocess features:

https://github.com/daniel5151/gdbstub/blob/dev/0.8/src/stub/core_impl/base.rs#L115-L116

This forces us to return extended thread IDs with a process and a thread in stop replies and qC. What if we only reply that we support multiprocess features in the (soon-to-exist) multiprocess mode? It helps us be more honest with the client about our actual capabilities, and then according to the protocol it's not supposed to even send us pids, or expect to receive pids from us. Then we don't have to worry about conjuring up some kind of pid (FAKE_PID...) to respond with for thread ID types that don't have one (like () or Tid).

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost!

You're right on 1, but for 2, what you actually want to do is change the IsValidTid trait itself to operate on this new ExtendedThreadId type (which, should prob just be a (Pid, Tid) tuple, rather than a custom type).

// update trait
pub trait IsValidTid: private::Sealed + PartialEq + Copy {
    #[doc(hidden)]
    fn into_fully_qualified_tid(self) -> (Pid, Tid);
    #[doc(hidden)]
    fn from_fully_qualified_tid(pid: Pid, tid: Tid) -> Option<Self>;
    #[doc(hidden)]
    fn sentinel() -> Self;
}

// update existing impl
impl IsValidTid for Tid {
    fn into_fully_qualified_tid(self) -> (Pid, Tid) {
        (self, crate::FAKE_PID)
    }

    fn from_fully_qualified_tid(pid: Pid, tid: Tid) -> Option<Self> {
        // notice how the Tid impl now enforces the FAKE_PID?
        if pid == crate::FAKE_PID { Some(tid) } else { None }
    }

    fn sentinel() -> Self {
        crate::SINGLE_THREAD_TID
    }
}

// create new impl
impl IsValidTid for (Pid, Tid) {
    fn into_fully_qualified_tid(self) -> (Pid, Tid) {
        self
    }

    fn from_fully_qualified_tid(pid: Pid, tid: Tid) -> Option<Self> {
        Some((pid, tid))
    }

    fn sentinel() -> Self {
        (crate::FAKE_PID, crate::SINGLE_THREAD_TID)
    }
}

P.S: might be time to rename SINGLE_THREAD_TID to FAKE_TID for consistency, hah. Similarly, IsValidTid can prob be renamed to ValidTid, since it's now far more than just a marker trait. neither of these needs to happen now - just jotting down the thoughts so I don't forget.


I'm not totally following, so apologies if this response is us talking past eachother 😅

You are correct that there is a narrow window of time where gdbstub needs to use a "dummy" thread-id value internally, as it hasn't yet interacted with the Target enough to ascertain the true thread-id it should be reporting. The inline comments in GdbStubImpl::new talk about it briefly.

That said, IIRC, the very first message any GDB client sends over is ?, which will trigger the attach path I talked about above, and would therefore give gdbstub a chance to update its internal current_{mem,resume}_tid value from the stop reply issued by the user's integration.

Similarly, if the GDB client were to start off with a vAttach to a specific PID, same logic applies - it would trigger the same attach path, we would sniff the current thread-if from the stop reply packet, and we'd be all set.

Essentially, my claim is that qC is never sent prior to us having a chance to ascertain a specific thread-id to report from it.

If this turns out to be false in practice / in some narrow edge case... we can always have gdbstub artificially start its state machine into the attach state (instead of starting in the Idle state) in order to force users to declare up-front what thread-id is currently attached (and in that artificial attach state, simply swallow the stop reason they report, as the GDB client wouldn't be expecting a stop reason packet at that point in the GDB RSP sequence). But this isn't something I think we need... since my claim is that all GDB clients are "reasonable" insofar as starting off each conversation with a ? / vAttach / vRun, packet in order to understand what state the stub is in.


your idea of only using multiprocess mode in, well, multi-process mode is intriguing, but comes with a major caveat: it means that single/multi-threaded targets would be excluded from extended mode facilities. See this comment in the docs https://docs.rs/gdbstub/latest/gdbstub/target/ext/extended_mode/trait.ExtendedMode.html#extended-mode-for-singlemulti-threaded-targets

But in any case, hopefully the explanation I offer above makes it a bit clearer why - in practice - things should work fine.

@jonathanzetier jonathanzetier May 19, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been operating under the assumption extended mode support and multiprocess support are orthogonal(-ish?), where stubs can support extended mode without multiprocess. The client can attach to any process it wants, it just can't attach to more than one of them at the same time. The documentation seems careful about specifying when packets are only available in extended mode versus when packets are only available in multiprocess mode, and I haven't seen anything suggesting that extended mode only applies for multiprocess stubs. The gdb client source code also doesn't seem to check for multiprocess support when it sends an extended mode packet (extended_remote_target::open in gdb/remote.c).

If you find that this isn't the case, please let me know!

Anyways, I agree that qC will always have a chance to snoop a Tid; the issue is that we lose the pid for Tid types that don't have a pid field. Please hear me out; I know there's already a lot written about how we don't need to care about the pid for 99% of the packets, and I agree: I'm saying that the response for qC is the 1% that does. Here's the exact scenario I'm worried about:

For the gdb clients I've tested, when the gdb client attaches to a process P, it sends vAttach P, Hgp0.0, qC, and then Hg<thread returned by qC>. The biggest note here is that the gdb client will crash with an assertion failure if the pid returned by qC doesn't match the pid passed by vAttach (aka P).

And here's how it would play out based on how I understand what you're proposing:

  1. gdbstub receives the vAttach P message, and passes P to the target's attach method.
  2. gdbstub snoops the stop reply that goes out to the client [0], and sets its internal current_{mem,resume}_tid fields. The stop reply takes a Tid (or ()), the stop reply's pid value is FAKE_PID after fully qualifying it, and we've totally lost track of P after this point.
  3. gdbstub receives the Hgp0.0 message, now current_mem_tid is an arbitrary thread. Not super relevant here.
  4. gdbstub receives the qC message. If it does not reply with a pid that is P, the gdb client will crash. When we fully qualify current_{mem,resume}_tid in our response, we send back FAKE_PID, which is probably not equal to P. There's nothing else we can do; gdbstub lost track of P in step 2! The gdb client crashes.

As always, please let me know if I'm misunderstanding what you're proposing and how it fits in here!

This is also why I'm saying not advertising multiprocess support might be the fix here: we don't have to include a process field in the response to qC anymore. We can reply with just a Tid value, and gdb doesn't lose its mind when we don't keep track of information we shouldn't have to care about.

I'm not sure what you mean about how this would break single/multi-threaded extended mode; the linked documentation seems to agree that we can have extended mode without needing to be multiprocess.


[0] I assume this is a future enhancement; gdbstub doesn't currently snoop the stop reply: vAttach and ? use report_reasonable_stop_reason, which doesn't call write_stop_common, which is where the current_{mem,resume}_tid get set.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... that's what I get for drafting a response before the morning coffee has fully kicked in, hah.

Yes, multi process extensions are orthogonal to extended mode, whoops.


[0] I assume this is a future enhancement; gdbstub doesn't currently snoop the stop reply: vAttach and ? use report_reasonable_stop_reason, which doesn't call write_stop_common, which is where the current_{mem,resume}_tid get set.

yes, all my comments are refer to a world post #194, where report_reasonable_stop_reason is in the rear-view mirror.


  1. gdbstub receives the vAttach P message, and passes P to the target's attach method.
  2. gdbstub snoops the stop reply that goes out to the client [0], and sets its internal current_{mem,resume}_tid fields. The stop reply takes a Tid (or ()), the stop reply's pid value is FAKE_PID after fully qualifying it, and we've totally lost track of P after this point.

Lets zoom in on these steps.

In a nutshell, here is my thesis wrt multi-process in 0.8: once proper multi-process support lands, any time the GDB client attempts to attach / interact with a PID that isn't FAKE_PID (i.e: 1), gdbstub raises a runtime error (likely including some error text that nudges users towards implementing proper support for multi-process). This is similar to the current behavior in single-threaded mode, in cases where a non-1 tid gets sent/recv'd by gdbstub.

And in this world, I see two ways this scenario you're describing could play out:

  1. with a descriptive runtime failure (as discussed above)
  2. if we simply respond to the vAttach P message with a stop reason that uses FAKE_PID... maybe the GDB client itself simply disregards the P it sent, and only cares that the effect of the vAttach (i.e: the stop reply packet) was that we attached to a process with pid = FAKE_PID?

If the behavior is 2, I feel like we're totally in the clear with my thesis, since it sidesteps the crash scenario entirely. If the behavior is 1, that's less fun for the user... but it doesn't seem unreasonable that if they want to multi-process drift, they should support multi-process extensions?


One thing to note about the multiprocess+ feature:

Note that reporting this feature indicates support for the syntactic extensions only, not that the stub necessarily supports debugging of more than one process at a time.

I bring this up because I'd be curious to understand how a stub would communicate to GDB that it only supports connecting to a single process at a time?

This ties into the question of enabling/disable this feature, as well as my thesis above... as this implies there is a class of targets that support multi-threaded debugging, and can switch between debugging a set of processes... but only one at a time. This is essentially the only kind of "multi-process" target that gdbstub currently supports (via the various hax that have landed in 0.7).

On one hand, it seems a bit sad to lose support for modeling these sorts of targets in multi-thread mode... but on the other hand, maybe it's fine if there's a "complexity jump" in gdbstub's API if you need to support jumping between processes as a multi-thread target?

But again, the crux of my question is how does such a target tell GDB / how does GDB infer that a target that supports multiprocess+ is a target that supports debugging multiple processes simultaneously, vs. one at a time


Here is one theory (which, full disclosure - the robot helped me draft):

GDB's architecture for multi-process debugging is entirely "try it and find out" (optimistic execution). It never infers the stub's capacity upfront because the protocol has no mechanism to communicate "I am a simultaneous target" vs "I am a one-at-a-time target".

Here is how the distinction actually plays out using that remote.c logic:

  1. The "Simultaneous" Target:
  • You attach to P1. GDB sends vAttach;P1. The stub replies with a stop packet. Success.
  • You type add-inferior and attach P2. GDB sends vAttach;P2.
  • The stub supports simultaneous debugging, so it attaches to P2 and sends another stop packet. GDB is now debugging both.
  1. The "One-at-a-Time" Target:
  • You attach to P1. GDB sends vAttach;P1. The stub replies with a stop packet. Success.
  • You type add-inferior and attach P2. GDB sends vAttach;P2.
  • The stub only supports one at a time. Because it is already occupied by P1, it rejects the packet by returning E01.
  • GDB parses the Enn, hits the default: case, triggers the error() macro, and aborts the attach. It tells the user "Attaching to P2 failed."
  • However, if the user had sent a D (detach) or vKill for P1 before trying to attach to P2, the stub would be "empty" again, and would accept the vAttach;P2 request.

So, maybe gdbstub can include some extra logic in single/multi-thread mode to enforce disconnect prior to re-attach?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha! Okay, I think that's the root cause of all this discussion! I was trying to keep the ability to attach to non-FAKE_PID processes in non-multiprocess targets, and it sounds like you're okay with dropping it.

Nice catch on the fact that multiprocess is just syntactic and means that the client/stub can send process IDs back and forth. Maybe this is still a compelling reason to not advertise multiprocess+ though? If the intention is to ignore any thread ID with pid != FAKE_PID, then telling the client "don't bother sending us a PID, we're only using the TID anyways" helps keep the client from sending us messages formatted in a way we don't care about...which ironically would actually help preserve the behavior of being able to attach to arbitrary processes.

@daniel5151 daniel5151 May 19, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to keep the ability to attach to non-FAKE_PID processes in non-multiprocess targets, and it sounds like you're okay with dropping it.

Yes. Well... mostly yes.

All the current code related to overriding FAKE_PID is only really there as a transient hack until proper multi-process support can land. I suspect that things "work" today in a pretty jank sense, and it was never totally clear to me what the existing semantics are / what they should be. It worked "well enough" in #129, and that's about it, hah.

So, while thinking about this problem (multi process, attach semantics, etc...), I strongly suggest imagining a codebase before #129.

Now, with that mindset, the question at hand - how to handle attaching?

Honestly, the more I think about it... the more I think that we should just straight up disallow vAttach when running in single/multi-threaded mode, eh? I think it just complicates the problem space way too much.

If someone wants to multi-process drift, they should go ahead and implement the multi-process handlers - simple as that. And whether or not they support attaching to multiple processes simultaneously or not is up to them (and the optionality of supporting simultaneous process debugging can be pointed out in the docs).

That said, I do want to preserve support for vRun when running in single/multi-threaded mode, as its super useful for swapping out the currently running code in, say, emulation contexts. I think that's more tractable, since I think the GDB client understands that the current process has been "swapped out" when you respond with a stop reason that has the same FAKE_PID?

To achieve these new attach / run semantics, we'll need to execute on that ExtendedMode trait rework that I hinted at a while back (recall that it was designed a long time ago, and isn't really aligned with modern gdbstub API design wrt. how it bundles all those ops together), since the current organization really isn't cutting it.


And honestly... now that I think about it... why does "extended mode" even need to be a thing that consumers are aware of?

Concepts of attach, run, etc... can all just be modeled as their own IDETs that hang directly off of {Single,Multi}ThreadBase/MultiProcessBase, and gdbstub can simply infer how to respond to the ! packet based on whether the user has implemented any of those IDETs.

Yeah... it really feels like the ExtendedMode trait should just go away, and its API surface re-allocated across the *Base traits appropriately. No reason to leak this RSP-ism to end users, right?


Maybe this is still a compelling reason to not advertise multiprocess+ though?

I'm open to the idea!

Forcing the feature on was a choice I made a loooooong time ago, and if I had to guess why, it was likely related to future proofing / improving client compatibility... but honestly, I don't totally know.

I do know that at some point, multiprocess+ feature negation was added (bfe83e1) to work around WinDbg being a really dumb GDB RSP client (at the time), but I wager most targets still want multiprocess+ extensions.

Indeed, I'd be interested to see how the changes we're making affect LLDB. The stance on LLDB compat is fuzzy (see #99), but the tl;dr is that I certainly don't want to break LLDB (especially since we just landed some juicy LLDB-only WASM extensions, hah).

If the intention is to ignore any thread ID with pid != FAKE_PID, then telling the client "don't bother sending us a PID, we're only using the TID anyways" helps keep the client from sending us messages formatted in a way we don't care about...which ironically would actually help preserve the behavior of being able to attach to arbitrary processes.

This doesn't really apply if we just straight up say "don't even expose vAttach in multi-threaded mode", but assuming you think that's a bad idea on my part, I'd be interested to see what the GDB client does if you force multiprocess+ off and then try doing some multi-process shenanigans with vAttach.

.features
.multiprocess()
.then_some(SpecificIdKind::WithId(self.get_current_pid(target)?)),
.then_some(SpecificIdKind::WithId(self.current_active_pid)),

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems wrong. this should be using the pid specified by the user via the tid parameter?

this ties into my other comment wrt. how current_active_pid shouldn't really be a "thing".

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah nice catch! That looks like a remnant that's been there for awhile, but nothing exposed the bug because only one process at a time has been able to be attached to (and before the changes from last week, it was only ever passed a Tid anyways), so the current_active_pid was never different from the PID that the gdb client sent.

@daniel5151

Copy link
Copy Markdown
Owner

As a meta-note, have you considered something like pre-commit and/or pre-push hooks? I've gotten used to them (perhaps too used to them, as seen above), it's an easy way to make sure that you don't forget a certain test/check, and there's the easy escape hatch of --no-verify to commit/push WIP.

I recently refactored CI into a runnable ./scripts/ci.sh script that you can run locally.

Feel free to add it as a pre-commit / pre-push hook :)

Anyways, I figure this might be a good time/place to address the issue of the report_reasonable_stop_reason with attach

As you can tell from my response in #199 (comment) - this is def something to be thinking about in relation to this work.

Did you want to go through with the new GdbStubStateMachine::Attached state proposed in #124 (comment)?

Yeah, I'm thinkin' about it...

Presumably, the flow would look something like this:

  • gdbstub is in Idle state
  • packet comes in requesting attach / ? / run
  • gdbstub calls a Target method to notify the user of the client's request
    • maybe we model ? and vAttach via the same Target method? i.e: fn attach(&mut self, tid: Option<T::Tid>), where a None represents the ? case of "initial connection, you pick which thread-id you want to attach to attach to"
  • gdbstub transitions into the Attach state, where it can only report a stop reason

One question I have is whether this new Attach state is even needed, vs. just recycling the Running state in this case? After all - the set of valid operations will be identical*

*ish? can you send a ctrl-c interrupt while waiting for a stop reply packet in response to a ? / vRun / vAttach response? If not... then a separate state makes sense (since you'd want to deny the ability to pass incoming_data until the stop-reason was reported)

@daniel5151

Copy link
Copy Markdown
Owner

Hey @jonathanzetier, any updates? No rush or anything, just checking in.

I just got back from a ~2 weeks of vacation myself, so it's not like I've been putting much time into my various projects in the past couple weeks, hah.

@jonathanzetier

Copy link
Copy Markdown
Author

No major updates, it's the last hurrah of my parental leave (baby starts daycare next week), so I've been more "barely time schedule" than "part time schedule" :-)

One smaller update is that before I proposed dropping the multiprocess feature advertising, I had already tested it with the armv4t test, and it seemed promising: the gdb client would only send thread IDs, even when the stub was responding with full extended thread IDs. I still feel like this approach conceptually simplifies the non-multiprocess targets (if we don't care about process IDs, the best way we can tell the client that is by not telling it that we do), and lets them "have their cake and eat it too" with respect to attaching to a process.

When I start working again, my plan is to basically push what I have for multiprocess support as-is (after rebasing it onto the other v0.8 changes you pushed), so we have something less hypothetical to talk about.

I know you had mentioned somewhere else that you preferred a (Pid, Tid) tuple over ExtendedThreadId { pid: Pid, tid: Tid } that I used in that PR. The main reason I preferred the ExtendedThreadId is that Pid and Tid felt too easily interchangeable; because they're just types instead of NewType, there's nothing preventing people from passing Pids to something expecting a Tid, or visa versa; for example this code shouldn't compile, but it would!

impl IsValidTid for Tid {
    fn into_fully_qualified_tid(self) -> (Pid, Tid) {
        (self, crate::FAKE_PID)
    }
    ....
}

Not to mention that as a target implementor, I'd much rather work with thread.pid and thread.tid than thread.0 and thread.1.

Anyways, that's my pitch for the new type over a tuple, but I can also use a tuple if you still prefer it.

@daniel5151

Copy link
Copy Markdown
Owner

Haha, no worries - the fact you've got time at all to poke around with some OSS right now is quite the feat in and of itself lol.

And your point wrt. type alias type confusion is very valid, and if I'm being honest - I was already thinking about turning Pid/Tid into proper newtypes to avoid that issue.

That said, whether it's a tuple or a struct isn't something we need to settle on now - I can easily tweak it before cutting 0.8, so feel free to take whatever approach you'd like.

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.

2 participants