11424dfb3Schristos /* Shared utility routines for GDB to interact with agent.
21424dfb3Schristos 
31424dfb3Schristos    Copyright (C) 2009-2020 Free Software Foundation, Inc.
41424dfb3Schristos 
51424dfb3Schristos    This file is part of GDB.
61424dfb3Schristos 
71424dfb3Schristos    This program is free software; you can redistribute it and/or modify
81424dfb3Schristos    it under the terms of the GNU General Public License as published by
91424dfb3Schristos    the Free Software Foundation; either version 3 of the License, or
101424dfb3Schristos    (at your option) any later version.
111424dfb3Schristos 
121424dfb3Schristos    This program is distributed in the hope that it will be useful,
131424dfb3Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
141424dfb3Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151424dfb3Schristos    GNU General Public License for more details.
161424dfb3Schristos 
171424dfb3Schristos    You should have received a copy of the GNU General Public License
181424dfb3Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
191424dfb3Schristos 
201424dfb3Schristos #include "common-defs.h"
211424dfb3Schristos #include "target/target.h"
221424dfb3Schristos #include "gdbsupport/symbol.h"
231424dfb3Schristos #include <unistd.h>
241424dfb3Schristos #include "filestuff.h"
251424dfb3Schristos 
261424dfb3Schristos #define IPA_SYM_STRUCT_NAME ipa_sym_addresses_common
271424dfb3Schristos #include "agent.h"
281424dfb3Schristos 
291424dfb3Schristos bool debug_agent = false;
301424dfb3Schristos 
311424dfb3Schristos /* A stdarg wrapper for debug_vprintf.  */
321424dfb3Schristos 
331424dfb3Schristos static void ATTRIBUTE_PRINTF (1, 2)
debug_agent_printf(const char * fmt,...)341424dfb3Schristos debug_agent_printf (const char *fmt, ...)
351424dfb3Schristos {
361424dfb3Schristos   va_list ap;
371424dfb3Schristos 
381424dfb3Schristos   if (!debug_agent)
391424dfb3Schristos     return;
401424dfb3Schristos   va_start (ap, fmt);
411424dfb3Schristos   debug_vprintf (fmt, ap);
421424dfb3Schristos   va_end (ap);
431424dfb3Schristos }
441424dfb3Schristos 
451424dfb3Schristos #define DEBUG_AGENT debug_agent_printf
461424dfb3Schristos 
471424dfb3Schristos /* Global flag to determine using agent or not.  */
481424dfb3Schristos bool use_agent = false;
491424dfb3Schristos 
501424dfb3Schristos /* Addresses of in-process agent's symbols both GDB and GDBserver cares
511424dfb3Schristos    about.  */
521424dfb3Schristos 
531424dfb3Schristos struct ipa_sym_addresses_common
541424dfb3Schristos {
551424dfb3Schristos   CORE_ADDR addr_helper_thread_id;
561424dfb3Schristos   CORE_ADDR addr_cmd_buf;
571424dfb3Schristos   CORE_ADDR addr_capability;
581424dfb3Schristos };
591424dfb3Schristos 
601424dfb3Schristos /* Cache of the helper thread id.  FIXME: this global should be made
611424dfb3Schristos    per-process.  */
621424dfb3Schristos static uint32_t helper_thread_id = 0;
631424dfb3Schristos 
641424dfb3Schristos static struct
651424dfb3Schristos {
661424dfb3Schristos   const char *name;
671424dfb3Schristos   int offset;
681424dfb3Schristos } symbol_list[] = {
691424dfb3Schristos   IPA_SYM(helper_thread_id),
701424dfb3Schristos   IPA_SYM(cmd_buf),
711424dfb3Schristos   IPA_SYM(capability),
721424dfb3Schristos };
731424dfb3Schristos 
741424dfb3Schristos static struct ipa_sym_addresses_common ipa_sym_addrs;
751424dfb3Schristos 
761424dfb3Schristos static bool all_agent_symbols_looked_up = false;
771424dfb3Schristos 
781424dfb3Schristos bool
agent_loaded_p(void)791424dfb3Schristos agent_loaded_p (void)
801424dfb3Schristos {
811424dfb3Schristos   return all_agent_symbols_looked_up;
821424dfb3Schristos }
831424dfb3Schristos 
841424dfb3Schristos /* Look up all symbols needed by agent.  Return 0 if all the symbols are
851424dfb3Schristos    found, return non-zero otherwise.  */
861424dfb3Schristos 
871424dfb3Schristos int
agent_look_up_symbols(void * arg)881424dfb3Schristos agent_look_up_symbols (void *arg)
891424dfb3Schristos {
901424dfb3Schristos   all_agent_symbols_looked_up = false;
911424dfb3Schristos 
921424dfb3Schristos   for (int i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
931424dfb3Schristos     {
941424dfb3Schristos       CORE_ADDR *addrp =
951424dfb3Schristos 	(CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset);
961424dfb3Schristos       struct objfile *objfile = (struct objfile *) arg;
971424dfb3Schristos 
981424dfb3Schristos       if (find_minimal_symbol_address (symbol_list[i].name, addrp,
991424dfb3Schristos 				       objfile) != 0)
1001424dfb3Schristos 	{
1011424dfb3Schristos 	  DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
1021424dfb3Schristos 	  return -1;
1031424dfb3Schristos 	}
1041424dfb3Schristos     }
1051424dfb3Schristos 
1061424dfb3Schristos   all_agent_symbols_looked_up = true;
1071424dfb3Schristos   return 0;
1081424dfb3Schristos }
1091424dfb3Schristos 
1101424dfb3Schristos static unsigned int
agent_get_helper_thread_id(void)1111424dfb3Schristos agent_get_helper_thread_id (void)
1121424dfb3Schristos {
1131424dfb3Schristos   if  (helper_thread_id == 0)
1141424dfb3Schristos     {
1151424dfb3Schristos       if (target_read_uint32 (ipa_sym_addrs.addr_helper_thread_id,
1161424dfb3Schristos 			      &helper_thread_id))
1171424dfb3Schristos 	warning (_("Error reading helper thread's id in lib"));
1181424dfb3Schristos     }
1191424dfb3Schristos 
1201424dfb3Schristos   return helper_thread_id;
1211424dfb3Schristos }
1221424dfb3Schristos 
1231424dfb3Schristos #ifdef HAVE_SYS_UN_H
1241424dfb3Schristos #include <sys/socket.h>
1251424dfb3Schristos #include <sys/un.h>
1261424dfb3Schristos #define SOCK_DIR P_tmpdir
1271424dfb3Schristos 
1281424dfb3Schristos #ifndef UNIX_PATH_MAX
1291424dfb3Schristos #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
1301424dfb3Schristos #endif
1311424dfb3Schristos 
1321424dfb3Schristos #endif
1331424dfb3Schristos 
1341424dfb3Schristos /* Connects to synchronization socket.  PID is the pid of inferior, which is
1351424dfb3Schristos    used to set up the connection socket.  */
1361424dfb3Schristos 
1371424dfb3Schristos static int
gdb_connect_sync_socket(int pid)1381424dfb3Schristos gdb_connect_sync_socket (int pid)
1391424dfb3Schristos {
1401424dfb3Schristos #ifdef HAVE_SYS_UN_H
141*f976f0c7Skamil   struct sockaddr_un addr = {};
1421424dfb3Schristos   int res, fd;
1431424dfb3Schristos   char path[UNIX_PATH_MAX];
1441424dfb3Schristos 
1451424dfb3Schristos   res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid);
1461424dfb3Schristos   if (res >= UNIX_PATH_MAX)
1471424dfb3Schristos     return -1;
1481424dfb3Schristos 
1491424dfb3Schristos   res = fd = gdb_socket_cloexec (PF_UNIX, SOCK_STREAM, 0);
1501424dfb3Schristos   if (res == -1)
1511424dfb3Schristos     {
1521424dfb3Schristos       warning (_("error opening sync socket: %s"), safe_strerror (errno));
1531424dfb3Schristos       return -1;
1541424dfb3Schristos     }
1551424dfb3Schristos 
1561424dfb3Schristos   addr.sun_family = AF_UNIX;
1571424dfb3Schristos 
1581424dfb3Schristos   res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
1591424dfb3Schristos   if (res >= UNIX_PATH_MAX)
1601424dfb3Schristos     {
1611424dfb3Schristos       warning (_("string overflow allocating socket name"));
1621424dfb3Schristos       close (fd);
1631424dfb3Schristos       return -1;
1641424dfb3Schristos     }
1651424dfb3Schristos 
1661424dfb3Schristos   res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
1671424dfb3Schristos   if (res == -1)
1681424dfb3Schristos     {
1691424dfb3Schristos       warning (_("error connecting sync socket (%s): %s. "
1701424dfb3Schristos 		 "Make sure the directory exists and that it is writable."),
1711424dfb3Schristos 		 path, safe_strerror (errno));
1721424dfb3Schristos       close (fd);
1731424dfb3Schristos       return -1;
1741424dfb3Schristos     }
1751424dfb3Schristos 
1761424dfb3Schristos   return fd;
1771424dfb3Schristos #else
1781424dfb3Schristos   return -1;
1791424dfb3Schristos #endif
1801424dfb3Schristos }
1811424dfb3Schristos 
1821424dfb3Schristos /* Execute an agent command in the inferior.  PID is the value of pid of the
1831424dfb3Schristos    inferior.  CMD is the buffer for command.  GDB or GDBserver will store the
1841424dfb3Schristos    command into it and fetch the return result from CMD.  The interaction
1851424dfb3Schristos    between GDB/GDBserver and the agent is synchronized by a synchronization
1861424dfb3Schristos    socket.  Return zero if success, otherwise return non-zero.  */
1871424dfb3Schristos 
1881424dfb3Schristos int
agent_run_command(int pid,const char * cmd,int len)1891424dfb3Schristos agent_run_command (int pid, const char *cmd, int len)
1901424dfb3Schristos {
1911424dfb3Schristos   int fd;
1921424dfb3Schristos   int tid = agent_get_helper_thread_id ();
1931424dfb3Schristos   ptid_t ptid = ptid_t (pid, tid, 0);
1941424dfb3Schristos 
1951424dfb3Schristos   int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf,
1961424dfb3Schristos 				 (gdb_byte *) cmd, len);
1971424dfb3Schristos 
1981424dfb3Schristos   if (ret != 0)
1991424dfb3Schristos     {
2001424dfb3Schristos       warning (_("unable to write"));
2011424dfb3Schristos       return -1;
2021424dfb3Schristos     }
2031424dfb3Schristos 
2041424dfb3Schristos   DEBUG_AGENT ("agent: resumed helper thread\n");
2051424dfb3Schristos 
2061424dfb3Schristos   /* Resume helper thread.  */
2071424dfb3Schristos   target_continue_no_signal (ptid);
2081424dfb3Schristos 
2091424dfb3Schristos   fd = gdb_connect_sync_socket (pid);
2101424dfb3Schristos   if (fd >= 0)
2111424dfb3Schristos     {
2121424dfb3Schristos       char buf[1] = "";
2131424dfb3Schristos 
2141424dfb3Schristos       DEBUG_AGENT ("agent: signalling helper thread\n");
2151424dfb3Schristos 
2161424dfb3Schristos       do
2171424dfb3Schristos 	{
2181424dfb3Schristos 	  ret = write (fd, buf, 1);
2191424dfb3Schristos 	} while (ret == -1 && errno == EINTR);
2201424dfb3Schristos 
2211424dfb3Schristos 	DEBUG_AGENT ("agent: waiting for helper thread's response\n");
2221424dfb3Schristos 
2231424dfb3Schristos       do
2241424dfb3Schristos 	{
2251424dfb3Schristos 	  ret = read (fd, buf, 1);
2261424dfb3Schristos 	} while (ret == -1 && errno == EINTR);
2271424dfb3Schristos 
2281424dfb3Schristos       close (fd);
2291424dfb3Schristos 
2301424dfb3Schristos       DEBUG_AGENT ("agent: helper thread's response received\n");
2311424dfb3Schristos     }
2321424dfb3Schristos   else
2331424dfb3Schristos     return -1;
2341424dfb3Schristos 
2351424dfb3Schristos   /* Need to read response with the inferior stopped.  */
2361424dfb3Schristos   if (ptid != null_ptid)
2371424dfb3Schristos     {
2381424dfb3Schristos       /* Stop thread PTID.  */
2391424dfb3Schristos       DEBUG_AGENT ("agent: stop helper thread\n");
2401424dfb3Schristos       target_stop_and_wait (ptid);
2411424dfb3Schristos     }
2421424dfb3Schristos 
2431424dfb3Schristos   if (fd >= 0)
2441424dfb3Schristos     {
2451424dfb3Schristos       if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
2461424dfb3Schristos 			      IPA_CMD_BUF_SIZE))
2471424dfb3Schristos 	{
2481424dfb3Schristos 	  warning (_("Error reading command response"));
2491424dfb3Schristos 	  return -1;
2501424dfb3Schristos 	}
2511424dfb3Schristos     }
2521424dfb3Schristos 
2531424dfb3Schristos   return 0;
2541424dfb3Schristos }
2551424dfb3Schristos 
2561424dfb3Schristos /* Each bit of it stands for a capability of agent.  */
2571424dfb3Schristos static uint32_t agent_capability = 0;
2581424dfb3Schristos 
2591424dfb3Schristos /* Return true if agent has capability AGENT_CAP, otherwise return false.  */
2601424dfb3Schristos 
2611424dfb3Schristos bool
agent_capability_check(enum agent_capa agent_capa)2621424dfb3Schristos agent_capability_check (enum agent_capa agent_capa)
2631424dfb3Schristos {
2641424dfb3Schristos   if (agent_capability == 0)
2651424dfb3Schristos     {
2661424dfb3Schristos       if (target_read_uint32 (ipa_sym_addrs.addr_capability,
2671424dfb3Schristos 			      &agent_capability))
2681424dfb3Schristos 	warning (_("Error reading capability of agent"));
2691424dfb3Schristos     }
2701424dfb3Schristos   return (agent_capability & agent_capa) != 0;
2711424dfb3Schristos }
2721424dfb3Schristos 
2731424dfb3Schristos /* Invalidate the cache of agent capability, so we'll read it from inferior
2741424dfb3Schristos    again.  Call it when launches a new program or reconnect to remote stub.  */
2751424dfb3Schristos 
2761424dfb3Schristos void
agent_capability_invalidate(void)2771424dfb3Schristos agent_capability_invalidate (void)
2781424dfb3Schristos {
2791424dfb3Schristos   agent_capability = 0;
2801424dfb3Schristos }
281