gdb:
* common/agent.c: New. * common/agent.h: New. * configure.ac: Add `sys/socket.h' and `sys/un.h' to AC_CHECK_HEADERS. * configure, configh.in: Regenerated. gdb/gdbserver: * Makefile.in (OBS): Add agent.o. Add new rule for agent.o. Track dependence of tracepoint.c on agent.h. * tracepoint.c (run_inferior_command_1): (run_inferior_command): Call agent_run_command. (gdb_ust_connect_sync_socket): Deleted. Move it to common/agent.c. (resume_thread, stop_thread): Likewise. (gdb_ust_socket_init): Renamed to ... (gdb_agent_socket_init): ... New. (gdb_ust_thread): Renamed to ... (gdb_agent_helper_thread): ... New. (gdb_ust_init): Move some code to ... (gdb_agent_init): ... here. New. [HAVE_UST]: Call gdb_ust_init. (initialize_tracepoint_ftlib): Call gdb_agent_init. * configure.ac: Add `sys/un.h' to AC_CHECK_HEADERS. * config.in, configure: Regenerated.
This commit is contained in:
parent
9fc0568578
commit
2fa291aca4
@ -1,3 +1,11 @@
|
||||
2012-03-03 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* common/agent.c: New.
|
||||
* common/agent.h: New.
|
||||
* configure.ac: Add `sys/socket.h' and `sys/un.h' to
|
||||
AC_CHECK_HEADERS.
|
||||
* configure, configh.in: Regenerated.
|
||||
|
||||
2012-03-02 Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
* sh-tdep.c (sh_frame_cache): Don't fetch the FPSCR register
|
||||
|
302
gdb/common/agent.c
Normal file
302
gdb/common/agent.c
Normal file
@ -0,0 +1,302 @@
|
||||
/* Shared utility routines for GDB to interact with agent.
|
||||
|
||||
Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
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"
|
||||
|
||||
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
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
/* 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),
|
||||
};
|
||||
|
||||
static struct ipa_sym_addresses ipa_sym_addrs;
|
||||
|
||||
/* Look up all symbols needed by agent. Return 0 if all the symbols are
|
||||
found, return non-zero otherwise. */
|
||||
|
||||
int
|
||||
agent_look_up_symbols (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
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
|
||||
struct minimal_symbol *sym = lookup_minimal_symbol (symbol_list[i].name,
|
||||
NULL, NULL);
|
||||
|
||||
if (sym != NULL)
|
||||
*addrp = SYMBOL_VALUE_ADDRESS (sym);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
DEBUG_AGENT ("symbol `%s' not found\n", symbol_list[i].name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
|
||||
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
|
||||
{
|
||||
warning ("Error reading helper thread's id in lib");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
res = fd = socket (PF_UNIX, SOCK_STREAM, 0);
|
||||
if (res == -1)
|
||||
{
|
||||
warning ("error opening sync socket: %s\n", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
|
||||
if (res >= UNIX_PATH_MAX)
|
||||
{
|
||||
warning ("string overflow allocating socket name\n");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
|
||||
if (res == -1)
|
||||
{
|
||||
warning ("error connecting sync socket (%s): %s. "
|
||||
"Make sure the directory exists and that it is writable.",
|
||||
path, strerror (errno));
|
||||
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
|
||||
agent_run_command (int pid, const char *cmd)
|
||||
{
|
||||
int fd;
|
||||
int tid = agent_get_helper_thread_id ();
|
||||
ptid_t ptid = ptid_build (pid, tid, 0);
|
||||
int len = strlen (cmd) + 1;
|
||||
|
||||
#ifdef GDBSERVER
|
||||
int ret = write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
||||
(const unsigned char *) cmd, len);
|
||||
#else
|
||||
int ret = target_write_memory (ipa_sym_addrs.addr_cmd_buf, cmd, len);
|
||||
#endif
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
warning ("unable to write");
|
||||
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;
|
||||
resume_info.sig = TARGET_SIGNAL_0;
|
||||
(*the_target->resume) (&resume_info, 1);
|
||||
}
|
||||
#else
|
||||
target_resume (ptid, 0, TARGET_SIGNAL_0);
|
||||
#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;
|
||||
resume_info.sig = TARGET_SIGNAL_0;
|
||||
(*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
|
||||
{
|
||||
warning ("Error reading command response");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
37
gdb/common/agent.h
Normal file
37
gdb/common/agent.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* Shared utility routines for GDB to interact with agent.
|
||||
|
||||
Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
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/>. */
|
||||
|
||||
int agent_run_command (int pid, const char *cmd);
|
||||
|
||||
int agent_look_up_symbols (void);
|
||||
|
||||
#define STRINGIZE_1(STR) #STR
|
||||
#define STRINGIZE(STR) STRINGIZE_1(STR)
|
||||
#define IPA_SYM(SYM) \
|
||||
{ \
|
||||
STRINGIZE (gdb_agent_ ## SYM), \
|
||||
offsetof (struct ipa_sym_addresses, addr_ ## SYM) \
|
||||
}
|
||||
|
||||
/* The size in bytes of the buffer used to talk to the IPA helper
|
||||
thread. */
|
||||
#define IPA_CMD_BUF_SIZE 1024
|
||||
|
||||
extern int debug_agent;
|
||||
|
@ -641,6 +641,9 @@
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
@ -650,6 +653,9 @@
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||
#undef HAVE_SYS_UN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/user.h> header file. */
|
||||
#undef HAVE_SYS_USER_H
|
||||
|
||||
|
2
gdb/configure
vendored
2
gdb/configure
vendored
@ -11629,7 +11629,7 @@ for ac_header in nlist.h machine/reg.h poll.h sys/poll.h proc_service.h \
|
||||
sys/reg.h sys/debugreg.h sys/select.h sys/syscall.h \
|
||||
sys/types.h sys/wait.h wait.h termios.h termio.h \
|
||||
sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h \
|
||||
dlfcn.h
|
||||
dlfcn.h sys/socket.h sys/un.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
|
@ -974,7 +974,7 @@ AC_CHECK_HEADERS([nlist.h machine/reg.h poll.h sys/poll.h proc_service.h \
|
||||
sys/reg.h sys/debugreg.h sys/select.h sys/syscall.h \
|
||||
sys/types.h sys/wait.h wait.h termios.h termio.h \
|
||||
sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h \
|
||||
dlfcn.h])
|
||||
dlfcn.h sys/socket.h sys/un.h])
|
||||
AC_CHECK_HEADERS(link.h, [], [],
|
||||
[#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
|
@ -1,3 +1,24 @@
|
||||
2012-03-03 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* Makefile.in (OBS): Add agent.o.
|
||||
Add new rule for agent.o.
|
||||
Track dependence of tracepoint.c on agent.h.
|
||||
* tracepoint.c (run_inferior_command_1):
|
||||
(run_inferior_command): Call agent_run_command.
|
||||
(gdb_ust_connect_sync_socket): Deleted. Move it to
|
||||
common/agent.c.
|
||||
(resume_thread, stop_thread): Likewise.
|
||||
(gdb_ust_socket_init): Renamed to ...
|
||||
(gdb_agent_socket_init): ... New.
|
||||
(gdb_ust_thread): Renamed to ...
|
||||
(gdb_agent_helper_thread): ... New.
|
||||
(gdb_ust_init): Move some code to ...
|
||||
(gdb_agent_init): ... here. New.
|
||||
[HAVE_UST]: Call gdb_ust_init.
|
||||
(initialize_tracepoint_ftlib): Call gdb_agent_init.
|
||||
* configure.ac: Add `sys/un.h' to AC_CHECK_HEADERS.
|
||||
* config.in, configure: Regenerated.
|
||||
|
||||
2012-03-02 Pedro Alves <palves@redhat.com>
|
||||
|
||||
* inferiors.c (add_pid_to_list, pull_pid_from_list): Delete.
|
||||
|
@ -134,7 +134,7 @@ LIBOBJS = @LIBOBJS@
|
||||
SOURCES = $(SFILES)
|
||||
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
|
||||
|
||||
OBS = ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
|
||||
OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
|
||||
utils.o version.o \
|
||||
mem-break.o hostio.o event-loop.o tracepoint.o \
|
||||
xml-utils.o common-utils.o ptid.o buffer.o \
|
||||
@ -337,6 +337,7 @@ signals_def = $(srcdir)/../../include/gdb/signals.def
|
||||
signals_h = $(srcdir)/../../include/gdb/signals.h $(signals_def)
|
||||
ptid_h = $(srcdir)/../common/ptid.h
|
||||
ax_h = $(srcdir)/ax.h
|
||||
agent_h = $(srcdir)/../common/agent.h
|
||||
linux_osdata_h = $(srcdir)/../common/linux-osdata.h
|
||||
server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h \
|
||||
$(srcdir)/mem-break.h $(srcdir)/../common/gdb_signals.h \
|
||||
@ -403,7 +404,7 @@ server.o: server.c $(server_h)
|
||||
target.o: target.c $(server_h)
|
||||
thread-db.o: thread-db.c $(server_h) $(linux_low_h) $(gdb_proc_service_h) \
|
||||
$(gdb_thread_db_h)
|
||||
tracepoint.o: tracepoint.c $(server_h) $(ax_h)
|
||||
tracepoint.o: tracepoint.c $(server_h) $(ax_h) $(agent_h)
|
||||
utils.o: utils.c $(server_h)
|
||||
gdbreplay.o: gdbreplay.c config.h
|
||||
dll.o: dll.c $(server_h)
|
||||
@ -429,6 +430,9 @@ ptid.o: ../common/ptid.c $(ptid_h)
|
||||
buffer.o: ../common/buffer.c $(server_h)
|
||||
$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER
|
||||
|
||||
agent.o: ../common/agent.c $(server_h) $(agent_h)
|
||||
$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER
|
||||
|
||||
# We build memmem.c without -Werror because this file is not under
|
||||
# our control. On LynxOS, the compiler generates some warnings
|
||||
# because str-two-way.h uses a constant (MAX_SIZE) whose definition
|
||||
|
@ -184,6 +184,9 @@
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/un.h> header file. */
|
||||
#undef HAVE_SYS_UN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
|
2
gdb/gdbserver/configure
vendored
2
gdb/gdbserver/configure
vendored
@ -4149,7 +4149,7 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
for ac_header in sgtty.h termio.h termios.h sys/reg.h string.h proc_service.h sys/procfs.h thread_db.h linux/elf.h stdlib.h unistd.h errno.h fcntl.h signal.h sys/file.h malloc.h sys/ioctl.h netinet/in.h sys/socket.h netdb.h netinet/tcp.h arpa/inet.h sys/wait.h
|
||||
for ac_header in sgtty.h termio.h termios.h sys/reg.h string.h proc_service.h sys/procfs.h thread_db.h linux/elf.h stdlib.h unistd.h errno.h fcntl.h signal.h sys/file.h malloc.h sys/ioctl.h netinet/in.h sys/socket.h netdb.h netinet/tcp.h arpa/inet.h sys/wait.h sys/un.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
|
@ -42,7 +42,7 @@ AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
|
||||
stdlib.h unistd.h dnl
|
||||
errno.h fcntl.h signal.h sys/file.h malloc.h dnl
|
||||
sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
|
||||
netinet/tcp.h arpa/inet.h sys/wait.h)
|
||||
netinet/tcp.h arpa/inet.h sys/wait.h sys/un.h)
|
||||
AC_CHECK_FUNCS(pread pwrite pread64 readlink)
|
||||
AC_REPLACE_FUNCS(memmem vasprintf vsnprintf)
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "server.h"
|
||||
#include "agent.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
@ -178,18 +180,8 @@ struct ipa_sym_addresses
|
||||
CORE_ADDR addr_get_trace_state_variable_value;
|
||||
CORE_ADDR addr_set_trace_state_variable_value;
|
||||
CORE_ADDR addr_ust_loaded;
|
||||
CORE_ADDR addr_helper_thread_id;
|
||||
CORE_ADDR addr_cmd_buf;
|
||||
};
|
||||
|
||||
#define STRINGIZE_1(STR) #STR
|
||||
#define STRINGIZE(STR) STRINGIZE_1(STR)
|
||||
#define IPA_SYM(SYM) \
|
||||
{ \
|
||||
STRINGIZE (gdb_agent_ ## SYM), \
|
||||
offsetof (struct ipa_sym_addresses, addr_ ## SYM) \
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
@ -225,11 +217,9 @@ static struct
|
||||
IPA_SYM(get_trace_state_variable_value),
|
||||
IPA_SYM(set_trace_state_variable_value),
|
||||
IPA_SYM(ust_loaded),
|
||||
IPA_SYM(helper_thread_id),
|
||||
IPA_SYM(cmd_buf),
|
||||
};
|
||||
|
||||
struct ipa_sym_addresses ipa_sym_addrs;
|
||||
static struct ipa_sym_addresses ipa_sym_addrs;
|
||||
|
||||
int all_tracepoint_symbols_looked_up;
|
||||
|
||||
@ -348,6 +338,9 @@ tracepoint_look_up_symbols (void)
|
||||
}
|
||||
}
|
||||
|
||||
if (agent_look_up_symbols () != 0)
|
||||
return;
|
||||
|
||||
all_tracepoint_symbols_looked_up = 1;
|
||||
}
|
||||
|
||||
@ -1242,10 +1235,6 @@ static LONGEST get_timestamp (void);
|
||||
#define cmpxchg(mem, oldval, newval) \
|
||||
__sync_val_compare_and_swap (mem, oldval, newval)
|
||||
|
||||
/* The size in bytes of the buffer used to talk to the IPA helper
|
||||
thread. */
|
||||
#define CMD_BUF_SIZE 1024
|
||||
|
||||
/* Record that an error occurred during expression evaluation. */
|
||||
|
||||
static void
|
||||
@ -2217,7 +2206,7 @@ cmd_qtinit (char *packet)
|
||||
static void
|
||||
unprobe_marker_at (CORE_ADDR address)
|
||||
{
|
||||
char cmd[CMD_BUF_SIZE];
|
||||
char cmd[IPA_CMD_BUF_SIZE];
|
||||
|
||||
sprintf (cmd, "unprobe_marker_at:%s", paddress (address));
|
||||
run_inferior_command (cmd);
|
||||
@ -2791,7 +2780,7 @@ have_fast_tracepoint_trampoline_buffer (char *buf)
|
||||
static int
|
||||
probe_marker_at (CORE_ADDR address, char *errout)
|
||||
{
|
||||
char cmd[CMD_BUF_SIZE];
|
||||
char cmd[IPA_CMD_BUF_SIZE];
|
||||
int err;
|
||||
|
||||
sprintf (cmd, "probe_marker_at:%s", paddress (address));
|
||||
@ -6144,7 +6133,7 @@ upload_fast_traceframes (void)
|
||||
#ifdef IN_PROCESS_AGENT
|
||||
|
||||
IP_AGENT_EXPORT int ust_loaded;
|
||||
IP_AGENT_EXPORT char cmd_buf[CMD_BUF_SIZE];
|
||||
IP_AGENT_EXPORT char cmd_buf[IPA_CMD_BUF_SIZE];
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
@ -6393,94 +6382,8 @@ static struct ltt_available_probe gdb_ust_probe =
|
||||
#endif /* HAVE_UST */
|
||||
#endif /* IN_PROCESS_AGENT */
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
|
||||
#endif
|
||||
|
||||
/* Where we put the socked used for synchronization. */
|
||||
#define SOCK_DIR P_tmpdir
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
static int
|
||||
gdb_ust_connect_sync_socket (int pid)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
int res, fd;
|
||||
char path[UNIX_PATH_MAX];
|
||||
|
||||
res = xsnprintf (path, UNIX_PATH_MAX, "%s/gdb_ust%d", SOCK_DIR, pid);
|
||||
if (res >= UNIX_PATH_MAX)
|
||||
{
|
||||
trace_debug ("string overflow allocating socket name");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = fd = socket (PF_UNIX, SOCK_STREAM, 0);
|
||||
if (res == -1)
|
||||
{
|
||||
warning ("error opening sync socket: %s\n", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
|
||||
res = xsnprintf (addr.sun_path, UNIX_PATH_MAX, "%s", path);
|
||||
if (res >= UNIX_PATH_MAX)
|
||||
{
|
||||
warning ("string overflow allocating socket name\n");
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = connect (fd, (struct sockaddr *) &addr, sizeof (addr));
|
||||
if (res == -1)
|
||||
{
|
||||
warning ("error connecting sync socket (%s): %s. "
|
||||
"Make sure the directory exists and that it is writable.",
|
||||
path, strerror (errno));
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Resume thread PTID. */
|
||||
|
||||
static void
|
||||
resume_thread (ptid_t ptid)
|
||||
{
|
||||
struct thread_resume resume_info;
|
||||
|
||||
resume_info.thread = ptid;
|
||||
resume_info.kind = resume_continue;
|
||||
resume_info.sig = TARGET_SIGNAL_0;
|
||||
(*the_target->resume) (&resume_info, 1);
|
||||
}
|
||||
|
||||
/* Stop thread PTID. */
|
||||
|
||||
static void
|
||||
stop_thread (ptid_t ptid)
|
||||
{
|
||||
struct thread_resume resume_info;
|
||||
|
||||
resume_info.thread = ptid;
|
||||
resume_info.kind = resume_stop;
|
||||
resume_info.sig = TARGET_SIGNAL_0;
|
||||
(*the_target->resume) (&resume_info, 1);
|
||||
}
|
||||
|
||||
/* Ask the in-process agent to run a command. Since we don't want to
|
||||
have to handle the IPA hitting breakpoints while running the
|
||||
command, we pause all threads, remove all breakpoints, and then set
|
||||
@ -6492,91 +6395,14 @@ static int
|
||||
run_inferior_command (char *cmd)
|
||||
{
|
||||
int err = -1;
|
||||
int fd = -1;
|
||||
int pid = ptid_get_pid (current_inferior->entry.id);
|
||||
int tid;
|
||||
ptid_t ptid = null_ptid;
|
||||
|
||||
trace_debug ("run_inferior_command: running: %s", cmd);
|
||||
|
||||
pause_all (0);
|
||||
uninsert_all_breakpoints ();
|
||||
|
||||
if (read_inferior_integer (ipa_sym_addrs.addr_helper_thread_id, &tid))
|
||||
{
|
||||
warning ("Error reading helper thread's id in lib");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tid == 0)
|
||||
{
|
||||
warning ("helper thread not initialized yet");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
||||
(unsigned char *) cmd, strlen (cmd) + 1))
|
||||
{
|
||||
warning ("Error writing command");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ptid = ptid_build (pid, tid, 0);
|
||||
|
||||
resume_thread (ptid);
|
||||
|
||||
fd = gdb_ust_connect_sync_socket (pid);
|
||||
if (fd >= 0)
|
||||
{
|
||||
char buf[1] = "";
|
||||
int ret;
|
||||
|
||||
trace_debug ("signalling helper thread");
|
||||
|
||||
do
|
||||
{
|
||||
ret = write (fd, buf, 1);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
trace_debug ("waiting for helper thread's response");
|
||||
|
||||
do
|
||||
{
|
||||
ret = read (fd, buf, 1);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
|
||||
close (fd);
|
||||
|
||||
trace_debug ("helper thread's response received");
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
/* Need to read response with the inferior stopped. */
|
||||
if (!ptid_equal (ptid, null_ptid))
|
||||
{
|
||||
int was_non_stop = non_stop;
|
||||
struct target_waitstatus status;
|
||||
|
||||
stop_thread (ptid);
|
||||
non_stop = 1;
|
||||
mywait (ptid, &status, 0, 0);
|
||||
non_stop = was_non_stop;
|
||||
}
|
||||
|
||||
if (fd >= 0)
|
||||
{
|
||||
if (read_inferior_memory (ipa_sym_addrs.addr_cmd_buf,
|
||||
(unsigned char *) cmd, CMD_BUF_SIZE))
|
||||
{
|
||||
warning ("Error reading command response");
|
||||
}
|
||||
else
|
||||
{
|
||||
err = 0;
|
||||
trace_debug ("run_inferior_command: response: %s", cmd);
|
||||
}
|
||||
}
|
||||
err = agent_run_command (pid, (const char *) cmd);
|
||||
|
||||
reinsert_all_breakpoints ();
|
||||
unpause_all (0);
|
||||
@ -6584,24 +6410,22 @@ run_inferior_command (char *cmd)
|
||||
return err;
|
||||
}
|
||||
|
||||
#else /* HAVE_UST */
|
||||
|
||||
static int
|
||||
run_inferior_command (char *cmd)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
#else /* !IN_PROCESS_AGENT */
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path)
|
||||
#endif
|
||||
|
||||
/* Where we put the socked used for synchronization. */
|
||||
#define SOCK_DIR P_tmpdir
|
||||
|
||||
/* Thread ID of the helper thread. GDBserver reads this to know which
|
||||
is the help thread. This is an LWP id on Linux. */
|
||||
int helper_thread_id;
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
static int
|
||||
init_named_socket (const char *name)
|
||||
{
|
||||
@ -6654,7 +6478,7 @@ init_named_socket (const char *name)
|
||||
}
|
||||
|
||||
static int
|
||||
gdb_ust_socket_init (void)
|
||||
gdb_agent_socket_init (void)
|
||||
{
|
||||
int result, fd;
|
||||
char name[UNIX_PATH_MAX];
|
||||
@ -6676,17 +6500,7 @@ gdb_ust_socket_init (void)
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Return an hexstr version of the STR C string, fit for sending to
|
||||
GDB. */
|
||||
|
||||
static char *
|
||||
cstr_to_hexstr (const char *str)
|
||||
{
|
||||
int len = strlen (str);
|
||||
char *hexstr = xmalloc (len * 2 + 1);
|
||||
convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
|
||||
return hexstr;
|
||||
}
|
||||
#ifdef HAVE_UST
|
||||
|
||||
/* The next marker to be returned on a qTsSTM command. */
|
||||
static const struct marker *next_st;
|
||||
@ -6726,6 +6540,18 @@ next_marker (const struct marker *m)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return an hexstr version of the STR C string, fit for sending to
|
||||
GDB. */
|
||||
|
||||
static char *
|
||||
cstr_to_hexstr (const char *str)
|
||||
{
|
||||
int len = strlen (str);
|
||||
char *hexstr = xmalloc (len * 2 + 1);
|
||||
convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
|
||||
return hexstr;
|
||||
}
|
||||
|
||||
/* Compose packet that is the response to the qTsSTM/qTfSTM/qTSTMat
|
||||
packets. */
|
||||
|
||||
@ -6886,16 +6712,29 @@ cmd_qtstmat (char *packet)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
gdb_ust_init (void)
|
||||
{
|
||||
if (!dlsym_ust ())
|
||||
return;
|
||||
|
||||
USTF(ltt_probe_register) (&gdb_ust_probe);
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/* Helper thread of agent. */
|
||||
|
||||
static void *
|
||||
gdb_ust_thread (void *arg)
|
||||
gdb_agent_helper_thread (void *arg)
|
||||
{
|
||||
int listen_fd;
|
||||
|
||||
while (1)
|
||||
{
|
||||
listen_fd = gdb_ust_socket_init ();
|
||||
listen_fd = gdb_agent_socket_init ();
|
||||
|
||||
if (helper_thread_id == 0)
|
||||
helper_thread_id = syscall (SYS_gettid);
|
||||
@ -6945,6 +6784,7 @@ gdb_ust_thread (void *arg)
|
||||
|
||||
if (cmd_buf[0])
|
||||
{
|
||||
#ifdef HAVE_UST
|
||||
if (strcmp ("qTfSTM", cmd_buf) == 0)
|
||||
{
|
||||
cmd_qtfstm (cmd_buf);
|
||||
@ -6971,12 +6811,7 @@ gdb_ust_thread (void *arg)
|
||||
{
|
||||
cmd_qtstmat (cmd_buf);
|
||||
}
|
||||
else if (strcmp (cmd_buf, "help") == 0)
|
||||
{
|
||||
strcpy (cmd_buf, "for help, press F1\n");
|
||||
}
|
||||
else
|
||||
strcpy (cmd_buf, "");
|
||||
#endif /* HAVE_UST */
|
||||
}
|
||||
|
||||
/* Fix compiler's warning: ignoring return value of 'write'. */
|
||||
@ -6989,18 +6824,16 @@ gdb_ust_thread (void *arg)
|
||||
}
|
||||
|
||||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static void
|
||||
gdb_ust_init (void)
|
||||
gdb_agent_init (void)
|
||||
{
|
||||
int res;
|
||||
pthread_t thread;
|
||||
sigset_t new_mask;
|
||||
sigset_t orig_mask;
|
||||
|
||||
if (!dlsym_ust ())
|
||||
return;
|
||||
|
||||
/* We want the helper thread to be as transparent as possible, so
|
||||
have it inherit an all-signals-blocked mask. */
|
||||
|
||||
@ -7011,7 +6844,7 @@ gdb_ust_init (void)
|
||||
|
||||
res = pthread_create (&thread,
|
||||
NULL,
|
||||
gdb_ust_thread,
|
||||
gdb_agent_helper_thread,
|
||||
NULL);
|
||||
|
||||
res = pthread_sigmask (SIG_SETMASK, &orig_mask, NULL);
|
||||
@ -7021,11 +6854,11 @@ gdb_ust_init (void)
|
||||
while (helper_thread_id == 0)
|
||||
usleep (1);
|
||||
|
||||
USTF(ltt_probe_register) (&gdb_ust_probe);
|
||||
#ifdef HAVE_UST
|
||||
gdb_ust_init ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
@ -7056,9 +6889,7 @@ initialize_tracepoint_ftlib (void)
|
||||
{
|
||||
initialize_tracepoint ();
|
||||
|
||||
#ifdef HAVE_UST
|
||||
gdb_ust_init ();
|
||||
#endif
|
||||
gdb_agent_init ();
|
||||
}
|
||||
|
||||
#endif /* IN_PROCESS_AGENT */
|
||||
|
Loading…
x
Reference in New Issue
Block a user