xref: /netbsd-src/external/gpl3/gdb/dist/gdbsupport/agent.cc (revision 889f3bb010ad20d396fb291b89f202288dac2c87)
18dffb485Schristos /* Shared utility routines for GDB to interact with agent.
28dffb485Schristos 
3*889f3bb0Schristos    Copyright (C) 2009-2024 Free Software Foundation, Inc.
48dffb485Schristos 
58dffb485Schristos    This file is part of GDB.
68dffb485Schristos 
78dffb485Schristos    This program is free software; you can redistribute it and/or modify
88dffb485Schristos    it under the terms of the GNU General Public License as published by
98dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
108dffb485Schristos    (at your option) any later version.
118dffb485Schristos 
128dffb485Schristos    This program is distributed in the hope that it will be useful,
138dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
148dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
158dffb485Schristos    GNU General Public License for more details.
168dffb485Schristos 
178dffb485Schristos    You should have received a copy of the GNU General Public License
188dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
198dffb485Schristos 
208dffb485Schristos #include "target/target.h"
218dffb485Schristos #include "gdbsupport/symbol.h"
228dffb485Schristos #include <unistd.h>
238dffb485Schristos #include "filestuff.h"
248dffb485Schristos 
258dffb485Schristos #define IPA_SYM_STRUCT_NAME ipa_sym_addresses_common
268dffb485Schristos #include "agent.h"
278dffb485Schristos 
288dffb485Schristos bool debug_agent = false;
298dffb485Schristos 
308dffb485Schristos /* A stdarg wrapper for debug_vprintf.  */
318dffb485Schristos 
328dffb485Schristos static void ATTRIBUTE_PRINTF (1, 2)
338dffb485Schristos debug_agent_printf (const char *fmt, ...)
348dffb485Schristos {
358dffb485Schristos   va_list ap;
368dffb485Schristos 
378dffb485Schristos   if (!debug_agent)
388dffb485Schristos     return;
398dffb485Schristos   va_start (ap, fmt);
408dffb485Schristos   debug_vprintf (fmt, ap);
418dffb485Schristos   va_end (ap);
428dffb485Schristos }
438dffb485Schristos 
448dffb485Schristos #define DEBUG_AGENT debug_agent_printf
458dffb485Schristos 
468dffb485Schristos /* Global flag to determine using agent or not.  */
478dffb485Schristos bool use_agent = false;
488dffb485Schristos 
498dffb485Schristos /* Addresses of in-process agent's symbols both GDB and GDBserver cares
508dffb485Schristos    about.  */
518dffb485Schristos 
528dffb485Schristos struct ipa_sym_addresses_common
538dffb485Schristos {
548dffb485Schristos   CORE_ADDR addr_helper_thread_id;
558dffb485Schristos   CORE_ADDR addr_cmd_buf;
568dffb485Schristos   CORE_ADDR addr_capability;
578dffb485Schristos };
588dffb485Schristos 
598dffb485Schristos /* Cache of the helper thread id.  FIXME: this global should be made
608dffb485Schristos    per-process.  */
618dffb485Schristos static uint32_t helper_thread_id = 0;
628dffb485Schristos 
638dffb485Schristos static struct
648dffb485Schristos {
658dffb485Schristos   const char *name;
668dffb485Schristos   int offset;
678dffb485Schristos } symbol_list[] = {
688dffb485Schristos   IPA_SYM(helper_thread_id),
698dffb485Schristos   IPA_SYM(cmd_buf),
708dffb485Schristos   IPA_SYM(capability),
718dffb485Schristos };
728dffb485Schristos 
738dffb485Schristos static struct ipa_sym_addresses_common ipa_sym_addrs;
748dffb485Schristos 
758dffb485Schristos static bool all_agent_symbols_looked_up = false;
768dffb485Schristos 
778dffb485Schristos bool
788dffb485Schristos agent_loaded_p (void)
798dffb485Schristos {
808dffb485Schristos   return all_agent_symbols_looked_up;
818dffb485Schristos }
828dffb485Schristos 
838dffb485Schristos /* Look up all symbols needed by agent.  Return 0 if all the symbols are
848dffb485Schristos    found, return non-zero otherwise.  */
858dffb485Schristos 
868dffb485Schristos int
878dffb485Schristos agent_look_up_symbols (void *arg)
888dffb485Schristos {
898dffb485Schristos   all_agent_symbols_looked_up = false;
908dffb485Schristos 
918dffb485Schristos   for (int i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
928dffb485Schristos     {
938dffb485Schristos       CORE_ADDR *addrp =
948dffb485Schristos 	(CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset);
958dffb485Schristos       struct objfile *objfile = (struct objfile *) arg;
968dffb485Schristos 
978dffb485Schristos       if (find_minimal_symbol_address (symbol_list[i].name, addrp,
988dffb485Schristos 				       objfile) != 0)
998dffb485Schristos 	{
1008dffb485Schristos 	  DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
1018dffb485Schristos 	  return -1;
1028dffb485Schristos 	}
1038dffb485Schristos     }
1048dffb485Schristos 
1058dffb485Schristos   all_agent_symbols_looked_up = true;
1068dffb485Schristos   return 0;
1078dffb485Schristos }
1088dffb485Schristos 
1098dffb485Schristos static unsigned int
1108dffb485Schristos agent_get_helper_thread_id (void)
1118dffb485Schristos {
1128dffb485Schristos   if  (helper_thread_id == 0)
1138dffb485Schristos     {
1148dffb485Schristos       if (target_read_uint32 (ipa_sym_addrs.addr_helper_thread_id,
1158dffb485Schristos 			      &helper_thread_id))
1168dffb485Schristos 	warning (_("Error reading helper thread's id in lib"));
1178dffb485Schristos     }
1188dffb485Schristos 
1198dffb485Schristos   return helper_thread_id;
1208dffb485Schristos }
1218dffb485Schristos 
1228dffb485Schristos #ifdef HAVE_SYS_UN_H
1238dffb485Schristos #include <sys/socket.h>
1248dffb485Schristos #include <sys/un.h>
1258dffb485Schristos #define SOCK_DIR P_tmpdir
1268dffb485Schristos 
1278dffb485Schristos #ifndef UNIX_PATH_MAX
1288dffb485Schristos #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
1298dffb485Schristos #endif
1308dffb485Schristos 
1318dffb485Schristos #endif
1328dffb485Schristos 
1338dffb485Schristos /* Connects to synchronization socket.  PID is the pid of inferior, which is
1348dffb485Schristos    used to set up the connection socket.  */
1358dffb485Schristos 
1368dffb485Schristos static int
1378dffb485Schristos gdb_connect_sync_socket (int pid)
1388dffb485Schristos {
1398dffb485Schristos #ifdef HAVE_SYS_UN_H
140cc2fb388Skamil   struct sockaddr_un addr = {};
1418dffb485Schristos   int res, fd;
1428dffb485Schristos   char path[UNIX_PATH_MAX];
1438dffb485Schristos 
1448dffb485Schristos   res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid);
1458dffb485Schristos   if (res >= UNIX_PATH_MAX)
1468dffb485Schristos     return -1;
1478dffb485Schristos 
1488dffb485Schristos   res = fd = gdb_socket_cloexec (PF_UNIX, SOCK_STREAM, 0);
1498dffb485Schristos   if (res == -1)
1508dffb485Schristos     {
1518dffb485Schristos       warning (_("error opening sync socket: %s"), safe_strerror (errno));
1528dffb485Schristos       return -1;
1538dffb485Schristos     }
1548dffb485Schristos 
1558dffb485Schristos   addr.sun_family = AF_UNIX;
1568dffb485Schristos 
1578dffb485Schristos   res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
1588dffb485Schristos   if (res >= UNIX_PATH_MAX)
1598dffb485Schristos     {
1608dffb485Schristos       warning (_("string overflow allocating socket name"));
1618dffb485Schristos       close (fd);
1628dffb485Schristos       return -1;
1638dffb485Schristos     }
1648dffb485Schristos 
1658dffb485Schristos   res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
1668dffb485Schristos   if (res == -1)
1678dffb485Schristos     {
1688dffb485Schristos       warning (_("error connecting sync socket (%s): %s. "
1698dffb485Schristos 		 "Make sure the directory exists and that it is writable."),
1708dffb485Schristos 		 path, safe_strerror (errno));
1718dffb485Schristos       close (fd);
1728dffb485Schristos       return -1;
1738dffb485Schristos     }
1748dffb485Schristos 
1758dffb485Schristos   return fd;
1768dffb485Schristos #else
1778dffb485Schristos   return -1;
1788dffb485Schristos #endif
1798dffb485Schristos }
1808dffb485Schristos 
181*889f3bb0Schristos /* Execute an agent command in the inferior.  PID is the value of pid
182*889f3bb0Schristos    of the inferior.  CMD is the buffer for command.  It is assumed to
183*889f3bb0Schristos    be at least IPA_CMD_BUF_SIZE bytes long.  GDB or GDBserver will
184*889f3bb0Schristos    store the command into it and fetch the return result from CMD.
185*889f3bb0Schristos    The interaction between GDB/GDBserver and the agent is synchronized
186*889f3bb0Schristos    by a synchronization socket.  Return zero if success, otherwise
187*889f3bb0Schristos    return non-zero.  */
1888dffb485Schristos 
1898dffb485Schristos int
190*889f3bb0Schristos agent_run_command (int pid, char *cmd, int len)
1918dffb485Schristos {
1928dffb485Schristos   int fd;
1938dffb485Schristos   int tid = agent_get_helper_thread_id ();
194924795e6Schristos   ptid_t ptid = ptid_t (pid, tid);
1958dffb485Schristos 
1968dffb485Schristos   int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf,
1978dffb485Schristos 				 (gdb_byte *) cmd, len);
1988dffb485Schristos 
1998dffb485Schristos   if (ret != 0)
2008dffb485Schristos     {
2018dffb485Schristos       warning (_("unable to write"));
2028dffb485Schristos       return -1;
2038dffb485Schristos     }
2048dffb485Schristos 
2058dffb485Schristos   DEBUG_AGENT ("agent: resumed helper thread\n");
2068dffb485Schristos 
2078dffb485Schristos   /* Resume helper thread.  */
2088dffb485Schristos   target_continue_no_signal (ptid);
2098dffb485Schristos 
2108dffb485Schristos   fd = gdb_connect_sync_socket (pid);
2118dffb485Schristos   if (fd >= 0)
2128dffb485Schristos     {
2138dffb485Schristos       char buf[1] = "";
2148dffb485Schristos 
2158dffb485Schristos       DEBUG_AGENT ("agent: signalling helper thread\n");
2168dffb485Schristos 
2178dffb485Schristos       do
2188dffb485Schristos 	{
2198dffb485Schristos 	  ret = write (fd, buf, 1);
2208dffb485Schristos 	} while (ret == -1 && errno == EINTR);
2218dffb485Schristos 
2228dffb485Schristos 	DEBUG_AGENT ("agent: waiting for helper thread's response\n");
2238dffb485Schristos 
2248dffb485Schristos       do
2258dffb485Schristos 	{
2268dffb485Schristos 	  ret = read (fd, buf, 1);
2278dffb485Schristos 	} while (ret == -1 && errno == EINTR);
2288dffb485Schristos 
2298dffb485Schristos       close (fd);
2308dffb485Schristos 
2318dffb485Schristos       DEBUG_AGENT ("agent: helper thread's response received\n");
2328dffb485Schristos     }
2338dffb485Schristos   else
2348dffb485Schristos     return -1;
2358dffb485Schristos 
2368dffb485Schristos   /* Need to read response with the inferior stopped.  */
2378dffb485Schristos   if (ptid != null_ptid)
2388dffb485Schristos     {
2398dffb485Schristos       /* Stop thread PTID.  */
2408dffb485Schristos       DEBUG_AGENT ("agent: stop helper thread\n");
2418dffb485Schristos       target_stop_and_wait (ptid);
2428dffb485Schristos     }
2438dffb485Schristos 
2448dffb485Schristos   if (fd >= 0)
2458dffb485Schristos     {
2468dffb485Schristos       if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
2478dffb485Schristos 			      IPA_CMD_BUF_SIZE))
2488dffb485Schristos 	{
2498dffb485Schristos 	  warning (_("Error reading command response"));
2508dffb485Schristos 	  return -1;
2518dffb485Schristos 	}
2528dffb485Schristos     }
2538dffb485Schristos 
2548dffb485Schristos   return 0;
2558dffb485Schristos }
2568dffb485Schristos 
2578dffb485Schristos /* Each bit of it stands for a capability of agent.  */
2588dffb485Schristos static uint32_t agent_capability = 0;
2598dffb485Schristos 
2608dffb485Schristos /* Return true if agent has capability AGENT_CAP, otherwise return false.  */
2618dffb485Schristos 
2628dffb485Schristos bool
2638dffb485Schristos agent_capability_check (enum agent_capa agent_capa)
2648dffb485Schristos {
2658dffb485Schristos   if (agent_capability == 0)
2668dffb485Schristos     {
2678dffb485Schristos       if (target_read_uint32 (ipa_sym_addrs.addr_capability,
2688dffb485Schristos 			      &agent_capability))
2698dffb485Schristos 	warning (_("Error reading capability of agent"));
2708dffb485Schristos     }
2718dffb485Schristos   return (agent_capability & agent_capa) != 0;
2728dffb485Schristos }
2738dffb485Schristos 
2748dffb485Schristos /* Invalidate the cache of agent capability, so we'll read it from inferior
2758dffb485Schristos    again.  Call it when launches a new program or reconnect to remote stub.  */
2768dffb485Schristos 
2778dffb485Schristos void
2788dffb485Schristos agent_capability_invalidate (void)
2798dffb485Schristos {
2808dffb485Schristos   agent_capability = 0;
2818dffb485Schristos }
282