1*ef5ccd6cSJohn Marino /* Shared utility routines for GDB to interact with agent.
2*ef5ccd6cSJohn Marino
3*ef5ccd6cSJohn Marino Copyright (C) 2009-2013 Free Software Foundation, Inc.
4*ef5ccd6cSJohn Marino
5*ef5ccd6cSJohn Marino This file is part of GDB.
6*ef5ccd6cSJohn Marino
7*ef5ccd6cSJohn Marino This program is free software; you can redistribute it and/or modify
8*ef5ccd6cSJohn Marino it under the terms of the GNU General Public License as published by
9*ef5ccd6cSJohn Marino the Free Software Foundation; either version 3 of the License, or
10*ef5ccd6cSJohn Marino (at your option) any later version.
11*ef5ccd6cSJohn Marino
12*ef5ccd6cSJohn Marino This program is distributed in the hope that it will be useful,
13*ef5ccd6cSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14*ef5ccd6cSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*ef5ccd6cSJohn Marino GNU General Public License for more details.
16*ef5ccd6cSJohn Marino
17*ef5ccd6cSJohn Marino You should have received a copy of the GNU General Public License
18*ef5ccd6cSJohn Marino along with this program. If not, see <http://www.gnu.org/licenses/>. */
19*ef5ccd6cSJohn Marino
20*ef5ccd6cSJohn Marino #ifdef GDBSERVER
21*ef5ccd6cSJohn Marino #include "server.h"
22*ef5ccd6cSJohn Marino #else
23*ef5ccd6cSJohn Marino #include "defs.h"
24*ef5ccd6cSJohn Marino #include "target.h"
25*ef5ccd6cSJohn Marino #include "inferior.h" /* for non_stop */
26*ef5ccd6cSJohn Marino #endif
27*ef5ccd6cSJohn Marino
28*ef5ccd6cSJohn Marino #include <string.h>
29*ef5ccd6cSJohn Marino #include <unistd.h>
30*ef5ccd6cSJohn Marino #include "agent.h"
31*ef5ccd6cSJohn Marino
32*ef5ccd6cSJohn Marino int debug_agent = 0;
33*ef5ccd6cSJohn Marino
34*ef5ccd6cSJohn Marino #ifdef GDBSERVER
35*ef5ccd6cSJohn Marino #define DEBUG_AGENT(fmt, args...) \
36*ef5ccd6cSJohn Marino if (debug_agent) \
37*ef5ccd6cSJohn Marino fprintf (stderr, fmt, ##args);
38*ef5ccd6cSJohn Marino #else
39*ef5ccd6cSJohn Marino #define DEBUG_AGENT(fmt, args...) \
40*ef5ccd6cSJohn Marino if (debug_agent) \
41*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, fmt, ##args);
42*ef5ccd6cSJohn Marino #endif
43*ef5ccd6cSJohn Marino
44*ef5ccd6cSJohn Marino /* Global flag to determine using agent or not. */
45*ef5ccd6cSJohn Marino int use_agent = 0;
46*ef5ccd6cSJohn Marino
47*ef5ccd6cSJohn Marino /* Addresses of in-process agent's symbols both GDB and GDBserver cares
48*ef5ccd6cSJohn Marino about. */
49*ef5ccd6cSJohn Marino
50*ef5ccd6cSJohn Marino struct ipa_sym_addresses
51*ef5ccd6cSJohn Marino {
52*ef5ccd6cSJohn Marino CORE_ADDR addr_helper_thread_id;
53*ef5ccd6cSJohn Marino CORE_ADDR addr_cmd_buf;
54*ef5ccd6cSJohn Marino CORE_ADDR addr_capability;
55*ef5ccd6cSJohn Marino };
56*ef5ccd6cSJohn Marino
57*ef5ccd6cSJohn Marino /* Cache of the helper thread id. FIXME: this global should be made
58*ef5ccd6cSJohn Marino per-process. */
59*ef5ccd6cSJohn Marino static unsigned int helper_thread_id = 0;
60*ef5ccd6cSJohn Marino
61*ef5ccd6cSJohn Marino static struct
62*ef5ccd6cSJohn Marino {
63*ef5ccd6cSJohn Marino const char *name;
64*ef5ccd6cSJohn Marino int offset;
65*ef5ccd6cSJohn Marino int required;
66*ef5ccd6cSJohn Marino } symbol_list[] = {
67*ef5ccd6cSJohn Marino IPA_SYM(helper_thread_id),
68*ef5ccd6cSJohn Marino IPA_SYM(cmd_buf),
69*ef5ccd6cSJohn Marino IPA_SYM(capability),
70*ef5ccd6cSJohn Marino };
71*ef5ccd6cSJohn Marino
72*ef5ccd6cSJohn Marino static struct ipa_sym_addresses ipa_sym_addrs;
73*ef5ccd6cSJohn Marino
74*ef5ccd6cSJohn Marino static int all_agent_symbols_looked_up = 0;
75*ef5ccd6cSJohn Marino
76*ef5ccd6cSJohn Marino int
agent_loaded_p(void)77*ef5ccd6cSJohn Marino agent_loaded_p (void)
78*ef5ccd6cSJohn Marino {
79*ef5ccd6cSJohn Marino return all_agent_symbols_looked_up;
80*ef5ccd6cSJohn Marino }
81*ef5ccd6cSJohn Marino
82*ef5ccd6cSJohn Marino /* Look up all symbols needed by agent. Return 0 if all the symbols are
83*ef5ccd6cSJohn Marino found, return non-zero otherwise. */
84*ef5ccd6cSJohn Marino
85*ef5ccd6cSJohn Marino int
agent_look_up_symbols(void * arg)86*ef5ccd6cSJohn Marino agent_look_up_symbols (void *arg)
87*ef5ccd6cSJohn Marino {
88*ef5ccd6cSJohn Marino int i;
89*ef5ccd6cSJohn Marino
90*ef5ccd6cSJohn Marino all_agent_symbols_looked_up = 0;
91*ef5ccd6cSJohn Marino
92*ef5ccd6cSJohn Marino for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
93*ef5ccd6cSJohn Marino {
94*ef5ccd6cSJohn Marino CORE_ADDR *addrp =
95*ef5ccd6cSJohn Marino (CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset);
96*ef5ccd6cSJohn Marino #ifdef GDBSERVER
97*ef5ccd6cSJohn Marino
98*ef5ccd6cSJohn Marino if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0)
99*ef5ccd6cSJohn Marino #else
100*ef5ccd6cSJohn Marino struct minimal_symbol *sym =
101*ef5ccd6cSJohn Marino lookup_minimal_symbol (symbol_list[i].name, NULL,
102*ef5ccd6cSJohn Marino (struct objfile *) arg);
103*ef5ccd6cSJohn Marino
104*ef5ccd6cSJohn Marino if (sym != NULL)
105*ef5ccd6cSJohn Marino *addrp = SYMBOL_VALUE_ADDRESS (sym);
106*ef5ccd6cSJohn Marino else
107*ef5ccd6cSJohn Marino #endif
108*ef5ccd6cSJohn Marino {
109*ef5ccd6cSJohn Marino DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
110*ef5ccd6cSJohn Marino return -1;
111*ef5ccd6cSJohn Marino }
112*ef5ccd6cSJohn Marino }
113*ef5ccd6cSJohn Marino
114*ef5ccd6cSJohn Marino all_agent_symbols_looked_up = 1;
115*ef5ccd6cSJohn Marino return 0;
116*ef5ccd6cSJohn Marino }
117*ef5ccd6cSJohn Marino
118*ef5ccd6cSJohn Marino static unsigned int
agent_get_helper_thread_id(void)119*ef5ccd6cSJohn Marino agent_get_helper_thread_id (void)
120*ef5ccd6cSJohn Marino {
121*ef5ccd6cSJohn Marino if (helper_thread_id == 0)
122*ef5ccd6cSJohn Marino {
123*ef5ccd6cSJohn Marino #ifdef GDBSERVER
124*ef5ccd6cSJohn Marino if (read_inferior_memory (ipa_sym_addrs.addr_helper_thread_id,
125*ef5ccd6cSJohn Marino (unsigned char *) &helper_thread_id,
126*ef5ccd6cSJohn Marino sizeof helper_thread_id))
127*ef5ccd6cSJohn Marino #else
128*ef5ccd6cSJohn Marino enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
129*ef5ccd6cSJohn Marino gdb_byte buf[4];
130*ef5ccd6cSJohn Marino
131*ef5ccd6cSJohn Marino if (target_read_memory (ipa_sym_addrs.addr_helper_thread_id,
132*ef5ccd6cSJohn Marino buf, sizeof buf) == 0)
133*ef5ccd6cSJohn Marino helper_thread_id = extract_unsigned_integer (buf, sizeof buf,
134*ef5ccd6cSJohn Marino byte_order);
135*ef5ccd6cSJohn Marino else
136*ef5ccd6cSJohn Marino #endif
137*ef5ccd6cSJohn Marino {
138*ef5ccd6cSJohn Marino warning (_("Error reading helper thread's id in lib"));
139*ef5ccd6cSJohn Marino }
140*ef5ccd6cSJohn Marino }
141*ef5ccd6cSJohn Marino
142*ef5ccd6cSJohn Marino return helper_thread_id;
143*ef5ccd6cSJohn Marino }
144*ef5ccd6cSJohn Marino
145*ef5ccd6cSJohn Marino #ifdef HAVE_SYS_UN_H
146*ef5ccd6cSJohn Marino #include <sys/socket.h>
147*ef5ccd6cSJohn Marino #include <sys/un.h>
148*ef5ccd6cSJohn Marino #define SOCK_DIR P_tmpdir
149*ef5ccd6cSJohn Marino
150*ef5ccd6cSJohn Marino #ifndef UNIX_PATH_MAX
151*ef5ccd6cSJohn Marino #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
152*ef5ccd6cSJohn Marino #endif
153*ef5ccd6cSJohn Marino
154*ef5ccd6cSJohn Marino #endif
155*ef5ccd6cSJohn Marino
156*ef5ccd6cSJohn Marino /* Connects to synchronization socket. PID is the pid of inferior, which is
157*ef5ccd6cSJohn Marino used to set up the connection socket. */
158*ef5ccd6cSJohn Marino
159*ef5ccd6cSJohn Marino static int
gdb_connect_sync_socket(int pid)160*ef5ccd6cSJohn Marino gdb_connect_sync_socket (int pid)
161*ef5ccd6cSJohn Marino {
162*ef5ccd6cSJohn Marino #ifdef HAVE_SYS_UN_H
163*ef5ccd6cSJohn Marino struct sockaddr_un addr;
164*ef5ccd6cSJohn Marino int res, fd;
165*ef5ccd6cSJohn Marino char path[UNIX_PATH_MAX];
166*ef5ccd6cSJohn Marino
167*ef5ccd6cSJohn Marino res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid);
168*ef5ccd6cSJohn Marino if (res >= UNIX_PATH_MAX)
169*ef5ccd6cSJohn Marino return -1;
170*ef5ccd6cSJohn Marino
171*ef5ccd6cSJohn Marino res = fd = socket (PF_UNIX, SOCK_STREAM, 0);
172*ef5ccd6cSJohn Marino if (res == -1)
173*ef5ccd6cSJohn Marino {
174*ef5ccd6cSJohn Marino warning (_("error opening sync socket: %s"), strerror (errno));
175*ef5ccd6cSJohn Marino return -1;
176*ef5ccd6cSJohn Marino }
177*ef5ccd6cSJohn Marino
178*ef5ccd6cSJohn Marino addr.sun_family = AF_UNIX;
179*ef5ccd6cSJohn Marino
180*ef5ccd6cSJohn Marino res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
181*ef5ccd6cSJohn Marino if (res >= UNIX_PATH_MAX)
182*ef5ccd6cSJohn Marino {
183*ef5ccd6cSJohn Marino warning (_("string overflow allocating socket name"));
184*ef5ccd6cSJohn Marino close (fd);
185*ef5ccd6cSJohn Marino return -1;
186*ef5ccd6cSJohn Marino }
187*ef5ccd6cSJohn Marino
188*ef5ccd6cSJohn Marino res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
189*ef5ccd6cSJohn Marino if (res == -1)
190*ef5ccd6cSJohn Marino {
191*ef5ccd6cSJohn Marino warning (_("error connecting sync socket (%s): %s. "
192*ef5ccd6cSJohn Marino "Make sure the directory exists and that it is writable."),
193*ef5ccd6cSJohn Marino path, strerror (errno));
194*ef5ccd6cSJohn Marino close (fd);
195*ef5ccd6cSJohn Marino return -1;
196*ef5ccd6cSJohn Marino }
197*ef5ccd6cSJohn Marino
198*ef5ccd6cSJohn Marino return fd;
199*ef5ccd6cSJohn Marino #else
200*ef5ccd6cSJohn Marino return -1;
201*ef5ccd6cSJohn Marino #endif
202*ef5ccd6cSJohn Marino }
203*ef5ccd6cSJohn Marino
204*ef5ccd6cSJohn Marino /* Execute an agent command in the inferior. PID is the value of pid of the
205*ef5ccd6cSJohn Marino inferior. CMD is the buffer for command. GDB or GDBserver will store the
206*ef5ccd6cSJohn Marino command into it and fetch the return result from CMD. The interaction
207*ef5ccd6cSJohn Marino between GDB/GDBserver and the agent is synchronized by a synchronization
208*ef5ccd6cSJohn Marino socket. Return zero if success, otherwise return non-zero. */
209*ef5ccd6cSJohn Marino
210*ef5ccd6cSJohn Marino int
agent_run_command(int pid,const char * cmd,int len)211*ef5ccd6cSJohn Marino agent_run_command (int pid, const char *cmd, int len)
212*ef5ccd6cSJohn Marino {
213*ef5ccd6cSJohn Marino int fd;
214*ef5ccd6cSJohn Marino int tid = agent_get_helper_thread_id ();
215*ef5ccd6cSJohn Marino ptid_t ptid = ptid_build (pid, tid, 0);
216*ef5ccd6cSJohn Marino
217*ef5ccd6cSJohn Marino #ifdef GDBSERVER
218*ef5ccd6cSJohn Marino int ret = write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
219*ef5ccd6cSJohn Marino (const unsigned char *) cmd, len);
220*ef5ccd6cSJohn Marino #else
221*ef5ccd6cSJohn Marino int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf, cmd, len);
222*ef5ccd6cSJohn Marino #endif
223*ef5ccd6cSJohn Marino
224*ef5ccd6cSJohn Marino if (ret != 0)
225*ef5ccd6cSJohn Marino {
226*ef5ccd6cSJohn Marino warning (_("unable to write"));
227*ef5ccd6cSJohn Marino return -1;
228*ef5ccd6cSJohn Marino }
229*ef5ccd6cSJohn Marino
230*ef5ccd6cSJohn Marino DEBUG_AGENT ("agent: resumed helper thread\n");
231*ef5ccd6cSJohn Marino
232*ef5ccd6cSJohn Marino /* Resume helper thread. */
233*ef5ccd6cSJohn Marino #ifdef GDBSERVER
234*ef5ccd6cSJohn Marino {
235*ef5ccd6cSJohn Marino struct thread_resume resume_info;
236*ef5ccd6cSJohn Marino
237*ef5ccd6cSJohn Marino resume_info.thread = ptid;
238*ef5ccd6cSJohn Marino resume_info.kind = resume_continue;
239*ef5ccd6cSJohn Marino resume_info.sig = GDB_SIGNAL_0;
240*ef5ccd6cSJohn Marino (*the_target->resume) (&resume_info, 1);
241*ef5ccd6cSJohn Marino }
242*ef5ccd6cSJohn Marino #else
243*ef5ccd6cSJohn Marino target_resume (ptid, 0, GDB_SIGNAL_0);
244*ef5ccd6cSJohn Marino #endif
245*ef5ccd6cSJohn Marino
246*ef5ccd6cSJohn Marino fd = gdb_connect_sync_socket (pid);
247*ef5ccd6cSJohn Marino if (fd >= 0)
248*ef5ccd6cSJohn Marino {
249*ef5ccd6cSJohn Marino char buf[1] = "";
250*ef5ccd6cSJohn Marino int ret;
251*ef5ccd6cSJohn Marino
252*ef5ccd6cSJohn Marino DEBUG_AGENT ("agent: signalling helper thread\n");
253*ef5ccd6cSJohn Marino
254*ef5ccd6cSJohn Marino do
255*ef5ccd6cSJohn Marino {
256*ef5ccd6cSJohn Marino ret = write (fd, buf, 1);
257*ef5ccd6cSJohn Marino } while (ret == -1 && errno == EINTR);
258*ef5ccd6cSJohn Marino
259*ef5ccd6cSJohn Marino DEBUG_AGENT ("agent: waiting for helper thread's response\n");
260*ef5ccd6cSJohn Marino
261*ef5ccd6cSJohn Marino do
262*ef5ccd6cSJohn Marino {
263*ef5ccd6cSJohn Marino ret = read (fd, buf, 1);
264*ef5ccd6cSJohn Marino } while (ret == -1 && errno == EINTR);
265*ef5ccd6cSJohn Marino
266*ef5ccd6cSJohn Marino close (fd);
267*ef5ccd6cSJohn Marino
268*ef5ccd6cSJohn Marino DEBUG_AGENT ("agent: helper thread's response received\n");
269*ef5ccd6cSJohn Marino }
270*ef5ccd6cSJohn Marino else
271*ef5ccd6cSJohn Marino return -1;
272*ef5ccd6cSJohn Marino
273*ef5ccd6cSJohn Marino /* Need to read response with the inferior stopped. */
274*ef5ccd6cSJohn Marino if (!ptid_equal (ptid, null_ptid))
275*ef5ccd6cSJohn Marino {
276*ef5ccd6cSJohn Marino struct target_waitstatus status;
277*ef5ccd6cSJohn Marino int was_non_stop = non_stop;
278*ef5ccd6cSJohn Marino /* Stop thread PTID. */
279*ef5ccd6cSJohn Marino DEBUG_AGENT ("agent: stop helper thread\n");
280*ef5ccd6cSJohn Marino #ifdef GDBSERVER
281*ef5ccd6cSJohn Marino {
282*ef5ccd6cSJohn Marino struct thread_resume resume_info;
283*ef5ccd6cSJohn Marino
284*ef5ccd6cSJohn Marino resume_info.thread = ptid;
285*ef5ccd6cSJohn Marino resume_info.kind = resume_stop;
286*ef5ccd6cSJohn Marino resume_info.sig = GDB_SIGNAL_0;
287*ef5ccd6cSJohn Marino (*the_target->resume) (&resume_info, 1);
288*ef5ccd6cSJohn Marino }
289*ef5ccd6cSJohn Marino
290*ef5ccd6cSJohn Marino non_stop = 1;
291*ef5ccd6cSJohn Marino mywait (ptid, &status, 0, 0);
292*ef5ccd6cSJohn Marino #else
293*ef5ccd6cSJohn Marino non_stop = 1;
294*ef5ccd6cSJohn Marino target_stop (ptid);
295*ef5ccd6cSJohn Marino
296*ef5ccd6cSJohn Marino memset (&status, 0, sizeof (status));
297*ef5ccd6cSJohn Marino target_wait (ptid, &status, 0);
298*ef5ccd6cSJohn Marino #endif
299*ef5ccd6cSJohn Marino non_stop = was_non_stop;
300*ef5ccd6cSJohn Marino }
301*ef5ccd6cSJohn Marino
302*ef5ccd6cSJohn Marino if (fd >= 0)
303*ef5ccd6cSJohn Marino {
304*ef5ccd6cSJohn Marino #ifdef GDBSERVER
305*ef5ccd6cSJohn Marino if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
306*ef5ccd6cSJohn Marino (unsigned char *) cmd, IPA_CMD_BUF_SIZE))
307*ef5ccd6cSJohn Marino #else
308*ef5ccd6cSJohn Marino if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
309*ef5ccd6cSJohn Marino IPA_CMD_BUF_SIZE))
310*ef5ccd6cSJohn Marino #endif
311*ef5ccd6cSJohn Marino {
312*ef5ccd6cSJohn Marino warning (_("Error reading command response"));
313*ef5ccd6cSJohn Marino return -1;
314*ef5ccd6cSJohn Marino }
315*ef5ccd6cSJohn Marino }
316*ef5ccd6cSJohn Marino
317*ef5ccd6cSJohn Marino return 0;
318*ef5ccd6cSJohn Marino }
319*ef5ccd6cSJohn Marino
320*ef5ccd6cSJohn Marino /* Each bit of it stands for a capability of agent. */
321*ef5ccd6cSJohn Marino static unsigned int agent_capability = 0;
322*ef5ccd6cSJohn Marino
323*ef5ccd6cSJohn Marino /* Return true if agent has capability AGENT_CAP, otherwise return false. */
324*ef5ccd6cSJohn Marino
325*ef5ccd6cSJohn Marino int
agent_capability_check(enum agent_capa agent_capa)326*ef5ccd6cSJohn Marino agent_capability_check (enum agent_capa agent_capa)
327*ef5ccd6cSJohn Marino {
328*ef5ccd6cSJohn Marino if (agent_capability == 0)
329*ef5ccd6cSJohn Marino {
330*ef5ccd6cSJohn Marino #ifdef GDBSERVER
331*ef5ccd6cSJohn Marino if (read_inferior_memory (ipa_sym_addrs.addr_capability,
332*ef5ccd6cSJohn Marino (unsigned char *) &agent_capability,
333*ef5ccd6cSJohn Marino sizeof agent_capability))
334*ef5ccd6cSJohn Marino #else
335*ef5ccd6cSJohn Marino enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
336*ef5ccd6cSJohn Marino gdb_byte buf[4];
337*ef5ccd6cSJohn Marino
338*ef5ccd6cSJohn Marino if (target_read_memory (ipa_sym_addrs.addr_capability,
339*ef5ccd6cSJohn Marino buf, sizeof buf) == 0)
340*ef5ccd6cSJohn Marino agent_capability = extract_unsigned_integer (buf, sizeof buf,
341*ef5ccd6cSJohn Marino byte_order);
342*ef5ccd6cSJohn Marino else
343*ef5ccd6cSJohn Marino #endif
344*ef5ccd6cSJohn Marino warning (_("Error reading capability of agent"));
345*ef5ccd6cSJohn Marino }
346*ef5ccd6cSJohn Marino return agent_capability & agent_capa;
347*ef5ccd6cSJohn Marino }
348*ef5ccd6cSJohn Marino
349*ef5ccd6cSJohn Marino /* Invalidate the cache of agent capability, so we'll read it from inferior
350*ef5ccd6cSJohn Marino again. Call it when launches a new program or reconnect to remote stub. */
351*ef5ccd6cSJohn Marino
352*ef5ccd6cSJohn Marino void
agent_capability_invalidate(void)353*ef5ccd6cSJohn Marino agent_capability_invalidate (void)
354*ef5ccd6cSJohn Marino {
355*ef5ccd6cSJohn Marino agent_capability = 0;
356*ef5ccd6cSJohn Marino }
357