Re: RFC: Don't kill the program after "file"

Jim Blandy
2006-06-14T19:55:52Z

Daniel Jacobowitz <drow@false.org> writes:
> I talked with Jim about this. He wasn't entirely happy with discarding
> the prompt for native debugging, where it traditionally makes sense; we
> didn't quite make it to an agreement on what ought to happen. He
> suggested adding a "process-oriented" flag to target vectors. For a
> process oriented target (i.e. one which can handle "run" and "kill" and
> so forth) it makes sense to offer to kill at this point; for
> board oriented targets it makes less sense. Another thing which just
> occured to me would be to make the file command succeed if you say "n"
> at the query.

I don't think this patch should be blocked on reaching a consensus on
this larger design issue, but I would like to expand on the thought a
bit.

We certainly want GDB's commands to work consistently, regardless of
architecture, whether we're working remotely or locally, and so on.
However, the distinction between a target that creates a new process
each time you 'run' (like native Unix debugging) versus a target like
a simple board without a kernel or memory management, where you're
simply manipulating registers and memory that are always there, can't
really be concealed from the user.

In the 'process' case, there really is no register set for GDB to
operate on until you start the program running. Commands like 'print
$pc' and 'where' need to produce an error.

$ gdb hello
GNU gdb Red Hat Linux (6.3.0.0-1.84rh) ...
(gdb) print $pc
No registers.
(gdb) where
No stack.
(gdb)

Commands like 'print a', where a is a global or static variable, read
their data directly to the executable file when there's no process, so
they can work even before a 'run'.

But in the non-process case, where GDB is talking to a system whose
state persists between program runs, there are always registers and
memory to play with; a 'load' just writes to memory to put the program
in place, and does some initialization like setting the PC. There's
no reason to prohibit things like register manipulation and stack
backtraces until something like a 'run' is done.

Note that this is not really a "native vs. remote" distinction. If
the remote end were a gdbserver running on a Linux machine, it would
make perfect sense for that remote target to employ a 'process' model.
(I think 'extended remote' mode works this way, essentially, but there
are details I'm confused about.) The distinction has to do with how
programs are run, not with our communications protocol.

GDB must expose this distinction the user; we can't unify the two
cases. To make the persistent case behave exactly like the process
case, we would need to prohibit well-defined, everyday operations.
The purpose of consistency is to make things simpler for the user, but
there's no good way to replace the lost functionality. And making the
process case behave like the persistent case doesn't make sense
either; there really are no registers until you start the program.

But at the moment, GDB is in kind of a suboptimal state: the
distinction is visible, but not exploited where it should be, and
there are a few attempts to ignore it that cause annoying behavior.
The behavior Daniel's dealing with is an example: if you're talking to
a remote target, the 'exec-file' command will currently disconnect you
from the target; this is consistent with the native behavior (where we
kill the inferior process), but not actually useful to people
debugging native targets.

I haven't tried to think through yet how to make this concrete --- how
commands should behave, and so on. I'm sure doing so would change my
understanding.