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