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