mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 04:24:43 +00:00
gdbserver: remove UST (static tracepoint) support (part 1)
UST support in gdbserver is substantially outdated. Simon says: ...[having HAVE_UST defined] never happens nowadays because it used a version of lttng-ust that has been deprecated for a loooong time (the 0.x series). So everything in HAVE_UST just bitrots. It might be possible to update all this code to use lttng-ust 2.x (1.x never existed), but I don't think it's going to happen unless somebody specifically asks for it. I would suggest removing support for UST from gdbserver. ...If we ever want to resurrect the support for UST and port to 2.x, we can get the code from the git history. This patch removes the support, mostly mechanically by deleting code guarded by `#ifdef HAVE_UST`. After these removals, `struct static_tracepoint_ctx` becomes unused. So, remove it, too. The following patches remove more code. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
2
gdb/NEWS
2
gdb/NEWS
@@ -22,6 +22,8 @@
|
||||
>end
|
||||
>end
|
||||
|
||||
* UST (static tracepoint) support from gdbserver has been removed.
|
||||
|
||||
* New commands
|
||||
|
||||
maintenance check psymtabs
|
||||
|
||||
@@ -24184,21 +24184,13 @@ of a multi-process mode debug session.
|
||||
@subsection Tracepoints support in @code{gdbserver}
|
||||
@cindex tracepoints support in @code{gdbserver}
|
||||
|
||||
On some targets, @code{gdbserver} supports tracepoints, fast
|
||||
tracepoints and static tracepoints.
|
||||
On some targets, @code{gdbserver} supports tracepoints and fast
|
||||
tracepoints.
|
||||
|
||||
For fast or static tracepoints to work, a special library called the
|
||||
For fast tracepoints to work, a special library called the
|
||||
@dfn{in-process agent} (IPA), must be loaded in the inferior process.
|
||||
This library is built and distributed as an integral part of
|
||||
@code{gdbserver}. In addition, support for static tracepoints
|
||||
requires building the in-process agent library with static tracepoints
|
||||
support. At present, the UST (LTTng Userspace Tracer,
|
||||
@url{http://lttng.org/ust}) tracing engine is supported. This support
|
||||
is automatically available if UST development headers are found in the
|
||||
standard include path when @code{gdbserver} is built, or if
|
||||
@code{gdbserver} was explicitly configured using @option{--with-ust}
|
||||
to point at such headers. You can explicitly disable the support
|
||||
using @option{--with-ust=no}.
|
||||
@code{gdbserver}.
|
||||
|
||||
There are several ways to load the in-process agent in your program:
|
||||
|
||||
|
||||
@@ -104,10 +104,6 @@ LIBIBERTY = $(LIBIBERTY_NORMAL)
|
||||
GDBSUPPORT_BUILDDIR = ../gdbsupport
|
||||
GDBSUPPORT = $(GDBSUPPORT_BUILDDIR)/libgdbsupport.a
|
||||
|
||||
# Where is ust? These will be empty if ust was not available.
|
||||
ustlibs = @ustlibs@
|
||||
ustinc = @ustinc@
|
||||
|
||||
# gnulib
|
||||
GNULIB_PARENT_DIR = ..
|
||||
include $(GNULIB_PARENT_DIR)/gnulib/Makefile.gnulib.inc
|
||||
@@ -489,10 +485,6 @@ MAKEOVERRIDES =
|
||||
regdat_sh = $(srcdir)/../gdb/regformats/regdat.sh
|
||||
osabi_def = $(srcdir)/../gdbsupport/osabi.def
|
||||
|
||||
UST_CFLAGS = \
|
||||
$(ustinc) \
|
||||
-DCONFIG_UST_GDB_INTEGRATION
|
||||
|
||||
# Undo gnulib replacements for the IPA shared library build.
|
||||
# The gnulib headers are still needed, but gnulib is not linked
|
||||
# into the IPA lib so replacement apis don't work.
|
||||
@@ -506,7 +498,6 @@ UNDO_GNULIB_CFLAGS = \
|
||||
# the first place.
|
||||
IPAGENT_CFLAGS = \
|
||||
$(INTERNAL_CFLAGS) \
|
||||
$(UST_CFLAGS) \
|
||||
$(UNDO_GNULIB_CFLAGS) \
|
||||
-fPIC -DIN_PROCESS_AGENT \
|
||||
-fvisibility=hidden
|
||||
|
||||
@@ -384,9 +384,6 @@
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if UST is available */
|
||||
#undef HAVE_UST
|
||||
|
||||
/* Define to 1 if you have the `vfork' function. */
|
||||
#undef HAVE_VFORK
|
||||
|
||||
|
||||
94
gdbserver/configure
vendored
94
gdbserver/configure
vendored
@@ -637,8 +637,6 @@ REPORT_BUGS_TO
|
||||
PKGVERSION
|
||||
WERROR_CFLAGS
|
||||
WARN_CFLAGS
|
||||
ustinc
|
||||
ustlibs
|
||||
CCDEPMODE
|
||||
CONFIG_SRC_SUBDIR
|
||||
CATOBJEXT
|
||||
@@ -775,9 +773,6 @@ with_libiconv_prefix
|
||||
with_libiconv_type
|
||||
with_libintl_prefix
|
||||
with_libintl_type
|
||||
with_ust
|
||||
with_ust_include
|
||||
with_ust_lib
|
||||
enable_werror
|
||||
enable_build_warnings
|
||||
enable_gdb_build_warnings
|
||||
@@ -1451,11 +1446,6 @@ Optional Packages:
|
||||
--with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib
|
||||
--without-libintl-prefix don't search for libintl in includedir and libdir
|
||||
--with-libintl-type=TYPE type of library to search for (auto/static/shared)
|
||||
--with-ust=PATH Specify prefix directory for the installed UST package
|
||||
Equivalent to --with-ust-include=PATH/include
|
||||
plus --with-ust-lib=PATH/lib
|
||||
--with-ust-include=PATH Specify directory for installed UST include files
|
||||
--with-ust-lib=PATH Specify the directory for the installed UST library
|
||||
--with-pkgversion=PKG Use PKG in the version string in place of "GDB"
|
||||
--with-bugurl=URL Direct users to URL to report a bug
|
||||
--with-libthread-db=PATH
|
||||
@@ -13601,90 +13591,6 @@ _ACEOF
|
||||
fi
|
||||
|
||||
|
||||
# Check for UST
|
||||
ustlibs=""
|
||||
ustinc=""
|
||||
|
||||
|
||||
# Check whether --with-ust was given.
|
||||
if test "${with_ust+set}" = set; then :
|
||||
withval=$with_ust;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-ust_include was given.
|
||||
if test "${with_ust_include+set}" = set; then :
|
||||
withval=$with_ust_include;
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --with-ust_lib was given.
|
||||
if test "${with_ust_lib+set}" = set; then :
|
||||
withval=$with_ust_lib;
|
||||
fi
|
||||
|
||||
|
||||
case $with_ust in
|
||||
no)
|
||||
ustlibs=
|
||||
ustinc=
|
||||
;;
|
||||
"" | yes)
|
||||
ustlibs=" -lust "
|
||||
ustinc=""
|
||||
;;
|
||||
*)
|
||||
ustlibs="-L$with_ust/lib -lust"
|
||||
ustinc="-I$with_ust/include "
|
||||
;;
|
||||
esac
|
||||
if test "x$with_ust_include" != x; then
|
||||
ustinc="-I$with_ust_include "
|
||||
fi
|
||||
if test "x$with_ust_lib" != x; then
|
||||
ustlibs="-L$with_ust_lib -lust"
|
||||
fi
|
||||
|
||||
if test "x$with_ust" != "xno"; then
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ustinc"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ust" >&5
|
||||
$as_echo_n "checking for ust... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#define CONFIG_UST_GDB_INTEGRATION
|
||||
#include <ust/ust.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; };
|
||||
|
||||
$as_echo "#define HAVE_UST 1" >>confdefs.h
|
||||
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
ustlibs= ; ustinc=
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
fi
|
||||
|
||||
# Flags needed for UST
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the compiler type" >&5
|
||||
|
||||
@@ -108,61 +108,6 @@ AC_CHECK_FUNCS([ \
|
||||
# Check the return and argument types of ptrace.
|
||||
GDB_AC_PTRACE
|
||||
|
||||
# Check for UST
|
||||
ustlibs=""
|
||||
ustinc=""
|
||||
|
||||
AC_ARG_WITH(ust, [ --with-ust=PATH Specify prefix directory for the installed UST package
|
||||
Equivalent to --with-ust-include=PATH/include
|
||||
plus --with-ust-lib=PATH/lib])
|
||||
AC_ARG_WITH(ust_include, [ --with-ust-include=PATH Specify directory for installed UST include files])
|
||||
AC_ARG_WITH(ust_lib, [ --with-ust-lib=PATH Specify the directory for the installed UST library])
|
||||
|
||||
case $with_ust in
|
||||
no)
|
||||
ustlibs=
|
||||
ustinc=
|
||||
;;
|
||||
"" | yes)
|
||||
ustlibs=" -lust "
|
||||
ustinc=""
|
||||
;;
|
||||
*)
|
||||
ustlibs="-L$with_ust/lib -lust"
|
||||
ustinc="-I$with_ust/include "
|
||||
;;
|
||||
esac
|
||||
if test "x$with_ust_include" != x; then
|
||||
ustinc="-I$with_ust_include "
|
||||
fi
|
||||
if test "x$with_ust_lib" != x; then
|
||||
ustlibs="-L$with_ust_lib -lust"
|
||||
fi
|
||||
|
||||
if test "x$with_ust" != "xno"; then
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $ustinc"
|
||||
AC_MSG_CHECKING([for ust])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[
|
||||
#define CONFIG_UST_GDB_INTEGRATION
|
||||
#include <ust/ust.h>
|
||||
],
|
||||
[]
|
||||
)],
|
||||
[AC_MSG_RESULT([yes]);
|
||||
AC_DEFINE(HAVE_UST, 1, [Define if UST is available])],
|
||||
[AC_MSG_RESULT([no])
|
||||
ustlibs= ; ustinc= ]
|
||||
)
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
fi
|
||||
|
||||
# Flags needed for UST
|
||||
AC_SUBST(ustlibs)
|
||||
AC_SUBST(ustinc)
|
||||
|
||||
AM_GDB_COMPILER_TYPE
|
||||
AM_GDB_WARNINGS
|
||||
|
||||
|
||||
@@ -76,94 +76,6 @@ get_raw_reg (const unsigned char *raw_regs, int regnum)
|
||||
return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
#include <ust/processor.h>
|
||||
|
||||
/* "struct registers" is the UST object type holding the registers at
|
||||
the time of the static tracepoint marker call. This doesn't
|
||||
contain RIP, but we know what it must have been (the marker
|
||||
address). */
|
||||
|
||||
#define ST_REGENTRY(REG) \
|
||||
{ \
|
||||
offsetof (struct registers, REG), \
|
||||
sizeof (((struct registers *) NULL)->REG) \
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
int offset;
|
||||
int size;
|
||||
} x86_64_st_collect_regmap[] =
|
||||
{
|
||||
ST_REGENTRY(rax),
|
||||
ST_REGENTRY(rbx),
|
||||
ST_REGENTRY(rcx),
|
||||
ST_REGENTRY(rdx),
|
||||
ST_REGENTRY(rsi),
|
||||
ST_REGENTRY(rdi),
|
||||
ST_REGENTRY(rbp),
|
||||
ST_REGENTRY(rsp),
|
||||
ST_REGENTRY(r8),
|
||||
ST_REGENTRY(r9),
|
||||
ST_REGENTRY(r10),
|
||||
ST_REGENTRY(r11),
|
||||
ST_REGENTRY(r12),
|
||||
ST_REGENTRY(r13),
|
||||
ST_REGENTRY(r14),
|
||||
ST_REGENTRY(r15),
|
||||
{ -1, 0 },
|
||||
ST_REGENTRY(rflags),
|
||||
ST_REGENTRY(cs),
|
||||
ST_REGENTRY(ss),
|
||||
};
|
||||
|
||||
#define X86_64_NUM_ST_COLLECT_GREGS \
|
||||
(sizeof (x86_64_st_collect_regmap) / sizeof (x86_64_st_collect_regmap[0]))
|
||||
|
||||
/* GDB's RIP register number. */
|
||||
#define AMD64_RIP_REGNUM 16
|
||||
|
||||
void
|
||||
supply_static_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *buf,
|
||||
CORE_ADDR pc)
|
||||
{
|
||||
int i;
|
||||
unsigned long newpc = pc;
|
||||
|
||||
supply_register (regcache, AMD64_RIP_REGNUM, &newpc);
|
||||
|
||||
for (i = 0; i < X86_64_NUM_ST_COLLECT_GREGS; i++)
|
||||
if (x86_64_st_collect_regmap[i].offset != -1)
|
||||
{
|
||||
switch (x86_64_st_collect_regmap[i].size)
|
||||
{
|
||||
case 8:
|
||||
supply_register (regcache, i,
|
||||
((char *) buf)
|
||||
+ x86_64_st_collect_regmap[i].offset);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
unsigned long reg
|
||||
= * (short *) (((char *) buf)
|
||||
+ x86_64_st_collect_regmap[i].offset);
|
||||
reg &= 0xffff;
|
||||
supply_register (regcache, i, ®);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
internal_error ("unhandled register size: %d",
|
||||
x86_64_st_collect_regmap[i].size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
/* Return target_desc to use for IPA, given the tdesc index passed by
|
||||
gdbserver. */
|
||||
|
||||
|
||||
@@ -111,83 +111,6 @@ get_raw_reg (const unsigned char *raw_regs, int regnum)
|
||||
return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
#include <ust/processor.h>
|
||||
|
||||
/* "struct registers" is the UST object type holding the registers at
|
||||
the time of the static tracepoint marker call. This doesn't
|
||||
contain EIP, but we know what it must have been (the marker
|
||||
address). */
|
||||
|
||||
#define ST_REGENTRY(REG) \
|
||||
{ \
|
||||
offsetof (struct registers, REG), \
|
||||
sizeof (((struct registers *) NULL)->REG) \
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
int offset;
|
||||
int size;
|
||||
} i386_st_collect_regmap[] =
|
||||
{
|
||||
ST_REGENTRY(eax),
|
||||
ST_REGENTRY(ecx),
|
||||
ST_REGENTRY(edx),
|
||||
ST_REGENTRY(ebx),
|
||||
ST_REGENTRY(esp),
|
||||
ST_REGENTRY(ebp),
|
||||
ST_REGENTRY(esi),
|
||||
ST_REGENTRY(edi),
|
||||
{ -1, 0 }, /* eip */
|
||||
ST_REGENTRY(eflags),
|
||||
ST_REGENTRY(cs),
|
||||
ST_REGENTRY(ss),
|
||||
};
|
||||
|
||||
#define i386_NUM_ST_COLLECT_GREGS \
|
||||
(sizeof (i386_st_collect_regmap) / sizeof (i386_st_collect_regmap[0]))
|
||||
|
||||
void
|
||||
supply_static_tracepoint_registers (struct regcache *regcache,
|
||||
const unsigned char *buf,
|
||||
CORE_ADDR pc)
|
||||
{
|
||||
int i;
|
||||
unsigned int newpc = pc;
|
||||
|
||||
supply_register (regcache, I386_EIP_REGNUM, &newpc);
|
||||
|
||||
for (i = 0; i < i386_NUM_ST_COLLECT_GREGS; i++)
|
||||
if (i386_st_collect_regmap[i].offset != -1)
|
||||
{
|
||||
switch (i386_st_collect_regmap[i].size)
|
||||
{
|
||||
case 4:
|
||||
supply_register (regcache, i,
|
||||
((char *) buf)
|
||||
+ i386_st_collect_regmap[i].offset);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
unsigned long reg
|
||||
= * (short *) (((char *) buf)
|
||||
+ i386_st_collect_regmap[i].offset);
|
||||
reg &= 0xffff;
|
||||
supply_register (regcache, i, ®);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
internal_error ("unhandled register size: %d",
|
||||
i386_st_collect_regmap[i].size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
|
||||
|
||||
/* This is only needed because reg-i386-linux-lib.o references it. We
|
||||
may use it proper at some point. */
|
||||
const char *gdbserver_xmltarget;
|
||||
|
||||
@@ -255,13 +255,7 @@ write_e_ipa_not_loaded (char *buffer)
|
||||
static void
|
||||
write_e_ust_not_loaded (char *buffer)
|
||||
{
|
||||
#ifdef HAVE_UST
|
||||
sprintf (buffer,
|
||||
"E.UST library not loaded in process. "
|
||||
"Static tracepoints unavailable.");
|
||||
#else
|
||||
sprintf (buffer, "E.GDBserver was built without static tracepoints support");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If the in-process agent library isn't loaded in the inferior, write
|
||||
@@ -1297,35 +1291,6 @@ struct fast_tracepoint_ctx
|
||||
struct tracepoint *tpoint;
|
||||
};
|
||||
|
||||
/* Static tracepoint specific data to be passed down to
|
||||
collect_data_at_tracepoint. */
|
||||
struct static_tracepoint_ctx
|
||||
{
|
||||
struct tracepoint_hit_ctx base;
|
||||
|
||||
/* The regcache corresponding to the registers state at the time of
|
||||
the tracepoint hit. Initialized lazily, from REGS. */
|
||||
struct regcache regcache;
|
||||
int regcache_initted;
|
||||
|
||||
/* The buffer space REGCACHE above uses. We use a separate buffer
|
||||
instead of letting the regcache malloc for both signal safety and
|
||||
performance reasons; this is allocated on the stack instead. */
|
||||
unsigned char *regspace;
|
||||
|
||||
/* The register buffer as passed on by lttng/ust. */
|
||||
struct registers *regs;
|
||||
|
||||
/* The "printf" formatter and the args the user passed to the marker
|
||||
call. We use this to be able to collect "static trace data"
|
||||
($_sdata). */
|
||||
const char *fmt;
|
||||
va_list *args;
|
||||
|
||||
/* The GDB tracepoint matching the probed marker that was "hit". */
|
||||
struct tracepoint *tpoint;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/* Static tracepoint specific data to be passed down to
|
||||
@@ -4585,12 +4550,6 @@ tracepoint_was_hit (thread_info *tinfo, CORE_ADDR stop_pc)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined IN_PROCESS_AGENT && defined HAVE_UST
|
||||
struct ust_marker_data;
|
||||
static void collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
|
||||
struct traceframe *tframe);
|
||||
#endif
|
||||
|
||||
/* Create a trace frame for the hit of the given tracepoint in the
|
||||
given thread. */
|
||||
|
||||
@@ -4706,27 +4665,6 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx)
|
||||
}
|
||||
regcache = &fctx->regcache;
|
||||
}
|
||||
#ifdef HAVE_UST
|
||||
if (ctx->type == static_tracepoint)
|
||||
{
|
||||
struct static_tracepoint_ctx *sctx
|
||||
= (struct static_tracepoint_ctx *) ctx;
|
||||
|
||||
if (!sctx->regcache_initted)
|
||||
{
|
||||
sctx->regcache_initted = 1;
|
||||
init_register_cache (&sctx->regcache, ipa_tdesc, sctx->regspace);
|
||||
supply_regblock (&sctx->regcache, NULL);
|
||||
/* Pass down the tracepoint address, because REGS doesn't
|
||||
include the PC, but we know what it must have been. */
|
||||
supply_static_tracepoint_registers (&sctx->regcache,
|
||||
(const unsigned char *)
|
||||
sctx->regs,
|
||||
sctx->tpoint->address);
|
||||
}
|
||||
regcache = &sctx->regcache;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (ctx->type == trap_tracepoint)
|
||||
{
|
||||
@@ -4842,13 +4780,8 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
|
||||
break;
|
||||
case 'L':
|
||||
{
|
||||
#if defined IN_PROCESS_AGENT && defined HAVE_UST
|
||||
trace_debug ("Want to collect static trace data");
|
||||
collect_ust_data_at_tracepoint (ctx, tframe);
|
||||
#else
|
||||
trace_debug ("warning: collecting static trace data, "
|
||||
"but static tracepoints are not supported");
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -6542,253 +6475,6 @@ upload_fast_traceframes (void)
|
||||
IP_AGENT_EXPORT_VAR int ust_loaded;
|
||||
IP_AGENT_EXPORT_VAR char cmd_buf[IPA_CMD_BUF_SIZE];
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
/* Static tracepoints. */
|
||||
|
||||
/* UST puts a "struct tracepoint" in the global namespace, which
|
||||
conflicts with our tracepoint. Arguably, being a library, it
|
||||
shouldn't take ownership of such a generic name. We work around it
|
||||
here. */
|
||||
#define tracepoint ust_tracepoint
|
||||
#include <ust/ust.h>
|
||||
#undef tracepoint
|
||||
|
||||
extern int serialize_to_text (char *outbuf, int bufsize,
|
||||
const char *fmt, va_list ap);
|
||||
|
||||
#define GDB_PROBE_NAME "gdb"
|
||||
|
||||
/* We dynamically search for the UST symbols instead of linking them
|
||||
in. This lets the user decide if the application uses static
|
||||
tracepoints, instead of always pulling libust.so in. This vector
|
||||
holds pointers to all functions we care about. */
|
||||
|
||||
static struct
|
||||
{
|
||||
int (*serialize_to_text) (char *outbuf, int bufsize,
|
||||
const char *fmt, va_list ap);
|
||||
|
||||
int (*ltt_probe_register) (struct ltt_available_probe *pdata);
|
||||
int (*ltt_probe_unregister) (struct ltt_available_probe *pdata);
|
||||
|
||||
int (*ltt_marker_connect) (const char *channel, const char *mname,
|
||||
const char *pname);
|
||||
int (*ltt_marker_disconnect) (const char *channel, const char *mname,
|
||||
const char *pname);
|
||||
|
||||
void (*marker_iter_start) (struct marker_iter *iter);
|
||||
void (*marker_iter_next) (struct marker_iter *iter);
|
||||
void (*marker_iter_stop) (struct marker_iter *iter);
|
||||
void (*marker_iter_reset) (struct marker_iter *iter);
|
||||
} ust_ops;
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* Cast through typeof to catch incompatible API changes. Since UST
|
||||
only builds with gcc, we can freely use gcc extensions here
|
||||
too. */
|
||||
#define GET_UST_SYM(SYM) \
|
||||
do \
|
||||
{ \
|
||||
if (ust_ops.SYM == NULL) \
|
||||
ust_ops.SYM = (typeof (&SYM)) dlsym (RTLD_DEFAULT, #SYM); \
|
||||
if (ust_ops.SYM == NULL) \
|
||||
return 0; \
|
||||
} while (0)
|
||||
|
||||
#define USTF(SYM) ust_ops.SYM
|
||||
|
||||
/* Get pointers to all libust.so functions we care about. */
|
||||
|
||||
static int
|
||||
dlsym_ust (void)
|
||||
{
|
||||
GET_UST_SYM (serialize_to_text);
|
||||
|
||||
GET_UST_SYM (ltt_probe_register);
|
||||
GET_UST_SYM (ltt_probe_unregister);
|
||||
GET_UST_SYM (ltt_marker_connect);
|
||||
GET_UST_SYM (ltt_marker_disconnect);
|
||||
|
||||
GET_UST_SYM (marker_iter_start);
|
||||
GET_UST_SYM (marker_iter_next);
|
||||
GET_UST_SYM (marker_iter_stop);
|
||||
GET_UST_SYM (marker_iter_reset);
|
||||
|
||||
ust_loaded = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Given an UST marker, return the matching gdb static tracepoint.
|
||||
The match is done by address. */
|
||||
|
||||
static struct tracepoint *
|
||||
ust_marker_to_static_tracepoint (const struct marker *mdata)
|
||||
{
|
||||
struct tracepoint *tpoint;
|
||||
|
||||
for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
|
||||
{
|
||||
if (tpoint->type != static_tracepoint)
|
||||
continue;
|
||||
|
||||
if (tpoint->address == (uintptr_t) mdata->location)
|
||||
return tpoint;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The probe function we install on lttng/ust markers. Whenever a
|
||||
probed ust marker is hit, this function is called. This is similar
|
||||
to gdb_collect, only for static tracepoints, instead of fast
|
||||
tracepoints. */
|
||||
|
||||
static void
|
||||
gdb_probe (const struct marker *mdata, void *probe_private,
|
||||
struct registers *regs, void *call_private,
|
||||
const char *fmt, va_list *args)
|
||||
{
|
||||
struct tracepoint *tpoint;
|
||||
struct static_tracepoint_ctx ctx;
|
||||
const struct target_desc *ipa_tdesc;
|
||||
|
||||
/* Don't do anything until the trace run is completely set up. */
|
||||
if (!tracing)
|
||||
{
|
||||
trace_debug ("gdb_probe: not tracing\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ipa_tdesc = get_ipa_tdesc (ipa_tdesc_idx);
|
||||
ctx.base.type = static_tracepoint;
|
||||
ctx.regcache_initted = 0;
|
||||
ctx.regs = regs;
|
||||
ctx.fmt = fmt;
|
||||
ctx.args = args;
|
||||
|
||||
/* Wrap the regblock in a register cache (in the stack, we don't
|
||||
want to malloc here). */
|
||||
ctx.regspace = alloca (ipa_tdesc->registers_size);
|
||||
if (ctx.regspace == NULL)
|
||||
{
|
||||
trace_debug ("Trace buffer block allocation failed, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
tpoint = ust_marker_to_static_tracepoint (mdata);
|
||||
if (tpoint == NULL)
|
||||
{
|
||||
trace_debug ("gdb_probe: marker not known: "
|
||||
"loc:0x%p, ch:\"%s\",n:\"%s\",f:\"%s\"",
|
||||
mdata->location, mdata->channel,
|
||||
mdata->name, mdata->format);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tpoint->enabled)
|
||||
{
|
||||
trace_debug ("gdb_probe: tracepoint disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.tpoint = tpoint;
|
||||
|
||||
trace_debug ("gdb_probe: collecting marker: "
|
||||
"loc:0x%p, ch:\"%s\",n:\"%s\",f:\"%s\"",
|
||||
mdata->location, mdata->channel,
|
||||
mdata->name, mdata->format);
|
||||
|
||||
/* Test the condition if present, and collect if true. */
|
||||
if (tpoint->cond == NULL
|
||||
|| condition_true_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
|
||||
tpoint))
|
||||
{
|
||||
collect_data_at_tracepoint ((struct tracepoint_hit_ctx *) &ctx,
|
||||
tpoint->address, tpoint);
|
||||
|
||||
if (stopping_tracepoint
|
||||
|| trace_buffer_is_full
|
||||
|| expr_eval_result != expr_eval_no_error)
|
||||
stop_tracing ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If there was a condition and it evaluated to false, the only
|
||||
way we would stop tracing is if there was an error during
|
||||
condition expression evaluation. */
|
||||
if (expr_eval_result != expr_eval_no_error)
|
||||
stop_tracing ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Called if the gdb static tracepoint requested collecting "$_sdata",
|
||||
static tracepoint string data. This is a string passed to the
|
||||
tracing library by the user, at the time of the tracepoint marker
|
||||
call. E.g., in the UST marker call:
|
||||
|
||||
trace_mark (ust, bar33, "str %s", "FOOBAZ");
|
||||
|
||||
the collected data is "str FOOBAZ".
|
||||
*/
|
||||
|
||||
static void
|
||||
collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx,
|
||||
struct traceframe *tframe)
|
||||
{
|
||||
struct static_tracepoint_ctx *umd = (struct static_tracepoint_ctx *) ctx;
|
||||
unsigned char *bufspace;
|
||||
int size;
|
||||
va_list copy;
|
||||
unsigned short blocklen;
|
||||
|
||||
if (umd == NULL)
|
||||
{
|
||||
trace_debug ("Wanted to collect static trace data, "
|
||||
"but there's no static trace data");
|
||||
return;
|
||||
}
|
||||
|
||||
va_copy (copy, *umd->args);
|
||||
size = USTF(serialize_to_text) (NULL, 0, umd->fmt, copy);
|
||||
va_end (copy);
|
||||
|
||||
trace_debug ("Want to collect ust data");
|
||||
|
||||
/* 'S' + size + string */
|
||||
bufspace = add_traceframe_block (tframe, umd->tpoint,
|
||||
1 + sizeof (blocklen) + size + 1);
|
||||
if (bufspace == NULL)
|
||||
{
|
||||
trace_debug ("Trace buffer block allocation failed, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Identify a static trace data block. */
|
||||
*bufspace = 'S';
|
||||
|
||||
blocklen = size + 1;
|
||||
memcpy (bufspace + 1, &blocklen, sizeof (blocklen));
|
||||
|
||||
va_copy (copy, *umd->args);
|
||||
USTF(serialize_to_text) ((char *) bufspace + 1 + sizeof (blocklen),
|
||||
size + 1, umd->fmt, copy);
|
||||
va_end (copy);
|
||||
|
||||
trace_debug ("Storing static tracepoint data in regblock: %s",
|
||||
bufspace + 1 + sizeof (blocklen));
|
||||
}
|
||||
|
||||
/* The probe to register with lttng/ust. */
|
||||
static struct ltt_available_probe gdb_ust_probe =
|
||||
{
|
||||
GDB_PROBE_NAME,
|
||||
NULL,
|
||||
gdb_probe,
|
||||
};
|
||||
|
||||
#endif /* HAVE_UST */
|
||||
#endif /* IN_PROCESS_AGENT */
|
||||
|
||||
#ifndef IN_PROCESS_AGENT
|
||||
@@ -6917,229 +6603,6 @@ gdb_agent_socket_init (void)
|
||||
return fd;
|
||||
}
|
||||
|
||||
#ifdef HAVE_UST
|
||||
|
||||
/* The next marker to be returned on a qTsSTM command. */
|
||||
static const struct marker *next_st;
|
||||
|
||||
/* Returns the first known marker. */
|
||||
|
||||
struct marker *
|
||||
first_marker (void)
|
||||
{
|
||||
struct marker_iter iter;
|
||||
|
||||
USTF(marker_iter_reset) (&iter);
|
||||
USTF(marker_iter_start) (&iter);
|
||||
|
||||
return iter.marker;
|
||||
}
|
||||
|
||||
/* Returns the marker following M. */
|
||||
|
||||
const struct marker *
|
||||
next_marker (const struct marker *m)
|
||||
{
|
||||
struct marker_iter iter;
|
||||
|
||||
USTF(marker_iter_reset) (&iter);
|
||||
USTF(marker_iter_start) (&iter);
|
||||
|
||||
for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
|
||||
{
|
||||
if (iter.marker == m)
|
||||
{
|
||||
USTF(marker_iter_next) (&iter);
|
||||
return iter.marker;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
bin2hex ((gdb_byte *) str, hexstr, len);
|
||||
return hexstr;
|
||||
}
|
||||
|
||||
/* Compose packet that is the response to the qTsSTM/qTfSTM/qTSTMat
|
||||
packets. */
|
||||
|
||||
static void
|
||||
response_ust_marker (char *packet, const struct marker *st)
|
||||
{
|
||||
char *strid, *format, *tmp;
|
||||
|
||||
next_st = next_marker (st);
|
||||
|
||||
tmp = xmalloc (strlen (st->channel) + 1 +
|
||||
strlen (st->name) + 1);
|
||||
sprintf (tmp, "%s/%s", st->channel, st->name);
|
||||
|
||||
strid = cstr_to_hexstr (tmp);
|
||||
free (tmp);
|
||||
|
||||
format = cstr_to_hexstr (st->format);
|
||||
|
||||
sprintf (packet, "m%s:%s:%s",
|
||||
paddress ((uintptr_t) st->location),
|
||||
strid,
|
||||
format);
|
||||
|
||||
free (strid);
|
||||
free (format);
|
||||
}
|
||||
|
||||
/* Return the first static tracepoint, and initialize the state
|
||||
machine that will iterate through all the static tracepoints. */
|
||||
|
||||
static void
|
||||
cmd_qtfstm (char *packet)
|
||||
{
|
||||
trace_debug ("Returning first trace state variable definition");
|
||||
|
||||
if (first_marker ())
|
||||
response_ust_marker (packet, first_marker ());
|
||||
else
|
||||
strcpy (packet, "l");
|
||||
}
|
||||
|
||||
/* Return additional trace state variable definitions. */
|
||||
|
||||
static void
|
||||
cmd_qtsstm (char *packet)
|
||||
{
|
||||
trace_debug ("Returning static tracepoint");
|
||||
|
||||
if (next_st)
|
||||
response_ust_marker (packet, next_st);
|
||||
else
|
||||
strcpy (packet, "l");
|
||||
}
|
||||
|
||||
/* Disconnect the GDB probe from a marker at a given address. */
|
||||
|
||||
static void
|
||||
unprobe_marker_at (char *packet)
|
||||
{
|
||||
char *p = packet;
|
||||
ULONGEST address;
|
||||
struct marker_iter iter;
|
||||
|
||||
p += sizeof ("unprobe_marker_at:") - 1;
|
||||
|
||||
p = unpack_varlen_hex (p, &address);
|
||||
|
||||
USTF(marker_iter_reset) (&iter);
|
||||
USTF(marker_iter_start) (&iter);
|
||||
for (; iter.marker != NULL; USTF(marker_iter_next) (&iter))
|
||||
if ((uintptr_t ) iter.marker->location == address)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = USTF(ltt_marker_disconnect) (iter.marker->channel,
|
||||
iter.marker->name,
|
||||
GDB_PROBE_NAME);
|
||||
if (result < 0)
|
||||
warning ("could not disable marker %s/%s",
|
||||
iter.marker->channel, iter.marker->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect the GDB probe to a marker at a given address. */
|
||||
|
||||
static int
|
||||
probe_marker_at (char *packet)
|
||||
{
|
||||
char *p = packet;
|
||||
ULONGEST address;
|
||||
struct marker_iter iter;
|
||||
struct marker *m;
|
||||
|
||||
p += sizeof ("probe_marker_at:") - 1;
|
||||
|
||||
p = unpack_varlen_hex (p, &address);
|
||||
|
||||
USTF(marker_iter_reset) (&iter);
|
||||
|
||||
for (USTF(marker_iter_start) (&iter), m = iter.marker;
|
||||
m != NULL;
|
||||
USTF(marker_iter_next) (&iter), m = iter.marker)
|
||||
if ((uintptr_t ) m->location == address)
|
||||
{
|
||||
int result;
|
||||
|
||||
trace_debug ("found marker for address. "
|
||||
"ltt_marker_connect (marker = %s/%s)",
|
||||
m->channel, m->name);
|
||||
|
||||
result = USTF(ltt_marker_connect) (m->channel, m->name,
|
||||
GDB_PROBE_NAME);
|
||||
if (result && result != -EEXIST)
|
||||
trace_debug ("ltt_marker_connect (marker = %s/%s, errno = %d)",
|
||||
m->channel, m->name, -result);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
sprintf (packet, "E.could not connect marker: channel=%s, name=%s",
|
||||
m->channel, m->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy (packet, "OK");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf (packet, "E.no marker found at 0x%s", paddress (address));
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
cmd_qtstmat (char *packet)
|
||||
{
|
||||
char *p = packet;
|
||||
ULONGEST address;
|
||||
struct marker_iter iter;
|
||||
struct marker *m;
|
||||
|
||||
p += sizeof ("qTSTMat:") - 1;
|
||||
|
||||
p = unpack_varlen_hex (p, &address);
|
||||
|
||||
USTF(marker_iter_reset) (&iter);
|
||||
|
||||
for (USTF(marker_iter_start) (&iter), m = iter.marker;
|
||||
m != NULL;
|
||||
USTF(marker_iter_next) (&iter), m = iter.marker)
|
||||
if ((uintptr_t ) m->location == address)
|
||||
{
|
||||
response_ust_marker (packet, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy (packet, "l");
|
||||
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>
|
||||
|
||||
static void
|
||||
@@ -7214,28 +6677,6 @@ gdb_agent_helper_thread (void *arg)
|
||||
{
|
||||
stop_loop = 1;
|
||||
}
|
||||
#ifdef HAVE_UST
|
||||
else if (strcmp ("qTfSTM", cmd_buf) == 0)
|
||||
{
|
||||
cmd_qtfstm (cmd_buf);
|
||||
}
|
||||
else if (strcmp ("qTsSTM", cmd_buf) == 0)
|
||||
{
|
||||
cmd_qtsstm (cmd_buf);
|
||||
}
|
||||
else if (startswith (cmd_buf, "unprobe_marker_at:"))
|
||||
{
|
||||
unprobe_marker_at (cmd_buf);
|
||||
}
|
||||
else if (startswith (cmd_buf, "probe_marker_at:"))
|
||||
{
|
||||
probe_marker_at (cmd_buf);
|
||||
}
|
||||
else if (startswith (cmd_buf, "qTSTMat:"))
|
||||
{
|
||||
cmd_qtstmat (cmd_buf);
|
||||
}
|
||||
#endif /* HAVE_UST */
|
||||
}
|
||||
|
||||
/* Fix compiler's warning: ignoring return value of 'write'. */
|
||||
@@ -7295,10 +6736,6 @@ gdb_agent_init (void)
|
||||
|
||||
while (helper_thread_id == 0)
|
||||
usleep (1);
|
||||
|
||||
#ifdef HAVE_UST
|
||||
gdb_ust_init ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
Reference in New Issue
Block a user