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