Skip to content

Commit e1d94b3

Browse files
committed
fbsd-nat: Fix several issues with detaching.
- Detach from any child processes implicitly attached to by the kernel due to fork following that have not yet been processed by GDB's core. - Delete breakpoints before detaching. inf-ptrace::detach does not do this (somewhat surprisingly), so add an override to remove breakpoints from a process before detaching from it. This also requires explicitly draining any pending SIGTRAP events for software breakpoints before detaching. In particular, threads may need their PC adjusted due to the software breakpoint before being resumed after detach. On more modern systems using the si_code from SIGTRAP to identify software breakpoint traps, the PC is adjusted in ::wait_1 as a side effect of parsing the event. To support older kernels, ::detach fixes up the PC for any SIGTRAP stop whose potential new PC matches an existing software breakpoint.
1 parent 12e5b10 commit e1d94b3

File tree

2 files changed

+276
-0
lines changed

2 files changed

+276
-0
lines changed

gdb/fbsd-nat.c

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,268 @@ fbsd_nat_target::attach (const char *args, int from_tty)
18371837
inf_ptrace_target::attach (args, from_tty);
18381838
}
18391839

1840+
/* If this thread has a pending fork event, there is a child process
1841+
GDB is attached to that the core of GDB doesn't know about.
1842+
Detach from it. */
1843+
1844+
void
1845+
fbsd_nat_target::detach_fork_children (thread_info *tp)
1846+
{
1847+
/* Check in thread_info::pending_waitstatus. */
1848+
if (tp->has_pending_waitstatus ())
1849+
{
1850+
const target_waitstatus &ws = tp->pending_waitstatus ();
1851+
1852+
if (ws.kind () == TARGET_WAITKIND_VFORKED
1853+
|| ws.kind () == TARGET_WAITKIND_FORKED)
1854+
{
1855+
pid_t pid = ws.child_ptid ().pid ();
1856+
fbsd_nat_debug_printf ("detaching from child %d", pid);
1857+
(void) ptrace (PT_DETACH, pid, (caddr_t) 1, 0);
1858+
}
1859+
}
1860+
1861+
/* Check in thread_info::pending_follow. */
1862+
if (tp->pending_follow.kind () == TARGET_WAITKIND_VFORKED
1863+
|| tp->pending_follow.kind () == TARGET_WAITKIND_FORKED)
1864+
{
1865+
pid_t pid = tp->pending_follow.child_ptid ().pid ();
1866+
fbsd_nat_debug_printf ("detaching from child %d", pid);
1867+
(void) ptrace (PT_DETACH, pid, (caddr_t) 1, 0);
1868+
}
1869+
}
1870+
1871+
/* Detach from any child processes associated with pending fork events
1872+
for a stopped process. Returns true if the process has terminated
1873+
and false if it is still alive. */
1874+
1875+
bool
1876+
fbsd_nat_target::detach_fork_children (inferior *inf)
1877+
{
1878+
/* Detach any child processes associated with pending fork events in
1879+
threads belonging to this process. */
1880+
for (thread_info *tp : inf->non_exited_threads ())
1881+
detach_fork_children (tp);
1882+
1883+
/* Unwind state associated with any pending events. Reset
1884+
fbsd_inf->resumed_lwps so that take_pending_event will harvest
1885+
events. */
1886+
fbsd_inferior *fbsd_inf = get_fbsd_inferior (inf);
1887+
ptid_t ptid = ptid_t (inf->pid);
1888+
fbsd_inf->resumed_lwps = ptid;
1889+
1890+
while (1)
1891+
{
1892+
gdb::optional<pending_event> event = take_pending_event (ptid);
1893+
if (!event.has_value ())
1894+
break;
1895+
1896+
switch (event->status.kind ())
1897+
{
1898+
case TARGET_WAITKIND_EXITED:
1899+
case TARGET_WAITKIND_SIGNALLED:
1900+
return true;
1901+
case TARGET_WAITKIND_FORKED:
1902+
case TARGET_WAITKIND_VFORKED:
1903+
{
1904+
pid_t pid = event->status.child_ptid ().pid ();
1905+
fbsd_nat_debug_printf ("detaching from child %d", pid);
1906+
(void) ptrace (PT_DETACH, pid, (caddr_t) 1, 0);
1907+
}
1908+
break;
1909+
}
1910+
}
1911+
return false;
1912+
}
1913+
1914+
/* Scan all of the threads for a stopped process invoking the supplied
1915+
callback on the ptrace_lwpinfo object for threads other than the
1916+
thread which reported the current stop. The callback can return
1917+
true to terminate the iteration early. This function returns true
1918+
if the callback returned true, otherwise it returns false. */
1919+
1920+
typedef bool (ptrace_event_ftype) (const struct ptrace_lwpinfo &pl);
1921+
1922+
static bool
1923+
iterate_other_ptrace_events (pid_t pid,
1924+
gdb::function_view<ptrace_event_ftype> callback)
1925+
{
1926+
/* Fetch the LWP ID of the thread that just reported the last stop
1927+
and ignore that LWP in the following loop. */
1928+
ptrace_lwpinfo pl;
1929+
if (ptrace (PT_LWPINFO, pid, (caddr_t) &pl, sizeof (pl)) != 0)
1930+
perror_with_name (("ptrace (PT_LWPINFO)"));
1931+
lwpid_t lwpid = pl.pl_lwpid;
1932+
1933+
int nlwps = ptrace (PT_GETNUMLWPS, pid, NULL, 0);
1934+
if (nlwps == -1)
1935+
perror_with_name (("ptrace (PT_GETLWPLIST)"));
1936+
if (nlwps == 1)
1937+
return false;
1938+
1939+
gdb::unique_xmalloc_ptr<lwpid_t[]> lwps (XCNEWVEC (lwpid_t, nlwps));
1940+
1941+
nlwps = ptrace (PT_GETLWPLIST, pid, (caddr_t) lwps.get (), nlwps);
1942+
if (nlwps == -1)
1943+
perror_with_name (("ptrace (PT_GETLWPLIST)"));
1944+
1945+
for (int i = 0; i < nlwps; i++)
1946+
{
1947+
if (lwps[i] == lwpid)
1948+
continue;
1949+
1950+
if (ptrace (PT_LWPINFO, lwps[i], (caddr_t) &pl, sizeof (pl)) != 0)
1951+
perror_with_name (("ptrace (PT_LWPINFO)"));
1952+
1953+
if (callback (pl))
1954+
return true;
1955+
}
1956+
return false;
1957+
}
1958+
1959+
/* True if there are any stopped threads with an interesting event. */
1960+
1961+
static bool
1962+
pending_ptrace_events (inferior *inf)
1963+
{
1964+
auto lambda = [] (const struct ptrace_lwpinfo &pl)
1965+
{
1966+
#if defined(PT_LWP_EVENTS) && __FreeBSD_kernel_version < 1400090
1967+
if (pl.pl_flags == PL_FLAG_BORN)
1968+
return true;
1969+
#endif
1970+
#ifdef TDP_RFPPWAIT
1971+
if (pl.pl_flags & PL_FLAG_FORKED)
1972+
return true;
1973+
#endif
1974+
if (pl.pl_event == PL_EVENT_SIGNAL)
1975+
{
1976+
if ((pl.pl_flags & PL_FLAG_SI) == 0)
1977+
{
1978+
/* Not sure which signal, assume it matters. */
1979+
return true;
1980+
}
1981+
if (pl.pl_siginfo.si_signo == SIGTRAP)
1982+
return true;
1983+
}
1984+
return false;
1985+
};
1986+
return iterate_other_ptrace_events (inf->pid,
1987+
gdb::make_function_view (lambda));
1988+
}
1989+
1990+
void
1991+
fbsd_nat_target::detach (inferior *inf, int from_tty)
1992+
{
1993+
fbsd_nat_debug_start_end ("pid %d", inf->pid);
1994+
1995+
stop_process (inf);
1996+
1997+
remove_breakpoints_inf (inf);
1998+
1999+
if (detach_fork_children (inf)) {
2000+
/* No need to detach now. */
2001+
target_announce_detach (from_tty);
2002+
2003+
detach_success (inf);
2004+
return;
2005+
}
2006+
2007+
/* If there are any pending events (SIGSTOP from stop_process or a
2008+
breakpoint hit that needs a PC fixup), drain events until the
2009+
process can be safely detached. */
2010+
fbsd_inferior *fbsd_inf = get_fbsd_inferior (inf);
2011+
ptid_t ptid = ptid_t (inf->pid);
2012+
if (fbsd_inf->pending_sigstop || pending_ptrace_events (inf))
2013+
{
2014+
bool pending_sigstop = fbsd_inf->pending_sigstop;
2015+
int sig = 0;
2016+
2017+
if (pending_sigstop)
2018+
fbsd_nat_debug_printf ("waiting for SIGSTOP");
2019+
2020+
/* Force wait_1 to report the SIGSTOP instead of swallowing it. */
2021+
fbsd_inf->pending_sigstop = false;
2022+
2023+
/* Report event for all threads from wait_1. */
2024+
fbsd_inf->resumed_lwps = ptid;
2025+
2026+
do
2027+
{
2028+
if (ptrace (PT_CONTINUE, inf->pid, (caddr_t) 1, sig) != 0)
2029+
perror_with_name (("ptrace(PT_CONTINUE)"));
2030+
2031+
target_waitstatus ws;
2032+
ptid_t wptid = wait_1 (ptid, &ws, 0);
2033+
2034+
switch (ws.kind ())
2035+
{
2036+
case TARGET_WAITKIND_EXITED:
2037+
case TARGET_WAITKIND_SIGNALLED:
2038+
/* No need to detach now. */
2039+
target_announce_detach (from_tty);
2040+
2041+
detach_success (inf);
2042+
return;
2043+
case TARGET_WAITKIND_FORKED:
2044+
case TARGET_WAITKIND_VFORKED:
2045+
{
2046+
pid_t pid = ws.child_ptid ().pid ();
2047+
fbsd_nat_debug_printf ("detaching from child %d", pid);
2048+
(void) ptrace (PT_DETACH, pid, (caddr_t) 1, 0);
2049+
sig = 0;
2050+
}
2051+
break;
2052+
case TARGET_WAITKIND_STOPPED:
2053+
sig = gdb_signal_to_host (ws.sig ());
2054+
switch (sig)
2055+
{
2056+
case SIGSTOP:
2057+
if (pending_sigstop)
2058+
{
2059+
sig = 0;
2060+
pending_sigstop = false;
2061+
}
2062+
break;
2063+
case SIGTRAP:
2064+
#ifndef USE_SIGTRAP_SIGINFO
2065+
{
2066+
/* Update PC from software breakpoint hit. */
2067+
struct regcache *regcache = get_thread_regcache (this, wptid);
2068+
struct gdbarch *gdbarch = regcache->arch ();
2069+
int decr_pc = gdbarch_decr_pc_after_break (gdbarch);
2070+
2071+
if (decr_pc != 0)
2072+
{
2073+
CORE_ADDR pc;
2074+
2075+
pc = regcache_read_pc (regcache);
2076+
if (breakpoint_inserted_here_p (regcache->aspace (),
2077+
pc - decr_pc))
2078+
{
2079+
fbsd_nat_debug_printf ("adjusted PC for LWP %ld",
2080+
wptid.lwp ());
2081+
regcache_write_pc (regcache, pc - decr_pc);
2082+
}
2083+
}
2084+
}
2085+
#endif
2086+
sig = 0;
2087+
break;
2088+
}
2089+
}
2090+
}
2091+
while (pending_sigstop || pending_ptrace_events (inf));
2092+
}
2093+
2094+
target_announce_detach (from_tty);
2095+
2096+
if (ptrace (PT_DETACH, inf->pid, (caddr_t) 1, 0) == -1)
2097+
perror_with_name (("ptrace (PT_DETACH)"));
2098+
2099+
detach_success (inf);
2100+
}
2101+
18402102
void
18412103
fbsd_nat_target::mourn_inferior ()
18422104
{

gdb/fbsd-nat.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class fbsd_nat_target : public inf_ptrace_target
8181

8282
void attach (const char *, int) override;
8383

84+
void detach (inferior *, int) override;
85+
8486
void mourn_inferior () override;
8587

8688
void resume (ptid_t, int, enum gdb_signal) override;
@@ -263,6 +265,18 @@ class fbsd_nat_target : public inf_ptrace_target
263265
/* List of pending events. */
264266

265267
std::list<pending_event> m_pending_events;
268+
269+
/* If this thread has a pending fork event, there is a child process
270+
GDB is attached to that the core of GDB doesn't know about.
271+
Detach from it. */
272+
273+
void detach_fork_children (thread_info *tp);
274+
275+
/* Detach from any child processes associated with pending fork events
276+
for a stopped process. Returns true if the process has terminated
277+
and false if it is still alive. */
278+
279+
bool detach_fork_children (inferior *inf);
266280
};
267281

268282
/* Fetch the signal information for PTID and store it in *SIGINFO.

0 commit comments

Comments
 (0)