Here are some problems we have faced while implementing our prototype :
[Protected ReadMem/WriteMem (I1)]:
A GDB user can request to see the content
of a corrupted pointer. The request PEEK_DATA will be performed by the COMMAND_MNGT
task. It shall not enter the default exception handler set by RGDBSD or it will
cause a dead lock in the RGDBSD code. Replacing the default exception vector
before calling readMem/writeMem can be temporarily sufficient but :
It will never work on MP system as it will rely on task priorities to insure
that other task will not cause exceptions while we have removed the default
exception handler,
This feature should not be usable in RGDBSD only but also by an embedded debugger
that may run without any task. It is also unavoidable in case of protected memory
and in this case no priority mechanism can be used,
In the case of using RGDBSD code on a dedicated nano kernel, this code will
be called from interrupt level and we need a way to be sure we can debug other
interrupts that may also cause exceptions,
[ATTACH Command Implementation (I2)]:
After the target rtems symbolic_ip_target_name
command, the normal operation is to issue an attach lid command where
lid represents a valid execution context. For Unix this is a process
id, for other multi-tasking system this is the id of a thread. After the attach
command, GDB expects to be waken up in the same manner as it is for normal events.
Once waken up it expects to have a complete register context available and also
that the target task is in a stopped state and that it can restart it using
the regular CONTINUE command. In RTEMS there is a way to get force a thread
to become inactive via rtems_task_suspend but no way to get the full
registers set for the thread. A partial context can be retrieved from the task
Registers data structure. On the other hand, relying on rtems_task_suspend
will be a problem for the nano-kernel implementation.
[Stopping Target System (I3)]:
Allthough it might not be obvious, most of the
actions made by a GDB user assume the target is not running. If you modify a
variable via the set variable = value command you expect that the value
is the one you have put when restarting. If a still running task modifies the
same value in the mean time, this may be false. On the other hand, stopping
all the tasks on the target system impose to have a very deep knowledge of the
system. Using an interrupt driven RGDBSD, may facilitate the implementation
on the nano-kernel.
[Getting Tasks Contexts (I4)]:
As previously mentionned there is no way to get
tasks execution contexts via the RTEMS API. This is needed when debugging for
example via this classical sequence :
(gdb) target rtems symbolic_ip_target_name
(gdb) info threads <= get a thread list on screen
(gdb)attach thread_id <= thread_id is one of the thread in
the list
(gdb) b a_function_of_interest
(gdb) continue
(gdb)backtrace <= print the call stack on the screen once we
have hit the breakpoint
(gdb) thread target another_thread_li <= change implicit current thread
value for gdb commands
(gdb)backtrace <= should print the backtrace for the chosen thread
In our execution model, we have a valid context only for the threads that hits
the breakpoint as it has been pushed by the exception handler code. The other
thread is still running and during the various RPC requesting memory access,
it even changes as the COMMAND_MNGT thread is going to sleep. So the backtrace
command will fail. We must find a way to make this work as it is very usefull
when debugging multi-threaded programs,
[Backtrace Stop convention (I5)]:
The backtrace command on RTEMS task does not
gracefully terminate as GDB does not find some backtrace termination condition
it expects.