Introduce target/target.h
[deliverable/binutils-gdb.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 "infrun.h"
25 #include "objfiles.h"
26 #endif
27 #include "target/target.h"
28 #include <unistd.h>
29 #include "agent.h"
30 #include "filestuff.h"
31
32 int debug_agent = 0;
33
34 /* A stdarg wrapper for debug_vprintf. */
35
36 static void ATTRIBUTE_PRINTF (1, 2)
37 debug_agent_printf (const char *fmt, ...)
38 {
39 va_list ap;
40
41 if (!debug_agent)
42 return;
43 va_start (ap, fmt);
44 debug_vprintf (fmt, ap);
45 va_end (ap);
46 }
47
48 #define DEBUG_AGENT debug_agent_printf
49
50 /* Global flag to determine using agent or not. */
51 int use_agent = 0;
52
53 /* Addresses of in-process agent's symbols both GDB and GDBserver cares
54 about. */
55
56 struct ipa_sym_addresses
57 {
58 CORE_ADDR addr_helper_thread_id;
59 CORE_ADDR addr_cmd_buf;
60 CORE_ADDR addr_capability;
61 };
62
63 /* Cache of the helper thread id. FIXME: this global should be made
64 per-process. */
65 static uint32_t helper_thread_id = 0;
66
67 static struct
68 {
69 const char *name;
70 int offset;
71 int required;
72 } symbol_list[] = {
73 IPA_SYM(helper_thread_id),
74 IPA_SYM(cmd_buf),
75 IPA_SYM(capability),
76 };
77
78 static struct ipa_sym_addresses ipa_sym_addrs;
79
80 static int all_agent_symbols_looked_up = 0;
81
82 int
83 agent_loaded_p (void)
84 {
85 return all_agent_symbols_looked_up;
86 }
87
88 /* Look up all symbols needed by agent. Return 0 if all the symbols are
89 found, return non-zero otherwise. */
90
91 int
92 agent_look_up_symbols (void *arg)
93 {
94 int i;
95
96 all_agent_symbols_looked_up = 0;
97
98 for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
99 {
100 CORE_ADDR *addrp =
101 (CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset);
102 #ifdef GDBSERVER
103
104 if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0)
105 #else
106 struct bound_minimal_symbol sym =
107 lookup_minimal_symbol (symbol_list[i].name, NULL,
108 (struct objfile *) arg);
109
110 if (sym.minsym != NULL)
111 *addrp = BMSYMBOL_VALUE_ADDRESS (sym);
112 else
113 #endif
114 {
115 DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
116 return -1;
117 }
118 }
119
120 all_agent_symbols_looked_up = 1;
121 return 0;
122 }
123
124 static unsigned int
125 agent_get_helper_thread_id (void)
126 {
127 if (helper_thread_id == 0)
128 {
129 if (target_read_uint32 (ipa_sym_addrs.addr_helper_thread_id,
130 &helper_thread_id))
131 warning (_("Error reading helper thread's id in lib"));
132 }
133
134 return helper_thread_id;
135 }
136
137 #ifdef HAVE_SYS_UN_H
138 #include <sys/socket.h>
139 #include <sys/un.h>
140 #define SOCK_DIR P_tmpdir
141
142 #ifndef UNIX_PATH_MAX
143 #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
144 #endif
145
146 #endif
147
148 /* Connects to synchronization socket. PID is the pid of inferior, which is
149 used to set up the connection socket. */
150
151 static int
152 gdb_connect_sync_socket (int pid)
153 {
154 #ifdef HAVE_SYS_UN_H
155 struct sockaddr_un addr;
156 int res, fd;
157 char path[UNIX_PATH_MAX];
158
159 res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid);
160 if (res >= UNIX_PATH_MAX)
161 return -1;
162
163 res = fd = gdb_socket_cloexec (PF_UNIX, SOCK_STREAM, 0);
164 if (res == -1)
165 {
166 warning (_("error opening sync socket: %s"), strerror (errno));
167 return -1;
168 }
169
170 addr.sun_family = AF_UNIX;
171
172 res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
173 if (res >= UNIX_PATH_MAX)
174 {
175 warning (_("string overflow allocating socket name"));
176 close (fd);
177 return -1;
178 }
179
180 res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
181 if (res == -1)
182 {
183 warning (_("error connecting sync socket (%s): %s. "
184 "Make sure the directory exists and that it is writable."),
185 path, strerror (errno));
186 close (fd);
187 return -1;
188 }
189
190 return fd;
191 #else
192 return -1;
193 #endif
194 }
195
196 /* Execute an agent command in the inferior. PID is the value of pid of the
197 inferior. CMD is the buffer for command. GDB or GDBserver will store the
198 command into it and fetch the return result from CMD. The interaction
199 between GDB/GDBserver and the agent is synchronized by a synchronization
200 socket. Return zero if success, otherwise return non-zero. */
201
202 int
203 agent_run_command (int pid, const char *cmd, int len)
204 {
205 int fd;
206 int tid = agent_get_helper_thread_id ();
207 ptid_t ptid = ptid_build (pid, tid, 0);
208
209 int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf,
210 (gdb_byte *) cmd, len);
211
212 if (ret != 0)
213 {
214 warning (_("unable to write"));
215 return -1;
216 }
217
218 DEBUG_AGENT ("agent: resumed helper thread\n");
219
220 /* Resume helper thread. */
221 #ifdef GDBSERVER
222 {
223 struct thread_resume resume_info;
224
225 resume_info.thread = ptid;
226 resume_info.kind = resume_continue;
227 resume_info.sig = GDB_SIGNAL_0;
228 (*the_target->resume) (&resume_info, 1);
229 }
230 #else
231 target_resume (ptid, 0, GDB_SIGNAL_0);
232 #endif
233
234 fd = gdb_connect_sync_socket (pid);
235 if (fd >= 0)
236 {
237 char buf[1] = "";
238 int ret;
239
240 DEBUG_AGENT ("agent: signalling helper thread\n");
241
242 do
243 {
244 ret = write (fd, buf, 1);
245 } while (ret == -1 && errno == EINTR);
246
247 DEBUG_AGENT ("agent: waiting for helper thread's response\n");
248
249 do
250 {
251 ret = read (fd, buf, 1);
252 } while (ret == -1 && errno == EINTR);
253
254 close (fd);
255
256 DEBUG_AGENT ("agent: helper thread's response received\n");
257 }
258 else
259 return -1;
260
261 /* Need to read response with the inferior stopped. */
262 if (!ptid_equal (ptid, null_ptid))
263 {
264 struct target_waitstatus status;
265 int was_non_stop = non_stop;
266 /* Stop thread PTID. */
267 DEBUG_AGENT ("agent: stop helper thread\n");
268 #ifdef GDBSERVER
269 {
270 struct thread_resume resume_info;
271
272 resume_info.thread = ptid;
273 resume_info.kind = resume_stop;
274 resume_info.sig = GDB_SIGNAL_0;
275 (*the_target->resume) (&resume_info, 1);
276 }
277
278 non_stop = 1;
279 mywait (ptid, &status, 0, 0);
280 #else
281 non_stop = 1;
282 target_stop (ptid);
283
284 memset (&status, 0, sizeof (status));
285 target_wait (ptid, &status, 0);
286 #endif
287 non_stop = was_non_stop;
288 }
289
290 if (fd >= 0)
291 {
292 if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
293 IPA_CMD_BUF_SIZE))
294 {
295 warning (_("Error reading command response"));
296 return -1;
297 }
298 }
299
300 return 0;
301 }
302
303 /* Each bit of it stands for a capability of agent. */
304 static uint32_t agent_capability = 0;
305
306 /* Return true if agent has capability AGENT_CAP, otherwise return false. */
307
308 int
309 agent_capability_check (enum agent_capa agent_capa)
310 {
311 if (agent_capability == 0)
312 {
313 if (target_read_uint32 (ipa_sym_addrs.addr_capability,
314 &agent_capability))
315 warning (_("Error reading capability of agent"));
316 }
317 return agent_capability & agent_capa;
318 }
319
320 /* Invalidate the cache of agent capability, so we'll read it from inferior
321 again. Call it when launches a new program or reconnect to remote stub. */
322
323 void
324 agent_capability_invalidate (void)
325 {
326 agent_capability = 0;
327 }
This page took 0.047531 seconds and 5 git commands to generate.