xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/netbsd-low.cc (revision bb15761eb435641d0c63854232729b2a51ed5f07)
1*bb15761eSchristos /* Copyright (C) 2020-2024 Free Software Foundation, Inc.
28dffb485Schristos 
38dffb485Schristos    This file is part of GDB.
48dffb485Schristos 
58dffb485Schristos    This program is free software; you can redistribute it and/or modify
68dffb485Schristos    it under the terms of the GNU General Public License as published by
78dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
88dffb485Schristos    (at your option) any later version.
98dffb485Schristos 
108dffb485Schristos    This program is distributed in the hope that it will be useful,
118dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
128dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
138dffb485Schristos    GNU General Public License for more details.
148dffb485Schristos 
158dffb485Schristos    You should have received a copy of the GNU General Public License
168dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
178dffb485Schristos 
188dffb485Schristos #include "target.h"
198dffb485Schristos #include "netbsd-low.h"
208dffb485Schristos #include "nat/netbsd-nat.h"
218dffb485Schristos 
228dffb485Schristos #include <sys/param.h>
238dffb485Schristos #include <sys/types.h>
248dffb485Schristos 
258dffb485Schristos #include <sys/ptrace.h>
268dffb485Schristos #include <sys/sysctl.h>
278dffb485Schristos 
288dffb485Schristos #include <limits.h>
298dffb485Schristos #include <unistd.h>
308dffb485Schristos #include <signal.h>
318dffb485Schristos 
328dffb485Schristos #include <elf.h>
338dffb485Schristos 
348dffb485Schristos #include <type_traits>
358dffb485Schristos 
368dffb485Schristos #include "gdbsupport/eintr.h"
378dffb485Schristos #include "gdbsupport/gdb_wait.h"
388dffb485Schristos #include "gdbsupport/filestuff.h"
398dffb485Schristos #include "gdbsupport/common-inferior.h"
408dffb485Schristos #include "nat/fork-inferior.h"
418dffb485Schristos #include "hostio.h"
428dffb485Schristos 
438dffb485Schristos int using_threads = 1;
448dffb485Schristos 
458dffb485Schristos /* Callback used by fork_inferior to start tracing the inferior.  */
468dffb485Schristos 
478dffb485Schristos static void
488dffb485Schristos netbsd_ptrace_fun ()
498dffb485Schristos {
508dffb485Schristos   /* Switch child to its own process group so that signals won't
518dffb485Schristos      directly affect GDBserver. */
528dffb485Schristos   if (setpgid (0, 0) < 0)
538dffb485Schristos     trace_start_error_with_name (("setpgid"));
548dffb485Schristos 
558dffb485Schristos   if (ptrace (PT_TRACE_ME, 0, nullptr, 0) < 0)
568dffb485Schristos     trace_start_error_with_name (("ptrace"));
578dffb485Schristos 
588dffb485Schristos   /* If GDBserver is connected to gdb via stdio, redirect the inferior's
598dffb485Schristos      stdout to stderr so that inferior i/o doesn't corrupt the connection.
608dffb485Schristos      Also, redirect stdin to /dev/null.  */
618dffb485Schristos   if (remote_connection_is_stdio ())
628dffb485Schristos     {
638dffb485Schristos       if (close (0) < 0)
648dffb485Schristos 	trace_start_error_with_name (("close"));
658dffb485Schristos       if (open ("/dev/null", O_RDONLY) < 0)
668dffb485Schristos 	trace_start_error_with_name (("open"));
678dffb485Schristos       if (dup2 (2, 1) < 0)
688dffb485Schristos 	trace_start_error_with_name (("dup2"));
698dffb485Schristos       if (write (2, "stdin/stdout redirected\n",
708dffb485Schristos 		 sizeof ("stdin/stdout redirected\n") - 1) < 0)
718dffb485Schristos 	{
728dffb485Schristos 	  /* Errors ignored.  */
738dffb485Schristos 	}
748dffb485Schristos     }
758dffb485Schristos }
768dffb485Schristos 
778dffb485Schristos /* Implement the create_inferior method of the target_ops vector.  */
788dffb485Schristos 
798dffb485Schristos int
808dffb485Schristos netbsd_process_target::create_inferior (const char *program,
818dffb485Schristos 					const std::vector<char *> &program_args)
828dffb485Schristos {
838dffb485Schristos   std::string str_program_args = construct_inferior_arguments (program_args);
848dffb485Schristos 
858dffb485Schristos   pid_t pid = fork_inferior (program, str_program_args.c_str (),
868dffb485Schristos 			     get_environ ()->envp (), netbsd_ptrace_fun,
878dffb485Schristos 			     nullptr, nullptr, nullptr, nullptr);
888dffb485Schristos 
894b169a6bSchristos   add_process (pid, 0);
908dffb485Schristos 
918dffb485Schristos   post_fork_inferior (pid, program);
928dffb485Schristos 
938dffb485Schristos   return pid;
948dffb485Schristos }
958dffb485Schristos 
968dffb485Schristos /* Implement the post_create_inferior target_ops method.  */
978dffb485Schristos 
988dffb485Schristos void
998dffb485Schristos netbsd_process_target::post_create_inferior ()
1008dffb485Schristos {
1018dffb485Schristos   pid_t pid = current_process ()->pid;
1028dffb485Schristos   netbsd_nat::enable_proc_events (pid);
1034b169a6bSchristos 
1044b169a6bSchristos   low_arch_setup ();
1058dffb485Schristos }
1068dffb485Schristos 
1078dffb485Schristos /* Implement the attach target_ops method.  */
1088dffb485Schristos 
1098dffb485Schristos int
1108dffb485Schristos netbsd_process_target::attach (unsigned long pid)
1118dffb485Schristos {
1128dffb485Schristos   /* Unimplemented.  */
1138dffb485Schristos   return -1;
1148dffb485Schristos }
1158dffb485Schristos 
1168dffb485Schristos /* Returns true if GDB is interested in any child syscalls.  */
1178dffb485Schristos 
1188dffb485Schristos static bool
1198dffb485Schristos gdb_catching_syscalls_p (pid_t pid)
1208dffb485Schristos {
1218dffb485Schristos   struct process_info *proc = find_process_pid (pid);
1228dffb485Schristos   return !proc->syscalls_to_catch.empty ();
1238dffb485Schristos }
1248dffb485Schristos 
1258dffb485Schristos /* Implement the resume target_ops method.  */
1268dffb485Schristos 
1278dffb485Schristos void
1288dffb485Schristos netbsd_process_target::resume (struct thread_resume *resume_info, size_t n)
1298dffb485Schristos {
1308dffb485Schristos   ptid_t resume_ptid = resume_info[0].thread;
1318dffb485Schristos   const int signal = resume_info[0].sig;
1328dffb485Schristos   const bool step = resume_info[0].kind == resume_step;
1338dffb485Schristos 
1348dffb485Schristos   if (resume_ptid == minus_one_ptid)
1358dffb485Schristos     resume_ptid = ptid_of (current_thread);
1368dffb485Schristos 
1378dffb485Schristos   const pid_t pid = resume_ptid.pid ();
1388dffb485Schristos   const lwpid_t lwp = resume_ptid.lwp ();
1398dffb485Schristos   regcache_invalidate_pid (pid);
1408dffb485Schristos 
1418dffb485Schristos   auto fn
1428dffb485Schristos     = [&] (ptid_t ptid)
1438dffb485Schristos       {
1448dffb485Schristos 	if (step)
1458dffb485Schristos 	  {
1468dffb485Schristos 	    if (ptid.lwp () == lwp || n != 1)
1478dffb485Schristos 	      {
1488dffb485Schristos 		if (ptrace (PT_SETSTEP, pid, NULL, ptid.lwp ()) == -1)
1498dffb485Schristos 		  perror_with_name (("ptrace"));
1508dffb485Schristos 		if (ptrace (PT_RESUME, pid, NULL, ptid.lwp ()) == -1)
1518dffb485Schristos 		  perror_with_name (("ptrace"));
1528dffb485Schristos 	      }
1538dffb485Schristos 	    else
1548dffb485Schristos 	      {
1558dffb485Schristos 		if (ptrace (PT_CLEARSTEP, pid, NULL, ptid.lwp ()) == -1)
1568dffb485Schristos 		  perror_with_name (("ptrace"));
1578dffb485Schristos 		if (ptrace (PT_SUSPEND, pid, NULL, ptid.lwp ()) == -1)
1588dffb485Schristos 		  perror_with_name (("ptrace"));
1598dffb485Schristos 	      }
1608dffb485Schristos 	  }
1618dffb485Schristos 	else
1628dffb485Schristos 	  {
1638dffb485Schristos 	    if (ptrace (PT_CLEARSTEP, pid, NULL, ptid.lwp ()) == -1)
1648dffb485Schristos 	      perror_with_name (("ptrace"));
1658dffb485Schristos 	    if (ptrace (PT_RESUME, pid, NULL, ptid.lwp ()) == -1)
1668dffb485Schristos 	      perror_with_name (("ptrace"));
1678dffb485Schristos 	  }
1688dffb485Schristos       };
1698dffb485Schristos 
1708dffb485Schristos   netbsd_nat::for_each_thread (pid, fn);
1718dffb485Schristos 
1728dffb485Schristos   int request = gdb_catching_syscalls_p (pid) ? PT_CONTINUE : PT_SYSCALL;
1738dffb485Schristos 
1748dffb485Schristos   errno = 0;
1758dffb485Schristos   ptrace (request, pid, (void *)1, signal);
1768dffb485Schristos   if (errno)
1778dffb485Schristos     perror_with_name (("ptrace"));
1788dffb485Schristos }
1798dffb485Schristos 
1808dffb485Schristos /* Returns true if GDB is interested in the reported SYSNO syscall.  */
1818dffb485Schristos 
1828dffb485Schristos static bool
1838dffb485Schristos netbsd_catch_this_syscall (int sysno)
1848dffb485Schristos {
1858dffb485Schristos   struct process_info *proc = current_process ();
1868dffb485Schristos 
1878dffb485Schristos   if (proc->syscalls_to_catch.empty ())
1888dffb485Schristos     return false;
1898dffb485Schristos 
1908dffb485Schristos   if (proc->syscalls_to_catch[0] == ANY_SYSCALL)
1918dffb485Schristos     return true;
1928dffb485Schristos 
1938dffb485Schristos   for (int iter : proc->syscalls_to_catch)
1948dffb485Schristos     if (iter == sysno)
1958dffb485Schristos       return true;
1968dffb485Schristos 
1978dffb485Schristos   return false;
1988dffb485Schristos }
1998dffb485Schristos 
2008dffb485Schristos /* Helper function for child_wait and the derivatives of child_wait.
2018dffb485Schristos    HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
2028dffb485Schristos    translation of that in OURSTATUS.  */
2038dffb485Schristos 
2048dffb485Schristos static void
2058dffb485Schristos netbsd_store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus)
2068dffb485Schristos {
2078dffb485Schristos   if (WIFEXITED (hoststatus))
2084b169a6bSchristos     ourstatus->set_exited (WEXITSTATUS (hoststatus));
2098dffb485Schristos   else if (!WIFSTOPPED (hoststatus))
2104b169a6bSchristos     ourstatus->set_signalled (gdb_signal_from_host (WTERMSIG (hoststatus)));
2118dffb485Schristos   else
2124b169a6bSchristos     ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (hoststatus)));
2138dffb485Schristos }
2148dffb485Schristos 
2158dffb485Schristos /* Implement a safe wrapper around waitpid().  */
2168dffb485Schristos 
2178dffb485Schristos static pid_t
2184b169a6bSchristos netbsd_waitpid (ptid_t ptid, struct target_waitstatus *ourstatus,
2194b169a6bSchristos 		target_wait_flags target_options)
2208dffb485Schristos {
2218dffb485Schristos   int status;
2224b169a6bSchristos   int options = (target_options & TARGET_WNOHANG) ? WNOHANG : 0;
2238dffb485Schristos 
2248dffb485Schristos   pid_t pid
2254b169a6bSchristos     = gdb::handle_eintr (-1, ::waitpid, ptid.pid (), &status, options);
2268dffb485Schristos 
2278dffb485Schristos   if (pid == -1)
2288dffb485Schristos     perror_with_name (_("Child process unexpectedly missing"));
2298dffb485Schristos 
2308dffb485Schristos   netbsd_store_waitstatus (ourstatus, status);
2318dffb485Schristos   return pid;
2328dffb485Schristos }
2338dffb485Schristos 
2348dffb485Schristos 
2358dffb485Schristos /* Implement the wait target_ops method.
2368dffb485Schristos 
2378dffb485Schristos    Wait for the child specified by PTID to do something.  Return the
2388dffb485Schristos    process ID of the child, or MINUS_ONE_PTID in case of error; store
2398dffb485Schristos    the status in *OURSTATUS.  */
2408dffb485Schristos 
2418dffb485Schristos static ptid_t
2428dffb485Schristos netbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus,
2434b169a6bSchristos 	     target_wait_flags target_options)
2448dffb485Schristos {
2458dffb485Schristos   pid_t pid = netbsd_waitpid (ptid, ourstatus, target_options);
2468dffb485Schristos   ptid_t wptid = ptid_t (pid);
2478dffb485Schristos 
2488dffb485Schristos   if (pid == 0)
2498dffb485Schristos     {
2508dffb485Schristos       gdb_assert (target_options & TARGET_WNOHANG);
2514b169a6bSchristos       ourstatus->set_ignore ();
2528dffb485Schristos       return null_ptid;
2538dffb485Schristos     }
2548dffb485Schristos 
2558dffb485Schristos   gdb_assert (pid != -1);
2568dffb485Schristos 
2578dffb485Schristos   /* If the child stopped, keep investigating its status.  */
2584b169a6bSchristos   if (ourstatus->kind () != TARGET_WAITKIND_STOPPED)
2598dffb485Schristos     return wptid;
2608dffb485Schristos 
2618dffb485Schristos   /* Extract the event and thread that received a signal.  */
2628dffb485Schristos   ptrace_siginfo_t psi;
2638dffb485Schristos   if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
2648dffb485Schristos     perror_with_name (("ptrace"));
2658dffb485Schristos 
2668dffb485Schristos   /* Pick child's siginfo_t.  */
2678dffb485Schristos   siginfo_t *si = &psi.psi_siginfo;
2688dffb485Schristos 
2698dffb485Schristos   lwpid_t lwp = psi.psi_lwpid;
2708dffb485Schristos 
2718dffb485Schristos   int signo = si->si_signo;
2728dffb485Schristos   const int code = si->si_code;
2738dffb485Schristos 
2748dffb485Schristos   /* Construct PTID with a specified thread that received the event.
2758dffb485Schristos      If a signal was targeted to the whole process, lwp is 0.  */
2768dffb485Schristos   wptid = ptid_t (pid, lwp, 0);
2778dffb485Schristos 
2788dffb485Schristos   /* Bail out on non-debugger oriented signals.  */
2798dffb485Schristos   if (signo != SIGTRAP)
2808dffb485Schristos     return wptid;
2818dffb485Schristos 
2828dffb485Schristos   /* Stop examining non-debugger oriented SIGTRAP codes.  */
2838dffb485Schristos   if (code <= SI_USER || code == SI_NOINFO)
2848dffb485Schristos     return wptid;
2858dffb485Schristos 
2868dffb485Schristos   /* Process state for threading events.  */
2878dffb485Schristos   ptrace_state_t pst = {};
2888dffb485Schristos   if (code == TRAP_LWP)
2898dffb485Schristos     if (ptrace (PT_GET_PROCESS_STATE, pid, &pst, sizeof (pst)) == -1)
2908dffb485Schristos       perror_with_name (("ptrace"));
2918dffb485Schristos 
2928dffb485Schristos   if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_EXIT)
2938dffb485Schristos     {
2948dffb485Schristos       /* If GDB attaches to a multi-threaded process, exiting
2958dffb485Schristos 	 threads might be skipped during post_attach that
2968dffb485Schristos 	 have not yet reported their PTRACE_LWP_EXIT event.
2978dffb485Schristos 	 Ignore exited events for an unknown LWP.  */
2988dffb485Schristos       thread_info *thr = find_thread_ptid (wptid);
2998dffb485Schristos       if (thr == nullptr)
3004b169a6bSchristos 	  ourstatus->set_spurious ();
3018dffb485Schristos       else
3028dffb485Schristos 	{
3038dffb485Schristos 	  /* NetBSD does not store an LWP exit status.  */
3044b169a6bSchristos 	  ourstatus->set_thread_exited (0);
3058dffb485Schristos 
3068dffb485Schristos 	  remove_thread (thr);
3078dffb485Schristos 	}
3088dffb485Schristos       return wptid;
3098dffb485Schristos     }
3108dffb485Schristos 
3118dffb485Schristos   if (find_thread_ptid (ptid_t (pid)))
3124b169a6bSchristos     switch_to_thread (find_thread_ptid (wptid));
3138dffb485Schristos 
3148dffb485Schristos   if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_CREATE)
3158dffb485Schristos     {
3168dffb485Schristos       /* If GDB attaches to a multi-threaded process, newborn
3178dffb485Schristos 	 threads might be added by nbsd_add_threads that have
3188dffb485Schristos 	 not yet reported their PTRACE_LWP_CREATE event.  Ignore
3198dffb485Schristos 	 born events for an already-known LWP.  */
3208dffb485Schristos       if (find_thread_ptid (wptid))
3214b169a6bSchristos 	ourstatus->set_spurious ();
3228dffb485Schristos       else
3238dffb485Schristos 	{
3248dffb485Schristos 	  add_thread (wptid, NULL);
3254b169a6bSchristos 	  ourstatus->set_thread_created ();
3268dffb485Schristos 	}
3278dffb485Schristos       return wptid;
3288dffb485Schristos     }
3298dffb485Schristos 
3308dffb485Schristos   if (code == TRAP_EXEC)
3318dffb485Schristos     {
3324b169a6bSchristos       ourstatus->set_execd
3334b169a6bSchristos 	(make_unique_xstrdup (netbsd_nat::pid_to_exec_file (pid)));
3348dffb485Schristos       return wptid;
3358dffb485Schristos     }
3368dffb485Schristos 
3378dffb485Schristos   if (code == TRAP_TRACE)
3388dffb485Schristos       return wptid;
3398dffb485Schristos 
3408dffb485Schristos   if (code == TRAP_SCE || code == TRAP_SCX)
3418dffb485Schristos     {
3428dffb485Schristos       int sysnum = si->si_sysnum;
3438dffb485Schristos 
3448dffb485Schristos       if (!netbsd_catch_this_syscall(sysnum))
3458dffb485Schristos 	{
3468dffb485Schristos 	  /* If the core isn't interested in this event, ignore it.  */
3474b169a6bSchristos 	  ourstatus->set_spurious ();
3488dffb485Schristos 	  return wptid;
3498dffb485Schristos 	}
3508dffb485Schristos 
3514b169a6bSchristos       if (code == TRAP_SCE)
3524b169a6bSchristos 	ourstatus->set_syscall_entry (sysnum);
3534b169a6bSchristos       else
3544b169a6bSchristos 	ourstatus->set_syscall_return (sysnum);
3554b169a6bSchristos 
3568dffb485Schristos       return wptid;
3578dffb485Schristos     }
3588dffb485Schristos 
3598dffb485Schristos   if (code == TRAP_BRKPT)
3608dffb485Schristos     {
3618dffb485Schristos #ifdef PTRACE_BREAKPOINT_ADJ
3628dffb485Schristos       CORE_ADDR pc;
3638dffb485Schristos       struct reg r;
3648dffb485Schristos       ptrace (PT_GETREGS, pid, &r, psi.psi_lwpid);
3658dffb485Schristos       pc = PTRACE_REG_PC (&r);
3668dffb485Schristos       PTRACE_REG_SET_PC (&r, pc - PTRACE_BREAKPOINT_ADJ);
3678dffb485Schristos       ptrace (PT_SETREGS, pid, &r, psi.psi_lwpid);
3688dffb485Schristos #endif
3698dffb485Schristos       return wptid;
3708dffb485Schristos     }
3718dffb485Schristos 
3728dffb485Schristos   /* Unclassified SIGTRAP event.  */
3734b169a6bSchristos   ourstatus->set_spurious ();
3748dffb485Schristos   return wptid;
3758dffb485Schristos }
3768dffb485Schristos 
3778dffb485Schristos /* Implement the wait target_ops method.  */
3788dffb485Schristos 
3798dffb485Schristos ptid_t
3808dffb485Schristos netbsd_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
3814b169a6bSchristos 			     target_wait_flags target_options)
3828dffb485Schristos {
3838dffb485Schristos   while (true)
3848dffb485Schristos     {
3858dffb485Schristos       ptid_t wptid = netbsd_wait (ptid, ourstatus, target_options);
3868dffb485Schristos 
3878dffb485Schristos       /* Register thread in the gdbcore if a thread was not reported earlier.
3888dffb485Schristos 	 This is required after ::create_inferior, when the gdbcore does not
3898dffb485Schristos 	 know about the first internal thread.
3908dffb485Schristos 	 This may also happen on attach, when an event is registered on a thread
3918dffb485Schristos 	 that was not fully initialized during the attach stage.  */
3928dffb485Schristos       if (wptid.lwp () != 0 && !find_thread_ptid (wptid)
3934b169a6bSchristos 	  && ourstatus->kind () != TARGET_WAITKIND_THREAD_EXITED)
3948dffb485Schristos 	add_thread (wptid, nullptr);
3958dffb485Schristos 
3964b169a6bSchristos       switch (ourstatus->kind ())
3978dffb485Schristos 	{
3988dffb485Schristos 	case TARGET_WAITKIND_EXITED:
3998dffb485Schristos 	case TARGET_WAITKIND_STOPPED:
4008dffb485Schristos 	case TARGET_WAITKIND_SIGNALLED:
4018dffb485Schristos 	case TARGET_WAITKIND_FORKED:
4028dffb485Schristos 	case TARGET_WAITKIND_VFORKED:
4038dffb485Schristos 	case TARGET_WAITKIND_EXECD:
4048dffb485Schristos 	case TARGET_WAITKIND_VFORK_DONE:
4058dffb485Schristos 	case TARGET_WAITKIND_SYSCALL_ENTRY:
4068dffb485Schristos 	case TARGET_WAITKIND_SYSCALL_RETURN:
4078dffb485Schristos 	  /* Pass the result to the generic code.  */
4088dffb485Schristos 	  return wptid;
4098dffb485Schristos 	case TARGET_WAITKIND_THREAD_CREATED:
4108dffb485Schristos 	case TARGET_WAITKIND_THREAD_EXITED:
4118dffb485Schristos 	  /* The core needlessly stops on these events.  */
412*bb15761eSchristos 	  [[fallthrough]];
4138dffb485Schristos 	case TARGET_WAITKIND_SPURIOUS:
4148dffb485Schristos 	  /* Spurious events are unhandled by the gdbserver core.  */
4158dffb485Schristos 	  if (ptrace (PT_CONTINUE, current_process ()->pid, (void *) 1, 0)
4168dffb485Schristos 	      == -1)
4178dffb485Schristos 	    perror_with_name (("ptrace"));
4188dffb485Schristos 	  break;
4198dffb485Schristos 	default:
4208dffb485Schristos 	  error (("Unknown stopped status"));
4218dffb485Schristos 	}
4228dffb485Schristos     }
4238dffb485Schristos }
4248dffb485Schristos 
4258dffb485Schristos /* Implement the kill target_ops method.  */
4268dffb485Schristos 
4278dffb485Schristos int
4288dffb485Schristos netbsd_process_target::kill (process_info *process)
4298dffb485Schristos {
4308dffb485Schristos   pid_t pid = process->pid;
4318dffb485Schristos   if (ptrace (PT_KILL, pid, nullptr, 0) == -1)
4328dffb485Schristos     return -1;
4338dffb485Schristos 
4348dffb485Schristos   int status;
4354b169a6bSchristos   if (gdb::handle_eintr (-1, ::waitpid, pid, &status, 0) == -1)
4368dffb485Schristos     return -1;
4378dffb485Schristos   mourn (process);
4388dffb485Schristos   return 0;
4398dffb485Schristos }
4408dffb485Schristos 
4418dffb485Schristos /* Implement the detach target_ops method.  */
4428dffb485Schristos 
4438dffb485Schristos int
4448dffb485Schristos netbsd_process_target::detach (process_info *process)
4458dffb485Schristos {
4468dffb485Schristos   pid_t pid = process->pid;
4478dffb485Schristos 
4488dffb485Schristos   ptrace (PT_DETACH, pid, (void *) 1, 0);
4498dffb485Schristos   mourn (process);
4508dffb485Schristos   return 0;
4518dffb485Schristos }
4528dffb485Schristos 
4538dffb485Schristos /* Implement the mourn target_ops method.  */
4548dffb485Schristos 
4558dffb485Schristos void
4568dffb485Schristos netbsd_process_target::mourn (struct process_info *proc)
4578dffb485Schristos {
4588dffb485Schristos   for_each_thread (proc->pid, remove_thread);
4598dffb485Schristos 
4608dffb485Schristos   remove_process (proc);
4618dffb485Schristos }
4628dffb485Schristos 
4638dffb485Schristos /* Implement the join target_ops method.  */
4648dffb485Schristos 
4658dffb485Schristos void
4668dffb485Schristos netbsd_process_target::join (int pid)
4678dffb485Schristos {
4688dffb485Schristos   /* The PT_DETACH is sufficient to detach from the process.
4698dffb485Schristos      So no need to do anything extra.  */
4708dffb485Schristos }
4718dffb485Schristos 
4728dffb485Schristos /* Implement the thread_alive target_ops method.  */
4738dffb485Schristos 
4748dffb485Schristos bool
4758dffb485Schristos netbsd_process_target::thread_alive (ptid_t ptid)
4768dffb485Schristos {
4778dffb485Schristos   return netbsd_nat::thread_alive (ptid);
4788dffb485Schristos }
4798dffb485Schristos 
4808dffb485Schristos /* Implement the fetch_registers target_ops method.  */
4818dffb485Schristos 
4828dffb485Schristos void
4838dffb485Schristos netbsd_process_target::fetch_registers (struct regcache *regcache, int regno)
4848dffb485Schristos {
4854b169a6bSchristos   const netbsd_regset_info *regset = get_regs_info ();
4868dffb485Schristos   ptid_t inferior_ptid = ptid_of (current_thread);
4878dffb485Schristos 
4888dffb485Schristos   while (regset->size >= 0)
4898dffb485Schristos     {
4908dffb485Schristos       std::vector<char> buf;
4918dffb485Schristos       buf.resize (regset->size);
4928dffb485Schristos       int res = ptrace (regset->get_request, inferior_ptid.pid (), buf.data (),
4938dffb485Schristos 			inferior_ptid.lwp ());
4948dffb485Schristos       if (res == -1)
4958dffb485Schristos 	perror_with_name (("ptrace"));
4968dffb485Schristos       regset->store_function (regcache, buf.data ());
4978dffb485Schristos       regset++;
4988dffb485Schristos     }
4998dffb485Schristos }
5008dffb485Schristos 
5018dffb485Schristos /* Implement the store_registers target_ops method.  */
5028dffb485Schristos 
5038dffb485Schristos void
5048dffb485Schristos netbsd_process_target::store_registers (struct regcache *regcache, int regno)
5058dffb485Schristos {
5064b169a6bSchristos   const netbsd_regset_info *regset = get_regs_info ();
5078dffb485Schristos   ptid_t inferior_ptid = ptid_of (current_thread);
5088dffb485Schristos 
5098dffb485Schristos   while (regset->size >= 0)
5108dffb485Schristos     {
5118dffb485Schristos       std::vector<char> buf;
5128dffb485Schristos       buf.resize (regset->size);
5138dffb485Schristos       int res = ptrace (regset->get_request, inferior_ptid.pid (), buf.data (),
5148dffb485Schristos 			inferior_ptid.lwp ());
5158dffb485Schristos       if (res == -1)
5168dffb485Schristos 	perror_with_name (("ptrace"));
5178dffb485Schristos 
5188dffb485Schristos       /* Then overlay our cached registers on that.  */
5198dffb485Schristos       regset->fill_function (regcache, buf.data ());
5208dffb485Schristos       /* Only now do we write the register set.  */
5218dffb485Schristos       res = ptrace (regset->set_request, inferior_ptid.pid (), buf. data (),
5228dffb485Schristos 		    inferior_ptid.lwp ());
5238dffb485Schristos       if (res == -1)
5248dffb485Schristos 	perror_with_name (("ptrace"));
5258dffb485Schristos       regset++;
5268dffb485Schristos     }
5278dffb485Schristos }
5288dffb485Schristos 
5298dffb485Schristos /* Implement the read_memory target_ops method.  */
5308dffb485Schristos 
5318dffb485Schristos int
5328dffb485Schristos netbsd_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr,
5338dffb485Schristos 				    int size)
5348dffb485Schristos {
5358dffb485Schristos   pid_t pid = current_process ()->pid;
5364b169a6bSchristos   return netbsd_nat::read_memory (pid, myaddr, memaddr, size, nullptr);
5378dffb485Schristos }
5388dffb485Schristos 
5398dffb485Schristos /* Implement the write_memory target_ops method.  */
5408dffb485Schristos 
5418dffb485Schristos int
5428dffb485Schristos netbsd_process_target::write_memory (CORE_ADDR memaddr,
5438dffb485Schristos 				     const unsigned char *myaddr, int size)
5448dffb485Schristos {
5458dffb485Schristos   pid_t pid = current_process ()->pid;
5464b169a6bSchristos   return netbsd_nat::write_memory (pid, myaddr, memaddr, size, nullptr);
5478dffb485Schristos }
5488dffb485Schristos 
5498dffb485Schristos /* Implement the request_interrupt target_ops method.  */
5508dffb485Schristos 
5518dffb485Schristos void
5528dffb485Schristos netbsd_process_target::request_interrupt ()
5538dffb485Schristos {
5548dffb485Schristos   ptid_t inferior_ptid = ptid_of (get_first_thread ());
5558dffb485Schristos 
5568dffb485Schristos   ::kill (inferior_ptid.pid (), SIGINT);
5578dffb485Schristos }
5588dffb485Schristos 
5598dffb485Schristos /* Read the AUX Vector for the specified PID, wrapping the ptrace(2) call
5608dffb485Schristos    with the PIOD_READ_AUXV operation and using the PT_IO standard input
5618dffb485Schristos    and output arguments.  */
5628dffb485Schristos 
5638dffb485Schristos static size_t
5648dffb485Schristos netbsd_read_auxv(pid_t pid, void *offs, void *addr, size_t len)
5658dffb485Schristos {
5668dffb485Schristos   struct ptrace_io_desc pio;
5678dffb485Schristos 
5688dffb485Schristos   pio.piod_op = PIOD_READ_AUXV;
5698dffb485Schristos   pio.piod_offs = offs;
5708dffb485Schristos   pio.piod_addr = addr;
5718dffb485Schristos   pio.piod_len = len;
5728dffb485Schristos 
5738dffb485Schristos   if (ptrace (PT_IO, pid, &pio, 0) == -1)
5748dffb485Schristos     perror_with_name (("ptrace"));
5758dffb485Schristos 
5768dffb485Schristos   return pio.piod_len;
5778dffb485Schristos }
5788dffb485Schristos 
5798dffb485Schristos /* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
5808dffb485Schristos    to debugger memory starting at MYADDR.  */
5818dffb485Schristos 
5828dffb485Schristos int
583*bb15761eSchristos netbsd_process_target::read_auxv (int pid, CORE_ADDR offset,
5848dffb485Schristos 				  unsigned char *myaddr, unsigned int len)
5858dffb485Schristos {
5868dffb485Schristos   return netbsd_read_auxv (pid, (void *) (intptr_t) offset, myaddr, len);
5878dffb485Schristos }
5888dffb485Schristos 
5898dffb485Schristos bool
5908dffb485Schristos netbsd_process_target::supports_z_point_type (char z_type)
5918dffb485Schristos {
5928dffb485Schristos   switch (z_type)
5938dffb485Schristos     {
5948dffb485Schristos     case Z_PACKET_SW_BP:
5958dffb485Schristos       return true;
5968dffb485Schristos     case Z_PACKET_HW_BP:
5978dffb485Schristos     case Z_PACKET_WRITE_WP:
5988dffb485Schristos     case Z_PACKET_READ_WP:
5998dffb485Schristos     case Z_PACKET_ACCESS_WP:
6008dffb485Schristos     default:
6018dffb485Schristos       return false; /* Not supported.  */
6028dffb485Schristos     }
6038dffb485Schristos }
6048dffb485Schristos 
6058dffb485Schristos /* Insert {break/watch}point at address ADDR.  SIZE is not used.  */
6068dffb485Schristos 
6078dffb485Schristos int
6088dffb485Schristos netbsd_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
6098dffb485Schristos 		     int size, struct raw_breakpoint *bp)
6108dffb485Schristos {
6118dffb485Schristos   switch (type)
6128dffb485Schristos     {
6138dffb485Schristos     case raw_bkpt_type_sw:
6148dffb485Schristos       return insert_memory_breakpoint (bp);
6158dffb485Schristos     case raw_bkpt_type_hw:
6168dffb485Schristos     case raw_bkpt_type_write_wp:
6178dffb485Schristos     case raw_bkpt_type_read_wp:
6188dffb485Schristos     case raw_bkpt_type_access_wp:
6198dffb485Schristos     default:
6208dffb485Schristos       return 1; /* Not supported.  */
6218dffb485Schristos     }
6228dffb485Schristos }
6238dffb485Schristos 
6248dffb485Schristos /* Remove {break/watch}point at address ADDR.  SIZE is not used.  */
6258dffb485Schristos 
6268dffb485Schristos int
6278dffb485Schristos netbsd_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
6288dffb485Schristos 				     int size, struct raw_breakpoint *bp)
6298dffb485Schristos {
6308dffb485Schristos   switch (type)
6318dffb485Schristos     {
6328dffb485Schristos     case raw_bkpt_type_sw:
6338dffb485Schristos       return remove_memory_breakpoint (bp);
6348dffb485Schristos     case raw_bkpt_type_hw:
6358dffb485Schristos     case raw_bkpt_type_write_wp:
6368dffb485Schristos     case raw_bkpt_type_read_wp:
6378dffb485Schristos     case raw_bkpt_type_access_wp:
6388dffb485Schristos     default:
6398dffb485Schristos       return 1; /* Not supported.  */
6408dffb485Schristos     }
6418dffb485Schristos }
6428dffb485Schristos 
6438dffb485Schristos /* Implement the stopped_by_sw_breakpoint target_ops method.  */
6448dffb485Schristos 
6458dffb485Schristos bool
6468dffb485Schristos netbsd_process_target::stopped_by_sw_breakpoint ()
6478dffb485Schristos {
6488dffb485Schristos   ptrace_siginfo_t psi;
6498dffb485Schristos   pid_t pid = current_process ()->pid;
6508dffb485Schristos 
6518dffb485Schristos   if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1)
6528dffb485Schristos     perror_with_name (("ptrace"));
6538dffb485Schristos 
6548dffb485Schristos   return psi.psi_siginfo.si_signo == SIGTRAP &&
6558dffb485Schristos 	 psi.psi_siginfo.si_code == TRAP_BRKPT;
6568dffb485Schristos }
6578dffb485Schristos 
6588dffb485Schristos /* Implement the supports_stopped_by_sw_breakpoint target_ops method.  */
6598dffb485Schristos 
6608dffb485Schristos bool
6618dffb485Schristos netbsd_process_target::supports_stopped_by_sw_breakpoint ()
6628dffb485Schristos {
6638dffb485Schristos   return true;
6648dffb485Schristos }
6658dffb485Schristos 
6668dffb485Schristos /* Implement the supports_qxfer_siginfo target_ops method.  */
6678dffb485Schristos 
6688dffb485Schristos bool
6698dffb485Schristos netbsd_process_target::supports_qxfer_siginfo ()
6708dffb485Schristos {
6718dffb485Schristos   return true;
6728dffb485Schristos }
6738dffb485Schristos 
6748dffb485Schristos /* Implement the qxfer_siginfo target_ops method.  */
6758dffb485Schristos 
6768dffb485Schristos int
6778dffb485Schristos netbsd_process_target::qxfer_siginfo (const char *annex, unsigned char *readbuf,
6788dffb485Schristos 				      unsigned const char *writebuf,
6798dffb485Schristos 				      CORE_ADDR offset, int len)
6808dffb485Schristos {
6818dffb485Schristos   if (current_thread == nullptr)
6828dffb485Schristos     return -1;
6838dffb485Schristos 
6848dffb485Schristos   pid_t pid = current_process ()->pid;
6858dffb485Schristos 
6868dffb485Schristos   return netbsd_nat::qxfer_siginfo(pid, annex, readbuf, writebuf, offset, len);
6878dffb485Schristos }
6888dffb485Schristos 
6898dffb485Schristos /* Implement the supports_non_stop target_ops method.  */
6908dffb485Schristos 
6918dffb485Schristos bool
6928dffb485Schristos netbsd_process_target::supports_non_stop ()
6938dffb485Schristos {
6948dffb485Schristos   return false;
6958dffb485Schristos }
6968dffb485Schristos 
6978dffb485Schristos /* Implement the supports_multi_process target_ops method.  */
6988dffb485Schristos 
6998dffb485Schristos bool
7008dffb485Schristos netbsd_process_target::supports_multi_process ()
7018dffb485Schristos {
7028dffb485Schristos   return true;
7038dffb485Schristos }
7048dffb485Schristos 
7058dffb485Schristos /* Check if fork events are supported.  */
7068dffb485Schristos 
7078dffb485Schristos bool
7088dffb485Schristos netbsd_process_target::supports_fork_events ()
7098dffb485Schristos {
7108dffb485Schristos   return false;
7118dffb485Schristos }
7128dffb485Schristos 
7138dffb485Schristos /* Check if vfork events are supported.  */
7148dffb485Schristos 
7158dffb485Schristos bool
7168dffb485Schristos netbsd_process_target::supports_vfork_events ()
7178dffb485Schristos {
7188dffb485Schristos   return false;
7198dffb485Schristos }
7208dffb485Schristos 
7218dffb485Schristos /* Check if exec events are supported.  */
7228dffb485Schristos 
7238dffb485Schristos bool
7248dffb485Schristos netbsd_process_target::supports_exec_events ()
7258dffb485Schristos {
7268dffb485Schristos   return true;
7278dffb485Schristos }
7288dffb485Schristos 
7298dffb485Schristos /* Implement the supports_disable_randomization target_ops method.  */
7308dffb485Schristos 
7318dffb485Schristos bool
7328dffb485Schristos netbsd_process_target::supports_disable_randomization ()
7338dffb485Schristos {
7348dffb485Schristos   return false;
7358dffb485Schristos }
7368dffb485Schristos 
7378dffb485Schristos /* Extract &phdr and num_phdr in the inferior.  Return 0 on success.  */
7388dffb485Schristos 
7398dffb485Schristos template <typename T>
7408dffb485Schristos int get_phdr_phnum_from_proc_auxv (const pid_t pid,
7418dffb485Schristos 				   CORE_ADDR *phdr_memaddr, int *num_phdr)
7428dffb485Schristos {
7438dffb485Schristos   typedef typename std::conditional<sizeof(T) == sizeof(int64_t),
7448dffb485Schristos 				    Aux64Info, Aux32Info>::type auxv_type;
7458dffb485Schristos   const size_t auxv_size = sizeof (auxv_type);
7468dffb485Schristos   const size_t auxv_buf_size = 128 * sizeof (auxv_type);
7478dffb485Schristos 
7488dffb485Schristos   std::vector<char> auxv_buf;
7498dffb485Schristos   auxv_buf.resize (auxv_buf_size);
7508dffb485Schristos 
7518dffb485Schristos   netbsd_read_auxv (pid, nullptr, auxv_buf.data (), auxv_buf_size);
7528dffb485Schristos 
7538dffb485Schristos   *phdr_memaddr = 0;
7548dffb485Schristos   *num_phdr = 0;
7558dffb485Schristos 
7568dffb485Schristos   for (char *buf = auxv_buf.data ();
7578dffb485Schristos        buf < (auxv_buf.data () + auxv_buf_size);
7588dffb485Schristos        buf += auxv_size)
7598dffb485Schristos     {
7608dffb485Schristos       auxv_type *const aux = (auxv_type *) buf;
7618dffb485Schristos 
7628dffb485Schristos       switch (aux->a_type)
7638dffb485Schristos 	{
7648dffb485Schristos 	case AT_PHDR:
7658dffb485Schristos 	  *phdr_memaddr = aux->a_v;
7668dffb485Schristos 	  break;
7678dffb485Schristos 	case AT_PHNUM:
7688dffb485Schristos 	  *num_phdr = aux->a_v;
7698dffb485Schristos 	  break;
7708dffb485Schristos 	}
7718dffb485Schristos 
7728dffb485Schristos       if (*phdr_memaddr != 0 && *num_phdr != 0)
7738dffb485Schristos 	break;
7748dffb485Schristos     }
7758dffb485Schristos 
7768dffb485Schristos   if (*phdr_memaddr == 0 || *num_phdr == 0)
7778dffb485Schristos     {
7788dffb485Schristos       warning ("Unexpected missing AT_PHDR and/or AT_PHNUM: "
7798dffb485Schristos 	       "phdr_memaddr = %s, phdr_num = %d",
7808dffb485Schristos 	       core_addr_to_string (*phdr_memaddr), *num_phdr);
7818dffb485Schristos       return 2;
7828dffb485Schristos     }
7838dffb485Schristos 
7848dffb485Schristos   return 0;
7858dffb485Schristos }
7868dffb485Schristos 
7878dffb485Schristos /* Return &_DYNAMIC (via PT_DYNAMIC) in the inferior, or 0 if not present.  */
7888dffb485Schristos 
7898dffb485Schristos template <typename T>
7908dffb485Schristos static CORE_ADDR
7914b169a6bSchristos get_dynamic (const pid_t pid)
7928dffb485Schristos {
7938dffb485Schristos   typedef typename std::conditional<sizeof(T) == sizeof(int64_t),
7948dffb485Schristos 				    Elf64_Phdr, Elf32_Phdr>::type phdr_type;
7958dffb485Schristos   const int phdr_size = sizeof (phdr_type);
7968dffb485Schristos 
7978dffb485Schristos   CORE_ADDR phdr_memaddr;
7988dffb485Schristos   int num_phdr;
7998dffb485Schristos   if (get_phdr_phnum_from_proc_auxv<T> (pid, &phdr_memaddr, &num_phdr))
8008dffb485Schristos     return 0;
8018dffb485Schristos 
8028dffb485Schristos   std::vector<unsigned char> phdr_buf;
8038dffb485Schristos   phdr_buf.resize (num_phdr * phdr_size);
8048dffb485Schristos 
8054b169a6bSchristos   if (netbsd_nat::read_memory (pid, phdr_buf.data (), phdr_memaddr,
8064b169a6bSchristos 			       phdr_buf.size (), nullptr))
8078dffb485Schristos     return 0;
8088dffb485Schristos 
8098dffb485Schristos   /* Compute relocation: it is expected to be 0 for "regular" executables,
8108dffb485Schristos      non-zero for PIE ones.  */
8118dffb485Schristos   CORE_ADDR relocation = -1;
8128dffb485Schristos   for (int i = 0; relocation == -1 && i < num_phdr; i++)
8138dffb485Schristos     {
8148dffb485Schristos       phdr_type *const p = (phdr_type *) (phdr_buf.data () + i * phdr_size);
8158dffb485Schristos 
8168dffb485Schristos       if (p->p_type == PT_PHDR)
8178dffb485Schristos 	relocation = phdr_memaddr - p->p_vaddr;
8188dffb485Schristos     }
8198dffb485Schristos 
8208dffb485Schristos   if (relocation == -1)
8218dffb485Schristos     {
8228dffb485Schristos       /* PT_PHDR is optional, but necessary for PIE in general.  Fortunately
8238dffb485Schristos 	 any real world executables, including PIE executables, have always
8248dffb485Schristos 	 PT_PHDR present.  PT_PHDR is not present in some shared libraries or
8258dffb485Schristos 	 in fpc (Free Pascal 2.4) binaries but neither of those have a need for
8268dffb485Schristos 	 or present DT_DEBUG anyway (fpc binaries are statically linked).
8278dffb485Schristos 
8288dffb485Schristos 	 Therefore if there exists DT_DEBUG there is always also PT_PHDR.
8298dffb485Schristos 
8308dffb485Schristos 	 GDB could find RELOCATION also from AT_ENTRY - e_entry.  */
8318dffb485Schristos 
8328dffb485Schristos       return 0;
8338dffb485Schristos     }
8348dffb485Schristos 
8358dffb485Schristos   for (int i = 0; i < num_phdr; i++)
8368dffb485Schristos     {
8378dffb485Schristos       phdr_type *const p = (phdr_type *) (phdr_buf.data () + i * phdr_size);
8388dffb485Schristos 
8398dffb485Schristos       if (p->p_type == PT_DYNAMIC)
8408dffb485Schristos 	return p->p_vaddr + relocation;
8418dffb485Schristos     }
8428dffb485Schristos 
8438dffb485Schristos   return 0;
8448dffb485Schristos }
8458dffb485Schristos 
8468dffb485Schristos /* Return &_r_debug in the inferior, or -1 if not present.  Return value
8478dffb485Schristos    can be 0 if the inferior does not yet have the library list initialized.
8488dffb485Schristos    We look for DT_MIPS_RLD_MAP first.  MIPS executables use this instead of
8498dffb485Schristos    DT_DEBUG, although they sometimes contain an unused DT_DEBUG entry too.  */
8508dffb485Schristos 
8518dffb485Schristos template <typename T>
8528dffb485Schristos static CORE_ADDR
8534b169a6bSchristos get_r_debug (const pid_t pid)
8548dffb485Schristos {
8558dffb485Schristos   typedef typename std::conditional<sizeof(T) == sizeof(int64_t),
8568dffb485Schristos 				    Elf64_Dyn, Elf32_Dyn>::type dyn_type;
8578dffb485Schristos   const int dyn_size = sizeof (dyn_type);
8588dffb485Schristos   unsigned char buf[sizeof (dyn_type)];  /* The larger of the two.  */
8598dffb485Schristos   CORE_ADDR map = -1;
8608dffb485Schristos 
8614b169a6bSchristos   CORE_ADDR dynamic_memaddr = get_dynamic<T> (pid);
8628dffb485Schristos   if (dynamic_memaddr == 0)
8638dffb485Schristos     return map;
8648dffb485Schristos 
8654b169a6bSchristos   while (netbsd_nat::read_memory (pid, buf, dynamic_memaddr, dyn_size, nullptr)
8664b169a6bSchristos 	 == 0)
8678dffb485Schristos     {
8688dffb485Schristos       dyn_type *const dyn = (dyn_type *) buf;
8698dffb485Schristos #if defined DT_MIPS_RLD_MAP
8708dffb485Schristos       union
8718dffb485Schristos       {
8728dffb485Schristos 	T map;
8738dffb485Schristos 	unsigned char buf[sizeof (T)];
8748dffb485Schristos       }
8758dffb485Schristos       rld_map;
8768dffb485Schristos 
8778dffb485Schristos       if (dyn->d_tag == DT_MIPS_RLD_MAP)
8788dffb485Schristos 	{
8794b169a6bSchristos 	  if (netbsd_nat::read_memory (pid, rld_map.buf, dyn->d_un.d_val,
8804b169a6bSchristos 				       sizeof (rld_map.buf), nullptr) == 0)
8818dffb485Schristos 	    return rld_map.map;
8828dffb485Schristos 	  else
8838dffb485Schristos 	    break;
8848dffb485Schristos 	}
8858dffb485Schristos #endif  /* DT_MIPS_RLD_MAP */
8868dffb485Schristos 
8878dffb485Schristos       if (dyn->d_tag == DT_DEBUG && map == -1)
8888dffb485Schristos 	map = dyn->d_un.d_val;
8898dffb485Schristos 
8908dffb485Schristos       if (dyn->d_tag == DT_NULL)
8918dffb485Schristos 	break;
8928dffb485Schristos 
8938dffb485Schristos       dynamic_memaddr += dyn_size;
8948dffb485Schristos     }
8958dffb485Schristos 
8968dffb485Schristos   return map;
8978dffb485Schristos }
8988dffb485Schristos 
8998dffb485Schristos /* Read one pointer from MEMADDR in the inferior.  */
9008dffb485Schristos 
9018dffb485Schristos static int
9024b169a6bSchristos read_one_ptr (const pid_t pid, CORE_ADDR memaddr, CORE_ADDR *ptr, int ptr_size)
9038dffb485Schristos {
9048dffb485Schristos   /* Go through a union so this works on either big or little endian
9058dffb485Schristos      hosts, when the inferior's pointer size is smaller than the size
9068dffb485Schristos      of CORE_ADDR.  It is assumed the inferior's endianness is the
9078dffb485Schristos      same of the superior's.  */
9088dffb485Schristos 
9098dffb485Schristos   union
9108dffb485Schristos   {
9118dffb485Schristos     CORE_ADDR core_addr;
9128dffb485Schristos     unsigned int ui;
9138dffb485Schristos     unsigned char uc;
9148dffb485Schristos   } addr;
9158dffb485Schristos 
9164b169a6bSchristos   int ret = netbsd_nat::read_memory (pid, &addr.uc, memaddr, ptr_size, nullptr);
9178dffb485Schristos   if (ret == 0)
9188dffb485Schristos     {
9198dffb485Schristos       if (ptr_size == sizeof (CORE_ADDR))
9208dffb485Schristos 	*ptr = addr.core_addr;
9218dffb485Schristos       else if (ptr_size == sizeof (unsigned int))
9228dffb485Schristos 	*ptr = addr.ui;
9238dffb485Schristos       else
9248dffb485Schristos 	gdb_assert_not_reached ("unhandled pointer size");
9258dffb485Schristos     }
9268dffb485Schristos   return ret;
9278dffb485Schristos }
9288dffb485Schristos 
9298dffb485Schristos /* Construct qXfer:libraries-svr4:read reply.  */
9308dffb485Schristos 
9318dffb485Schristos template <typename T>
9328dffb485Schristos int
9334b169a6bSchristos netbsd_qxfer_libraries_svr4 (const pid_t pid, const char *annex,
9348dffb485Schristos 			     unsigned char *readbuf,
9358dffb485Schristos 			     unsigned const char *writebuf,
9368dffb485Schristos 			     CORE_ADDR offset, int len)
9378dffb485Schristos {
9388dffb485Schristos   struct link_map_offsets
9398dffb485Schristos   {
9408dffb485Schristos     /* Offset and size of r_debug.r_version.  */
9418dffb485Schristos     int r_version_offset;
9428dffb485Schristos 
9438dffb485Schristos     /* Offset and size of r_debug.r_map.  */
9448dffb485Schristos     int r_map_offset;
9458dffb485Schristos 
9468dffb485Schristos     /* Offset to l_addr field in struct link_map.  */
9478dffb485Schristos     int l_addr_offset;
9488dffb485Schristos 
9498dffb485Schristos     /* Offset to l_name field in struct link_map.  */
9508dffb485Schristos     int l_name_offset;
9518dffb485Schristos 
9528dffb485Schristos     /* Offset to l_ld field in struct link_map.  */
9538dffb485Schristos     int l_ld_offset;
9548dffb485Schristos 
9558dffb485Schristos     /* Offset to l_next field in struct link_map.  */
9568dffb485Schristos     int l_next_offset;
9578dffb485Schristos 
9588dffb485Schristos     /* Offset to l_prev field in struct link_map.  */
9598dffb485Schristos     int l_prev_offset;
9608dffb485Schristos   };
9618dffb485Schristos 
9628dffb485Schristos   static const struct link_map_offsets lmo_32bit_offsets =
9638dffb485Schristos     {
9648dffb485Schristos       0,     /* r_version offset. */
9658dffb485Schristos       4,     /* r_debug.r_map offset.  */
9668dffb485Schristos       0,     /* l_addr offset in link_map.  */
9678dffb485Schristos       4,     /* l_name offset in link_map.  */
9688dffb485Schristos       8,     /* l_ld offset in link_map.  */
9698dffb485Schristos       12,    /* l_next offset in link_map.  */
9708dffb485Schristos       16     /* l_prev offset in link_map.  */
9718dffb485Schristos     };
9728dffb485Schristos 
9738dffb485Schristos   static const struct link_map_offsets lmo_64bit_offsets =
9748dffb485Schristos     {
9758dffb485Schristos       0,     /* r_version offset. */
9768dffb485Schristos       8,     /* r_debug.r_map offset.  */
9778dffb485Schristos       0,     /* l_addr offset in link_map.  */
9788dffb485Schristos       8,     /* l_name offset in link_map.  */
9798dffb485Schristos       16,    /* l_ld offset in link_map.  */
9808dffb485Schristos       24,    /* l_next offset in link_map.  */
9818dffb485Schristos       32     /* l_prev offset in link_map.  */
9828dffb485Schristos     };
9838dffb485Schristos 
9848dffb485Schristos   CORE_ADDR lm_addr = 0, lm_prev = 0;
9858dffb485Schristos   CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev;
9868dffb485Schristos   int header_done = 0;
9878dffb485Schristos 
9888dffb485Schristos   const struct link_map_offsets *lmo
9898dffb485Schristos     = ((sizeof (T) == sizeof (int64_t))
9908dffb485Schristos        ? &lmo_64bit_offsets : &lmo_32bit_offsets);
9918dffb485Schristos   int ptr_size = sizeof (T);
9928dffb485Schristos 
9938dffb485Schristos   while (annex[0] != '\0')
9948dffb485Schristos     {
9958dffb485Schristos       const char *sep = strchr (annex, '=');
9968dffb485Schristos       if (sep == nullptr)
9978dffb485Schristos 	break;
9988dffb485Schristos 
9998dffb485Schristos       int name_len = sep - annex;
10008dffb485Schristos       CORE_ADDR *addrp;
10018dffb485Schristos       if (name_len == 5 && startswith (annex, "start"))
10028dffb485Schristos 	addrp = &lm_addr;
10038dffb485Schristos       else if (name_len == 4 && startswith (annex, "prev"))
10048dffb485Schristos 	addrp = &lm_prev;
10058dffb485Schristos       else
10068dffb485Schristos 	{
10078dffb485Schristos 	  annex = strchr (sep, ';');
10088dffb485Schristos 	  if (annex == nullptr)
10098dffb485Schristos 	    break;
10108dffb485Schristos 	  annex++;
10118dffb485Schristos 	  continue;
10128dffb485Schristos 	}
10138dffb485Schristos 
10148dffb485Schristos       annex = decode_address_to_semicolon (addrp, sep + 1);
10158dffb485Schristos     }
10168dffb485Schristos 
10178dffb485Schristos   if (lm_addr == 0)
10188dffb485Schristos     {
10194b169a6bSchristos       CORE_ADDR r_debug = get_r_debug<T> (pid);
10208dffb485Schristos 
10218dffb485Schristos       /* We failed to find DT_DEBUG.  Such situation will not change
10228dffb485Schristos 	 for this inferior - do not retry it.  Report it to GDB as
10238dffb485Schristos 	 E01, see for the reasons at the GDB solib-svr4.c side.  */
10248dffb485Schristos       if (r_debug == (CORE_ADDR) -1)
10258dffb485Schristos 	return -1;
10268dffb485Schristos 
10278dffb485Schristos       if (r_debug != 0)
10288dffb485Schristos 	{
10298dffb485Schristos 	  CORE_ADDR map_offset = r_debug + lmo->r_map_offset;
10304b169a6bSchristos 	  if (read_one_ptr (pid, map_offset, &lm_addr, ptr_size) != 0)
10318dffb485Schristos 	    warning ("unable to read r_map from %s",
10328dffb485Schristos 		     core_addr_to_string (map_offset));
10338dffb485Schristos 	}
10348dffb485Schristos     }
10358dffb485Schristos 
10368dffb485Schristos   std::string document = "<library-list-svr4 version=\"1.0\"";
10378dffb485Schristos 
10388dffb485Schristos   while (lm_addr
10394b169a6bSchristos 	 && read_one_ptr (pid, lm_addr + lmo->l_name_offset,
10408dffb485Schristos 			  &l_name, ptr_size) == 0
10414b169a6bSchristos 	 && read_one_ptr (pid, lm_addr + lmo->l_addr_offset,
10428dffb485Schristos 			  &l_addr, ptr_size) == 0
10434b169a6bSchristos 	 && read_one_ptr (pid, lm_addr + lmo->l_ld_offset,
10448dffb485Schristos 			  &l_ld, ptr_size) == 0
10454b169a6bSchristos 	 && read_one_ptr (pid, lm_addr + lmo->l_prev_offset,
10468dffb485Schristos 			  &l_prev, ptr_size) == 0
10474b169a6bSchristos 	 && read_one_ptr (pid, lm_addr + lmo->l_next_offset,
10488dffb485Schristos 			  &l_next, ptr_size) == 0)
10498dffb485Schristos     {
10508dffb485Schristos       if (lm_prev != l_prev)
10518dffb485Schristos 	{
10528dffb485Schristos 	  warning ("Corrupted shared library list: 0x%lx != 0x%lx",
10538dffb485Schristos 		   (long) lm_prev, (long) l_prev);
10548dffb485Schristos 	  break;
10558dffb485Schristos 	}
10568dffb485Schristos 
10578dffb485Schristos       /* Ignore the first entry even if it has valid name as the first entry
10588dffb485Schristos 	 corresponds to the main executable.  The first entry should not be
10598dffb485Schristos 	 skipped if the dynamic loader was loaded late by a static executable
10608dffb485Schristos 	 (see solib-svr4.c parameter ignore_first).  But in such case the main
10618dffb485Schristos 	 executable does not have PT_DYNAMIC present and this function already
10628dffb485Schristos 	 exited above due to failed get_r_debug.  */
10638dffb485Schristos       if (lm_prev == 0)
10648dffb485Schristos 	string_appendf (document, " main-lm=\"0x%lx\"",
10658dffb485Schristos 			(unsigned long) lm_addr);
10668dffb485Schristos       else
10678dffb485Schristos 	{
10688dffb485Schristos 	  unsigned char libname[PATH_MAX];
10698dffb485Schristos 
10708dffb485Schristos 	  /* Not checking for error because reading may stop before
10718dffb485Schristos 	     we've got PATH_MAX worth of characters.  */
10728dffb485Schristos 	  libname[0] = '\0';
10734b169a6bSchristos 	  netbsd_nat::read_memory (pid, libname, l_name, sizeof (libname) - 1,
10744b169a6bSchristos 				   nullptr);
10758dffb485Schristos 	  libname[sizeof (libname) - 1] = '\0';
10768dffb485Schristos 	  if (libname[0] != '\0')
10778dffb485Schristos 	    {
10788dffb485Schristos 	      if (!header_done)
10798dffb485Schristos 		{
10808dffb485Schristos 		  /* Terminate `<library-list-svr4'.  */
10818dffb485Schristos 		  document += '>';
10828dffb485Schristos 		  header_done = 1;
10838dffb485Schristos 		}
10848dffb485Schristos 
10858dffb485Schristos 	      string_appendf (document, "<library name=\"");
10864b169a6bSchristos 	      xml_escape_text_append (document, (char *) libname);
10878dffb485Schristos 	      string_appendf (document, "\" lm=\"0x%lx\" "
10888dffb485Schristos 			      "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
10898dffb485Schristos 			      (unsigned long) lm_addr, (unsigned long) l_addr,
10908dffb485Schristos 			      (unsigned long) l_ld);
10918dffb485Schristos 	    }
10928dffb485Schristos 	}
10938dffb485Schristos 
10948dffb485Schristos       lm_prev = lm_addr;
10958dffb485Schristos       lm_addr = l_next;
10968dffb485Schristos     }
10978dffb485Schristos 
10988dffb485Schristos   if (!header_done)
10998dffb485Schristos     {
11008dffb485Schristos       /* Empty list; terminate `<library-list-svr4'.  */
11018dffb485Schristos       document += "/>";
11028dffb485Schristos     }
11038dffb485Schristos   else
11048dffb485Schristos     document += "</library-list-svr4>";
11058dffb485Schristos 
11068dffb485Schristos   int document_len = document.length ();
11078dffb485Schristos   if (offset < document_len)
11088dffb485Schristos     document_len -= offset;
11098dffb485Schristos   else
11108dffb485Schristos     document_len = 0;
11118dffb485Schristos   if (len > document_len)
11128dffb485Schristos     len = document_len;
11138dffb485Schristos 
11148dffb485Schristos   memcpy (readbuf, document.data () + offset, len);
11158dffb485Schristos 
11168dffb485Schristos   return len;
11178dffb485Schristos }
11188dffb485Schristos 
11198dffb485Schristos /* Return true if FILE is a 64-bit ELF file,
11208dffb485Schristos    false if the file is not a 64-bit ELF file,
11218dffb485Schristos    and error if the file is not accessible or doesn't exist.  */
11228dffb485Schristos 
11238dffb485Schristos static bool
11248dffb485Schristos elf_64_file_p (const char *file)
11258dffb485Schristos {
11264b169a6bSchristos   int fd = gdb::handle_eintr (-1, ::open, file, O_RDONLY);
11278dffb485Schristos   if (fd < 0)
11288dffb485Schristos     perror_with_name (("open"));
11298dffb485Schristos 
11308dffb485Schristos   Elf64_Ehdr header;
11314b169a6bSchristos   ssize_t ret = gdb::handle_eintr (-1, ::read, fd, &header, sizeof (header));
11328dffb485Schristos   if (ret == -1)
11338dffb485Schristos     perror_with_name (("read"));
11344b169a6bSchristos   gdb::handle_eintr (-1, ::close, fd);
11358dffb485Schristos   if (ret != sizeof (header))
11368dffb485Schristos     error ("Cannot read ELF file header: %s", file);
11378dffb485Schristos 
11388dffb485Schristos   if (header.e_ident[EI_MAG0] != ELFMAG0
11398dffb485Schristos       || header.e_ident[EI_MAG1] != ELFMAG1
11408dffb485Schristos       || header.e_ident[EI_MAG2] != ELFMAG2
11418dffb485Schristos       || header.e_ident[EI_MAG3] != ELFMAG3)
11428dffb485Schristos     error ("Unrecognized ELF file header: %s", file);
11438dffb485Schristos 
11448dffb485Schristos   return header.e_ident[EI_CLASS] == ELFCLASS64;
11458dffb485Schristos }
11468dffb485Schristos 
11478dffb485Schristos /* Construct qXfer:libraries-svr4:read reply.  */
11488dffb485Schristos 
11498dffb485Schristos int
11508dffb485Schristos netbsd_process_target::qxfer_libraries_svr4 (const char *annex,
11518dffb485Schristos 					     unsigned char *readbuf,
11528dffb485Schristos 					     unsigned const char *writebuf,
11538dffb485Schristos 					     CORE_ADDR offset, int len)
11548dffb485Schristos {
11558dffb485Schristos   if (writebuf != nullptr)
11568dffb485Schristos     return -2;
11578dffb485Schristos   if (readbuf == nullptr)
11588dffb485Schristos     return -1;
11598dffb485Schristos 
11608dffb485Schristos   struct process_info *proc = current_process ();
11618dffb485Schristos   pid_t pid = proc->pid;
11628dffb485Schristos   bool is_elf64 = elf_64_file_p (netbsd_nat::pid_to_exec_file (pid));
11638dffb485Schristos 
11648dffb485Schristos   if (is_elf64)
11654b169a6bSchristos     return netbsd_qxfer_libraries_svr4<int64_t> (pid, annex, readbuf,
11668dffb485Schristos 						 writebuf, offset, len);
11678dffb485Schristos   else
11684b169a6bSchristos     return netbsd_qxfer_libraries_svr4<int32_t> (pid, annex, readbuf,
11698dffb485Schristos 						 writebuf, offset, len);
11708dffb485Schristos }
11718dffb485Schristos 
11728dffb485Schristos /* Implement the supports_qxfer_libraries_svr4 target_ops method.  */
11738dffb485Schristos 
11748dffb485Schristos bool
11758dffb485Schristos netbsd_process_target::supports_qxfer_libraries_svr4 ()
11768dffb485Schristos {
11778dffb485Schristos   return true;
11788dffb485Schristos }
11798dffb485Schristos 
11808dffb485Schristos /* Return the name of a file that can be opened to get the symbols for
11818dffb485Schristos    the child process identified by PID.  */
11828dffb485Schristos 
11834b169a6bSchristos const char *
11848dffb485Schristos netbsd_process_target::pid_to_exec_file (pid_t pid)
11858dffb485Schristos {
11864b169a6bSchristos   return netbsd_nat::pid_to_exec_file (pid);
11878dffb485Schristos }
11888dffb485Schristos 
11898dffb485Schristos /* Implementation of the target_ops method "supports_pid_to_exec_file".  */
11908dffb485Schristos 
11918dffb485Schristos bool
11928dffb485Schristos netbsd_process_target::supports_pid_to_exec_file ()
11938dffb485Schristos {
11948dffb485Schristos   return true;
11958dffb485Schristos }
11968dffb485Schristos 
11978dffb485Schristos /* Implementation of the target_ops method "supports_hardware_single_step".  */
11988dffb485Schristos bool
11998dffb485Schristos netbsd_process_target::supports_hardware_single_step ()
12008dffb485Schristos {
12018dffb485Schristos   return true;
12028dffb485Schristos }
12038dffb485Schristos 
12048dffb485Schristos /* Implementation of the target_ops method "sw_breakpoint_from_kind".  */
12058dffb485Schristos 
12068dffb485Schristos const gdb_byte *
12078dffb485Schristos netbsd_process_target::sw_breakpoint_from_kind (int kind, int *size)
12088dffb485Schristos {
12098dffb485Schristos   static gdb_byte brkpt[PTRACE_BREAKPOINT_SIZE] = {*PTRACE_BREAKPOINT};
12108dffb485Schristos 
12118dffb485Schristos   *size = PTRACE_BREAKPOINT_SIZE;
12128dffb485Schristos 
12138dffb485Schristos   return brkpt;
12148dffb485Schristos }
12158dffb485Schristos 
12168dffb485Schristos /* Implement the thread_name target_ops method.  */
12178dffb485Schristos 
12188dffb485Schristos const char *
12198dffb485Schristos netbsd_process_target::thread_name (ptid_t ptid)
12208dffb485Schristos {
12218dffb485Schristos   return netbsd_nat::thread_name (ptid);
12228dffb485Schristos }
12238dffb485Schristos 
12248dffb485Schristos /* Implement the supports_catch_syscall target_ops method.  */
12258dffb485Schristos 
12268dffb485Schristos bool
12278dffb485Schristos netbsd_process_target::supports_catch_syscall ()
12288dffb485Schristos {
12298dffb485Schristos   return true;
12308dffb485Schristos }
12318dffb485Schristos 
12328dffb485Schristos /* Implement the supports_read_auxv target_ops method.  */
12338dffb485Schristos 
12348dffb485Schristos bool
12358dffb485Schristos netbsd_process_target::supports_read_auxv ()
12368dffb485Schristos {
12378dffb485Schristos   return true;
12388dffb485Schristos }
12398dffb485Schristos 
12408dffb485Schristos void
12418dffb485Schristos initialize_low ()
12428dffb485Schristos {
12434b169a6bSchristos   set_target_ops (the_netbsd_target);
12448dffb485Schristos }
1245