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