17d62b00eSchristos /* Shared utility routines for GDB to interact with agent. 27d62b00eSchristos 3*6881a400Schristos Copyright (C) 2009-2023 Free Software Foundation, Inc. 47d62b00eSchristos 57d62b00eSchristos This file is part of GDB. 67d62b00eSchristos 77d62b00eSchristos This program is free software; you can redistribute it and/or modify 87d62b00eSchristos it under the terms of the GNU General Public License as published by 97d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 107d62b00eSchristos (at your option) any later version. 117d62b00eSchristos 127d62b00eSchristos This program is distributed in the hope that it will be useful, 137d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 147d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 157d62b00eSchristos GNU General Public License for more details. 167d62b00eSchristos 177d62b00eSchristos You should have received a copy of the GNU General Public License 187d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 197d62b00eSchristos 207d62b00eSchristos #include "common-defs.h" 217d62b00eSchristos #include "target/target.h" 227d62b00eSchristos #include "gdbsupport/symbol.h" 237d62b00eSchristos #include <unistd.h> 247d62b00eSchristos #include "filestuff.h" 257d62b00eSchristos 267d62b00eSchristos #define IPA_SYM_STRUCT_NAME ipa_sym_addresses_common 277d62b00eSchristos #include "agent.h" 287d62b00eSchristos 297d62b00eSchristos bool debug_agent = false; 307d62b00eSchristos 317d62b00eSchristos /* A stdarg wrapper for debug_vprintf. */ 327d62b00eSchristos 337d62b00eSchristos static void ATTRIBUTE_PRINTF (1, 2) 347d62b00eSchristos debug_agent_printf (const char *fmt, ...) 357d62b00eSchristos { 367d62b00eSchristos va_list ap; 377d62b00eSchristos 387d62b00eSchristos if (!debug_agent) 397d62b00eSchristos return; 407d62b00eSchristos va_start (ap, fmt); 417d62b00eSchristos debug_vprintf (fmt, ap); 427d62b00eSchristos va_end (ap); 437d62b00eSchristos } 447d62b00eSchristos 457d62b00eSchristos #define DEBUG_AGENT debug_agent_printf 467d62b00eSchristos 477d62b00eSchristos /* Global flag to determine using agent or not. */ 487d62b00eSchristos bool use_agent = false; 497d62b00eSchristos 507d62b00eSchristos /* Addresses of in-process agent's symbols both GDB and GDBserver cares 517d62b00eSchristos about. */ 527d62b00eSchristos 537d62b00eSchristos struct ipa_sym_addresses_common 547d62b00eSchristos { 557d62b00eSchristos CORE_ADDR addr_helper_thread_id; 567d62b00eSchristos CORE_ADDR addr_cmd_buf; 577d62b00eSchristos CORE_ADDR addr_capability; 587d62b00eSchristos }; 597d62b00eSchristos 607d62b00eSchristos /* Cache of the helper thread id. FIXME: this global should be made 617d62b00eSchristos per-process. */ 627d62b00eSchristos static uint32_t helper_thread_id = 0; 637d62b00eSchristos 647d62b00eSchristos static struct 657d62b00eSchristos { 667d62b00eSchristos const char *name; 677d62b00eSchristos int offset; 687d62b00eSchristos } symbol_list[] = { 697d62b00eSchristos IPA_SYM(helper_thread_id), 707d62b00eSchristos IPA_SYM(cmd_buf), 717d62b00eSchristos IPA_SYM(capability), 727d62b00eSchristos }; 737d62b00eSchristos 747d62b00eSchristos static struct ipa_sym_addresses_common ipa_sym_addrs; 757d62b00eSchristos 767d62b00eSchristos static bool all_agent_symbols_looked_up = false; 777d62b00eSchristos 787d62b00eSchristos bool 797d62b00eSchristos agent_loaded_p (void) 807d62b00eSchristos { 817d62b00eSchristos return all_agent_symbols_looked_up; 827d62b00eSchristos } 837d62b00eSchristos 847d62b00eSchristos /* Look up all symbols needed by agent. Return 0 if all the symbols are 857d62b00eSchristos found, return non-zero otherwise. */ 867d62b00eSchristos 877d62b00eSchristos int 887d62b00eSchristos agent_look_up_symbols (void *arg) 897d62b00eSchristos { 907d62b00eSchristos all_agent_symbols_looked_up = false; 917d62b00eSchristos 927d62b00eSchristos for (int i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++) 937d62b00eSchristos { 947d62b00eSchristos CORE_ADDR *addrp = 957d62b00eSchristos (CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset); 967d62b00eSchristos struct objfile *objfile = (struct objfile *) arg; 977d62b00eSchristos 987d62b00eSchristos if (find_minimal_symbol_address (symbol_list[i].name, addrp, 997d62b00eSchristos objfile) != 0) 1007d62b00eSchristos { 1017d62b00eSchristos DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name); 1027d62b00eSchristos return -1; 1037d62b00eSchristos } 1047d62b00eSchristos } 1057d62b00eSchristos 1067d62b00eSchristos all_agent_symbols_looked_up = true; 1077d62b00eSchristos return 0; 1087d62b00eSchristos } 1097d62b00eSchristos 1107d62b00eSchristos static unsigned int 1117d62b00eSchristos agent_get_helper_thread_id (void) 1127d62b00eSchristos { 1137d62b00eSchristos if (helper_thread_id == 0) 1147d62b00eSchristos { 1157d62b00eSchristos if (target_read_uint32 (ipa_sym_addrs.addr_helper_thread_id, 1167d62b00eSchristos &helper_thread_id)) 1177d62b00eSchristos warning (_("Error reading helper thread's id in lib")); 1187d62b00eSchristos } 1197d62b00eSchristos 1207d62b00eSchristos return helper_thread_id; 1217d62b00eSchristos } 1227d62b00eSchristos 1237d62b00eSchristos #ifdef HAVE_SYS_UN_H 1247d62b00eSchristos #include <sys/socket.h> 1257d62b00eSchristos #include <sys/un.h> 1267d62b00eSchristos #define SOCK_DIR P_tmpdir 1277d62b00eSchristos 1287d62b00eSchristos #ifndef UNIX_PATH_MAX 1297d62b00eSchristos #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path) 1307d62b00eSchristos #endif 1317d62b00eSchristos 1327d62b00eSchristos #endif 1337d62b00eSchristos 1347d62b00eSchristos /* Connects to synchronization socket. PID is the pid of inferior, which is 1357d62b00eSchristos used to set up the connection socket. */ 1367d62b00eSchristos 1377d62b00eSchristos static int 1387d62b00eSchristos gdb_connect_sync_socket (int pid) 1397d62b00eSchristos { 1407d62b00eSchristos #ifdef HAVE_SYS_UN_H 1417d62b00eSchristos struct sockaddr_un addr = {}; 1427d62b00eSchristos int res, fd; 1437d62b00eSchristos char path[UNIX_PATH_MAX]; 1447d62b00eSchristos 1457d62b00eSchristos res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid); 1467d62b00eSchristos if (res >= UNIX_PATH_MAX) 1477d62b00eSchristos return -1; 1487d62b00eSchristos 1497d62b00eSchristos res = fd = gdb_socket_cloexec (PF_UNIX, SOCK_STREAM, 0); 1507d62b00eSchristos if (res == -1) 1517d62b00eSchristos { 1527d62b00eSchristos warning (_("error opening sync socket: %s"), safe_strerror (errno)); 1537d62b00eSchristos return -1; 1547d62b00eSchristos } 1557d62b00eSchristos 1567d62b00eSchristos addr.sun_family = AF_UNIX; 1577d62b00eSchristos 1587d62b00eSchristos res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path); 1597d62b00eSchristos if (res >= UNIX_PATH_MAX) 1607d62b00eSchristos { 1617d62b00eSchristos warning (_("string overflow allocating socket name")); 1627d62b00eSchristos close (fd); 1637d62b00eSchristos return -1; 1647d62b00eSchristos } 1657d62b00eSchristos 1667d62b00eSchristos res = connect (fd, (struct sockaddr *) &addr, sizeof (addr)); 1677d62b00eSchristos if (res == -1) 1687d62b00eSchristos { 1697d62b00eSchristos warning (_("error connecting sync socket (%s): %s. " 1707d62b00eSchristos "Make sure the directory exists and that it is writable."), 1717d62b00eSchristos path, safe_strerror (errno)); 1727d62b00eSchristos close (fd); 1737d62b00eSchristos return -1; 1747d62b00eSchristos } 1757d62b00eSchristos 1767d62b00eSchristos return fd; 1777d62b00eSchristos #else 1787d62b00eSchristos return -1; 1797d62b00eSchristos #endif 1807d62b00eSchristos } 1817d62b00eSchristos 1827d62b00eSchristos /* Execute an agent command in the inferior. PID is the value of pid of the 1837d62b00eSchristos inferior. CMD is the buffer for command. GDB or GDBserver will store the 1847d62b00eSchristos command into it and fetch the return result from CMD. The interaction 1857d62b00eSchristos between GDB/GDBserver and the agent is synchronized by a synchronization 1867d62b00eSchristos socket. Return zero if success, otherwise return non-zero. */ 1877d62b00eSchristos 1887d62b00eSchristos int 1897d62b00eSchristos agent_run_command (int pid, const char *cmd, int len) 1907d62b00eSchristos { 1917d62b00eSchristos int fd; 1927d62b00eSchristos int tid = agent_get_helper_thread_id (); 193*6881a400Schristos ptid_t ptid = ptid_t (pid, tid); 1947d62b00eSchristos 1957d62b00eSchristos int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf, 1967d62b00eSchristos (gdb_byte *) cmd, len); 1977d62b00eSchristos 1987d62b00eSchristos if (ret != 0) 1997d62b00eSchristos { 2007d62b00eSchristos warning (_("unable to write")); 2017d62b00eSchristos return -1; 2027d62b00eSchristos } 2037d62b00eSchristos 2047d62b00eSchristos DEBUG_AGENT ("agent: resumed helper thread\n"); 2057d62b00eSchristos 2067d62b00eSchristos /* Resume helper thread. */ 2077d62b00eSchristos target_continue_no_signal (ptid); 2087d62b00eSchristos 2097d62b00eSchristos fd = gdb_connect_sync_socket (pid); 2107d62b00eSchristos if (fd >= 0) 2117d62b00eSchristos { 2127d62b00eSchristos char buf[1] = ""; 2137d62b00eSchristos 2147d62b00eSchristos DEBUG_AGENT ("agent: signalling helper thread\n"); 2157d62b00eSchristos 2167d62b00eSchristos do 2177d62b00eSchristos { 2187d62b00eSchristos ret = write (fd, buf, 1); 2197d62b00eSchristos } while (ret == -1 && errno == EINTR); 2207d62b00eSchristos 2217d62b00eSchristos DEBUG_AGENT ("agent: waiting for helper thread's response\n"); 2227d62b00eSchristos 2237d62b00eSchristos do 2247d62b00eSchristos { 2257d62b00eSchristos ret = read (fd, buf, 1); 2267d62b00eSchristos } while (ret == -1 && errno == EINTR); 2277d62b00eSchristos 2287d62b00eSchristos close (fd); 2297d62b00eSchristos 2307d62b00eSchristos DEBUG_AGENT ("agent: helper thread's response received\n"); 2317d62b00eSchristos } 2327d62b00eSchristos else 2337d62b00eSchristos return -1; 2347d62b00eSchristos 2357d62b00eSchristos /* Need to read response with the inferior stopped. */ 2367d62b00eSchristos if (ptid != null_ptid) 2377d62b00eSchristos { 2387d62b00eSchristos /* Stop thread PTID. */ 2397d62b00eSchristos DEBUG_AGENT ("agent: stop helper thread\n"); 2407d62b00eSchristos target_stop_and_wait (ptid); 2417d62b00eSchristos } 2427d62b00eSchristos 2437d62b00eSchristos if (fd >= 0) 2447d62b00eSchristos { 2457d62b00eSchristos if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd, 2467d62b00eSchristos IPA_CMD_BUF_SIZE)) 2477d62b00eSchristos { 2487d62b00eSchristos warning (_("Error reading command response")); 2497d62b00eSchristos return -1; 2507d62b00eSchristos } 2517d62b00eSchristos } 2527d62b00eSchristos 2537d62b00eSchristos return 0; 2547d62b00eSchristos } 2557d62b00eSchristos 2567d62b00eSchristos /* Each bit of it stands for a capability of agent. */ 2577d62b00eSchristos static uint32_t agent_capability = 0; 2587d62b00eSchristos 2597d62b00eSchristos /* Return true if agent has capability AGENT_CAP, otherwise return false. */ 2607d62b00eSchristos 2617d62b00eSchristos bool 2627d62b00eSchristos agent_capability_check (enum agent_capa agent_capa) 2637d62b00eSchristos { 2647d62b00eSchristos if (agent_capability == 0) 2657d62b00eSchristos { 2667d62b00eSchristos if (target_read_uint32 (ipa_sym_addrs.addr_capability, 2677d62b00eSchristos &agent_capability)) 2687d62b00eSchristos warning (_("Error reading capability of agent")); 2697d62b00eSchristos } 2707d62b00eSchristos return (agent_capability & agent_capa) != 0; 2717d62b00eSchristos } 2727d62b00eSchristos 2737d62b00eSchristos /* Invalidate the cache of agent capability, so we'll read it from inferior 2747d62b00eSchristos again. Call it when launches a new program or reconnect to remote stub. */ 2757d62b00eSchristos 2767d62b00eSchristos void 2777d62b00eSchristos agent_capability_invalidate (void) 2787d62b00eSchristos { 2797d62b00eSchristos agent_capability = 0; 2807d62b00eSchristos } 281