debugger-only log on Linux, equivalent of OutputDebugString

Simon Marchi simark@simark.ca
Thu Sep 17 19:01:50 GMT 2020


On 2020-09-17 1:10 p.m., Tom Tromey wrote:
>>>>>> ">" == A M Miera via Gdb <gdb@sourceware.org> writes:
>
>>> The main question I'd like to ask though, is this: is that actually
>>> the right way to go, or can this be done better in terms of operation
>>> principles? I have several concerns here:
>>> a. this might be very system-specific, e.g. for bare-metal Cortex-Mx
>>> targets there's sth called "semihosting", which effectively does the
>>> same (though is something different in principle). Windows already its
>>> own call, too, etc.
>>> b. most likely a simple pipe-based solution is not going to work with
>>> remote targets, e.g. gdbserver? Should it be added?
>>> c. and last but not least: maybe a mechanism already exists and I'm
>>> reinventing the wheel now?
>
> I don't know of another existing implementation of this.
>
> Your approach sounds maybe a bit like what "libust" is doing.
> That might be worth a look.
>
> Tom
>

Just to clarify, Tom is talking about the LTTng-UST project [1].  This
is tracing, so not quite exactly what you describe, but perhaps it could
cater to your use case.  The overhead when tracing is quite low (and it
doesn't use locking, so it stays good even with multiple threads) and
essentially zero when tracing is disabled.

Otherwise, if performance is not really a concern, you can easily
implement something naive based on breakpoints in Python.  This has the
advantage that it would work with pretty much any target, remote or not.
For example:

~~~
    class OutputDebugStringBreakpoint(gdb.Breakpoint):
        def __init__(self):
            super().__init__("OutputDebugString", internal=True)

        def stop(self):
            s = gdb.parse_and_eval("str")
            print(s.string(), end='')

            # Return false: don't stop.
            return False

    OutputDebugStringBreakpoint()
~~~

With the script above, you just need to make sure your program contains
an empty function "OutputDebugString" that isn't optimized away and is
compiled with debug info, such that the script is able to find the value
of the "str" argument.

I read a bit on how OutputDebugString works on Windows [2]: it uses a
shared memory mapping between the inferior and the debugger (or
kernel?).  It probably results in less overhead than an approach based
on breakpoints like what I have shown above, because the process
probably doesn't wait until the debugger has printed the string to keep
going.  We could imagine something similar in the GDB world, but it
would require target-specific work.  GDBserver could also implement the
"host" side, collect the output strings and send them to GDB which will
then print them.  While writing this, I now notice that it sounds not
too far from the fast tracepoints.

Note that there already exists something for this in the remote
protocol, the 'O' stop reply packet [3].  Maybe some debug stubs (even
for debugging hardware like the Cortex-M) use it?  I don't know.  But
according to the doc, it doesn't work with non-stop.

Looking at the qemu source code, it looks like it supports sending the
'O' packet, but I don't know how it's used.

I just looked in the gdb/gdbserver code [4][5], apparently gdb supports
printing the strings passed to OutputDebugString on Windows.  It arrives
in the form a debug event containing the string to print, that's quite
simple.  GDBserver relays this string using the 'O' packet mentioned
above.

Simon

[1] https://lttng.org/
[2] http://www.unixwiz.net/techtips/outputdebugstring.html#protocol
[3] https://sourceware.org/gdb/current/onlinedocs/gdb/Stop-Reply-Packets.html
[4] https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/windows-nat.c;h=188a920cbb061f0d8639340ffec40b7d9afd4b3b;hb=HEAD#l1720
[5] https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdbserver/win32-low.cc;h=a11cc740925a13edb7c2e689998cd215fc32abfa;hb=HEAD#l1571


More information about the Gdb mailing list