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