I think this code was originally written by Nate who is no longer with us.
Looking at it, what I *think* it's doing starts in listen(). That sets up a
poll queue event which listens for connection from gdb. When that gets
triggered, that (slightly indirectly) calls connect which will check if
somebody is already attached, and if not call the attach function. That
will set up a poll queue event which waits for data to show up on the new
connection. Once that happens, the incomingData method is called, and that
sets up an event which will trigger at the next instruction boundary so
that the remote GDB stub is operating synchronously with the rest of gem5 I
think, and also so that it's not trying to look at state half way through
an instruction. When that trap event fires, it calls the trap() method.

So at this point we know that there was a connect, we got sent data through
it, and we're at an instruction boundary, if we're entering the debug loop
because gdb connected to us.

If we're entering the gdb loop for some other reason (in the comment there
it mentions the kernel's debug stub running in the guest triggering a
breakpoint) then that's what I think that "if" is for. If we aren't active
(because we didn't call attach() yet, ie no gdb has connected to us), then
record that we are in fact active. If we were already active, ie gdb was
already talking to us, tell it we got a trap and it can send us commands.

Regardless, then we try to read commands from gdb and execute them one by
one. Getting commands is started by the recv(data) call in that function
which eventually trickles down to a call to read() on the socket to
retrieve a byte. If that blocks, then gdb hasn't told us what to do yet.

In the case where the CPU has been told to wait for GDB, gem5 just blocks
after the GDB stub has been created until something connects to it.

I don't see any race condition here. If gem5 has been told to wait, it
waits. If gdb has connected to it and hasn't told it to keep running, it
blocks.

If, on the other hand, somebody throws a BadClient exception, for instance
because the data from gdb is malformed, then gdb will be disconnected and
the command loop will exit. This prevents a rogue connection or a
misbehaving client from jamming up the gdb server and locking the
simulation from progressing. The client can attempt to reattach to continue
debugging which would act like a connection reboot, flushing away the
broken connection and starting over. Also commands which return false tell
the command loop to exit. This is how the continue command breaks out of
the loop so the simulation can progress.

Gabe

On Thu, Aug 6, 2020 at 5:25 PM Boris Shingarov via gem5-dev <
[email protected]> wrote:

> It gets worse: I am beginning to suspect that this race is what ultimately
> causes the "xml for the wrong xlen" mystery (if the timing is unlucky, the
> CSPR isn't set yet).
>
> -----"Boris Shingarov via gem5-dev" <[email protected]> wrote: -----
> To: [email protected]
> From: "Boris Shingarov via gem5-dev" <[email protected]>
> Date: 08/06/2020 08:14PM
> Cc: "Boris Shingarov" <[email protected]>
> Subject: [gem5-dev] Possible race condition (Remote GDB)
>
> It looks to me that there is a race condition inherent in the design of
> DataEvent.
> The effect is that, even when CPU.wait_for_gdb attr is set and after the
> the RSP socket has connected, the relative timing of gdb's vs gem5's
> execution may or may not lead to gdb's presence being ignored.  It's like
> "hey gdb,I know you already connected, but if you aren't quick enough that
> the qSupported reaches the queue within N ms after connecting, I am going
> ahead without you; (and no I am not telling you what N is)".
>
> It looks like one fundamental issue here is the historical packet-oriented
> nature of RSP.  But it also looks like remote_gdb.cc:434,
>
> if (!active) {
>     active = true;
> } else {
>     // Tell remote host that an exception has occurred.
>     send(csprintf("S%02x", type).c_str());
> }
>
> plays a central role.
> Can someone comment on how this is intended to work?  I must admit the
> comment above that code doesn't make sense to me.
>
> _______________________________________________
> gem5-dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
> _______________________________________________
> gem5-dev mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
> %(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
>
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to