This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/4] Remote exec events on Linux


This patch implements support for exec events in gdbserver on linux, in
multiprocess mode (target extended-remote).  Follow-exec-mode and rerun
behave as expected.  Catchpoints for exec are not yet implemented since
it will be easier to implement catchpoints for fork, vfork, and exec
all at the same time.

TESTING
---------
The patch was tested on GNU/Linux x86_64 with --target_board set to
native-gdbserver and native-extended-gdbserver, as well as testing
native GDB.  The test results for native-gdbserver were unchanged.
Thirteen tests that used to fail for native-extended-gdbserver on
Linux pass with this patch, and the non-ldr-exc-*.exp tests all
pass in non-stop mode and extended-remote.  There are several 
failures in the new non-ldr-exc-*.exp tests in non-stop mode
with native GDB.

One caveat: when an exec is detected, gdbserver emits a couple of warnings:
     gdbserver: unexpected r_debug version 0
     gdbserver: unexpected r_debug version 0
However, debugging of shared libraries that are loaded by the exec'd
program works just fine.  These messages may be caused by gdbserver
making an attempt to initialize the solib hook before the r_debug
structure has been initialized.  I intend to follow up in a subsequent
patch.

IMPLEMENTATION
----------------
Support for exec events in single-threaded programs was a fairly
straightforward replication of the implementation in native GDB:
    1) Enable exec events via ptrace options.
    2) Add support for handling the exec events to the handle_extended_wait
       and linux_wait_for_event_filtered.  Detect the exec event, then
       find and save the pathname of the executable file being exec'd.
    3) Implement an additional "stop reason", "exec", in the RSP stop reply
       packet "T".
Existing GDB code takes care of handling the exec event on the host side
without modification.

Support for exec events in multi-threaded programs required some
additional work that required a couple of significant changes to existing
code.  In a nutshell, the changes are to:
    4) Use the PTRACE_EVENT_EXIT extended event to handle thread exit,
       while not exposing any change in exit handling to the user.  The
       rationale for this is discussed in the "patch 0" email of this
       series.
    5) Recognize when the exec'ing thread has vanished (become the thread
       group leader) in send_sigstop.  Native GDB does this differently.

Regarding items 4 & 5: 
Recall that when a non-leader thread exec's, all the other threads are
terminated and the exec'ing thread changes its thread id to that of the
old leader (the process id) as part of the exec.  There is no event
reported for the "exit" of the exec'ing thread; it appears to have
vanished.  The original thread group leader can't be reaped until all
the other threads have been reaped, and some way of determining that it
has exited is required in order to update the lwp list (#4 above). Also,
some mechanism for deleting the lwp entry corresponding to the exec'ing
thread is needed (#5 above).

The rationale for #4 is that in my testing I ran into a race condition in
the mechanism that's intended to detect when a thread group leader has
exited, check_zombie_leaders.  The race occurred when there were only two
threads in the program.  In this case the leader thread passes through a
very brief zombie state before being replaced by the exec'ing thread as
the thread group leader.  This state transition is asynchronous, with no
dependency on anything gdbserver does.  Using PTRACE_EVENT_EXIT ensures
that the leader exit will be detected.  I can provide a more detailed
explanation or the race, but I didn't want to be too long-winded here.

Regarding item #5, determining that the exec'ing thread has "vanished",
In native GDB this is done by calling waitpid(PID), and if it returns
ECHILD it means that the thread is gone.  We don't want to use
waitpid(PID) in gdbserver, based on the discussion in
https://www.sourceware.org/ml/gdb-patches/2014-02/msg00828.html. An
alternative is to send a signal to each thread and look for an ESRCH
(No such process) error.  In all-stop mode this can be done in the 
normal course of events, since when gdbserver reports an exec event
it stops all the other threads with a SIGSTOP.  In non-stop mode, when
an exec event has been detected, we can call stop_all_lwps/unstop_all_lwps
to accomplish the same thing.

gdb/
2014-04-02  Don Breazeal  <donb@codesourcery.com>

        * common/linux-ptrace.c (linux_test_for_tracefork)
        [GDBSERVER]: Add exec tracing to ptrace options if OS supports
        it.
        * remote.c (remote_parse_stop_reply): Support new RSP stop
        reply reason 'exec'.

gdbserver/
2014-04-02  Don Breazeal  <donb@codesourcery.com>

        * gdb/gdbserver/linux-low.c (linux_child_pid_to_exec_file): New
        function.
        (handle_extended_wait): Add support for PTRACE_EVENT_EXEC.
        (check_zombie_leaders): Update comment.
        (linux_low_filter_event): Add support for PTRACE_EVENT_EXEC.
        (linux_wait_for_event_filtered): Update comment.
        (extended_event_reported): New function.
        (send_sigstop): Delete lwp on 'No such process' error and
        reset current_inferior.
        * gdb/gdbserver/linux-low.h (struct lwp_info): New member
        'waitstatus'.
        * gdb/gdbserver/remote-utils.c (prepare_resume_reply): Support
        new RSP stop reply reason 'exec'.

Attachment: 0002-remote-exec.patch
Description: 0002-remote-exec.patch


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]