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