source: rtems/doc/rgdb_specs/daemon.t @ 64e0f6c4
Last change on this file since 64e0f6c4 was 64e0f6c4, checked in by Joel Sherrill <joel.sherrill@…>, on 04/02/99 at 17:23:36

Can now produce html, info, and PostScript? without errors. Links
between chapters are correct.

  • Property mode set to 100644
File size: 19.1 KB
2@c  RTEMS Remote Debugger Server Specifications
4@c  Written by: Eric Valette <>
5@c              Emmanuel Raguet <>
8@c  $Id$
11@chapter RTEMS Debugger Server Daemon
13We will describe in this section how this debugger server will be
14implemented on RTEMS environment. Our initial target is based on Intel Pentium
15and we will use an Ethernet link to communicate between the host and the target.
17The RTEMS remote debugger will be composed by several tasks and exception
18handlers :
20@itemize @bullet
21@item an initialization task which opens the sockets and runs the SUN RPC
22server. This task will also connect the interrupt handlers and launch the communication
24@item a communication task which receives the SUN RPC commands, executes
25them and sends the result to the GDB client,
26@item A debuggee event management task which waits for events. We need a different
27task than the command management task in order to be able to still accept commands
28while no event has yet occurred for the debuggee. An example could be a continue
29command from GDB and then hitting to DEL key to see what is currently going
30on on the target side because an expected breakpoint is not caught...
31@item a debug exception handler which manages the hardware breakpoint and
32single step exceptions (INT 1 on Intel x86),
33@item a breakpoint exception handler which manages the software breakpoints
34exceptions (INT 3 on Intel x86),
35@item a default exception handler used to catch every possible errors make on the
36target system,
37@end itemize
39@c XXX figure reference
40@c XXX references to other sections
41Figure @b{remote debugger tasks and handlers} represents these
42different tasks and handlers. The synchronization between the different task
43and exception handlers will be described below in the section
44@b{Synchronization Among Tasks and Exception Handlers}.
45Some open issues we have faced for a prototype implementation are described
46in the section @b{Open Issues}. The temporary workaround we chose are described
47in chapter @b{Workarounds for Open Issues in Prototype}.
50@section The INITIALIZATION task
52This is the task that must be executed at the boot phase of RTEMS.
53It initializes the debug context. It must :
55@itemize @bullet
56@item open the UDP sockets,
57@item run the SUN RPC server main loop,
58@item create the COMMAND MANAGEMENT task,
59@item connect the DEBUG EXCEPTION handler,
60@item connect the SOFTWARE BREAKPOINT handler,
61@item delete itself.
62@end itemize
63If an error occurs at any step of the execution, the connections established
64before the error will be closed, before the initialization task deletes itself.
67@section The COMMAND_MNGT task
69This task is in charge of receiving the SUN RPC messages and executing
70the associated commands. This task must have an important priority because it
71must be executed each time a command message comes from the debugger. It must
72be executed even if one or both exception handlers are executed. But the COMMAND
73MANAGEMENT task must not block the TCP/IP module without which no message can
74be received.
76When not executing a command, this task is waiting for a SUN RPC message
77on the primary port. This idle state blocks the task, so the other active tasks
78can run. Once a message comes from Ethernet via the primary port, the COMMAND
79MANAGEMENT task wakes up and receives the message which is a request from GDB.
80This request is sent to the SUN RPC server code which extracts the command and
81its arguments, executes it and, if needed, sends a result to GDB. After having
82performed these actions, the task sleeps, waiting for another message.
84A particular case is the reception of the ATTACH command : in this
85case the COMMAND_MNGT task creates the EVENT_MNGT task described below before
86going to wait on UDP socket again.
89@section The EVENT_MNGT task
91This task is in charge of managing events happening on the debuggee such as
92breakpoint, exceptions. This task does a basic simple loop waiting for event
93on a synchronization variable. It is waken up by exception handlers code. It
94then signals GDB that an event occurred and then go sleeping again as further
95requests will be processed by the COMMAND_MNGT task.
98@section The DEBUG EXCEPTION handler
100This handler is connected to the DEBUG exception (INT 1 on Intel ix86).
101This exception is entered when :
103@itemize @bullet
104@item executing a single-step instruction,
105@item hardware breakpoint condition is true,
106@end itemize
107These events will be treated by the debugger because they are the
108primary event used when debugging a software for instruction stepping. In both
109cases, the DEBUG EXCEPTION handler code is executed. Please note that the execution
110context of the exception handler is the supervisor stack of the task that generated
111the exception . This implies :
113@itemize @bullet
114@item We may sleep in this context,
115@item We have as many possible execution context for the DEBUG EXCEPTION handler as
116we need to,
117@item When we enter the high level exception handler code, a normalized exception
118context has been pushed on the system stack and a pointer to this context is
119available as the first argument (cf c/src/exec/score/cpu/i386/cpu.c for more
121@end itemize
122First the exception handler wakeup the EVENT_MNGT task. Then it will
123cause the faulting thread to sleep on a synchronization object. As soon as GDB
124receives the event notifying that the debuggee status has changed, it will start
125sending requests to get the debuggee status (registers set, faulty task id,
126...). These requests are handled by the COMMAND MANAGEMENT task. When this task
127receive a PTRACE_CONT command it will resume the execution of the task that
128caused the exception by doing a V on the synchronization object.
131@section The BREAKPOINT EXCEPTION handler
133This handler is connected to the BREAKPOINT exception (INT3 on Intel
134Ix86). Each time the debugger wants to place a software breakpoint in the debuggee,
135a debuggee opcode is temporarily replaced by an instruction causing BREAKPOINT
136exception (the ``INT 3'' instruction on Intel ix86). When ``INT 3'' is executed,
137the BREAKPOINT handler is executed. Otherwise, the exception processing is the
138same than the one described in previous section.
141@section Synchronization Among Tasks and Exception Handlers
143The previous chapters have presented a simplified and static view of the various
144tasks and exceptions handlers. This chapter is more focussed on synchronization
145requirements about the various pieces of code executed when RGDBSD is operating.
148@subsection Implicit Synchronization Using Task Priorities
150This chapter is relevant on Uniprocessor System (UP) only. However, it will
151also list the requirements for explicit synchronization on Multi-processor Systems
152(MP). Below are the task priorities sorted by high priority. They are not supposed
153to be equal :
156@item Network Input Task. This is the highest priority task. This can be regarded
157as a software interrupt task for FreeBSD code,
158@item RGDBSD command task. As this task waits on UDP sockets, it shall not prevent
159the previous task from running. As the main debug entry point, it should preempt
160any other task in the system,
161@item RGDBSD event task. This task should preempt any task but the two mentionned
162before to signal a debug event to GDB. The command task shall be able to preempt
163this task for emergency command such as DEL, or REBOOT,
164@item Applications tasks (task we are able to debug),
165@end enumerate
166Using theses priorities eliminates the need for adding more synchronization
167objects in the next section. My belief is that symmetric MP support will require
168more important change in the RTEMS than RGDBSD itself like multiple scheduler
169queues, task to processor binding for non symmetric IO, use a different implementation
170for @emph{task_disable_preemption}, ...
173@subsection Explicit Synchronization
175This chapter will describe the synchronization variables that need to be implemented
176in order to sequence debug events in a way that is compatible with what GDB
177code expects. The root of the problem is that GDB code mainly expects that once
178a debug event has occurred on the debuggee, the entire debuggee is frozen and
179no other event will occur before the CONTINUE command is issued. This behavior
180is hard to achieve in our case as once we hit a breakpoint, only the task that
181hits the breakpoint will be asleep on a synchronization object. Other tasks
182may hit other breakpoints while we are waiting commands from GDB generating
183potential unexpected events. There is a solutions if RGDBSD itself use RTEMS
184threads to fix this problem by creating a task that loops forever at a priority
185superior to any debugged task but below RGDBSD task priorities. Unfortunately
186this will not work for the case we use the nano-kernel implementation and we
187think it is better to study synchronization problems now. We also expects that
188multi-thread debug support hardening in GDB will remove some event serializations
189requirements. Here is the list of synchronization variables we plan to use and
190their usage. They are all regular semaphores. They are not binary semaphores
191because the task that does V is not the task that has done the P.
193@itemize @bullet
194@item @emph{WakeUpEventTask} : used by exception handler code to wake up the EVENT_MNGT
195task by doing a V operation on this object. When target code is running normally
196the EVENT_MNGT task sleeps due to a P operation on this semaphore,
197@item @emph{SerializeDebugEvent} : used to serialize events in a way compatible to
198what GDB expects. Before doing a V operation on @emph{WakeUpEventTask}, the
199exception handler does a P on this semaphore to be sure processing of another
200exception is not in progress. Upon reception of a CONTINUE command, the COMMAND_MNGT
201task will issue a V operation so that the exception code can wake up EVENT_MNGT
202task using the mechanism described above,
203@item @emph{RestartFromException} : (in fact one semaphore per task) used by exception
204handling code to put a faulty task to sleep once it has generated an exception
205by doing a P operation on this semaphore. In the case the exception was generated
206due to a breakpoint, GDB command will modify back the BREAKPOINT opcode to the
207original value before doing the CONTINUE command. This command will perform
208a V on this semaphore. In the case it is a real non restartable exception (faulty
209memory reference via invalid pointer for example), GDB will not allow to restart
210the program avoiding any loop. So not special analysis of cause of exception
211is foreseen as far as RGDBSD code is concerned,
212@end itemize
214@section Open Issues
216Here are some problems we have faced while implementing our prototype :
218@table @b
219@item [Protected ReadMem/WriteMem (I1)]:
220A GDB user can request to see the content
221of a corrupted pointer. The request PEEK_DATA will be performed by the COMMAND_MNGT
222task. It shall not enter the default exception handler set by RGDBSD or it will
223cause a dead lock in the RGDBSD code. Replacing the default exception vector
224before calling @b{readMem/writeMem} can be temporarily sufficient but :
226@itemize @bullet
227@item It will never work on MP system as it will rely on task priorities to insure
228that other task will not cause exceptions while we have removed the default
229exception handler,
231@item This feature should not be usable in RGDBSD only but also by an embedded debugger
232that may run without any task. It is also unavoidable in case of protected memory
233and in this case no priority mechanism can be used,
235@item In the case of using RGDBSD code on a dedicated nano kernel, this code will
236be called from interrupt level and we need a way to be sure we can debug other
237interrupts that may also cause exceptions,
238@end itemize
240@item [ATTACH Command Implementation (I2)]:
241After the @emph{target rtems symbolic_ip_target_name}
242command, the normal operation is to issue an @emph{attach lid} command where
243@emph{lid} represents a valid execution context. For Unix this is a process
244id, for other multi-tasking system this is the id of a thread. After the attach
245command, GDB expects to be waken up in the same manner as it is for normal events.
246Once waken up it expects to have a complete register context available and also
247that the target task is in a stopped state and that it can restart it using
248the regular CONTINUE command. In RTEMS there is a way to get force a thread
249to become inactive via @emph{rtems_task_suspend} but no way to get the full
250registers set for the thread. A partial context can be retrieved from the task
251@emph{Registers} data structure. On the other hand, relying on @emph{rtems_task_suspend}
252will be a problem for the nano-kernel implementation.
254@item [Stopping Target System (I3)]:
255Allthough it might not be obvious, most of the
256actions made by a GDB user assume the target is not running. If you modify a
257variable via the @emph{set variable = value} command you expect that the value
258is the one you have put when restarting. If a still running task modifies the
259same value in the mean time, this may be false. On the other hand, stopping
260all the tasks on the target system impose to have a very deep knowledge of the
261system. Using an interrupt driven RGDBSD, may facilitate the implementation
262on the nano-kernel.
264@item [Getting Tasks Contexts (I4)]:
265As previously mentionned there is no way to get
266tasks execution contexts via the RTEMS API. This is needed when debugging for
267example via this classical sequence :
271@item @emph{(gdb) target rtems symbolic_ip_target_name}
273@item @emph{(gdb) info threads <=} get a thread list on screen
275@item @emph{(gdb)} @emph{attach thread_id} <= thread_id is one of the thread in
276the list
278@item @emph{(gdb) b a_function_of_interest }
280@item @emph{(gdb) continue}
282@item @emph{(gdb)} @emph{backtrace} <= print the call stack on the screen once we
283have hit the breakpoint
285@item @emph{(gdb) thread target another_thread_li <=} change implicit current thread
286value for gdb commands
288@item @emph{(gdb)} @emph{backtrace <=} should print the backtrace for the chosen thread
289@end enumerate
290In our execution model, we have a valid context only for the threads that hits
291the breakpoint as it has been pushed by the exception handler code. The other
292thread is still running and during the various RPC requesting memory access,
293it even changes as the COMMAND_MNGT thread is going to sleep. So the backtrace
294command will fail. We must find a way to make this work as it is very usefull
295when debugging multi-threaded programs,
298@item [Backtrace Stop convention (I5)]:
299The backtrace command on RTEMS task does not
300gracefully terminate as GDB does not find some backtrace termination condition
301it expects.
302@end table
304@section Workarounds for Open Issues in Prototype
306@table @b
308@item [(I1)]:
309Not implemented.We would rather like to work on the formalization of
310per thread flags and global flags that are much more general than any kludge
311we could implement,
313@item [(I2)]:
314We have tried two solutions in our prototype. The first one was to use
315the @emph{idle} thread context contained in the @emph{Registers} task control
316block field. The drawback of this solution was that we had to implement specific
317code for the continue operation immediately following the attach command. We
318then decided to create a dedicated task that will only exist during the attach
319phase. This task will call the ``ENTER_RGDB'' exception. This call will execute
320the Exception Handler that saves a valid context and that notifies a change
321to GDB. After the first CONTINUE command from GDB, this task will continue its
322execution and delete itself,
324@item [(I3)]:
325As explained above in the synchronization chapter, we choose to serialize
326events in a way that makes GDB think the system is frozen,
328@item [(I4)]:
329As a temporary fix, we have called @emph{rtems_task_suspend} and used
330the context switch contex for tasks that are unknown to RGDBSD,
332@item [(I5)]:
333Not Implemented yet. If I remember correctly, setting the frame pointer
334to 0 at task initialization for CISC processor solves this problem (ebp = 0x0
335on Intel or a6 = 0x0 on 680x0). This should be done in rtems_task_create function
336in the path to really starts the task for the first time. The processor/system
337specific stop condition can be found as macros in the GDB source tree.
338@end table
340@section Output of a Debug Session with the Prototype
343GNU gdb 4.17
344Copyright 1998 Free Software Foundation, Inc.
345GDB is free software, covered by the GNU General Public License, and you are
346welcome to change it and/or distribute copies of it under certain conditions.
347Type "show copying" to see the conditions.
348There is absolutely no warranty for GDB.  Type "show warranty" for details.
349This GDB was configured as --host=i686-pc-linux-gnu --target=i386-rtems".
350Attaching remote machine across net...
351Connected to net-test.
352Now the "run" command will start a remote process.
353Setting up the environment for debugging gdb.
354(gdb) attach 1
355Attaching program: /build-rtems/pc386/tests/debug.exe pid 1
3560x230715 in enterRdbg ()
357(gdb) info threads
358There are 8 threads:
359Id.       Name   Detached   Suspended
360134283273 Rini   No         No <= current target thread
3610x230715 in enterRdbg ()
362134283272 Evnt   No         No
363_Thread_Dispatch () at /rtems/c/src/exec/score/src/thread.c:315
364134283271 SPE2   No         No
365_Thread_Dispatch () at /rtems/c/src/exec/score/src/thread.c:315
366134283270 SPE1   No         No
367_Thread_Handler  () at /rtems/c/src/exec/score/src/thread.c:1107
368134283269 RDBG   No         No
3690x230715 in enterRdbg ()
370134283268 SCrx   No         No
371_Thread_Dispatch () at /rtems/c/src/exec/score/src/thread.c:315
372134283267 SCtx   No         No
373_Thread_Dispatch () at /rtems/c/src/exec/score/src/thread.c:315
374134283266 ntwk   No         No
375_Thread_Dispatch () at /rtems/c/src/exec/score/src/thread.c:315
376(gdb) b init.c:89
377Breakpoint 1 at 0x200180: file /rtems/c/src/tests/samples/debug/init.c, line 89.
378(gdb) c
380Thread 134283273 (Rini) has been deleted.
381[Switching to Rtems thread 134283271 (Not suspended) ( <= current target thread )]
382Breakpoint 1, example2 (argument=4) at /rtems/c/src/tests/samples/debug/init.c:89
38389          tuto += tuti;
384(gdb) s
38590          if (print_enable2)
386(gdb) c
388Breakpoint 1, example2 (argument=4) at /rtems/c/src/tests/samples/debug/init.c:89
38989          tuto += tuti;
390(gdb) b init.c:66
391Breakpoint 2 at 0x200128: file /rtems/c/src/tests/samples/debug/init.c, line 66.
392(gdb) c
394Switching to Rtems thread 134283270 (Not suspended) ( <= current target thread )]
395Breakpoint 2, example1 (argument=4) at /rtems/c/src/tests/samples/debug/init.c:66
39666          toto += titi;
397(gdb) c
399[Switching to Rtems thread 134283271 (Not suspended) ( <= current target thread )]
400Breakpoint 1, example2 (argument=4) at /rtems/c/src/tests/samples/debug/init.c:89
40189          tuto += tuti;
402(gdb) bt
403#0  example2 (argument=4)
404    at /rtems/c/src/tests/samples/debug/init.c:89
405#1  0xf0009bd0 in ?? ()
406(gdb) thread target 134283270
407thread 134283270 [SPE1], _Thread_Dispatch () at /rtems/c/src/exec/score/src/thread.c:315
408315         executing = _Thread_Executing;
409(gdb) c
411Breakpoint 2, example1 (argument=4) at /rtems/c/src/tests/samples/debug/init.c:66
41266          toto += titi;
413(gdb) detach
414Detaching program: /build-rtems/pc386/tests/debug.exe pid 1
415Warning: the next command will be done localy! If you want to restart another remote
416program, reuse the target command
418@end example
Note: See TracBrowser for help on using the repository browser.