1 /* Shared utility routines for GDB to interact with agent.
3 Copyright (C) 2009-2012 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
25 #include "inferior.h" /* for non_stop */
35 #define DEBUG_AGENT(fmt, args...) \
37 fprintf (stderr, fmt, ##args);
39 #define DEBUG_AGENT(fmt, args...) \
41 fprintf_unfiltered (gdb_stdlog, fmt, ##args);
44 /* Global flag to determine using agent or not. */
47 /* Addresses of in-process agent's symbols both GDB and GDBserver cares
50 struct ipa_sym_addresses
52 CORE_ADDR addr_helper_thread_id
;
53 CORE_ADDR addr_cmd_buf
;
56 /* Cache of the helper thread id. FIXME: this global should be made
58 static unsigned int helper_thread_id
= 0;
66 IPA_SYM(helper_thread_id
),
70 static struct ipa_sym_addresses ipa_sym_addrs
;
72 /* Look up all symbols needed by agent. Return 0 if all the symbols are
73 found, return non-zero otherwise. */
76 agent_look_up_symbols (void)
80 for (i
= 0; i
< sizeof (symbol_list
) / sizeof (symbol_list
[0]); i
++)
83 (CORE_ADDR
*) ((char *) &ipa_sym_addrs
+ symbol_list
[i
].offset
);
86 if (look_up_one_symbol (symbol_list
[i
].name
, addrp
, 1) == 0)
88 struct minimal_symbol
*sym
= lookup_minimal_symbol (symbol_list
[i
].name
,
92 *addrp
= SYMBOL_VALUE_ADDRESS (sym
);
96 DEBUG_AGENT ("symbol `%s' not found\n", symbol_list
[i
].name
);
105 agent_get_helper_thread_id (void)
107 if (helper_thread_id
== 0)
110 if (read_inferior_memory (ipa_sym_addrs
.addr_helper_thread_id
,
111 (unsigned char *) &helper_thread_id
,
112 sizeof helper_thread_id
))
114 enum bfd_endian byte_order
= gdbarch_byte_order (target_gdbarch
);
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
,
124 warning ("Error reading helper thread's id in lib");
128 return helper_thread_id
;
132 #include <sys/socket.h>
134 #define SOCK_DIR P_tmpdir
136 #ifndef UNIX_PATH_MAX
137 #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
142 /* Connects to synchronization socket. PID is the pid of inferior, which is
143 used to set up the connection socket. */
146 gdb_connect_sync_socket (int pid
)
149 struct sockaddr_un addr
;
151 char path
[UNIX_PATH_MAX
];
153 res
= xsnprintf (path
, UNIX_PATH_MAX
, "%s/gdb_ust%d", P_tmpdir
, pid
);
154 if (res
>= UNIX_PATH_MAX
)
157 res
= fd
= socket (PF_UNIX
, SOCK_STREAM
, 0);
160 warning ("error opening sync socket: %s\n", strerror (errno
));
164 addr
.sun_family
= AF_UNIX
;
166 res
= xsnprintf (addr
.sun_path
, UNIX_PATH_MAX
, "%s", path
);
167 if (res
>= UNIX_PATH_MAX
)
169 warning ("string overflow allocating socket name\n");
174 res
= connect (fd
, (struct sockaddr
*) &addr
, sizeof (addr
));
177 warning ("error connecting sync socket (%s): %s. "
178 "Make sure the directory exists and that it is writable.",
179 path
, strerror (errno
));
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. */
197 agent_run_command (int pid
, const char *cmd
)
200 int tid
= agent_get_helper_thread_id ();
201 ptid_t ptid
= ptid_build (pid
, tid
, 0);
202 int len
= strlen (cmd
) + 1;
205 int ret
= write_inferior_memory (ipa_sym_addrs
.addr_cmd_buf
,
206 (const unsigned char *) cmd
, len
);
208 int ret
= target_write_memory (ipa_sym_addrs
.addr_cmd_buf
, cmd
, len
);
213 warning ("unable to write");
217 DEBUG_AGENT ("agent: resumed helper thread\n");
219 /* Resume helper thread. */
222 struct thread_resume resume_info
;
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);
230 target_resume (ptid
, 0, TARGET_SIGNAL_0
);
233 fd
= gdb_connect_sync_socket (pid
);
239 DEBUG_AGENT ("agent: signalling helper thread\n");
243 ret
= write (fd
, buf
, 1);
244 } while (ret
== -1 && errno
== EINTR
);
246 DEBUG_AGENT ("agent: waiting for helper thread's response\n");
250 ret
= read (fd
, buf
, 1);
251 } while (ret
== -1 && errno
== EINTR
);
255 DEBUG_AGENT ("agent: helper thread's response received\n");
260 /* Need to read response with the inferior stopped. */
261 if (!ptid_equal (ptid
, null_ptid
))
263 struct target_waitstatus status
;
264 int was_non_stop
= non_stop
;
265 /* Stop thread PTID. */
266 DEBUG_AGENT ("agent: stop helper thread\n");
269 struct thread_resume resume_info
;
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);
278 mywait (ptid
, &status
, 0, 0);
283 memset (&status
, 0, sizeof (status
));
284 target_wait (ptid
, &status
, 0);
286 non_stop
= was_non_stop
;
292 if (read_inferior_memory (ipa_sym_addrs
.addr_cmd_buf
,
293 (unsigned char *) cmd
, IPA_CMD_BUF_SIZE
))
295 if (target_read_memory (ipa_sym_addrs
.addr_cmd_buf
, (gdb_byte
*) cmd
,
299 warning ("Error reading command response");