2012-03-03 03:08:36 +00:00
|
|
|
/* Shared utility routines for GDB to interact with agent.
|
|
|
|
|
2013-01-01 06:33:28 +00:00
|
|
|
Copyright (C) 2009-2013 Free Software Foundation, Inc.
|
2012-03-03 03:08:36 +00:00
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
#include "server.h"
|
|
|
|
#else
|
|
|
|
#include "defs.h"
|
|
|
|
#include "target.h"
|
|
|
|
#include "inferior.h" /* for non_stop */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "agent.h"
|
PR gdb/7912:
* Makefile.in (SFILES): Add filestuff.c
(COMMON_OBS): Add filestuff.o.
(filestuff.o): New target.
* auto-load.c (auto_load_objfile_script_1): Use
gdb_fopen_cloexec.
* auxv.c (procfs_xfer_auxv): Use gdb_open_cloexec.
* cli/cli-cmds.c (shell_escape): Call close_most_fds.
* cli/cli-dump.c (fopen_with_cleanup): Use gdb_fopen_cloexec.
* common/agent.c (gdb_connect_sync_socket): Use
gdb_socket_cloexec.
* common/filestuff.c: New file.
* common/filestuff.h: New file.
* common/linux-osdata.c (linux_common_core_of_thread)
(command_from_pid, commandline_from_pid, print_source_lines)
(linux_xfer_osdata_shm, linux_xfer_osdata_sem)
(linux_xfer_osdata_msg, linux_xfer_osdata_modules): Use
gdb_fopen_cloexec.
* common/linux-procfs.c (linux_proc_get_int)
(linux_proc_pid_has_state): Use gdb_fopen_cloexec.
* config.in, configure: Rebuild.
* configure.ac: Don't check for sys/socket.h. Check for
fdwalk, pipe2.
* corelow.c (core_open): Use gdb_open_cloexec.
* dwarf2read.c (write_psymtabs_to_index): Use gdb_fopen_cloexec.
* fork-child.c (fork_inferior): Call close_most_fds.
* gdb_bfd.c (gdb_bfd_open): Use gdb_open_cloexec.
* inf-child.c (inf_child_fileio_readlink): Use gdb_open_cloexec.
* linux-nat.c (linux_nat_thread_name, linux_proc_pending_signals):
Use gdb_fopen_cloexec.
(linux_proc_xfer_partial, linux_proc_xfer_spu): Use
gdb_open_cloexec.
(linux_async_pipe): Use gdb_pipe_cloexec.
* remote-fileio.c (remote_fileio_func_open): Use
gdb_open_cloexec.
* remote.c (remote_file_put, remote_file_get): Use
gdb_fopen_cloexec.
* ser-pipe.c (pipe_open): Use gdb_socketpair_cloexec,
close_most_fds.
* ser-tcp.c (net_open): Use gdb_socket_cloexec.
* ser-unix.c (hardwire_open): Use gdb_open_cloexec.
* solib.c (solib_find): Use gdb_open_cloexec.
* source.c (openp, find_and_open_source): Use gdb_open_cloexec.
* tracepoint.c (tfile_start): Use gdb_fopen_cloexec.
(tfile_open): Use gdb_open_cloexec.
* tui/tui-io.c (tui_initialize_io): Use gdb_pipe_cloexec.
* ui-file.c (gdb_fopen): Use gdb_fopen_cloexec.
* xml-support.c (xml_fetch_content_from_file): Use
gdb_fopen_cloexec.
* main.c (captured_main): Call notice_open_fds.
gdbserver
* Makefile.in (SFILES): Add filestuff.c.
(OBS): Add filestuff.o.
(filestuff.o): New target.
* config.in, configure: Rebuild.
* configure.ac: Check for fdwalk, pipe2.
2013-04-22 16:46:15 +00:00
|
|
|
#include "filestuff.h"
|
2012-03-03 03:08:36 +00:00
|
|
|
|
|
|
|
int debug_agent = 0;
|
|
|
|
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
#define DEBUG_AGENT(fmt, args...) \
|
|
|
|
if (debug_agent) \
|
|
|
|
fprintf (stderr, fmt, ##args);
|
|
|
|
#else
|
|
|
|
#define DEBUG_AGENT(fmt, args...) \
|
|
|
|
if (debug_agent) \
|
|
|
|
fprintf_unfiltered (gdb_stdlog, fmt, ##args);
|
|
|
|
#endif
|
|
|
|
|
2012-03-03 03:32:46 +00:00
|
|
|
/* Global flag to determine using agent or not. */
|
|
|
|
int use_agent = 0;
|
|
|
|
|
2012-03-03 03:08:36 +00:00
|
|
|
/* Addresses of in-process agent's symbols both GDB and GDBserver cares
|
|
|
|
about. */
|
|
|
|
|
|
|
|
struct ipa_sym_addresses
|
|
|
|
{
|
|
|
|
CORE_ADDR addr_helper_thread_id;
|
|
|
|
CORE_ADDR addr_cmd_buf;
|
2012-03-03 04:04:35 +00:00
|
|
|
CORE_ADDR addr_capability;
|
2012-03-03 03:08:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Cache of the helper thread id. FIXME: this global should be made
|
|
|
|
per-process. */
|
|
|
|
static unsigned int helper_thread_id = 0;
|
|
|
|
|
|
|
|
static struct
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
int offset;
|
|
|
|
int required;
|
|
|
|
} symbol_list[] = {
|
|
|
|
IPA_SYM(helper_thread_id),
|
|
|
|
IPA_SYM(cmd_buf),
|
2012-03-03 04:04:35 +00:00
|
|
|
IPA_SYM(capability),
|
2012-03-03 03:08:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct ipa_sym_addresses ipa_sym_addrs;
|
|
|
|
|
2012-03-03 04:34:52 +00:00
|
|
|
static int all_agent_symbols_looked_up = 0;
|
|
|
|
|
|
|
|
int
|
|
|
|
agent_loaded_p (void)
|
|
|
|
{
|
|
|
|
return all_agent_symbols_looked_up;
|
|
|
|
}
|
|
|
|
|
2012-03-03 03:08:36 +00:00
|
|
|
/* Look up all symbols needed by agent. Return 0 if all the symbols are
|
|
|
|
found, return non-zero otherwise. */
|
|
|
|
|
|
|
|
int
|
2012-03-03 09:51:29 +00:00
|
|
|
agent_look_up_symbols (void *arg)
|
2012-03-03 03:08:36 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-03-03 04:34:52 +00:00
|
|
|
all_agent_symbols_looked_up = 0;
|
|
|
|
|
2012-03-03 03:08:36 +00:00
|
|
|
for (i = 0; i < sizeof (symbol_list) / sizeof (symbol_list[0]); i++)
|
|
|
|
{
|
|
|
|
CORE_ADDR *addrp =
|
|
|
|
(CORE_ADDR *) ((char *) &ipa_sym_addrs + symbol_list[i].offset);
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
|
|
|
|
if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0)
|
|
|
|
#else
|
2012-03-03 09:51:29 +00:00
|
|
|
struct minimal_symbol *sym =
|
|
|
|
lookup_minimal_symbol (symbol_list[i].name, NULL,
|
|
|
|
(struct objfile *) arg);
|
2012-03-03 03:08:36 +00:00
|
|
|
|
|
|
|
if (sym != NULL)
|
|
|
|
*addrp = SYMBOL_VALUE_ADDRESS (sym);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-03 04:34:52 +00:00
|
|
|
all_agent_symbols_looked_up = 1;
|
2012-03-03 03:08:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
agent_get_helper_thread_id (void)
|
|
|
|
{
|
|
|
|
if (helper_thread_id == 0)
|
|
|
|
{
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
if (read_inferior_memory (ipa_sym_addrs.addr_helper_thread_id,
|
|
|
|
(unsigned char *) &helper_thread_id,
|
|
|
|
sizeof helper_thread_id))
|
|
|
|
#else
|
* gdbarch.sh (target_gdbarch): Remove macro.
(get_target_gdbarch): Rename to target_gdbarch.
* gdbarch.c, gdbarch.h: Rebuild.
* ada-tasks.c, aix-thread.c, amd64-linux-nat.c, arch-utils.c,
arm-tdep.c, auxv.c, breakpoint.c, bsd-uthread.c, corefile.c,
darwin-nat-info.c, dcache.c, dsrec.c, exec.c, fbsd-nat.c,
filesystem.c, gcore.c, gnu-nat.c, i386-darwin-nat.c, i386-nat.c,
ia64-vms-tdep.c, inf-ptrace.c, infcmd.c, jit.c, linux-nat.c,
linux-tdep.c, linux-thread-db.c, m32r-rom.c, memattr.c,
mep-tdep.c, microblaze-tdep.c, mips-linux-nat.c,
mips-linux-tdep.c, mips-tdep.c, monitor.c, moxie-tdep.c,
nto-procfs.c, nto-tdep.c, ppc-linux-nat.c, proc-service.c,
procfs.c, progspace.c, ravenscar-thread.c, record.c,
remote-m32r-sdi.c, remote-mips.c, remote-sim.c, remote.c,
rl78-tdep.c, rs6000-nat.c, rx-tdep.c, s390-nat.c, sol-thread.c,
solib-darwin.c, solib-dsbt.c, solib-frv.c, solib-ia64-hpux.c,
solib-irix.c, solib-pa64.c, solib-som.c, solib-spu.c,
solib-sunos.c, solib-svr4.c, solib.c, spu-linux-nat.c,
spu-multiarch.c, spu-tdep.c, symfile-mem.c, symfile.c, symtab.c,
target-descriptions.c, target.c, target.h, tracepoint.c,
windows-nat.c, windows-tdep.c, xcoffsolib.c, cli/cli-dump.c,
common/agent.c, mi/mi-interp.c, python/py-finishbreakpoint.c,
python/py-inferior.c, python/python.c: Update.
2012-11-09 19:58:03 +00:00
|
|
|
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
2012-03-03 03:08:36 +00:00
|
|
|
gdb_byte buf[4];
|
|
|
|
|
|
|
|
if (target_read_memory (ipa_sym_addrs.addr_helper_thread_id,
|
|
|
|
buf, sizeof buf) == 0)
|
|
|
|
helper_thread_id = extract_unsigned_integer (buf, sizeof buf,
|
|
|
|
byte_order);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("Error reading helper thread's id in lib"));
|
2012-03-03 03:08:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return helper_thread_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#define SOCK_DIR P_tmpdir
|
|
|
|
|
|
|
|
#ifndef UNIX_PATH_MAX
|
|
|
|
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Connects to synchronization socket. PID is the pid of inferior, which is
|
|
|
|
used to set up the connection socket. */
|
|
|
|
|
|
|
|
static int
|
|
|
|
gdb_connect_sync_socket (int pid)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_SYS_UN_H
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
int res, fd;
|
|
|
|
char path[UNIX_PATH_MAX];
|
|
|
|
|
|
|
|
res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", P_tmpdir, pid);
|
|
|
|
if (res >= UNIX_PATH_MAX)
|
|
|
|
return -1;
|
|
|
|
|
PR gdb/7912:
* Makefile.in (SFILES): Add filestuff.c
(COMMON_OBS): Add filestuff.o.
(filestuff.o): New target.
* auto-load.c (auto_load_objfile_script_1): Use
gdb_fopen_cloexec.
* auxv.c (procfs_xfer_auxv): Use gdb_open_cloexec.
* cli/cli-cmds.c (shell_escape): Call close_most_fds.
* cli/cli-dump.c (fopen_with_cleanup): Use gdb_fopen_cloexec.
* common/agent.c (gdb_connect_sync_socket): Use
gdb_socket_cloexec.
* common/filestuff.c: New file.
* common/filestuff.h: New file.
* common/linux-osdata.c (linux_common_core_of_thread)
(command_from_pid, commandline_from_pid, print_source_lines)
(linux_xfer_osdata_shm, linux_xfer_osdata_sem)
(linux_xfer_osdata_msg, linux_xfer_osdata_modules): Use
gdb_fopen_cloexec.
* common/linux-procfs.c (linux_proc_get_int)
(linux_proc_pid_has_state): Use gdb_fopen_cloexec.
* config.in, configure: Rebuild.
* configure.ac: Don't check for sys/socket.h. Check for
fdwalk, pipe2.
* corelow.c (core_open): Use gdb_open_cloexec.
* dwarf2read.c (write_psymtabs_to_index): Use gdb_fopen_cloexec.
* fork-child.c (fork_inferior): Call close_most_fds.
* gdb_bfd.c (gdb_bfd_open): Use gdb_open_cloexec.
* inf-child.c (inf_child_fileio_readlink): Use gdb_open_cloexec.
* linux-nat.c (linux_nat_thread_name, linux_proc_pending_signals):
Use gdb_fopen_cloexec.
(linux_proc_xfer_partial, linux_proc_xfer_spu): Use
gdb_open_cloexec.
(linux_async_pipe): Use gdb_pipe_cloexec.
* remote-fileio.c (remote_fileio_func_open): Use
gdb_open_cloexec.
* remote.c (remote_file_put, remote_file_get): Use
gdb_fopen_cloexec.
* ser-pipe.c (pipe_open): Use gdb_socketpair_cloexec,
close_most_fds.
* ser-tcp.c (net_open): Use gdb_socket_cloexec.
* ser-unix.c (hardwire_open): Use gdb_open_cloexec.
* solib.c (solib_find): Use gdb_open_cloexec.
* source.c (openp, find_and_open_source): Use gdb_open_cloexec.
* tracepoint.c (tfile_start): Use gdb_fopen_cloexec.
(tfile_open): Use gdb_open_cloexec.
* tui/tui-io.c (tui_initialize_io): Use gdb_pipe_cloexec.
* ui-file.c (gdb_fopen): Use gdb_fopen_cloexec.
* xml-support.c (xml_fetch_content_from_file): Use
gdb_fopen_cloexec.
* main.c (captured_main): Call notice_open_fds.
gdbserver
* Makefile.in (SFILES): Add filestuff.c.
(OBS): Add filestuff.o.
(filestuff.o): New target.
* config.in, configure: Rebuild.
* configure.ac: Check for fdwalk, pipe2.
2013-04-22 16:46:15 +00:00
|
|
|
res = fd = gdb_socket_cloexec (PF_UNIX, SOCK_STREAM, 0);
|
2012-03-03 03:08:36 +00:00
|
|
|
if (res == -1)
|
|
|
|
{
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("error opening sync socket: %s"), strerror (errno));
|
2012-03-03 03:08:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr.sun_family = AF_UNIX;
|
|
|
|
|
|
|
|
res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
|
|
|
|
if (res >= UNIX_PATH_MAX)
|
|
|
|
{
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("string overflow allocating socket name"));
|
2012-03-03 03:08:36 +00:00
|
|
|
close (fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
|
|
|
|
if (res == -1)
|
|
|
|
{
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("error connecting sync socket (%s): %s. "
|
|
|
|
"Make sure the directory exists and that it is writable."),
|
|
|
|
path, strerror (errno));
|
2012-03-03 03:08:36 +00:00
|
|
|
close (fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
#else
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Execute an agent command in the inferior. PID is the value of pid of the
|
|
|
|
inferior. CMD is the buffer for command. GDB or GDBserver will store the
|
|
|
|
command into it and fetch the return result from CMD. The interaction
|
|
|
|
between GDB/GDBserver and the agent is synchronized by a synchronization
|
|
|
|
socket. Return zero if success, otherwise return non-zero. */
|
|
|
|
|
|
|
|
int
|
2012-04-16 11:24:47 +00:00
|
|
|
agent_run_command (int pid, const char *cmd, int len)
|
2012-03-03 03:08:36 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int tid = agent_get_helper_thread_id ();
|
|
|
|
ptid_t ptid = ptid_build (pid, tid, 0);
|
|
|
|
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
int ret = write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
|
|
|
(const unsigned char *) cmd, len);
|
|
|
|
#else
|
2013-04-19 15:27:54 +00:00
|
|
|
int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf,
|
|
|
|
(gdb_byte *) cmd, len);
|
2012-03-03 03:08:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("unable to write"));
|
2012-03-03 03:08:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_AGENT ("agent: resumed helper thread\n");
|
|
|
|
|
|
|
|
/* Resume helper thread. */
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
{
|
|
|
|
struct thread_resume resume_info;
|
|
|
|
|
|
|
|
resume_info.thread = ptid;
|
|
|
|
resume_info.kind = resume_continue;
|
2012-05-24 16:51:47 +00:00
|
|
|
resume_info.sig = GDB_SIGNAL_0;
|
2012-03-03 03:08:36 +00:00
|
|
|
(*the_target->resume) (&resume_info, 1);
|
|
|
|
}
|
|
|
|
#else
|
2012-05-24 16:51:47 +00:00
|
|
|
target_resume (ptid, 0, GDB_SIGNAL_0);
|
2012-03-03 03:08:36 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
fd = gdb_connect_sync_socket (pid);
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
char buf[1] = "";
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
DEBUG_AGENT ("agent: signalling helper thread\n");
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ret = write (fd, buf, 1);
|
|
|
|
} while (ret == -1 && errno == EINTR);
|
|
|
|
|
|
|
|
DEBUG_AGENT ("agent: waiting for helper thread's response\n");
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ret = read (fd, buf, 1);
|
|
|
|
} while (ret == -1 && errno == EINTR);
|
|
|
|
|
|
|
|
close (fd);
|
|
|
|
|
|
|
|
DEBUG_AGENT ("agent: helper thread's response received\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Need to read response with the inferior stopped. */
|
|
|
|
if (!ptid_equal (ptid, null_ptid))
|
|
|
|
{
|
|
|
|
struct target_waitstatus status;
|
|
|
|
int was_non_stop = non_stop;
|
|
|
|
/* Stop thread PTID. */
|
|
|
|
DEBUG_AGENT ("agent: stop helper thread\n");
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
{
|
|
|
|
struct thread_resume resume_info;
|
|
|
|
|
|
|
|
resume_info.thread = ptid;
|
|
|
|
resume_info.kind = resume_stop;
|
2012-05-24 16:51:47 +00:00
|
|
|
resume_info.sig = GDB_SIGNAL_0;
|
2012-03-03 03:08:36 +00:00
|
|
|
(*the_target->resume) (&resume_info, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
non_stop = 1;
|
|
|
|
mywait (ptid, &status, 0, 0);
|
|
|
|
#else
|
|
|
|
non_stop = 1;
|
|
|
|
target_stop (ptid);
|
|
|
|
|
|
|
|
memset (&status, 0, sizeof (status));
|
|
|
|
target_wait (ptid, &status, 0);
|
|
|
|
#endif
|
|
|
|
non_stop = was_non_stop;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
|
|
|
(unsigned char *) cmd, IPA_CMD_BUF_SIZE))
|
|
|
|
#else
|
|
|
|
if (target_read_memory (ipa_sym_addrs.addr_cmd_buf, (gdb_byte *) cmd,
|
|
|
|
IPA_CMD_BUF_SIZE))
|
|
|
|
#endif
|
|
|
|
{
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("Error reading command response"));
|
2012-03-03 03:08:36 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2012-03-03 04:04:35 +00:00
|
|
|
|
|
|
|
/* Each bit of it stands for a capability of agent. */
|
|
|
|
static unsigned int agent_capability = 0;
|
|
|
|
|
|
|
|
/* Return true if agent has capability AGENT_CAP, otherwise return false. */
|
|
|
|
|
|
|
|
int
|
|
|
|
agent_capability_check (enum agent_capa agent_capa)
|
|
|
|
{
|
|
|
|
if (agent_capability == 0)
|
|
|
|
{
|
|
|
|
#ifdef GDBSERVER
|
|
|
|
if (read_inferior_memory (ipa_sym_addrs.addr_capability,
|
|
|
|
(unsigned char *) &agent_capability,
|
|
|
|
sizeof agent_capability))
|
|
|
|
#else
|
* gdbarch.sh (target_gdbarch): Remove macro.
(get_target_gdbarch): Rename to target_gdbarch.
* gdbarch.c, gdbarch.h: Rebuild.
* ada-tasks.c, aix-thread.c, amd64-linux-nat.c, arch-utils.c,
arm-tdep.c, auxv.c, breakpoint.c, bsd-uthread.c, corefile.c,
darwin-nat-info.c, dcache.c, dsrec.c, exec.c, fbsd-nat.c,
filesystem.c, gcore.c, gnu-nat.c, i386-darwin-nat.c, i386-nat.c,
ia64-vms-tdep.c, inf-ptrace.c, infcmd.c, jit.c, linux-nat.c,
linux-tdep.c, linux-thread-db.c, m32r-rom.c, memattr.c,
mep-tdep.c, microblaze-tdep.c, mips-linux-nat.c,
mips-linux-tdep.c, mips-tdep.c, monitor.c, moxie-tdep.c,
nto-procfs.c, nto-tdep.c, ppc-linux-nat.c, proc-service.c,
procfs.c, progspace.c, ravenscar-thread.c, record.c,
remote-m32r-sdi.c, remote-mips.c, remote-sim.c, remote.c,
rl78-tdep.c, rs6000-nat.c, rx-tdep.c, s390-nat.c, sol-thread.c,
solib-darwin.c, solib-dsbt.c, solib-frv.c, solib-ia64-hpux.c,
solib-irix.c, solib-pa64.c, solib-som.c, solib-spu.c,
solib-sunos.c, solib-svr4.c, solib.c, spu-linux-nat.c,
spu-multiarch.c, spu-tdep.c, symfile-mem.c, symfile.c, symtab.c,
target-descriptions.c, target.c, target.h, tracepoint.c,
windows-nat.c, windows-tdep.c, xcoffsolib.c, cli/cli-dump.c,
common/agent.c, mi/mi-interp.c, python/py-finishbreakpoint.c,
python/py-inferior.c, python/python.c: Update.
2012-11-09 19:58:03 +00:00
|
|
|
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
|
2012-03-03 04:04:35 +00:00
|
|
|
gdb_byte buf[4];
|
|
|
|
|
|
|
|
if (target_read_memory (ipa_sym_addrs.addr_capability,
|
|
|
|
buf, sizeof buf) == 0)
|
|
|
|
agent_capability = extract_unsigned_integer (buf, sizeof buf,
|
|
|
|
byte_order);
|
|
|
|
else
|
|
|
|
#endif
|
2012-03-04 03:31:09 +00:00
|
|
|
warning (_("Error reading capability of agent"));
|
2012-03-03 04:04:35 +00:00
|
|
|
}
|
|
|
|
return agent_capability & agent_capa;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalidate the cache of agent capability, so we'll read it from inferior
|
|
|
|
again. Call it when launches a new program or reconnect to remote stub. */
|
|
|
|
|
|
|
|
void
|
|
|
|
agent_capability_invalidate (void)
|
|
|
|
{
|
|
|
|
agent_capability = 0;
|
|
|
|
}
|