From 473cd1a4f770f42123b32bf3a737a7503a291e0b Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 1 May 2009 17:45:43 +0000 Subject: * go32-nat.c: Add comments about dirty secrets of DJGPP debugging. --- gdb/go32-nat.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'gdb/go32-nat.c') diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c index b62d3ff318e..edcdbd5cec2 100644 --- a/gdb/go32-nat.c +++ b/gdb/go32-nat.c @@ -18,6 +18,70 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +/* To whomever it may concern, here's a general description of how + debugging in DJGPP works, and the special quirks GDB does to + support that. + + When the DJGPP port of GDB is debugging a DJGPP program natively, + there aren't 2 separate processes, the debuggee and GDB itself, as + on other systems. (This is DOS, where there can only be one active + process at any given time, remember?) Instead, GDB and the + debuggee live in the same process. So when GDB calls + go32_create_inferior below, and that function calls edi_init from + the DJGPP debug support library libdbg.a, we load the debuggee's + executable file into GDB's address space, set it up for execution + as the stub loader (a short real-mode program prepended to each + DJGPP executable) normally would, and do a lot of preparations for + swapping between GDB's and debuggee's internal state, primarily wrt + the exception handlers. This swapping happens every time we resume + the debuggee or switch back to GDB's code, and it includes: + + . swapping all the segment registers + . swapping the PSP (the Program Segment Prefix) + . swapping the signal handlers + . swapping the exception handlers + . swapping the FPU status + . swapping the 3 standard file handles (more about this below) + + Then running the debuggee simply means longjmp into it where its PC + is and let it run until it stops for some reason. When it stops, + GDB catches the exception that stopped it and longjmp's back into + its own code. All the possible exit points of the debuggee are + watched; for example, the normal exit point is recognized because a + DOS program issues a special system call to exit. If one of those + exit points is hit, we mourn the inferior and clean up after it. + Cleaning up is very important, even if the process exits normally, + because otherwise we might leave behind traces of previous + execution, and in several cases GDB itself might be left hosed, + because all the exception handlers were not restored. + + Swapping of the standard handles (in redir_to_child and + redir_to_debugger) is needed because, since both GDB and the + debuggee live in the same process, as far as the OS is concerned, + the share the same file table. This means that the standard + handles 0, 1, and 2 point to the same file table entries, and thus + are connected to the same devices. Therefore, if the debugger + redirects its standard output, the standard output of the debuggee + is also automagically redirected to the same file/device! + Similarly, if the debuggee redirects its stdout to a file, you + won't be able to see debugger's output (it will go to the same file + where the debuggee has its output); and if the debuggee closes its + standard input, you will lose the ability to talk to debugger! + + For this reason, every time the debuggee is about to be resumed, we + call redir_to_child, which redirects the standard handles to where + the debuggee expects them to be. When the debuggee stops and GDB + regains control, we call redir_to_debugger, which redirects those 3 + handles back to where GDB expects. + + Note that only the first 3 handles are swapped, so if the debuggee + redirects or closes any other handles, GDB will not notice. In + particular, the exit code of a DJGPP program forcibly closes all + file handles beyond the first 3 ones, so when the debuggee exits, + GDB currently loses its stdaux and stdprn streams. Fortunately, + GDB does not use those as of this writing, and will never need + to. */ + #include #include "defs.h" -- cgit v1.2.1