--- a/aclocal.m4 +++ b/aclocal.m4 @@ -85,6 +85,32 @@ AC_MSG_CHECKING([whether to am_maintaine ] ) +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])# PKG_PROG_PKG_CONFIG + + AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Copyright (C) 2006, 2008 Free Software Foundation, Inc. --- a/config.in +++ b/config.in @@ -216,6 +216,10 @@ /* Define to 1 if you have the `w' library (-lw). */ #undef HAVE_LIBW +/* Define to 1 if you have the `babeltrace' library + (-lbabeltrace -lbabeltrace-ctf). */ +#undef HAVE_LIBBABELTRACE + /* Define to 1 if you have the header file. */ #undef HAVE_LINK_H --- a/configure +++ b/configure @@ -592,6 +592,9 @@ enable_option_checking=no ac_subst_vars='LTLIBOBJS LIBOBJS GDB_NM_FILE +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG frags target_subdir CONFIG_UNINSTALL @@ -819,6 +822,7 @@ with_x enable_sim enable_multi_ice enable_gdbserver +enable_ctf_target ' ac_precious_vars='build_alias host_alias @@ -833,7 +837,10 @@ MAKEINFO MAKEINFOFLAGS YACC YFLAGS -XMKMF' +XMKMF +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR' ac_subdirs_all='testsuite gdbtk multi-ice @@ -1482,6 +1489,7 @@ Optional Features: --enable-multi-ice build the multi-ice-gdb-server --enable-gdbserver automatically build gdbserver (yes/no/auto, default is auto) + --enable-ctf-target enable ctf target (yes/no/auto, default is auto) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1551,6 +1559,11 @@ Some influential environment variables: This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. XMKMF Path to xmkmf, Makefile generator for X Window System + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -14090,6 +14103,222 @@ if test "$enable_gdbserver" = "yes" -a " as_fn_error "Automatic gdbserver build is not supported for this configuration" "$LINENO" 5 fi +# Check whether --enable-ctf-target was given. +if test "${enable_ctf_target+set}" = set; then : + enableval=$enable_ctf_target; case "${enableval}" in + yes| no|auto) ;; + *) as_fn_error "bad value ${enableval} for --enable-ctf-target option" "$LINENO" 5 ;; +esac +else + enable_ctf_target=auto +fi + + +if test "$enable_ctf_target" = "yes" || test "$enable_ctf_target" = "auto"; then + pkg_config_args=babeltrace + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.16 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + + if test "x$PKG_CONFIG" = x ; then + no_babeltrace=yes + PKG_CONFIG=no + fi + + if test x"$no_babeltrace" = x ; then + BABELTRACE_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + BABELTRACE_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $BABELTRACE_CFLAGS" + LIBS="$LIBS $BABELTRACE_LIBS" + rm -f conf.glibtest + if test "$cross_compiling" = yes; then : + $as_echo $ac_n "cross compiling; assumed OK... $ac_c" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include + +int +main () +{ + if (!bt_context_create()) + return 1; + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + no_babeltrace=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + if test "x$no_babeltrace" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_LIBBABELTRACE 1" >>confdefs.h + + LIBS="$LIBS $BABELTRACE_LIBS" + CPPFLAGS="$CPPFLAGS $BABELTRACE_LIBS" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + if test "$PKG_CONFIG" = "no" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** A new enough version of pkg-config was not found." >&5 +$as_echo "$as_me: WARNING: *** A new enough version of pkg-config was not found." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** See http://www.freedesktop.org/software/pkgconfig/" >&5 +$as_echo "$as_me: WARNING: *** See http://www.freedesktop.org/software/pkgconfig/" >&2;} + else + if test -f conf.glibtest ; then + : + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Could not run libbabeltrace test program." >&5 +$as_echo "$as_me: WARNING: *** Could not run libbabeltrace test program." >&2;} + fi + fi + if test "$enable_ctf_target" = "yes"; then + as_fn_error "libbabeltrace are required in order to enable CTF target" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libbabeltrace is missing or unusable; CTF target is unavailable." >&5 +$as_echo "$as_me: WARNING: libbabeltrace is missing or unusable; CTF target is unavailable." >&2;} + enable_ctf_target = no + fi + fi + rm -f conf.glibtest +fi +if test "$enable_ctf_target" = "no"; then + : +fi + # If nativefile (NAT_FILE) is not set in config/*/*.m[ht] files, we link # to an empty version. --- a/configure.ac +++ b/configure.ac @@ -2318,6 +2318,77 @@ if test "$enable_gdbserver" = "yes" -a " AC_MSG_ERROR(Automatic gdbserver build is not supported for this configuration) fi +AC_ARG_ENABLE(ctf-target, +AS_HELP_STRING([--enable-ctf-target], + [enable ctf target (yes/no/auto, default is auto)]), +[case "${enableval}" in + yes| no|auto) ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-ctf-target option) ;; +esac],[enable_ctf_target=auto]) + +if test "$enable_ctf_target" = "yes" || test "$enable_ctf_target" = "auto"; then + pkg_config_args=babeltrace + PKG_PROG_PKG_CONFIG(0.16) + + if test "x$PKG_CONFIG" = x ; then + no_babeltrace=yes + PKG_CONFIG=no + fi + + if test x"$no_babeltrace" = x ; then + BABELTRACE_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args` + BABELTRACE_LIBS=`$PKG_CONFIG --libs $pkg_config_args` + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $BABELTRACE_CFLAGS" + LIBS="$LIBS $BABELTRACE_LIBS" + rm -f conf.glibtest + AC_TRY_RUN([ +#include +#include +#include + +int +main () +{ + if (!bt_context_create()) + return 1; + return 0; +} +],, no_babeltrace=yes,[$as_echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + if test "x$no_babeltrace" = x ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_LIBBABELTRACE, 1, [Define if you have the $1 library.]) + LIBS="$LIBS $BABELTRACE_LIBS" + CPPFLAGS="$CPPFLAGS $BABELTRACE_LIBS" + else + AC_MSG_RESULT(no) + if test "$PKG_CONFIG" = "no" ; then + AC_MSG_WARN([*** A new enough version of pkg-config was not found.]) + AC_MSG_WARN([*** See http://www.freedesktop.org/software/pkgconfig/]) + else + if test -f conf.glibtest ; then + : + else + AC_MSG_WARN([*** Could not run libbabeltrace test program.]) + fi + fi + if test "$enable_ctf_target" = "yes"; then + AC_MSG_ERROR([libbabeltrace are required in order to enable CTF target]) + else + AC_MSG_WARN([libbabeltrace is missing or unusable; CTF target is unavailable.]) + enable_ctf_target = no + fi + fi + rm -f conf.glibtest +fi +if test "$enable_ctf_target" = "no"; then + : +fi + # If nativefile (NAT_FILE) is not set in config/*/*.m[ht] files, we link # to an empty version. --- a/ctf.c +++ b/ctf.c @@ -24,6 +24,7 @@ #include "gdbcmd.h" #include "exceptions.h" #include "stack.h" +#include "valprint.h" #include @@ -1338,3 +1339,479 @@ traceframe %d is dropped because type of do_cleanups (old_chain); } + +#ifdef HAVE_LIBBABELTRACE +#include +#include +#include + +/* The struct pointer for current CTF directory. */ +static struct bt_context *ctx = NULL; +static struct bt_ctf_iter *iter = NULL; +/* The event struct of current traceframe. */ +static struct bt_ctf_event *ctf_event; +/* The number of current traceframe. */ +static int current_tp; + +static struct target_ops ctf_ops; + +static void +ctf_close_dir (void) +{ + if (iter) + { + bt_ctf_iter_destroy (iter); + iter = NULL; + } + if (ctx) + { + bt_context_put (ctx); + ctx = NULL; + } +} + +/* Use libbabeltrace open DIRNAME. Setup CTX, ITER, CTF_EVENT + and CURRENT_TP. */ + +static void +ctf_open_dir (char *dirname) +{ + int ret; + struct bt_iter_pos begin_pos; + + ctx = bt_context_create (); + if (!ctx) + error (_("Unable to initialize libbabeltrace")); + ret = bt_context_add_trace (ctx, dirname, "ctf", NULL, NULL, NULL); + if (ret < 0) + { + ctf_close_dir (); + error (_("Unable to use libbabeltrace open \"%s\""), dirname); + } + + begin_pos.type = BT_SEEK_BEGIN; + iter = bt_ctf_iter_create (ctx, &begin_pos, NULL); + if (!iter) + { + ctf_close_dir (); + error (_("Unable to use libbabeltrace open \"%s\""), dirname); + } + + current_tp = 0; + ctf_event = bt_ctf_iter_read_event (iter); + if (!ctf_event) + { + ctf_close_dir (); + error (_("Unable to use libbabeltrace open \"%s\""), dirname); + } +} + +/* Find the field that name is NAME from D and return it. + Return NULL if fail. */ + +static const struct definition * +ctf_find_field (const struct definition *d, const char *name) +{ + struct definition const * const *list_d; + unsigned int list_d_count, i; + + if (bt_ctf_get_field_list (ctf_event, d, &list_d, &list_d_count)) + return NULL; + for (i = 0; i < list_d_count; i++) + { + if (strcmp (bt_ctf_field_name (list_d[i]), name) == 0) + return list_d[i]; + } + + return NULL; +} + +/* Get the id of current traceframe and set it to TPP. + Return -1 if fail. */ + +static int +ctf_event_id (int *tpp) +{ + const struct definition *top_d; + struct definition const * const *list_d; + unsigned int list_d_count, i; + const struct definition *d_id = NULL; + const struct definition *d_v = NULL; + + top_d = bt_ctf_get_top_level_scope (ctf_event, BT_STREAM_EVENT_HEADER); + if (!top_d) + return -1; + if (bt_ctf_get_field_list (ctf_event, top_d, &list_d, &list_d_count)) + return -1; + + for (i = 0; i < list_d_count; i++) + { + if (strcmp (bt_ctf_field_name (list_d[i]), "id") == 0) + d_id = list_d[i]; + else if (strcmp (bt_ctf_field_name (list_d[i]), "v") == 0) + d_v = list_d[i]; + if (d_id && d_v) + break; + } + if (!d_id) + return -1; + +getval: + switch (bt_ctf_field_type (bt_ctf_get_decl_from_def (d_id))) + { + case CTF_TYPE_INTEGER: + { + int64_t val; + + if (bt_ctf_get_int_signedness (bt_ctf_get_decl_from_def (d_id))) + val = bt_ctf_get_int64 (d_id); + else + val = bt_ctf_get_uint64 (d_id); + if (val < INT_MIN || val > INT_MAX) + { + warning (_("tracepoint id is too big or too small.")); + return -1; + } + *tpp = (int) val; + } + break; + + case CTF_TYPE_ENUM: + if (strcmp (bt_ctf_get_enum_str (d_id), "compact") == 0) + d_id = bt_ctf_get_enum_int (d_id); + else + { + if (!d_v) + return -1; + if (bt_ctf_field_type (bt_ctf_get_decl_from_def (d_v)) + != CTF_TYPE_VARIANT) + return -1; + + d_v = ctf_find_field (d_v, "extended"); + if (!d_v) + return -1; + if (bt_ctf_field_type (bt_ctf_get_decl_from_def (d_v)) + != CTF_TYPE_STRUCT) + return -1; + d_id = ctf_find_field (d_v, "id"); + if (!d_id) + return -1; + } + goto getval; + break; + + default: + warning (_("type of tracepoint id is not supported.")); + return -1; + break; + } + + return 0; +} + +/* Convert DEF to a value struct and return it. */ + +static struct value * +ctf_def_to_val (const struct definition *def) +{ + struct value *ret = NULL; + + if (!def) + return ret; + + switch (bt_ctf_field_type (bt_ctf_get_decl_from_def (def))) + { + case CTF_TYPE_INTEGER: + if (bt_ctf_get_int_signedness (bt_ctf_get_decl_from_def (def))) + { + int64_t val; + val = bt_ctf_get_int64 (def); + ret = value_from_longest + (builtin_type (target_gdbarch ())->builtin_int64, val); + } + else + { + uint64_t val; + val = bt_ctf_get_uint64 (def); + ret = value_from_longest + (builtin_type (target_gdbarch ())->builtin_uint64, val); + } + break; + + case CTF_TYPE_ENUM: + ret = ctf_def_to_val (bt_ctf_get_enum_int (def)); + break; + } + + return ret; +} + +/* Add each variable of current traceframe to GDB as internalvar. */ + +static int +ctf_event_to_internalvar (void) +{ + const struct definition *top_d; + struct definition const * const *list_d; + unsigned int list_d_count, i; + + top_d = bt_ctf_get_top_level_scope (ctf_event, BT_EVENT_FIELDS); + if (!top_d) + return -1; + if (bt_ctf_get_field_list (ctf_event, top_d, &list_d, &list_d_count)) + return -1; + + for (i = 0; i < list_d_count; i++) + { + struct value *val; + const char *name; + + val = ctf_def_to_val (list_d[i]); + name = bt_ctf_field_name (list_d[i]); + if (val) + set_internalvar (lookup_internalvar (name), val); + else + warning (_("$%s is not supported."), name); + } + + return 0; +} + +/* Set current traceframe to first one. + Return -1 if fail. */ + +static int +ctf_goto_begin (void) +{ + struct bt_iter_pos pos; + + pos.type = BT_SEEK_BEGIN; + if (bt_iter_set_pos (bt_ctf_get_iter (iter), &pos)) + return -1; + current_tp = 0; + ctf_event = bt_ctf_iter_read_event (iter); + if (!ctf_event) + return -1; + + return 0; +} + +/* Find the NUM traceframe and select it. + If success, return the num of traceframe and set tracepoint id to + TPP. + If fail, return -1. */ + +static int +ctf_find_num (int num, int *tpp) +{ + if (num < current_tp) + { + if (ctf_goto_begin ()) + return -1; + } + + while (1) + { + if (current_tp == num) + break; + if (bt_iter_next (bt_ctf_get_iter (iter)) < 0) + return -1; + ctf_event = bt_ctf_iter_read_event (iter); + if (!ctf_event) + { + ctf_goto_begin (); + return -1; + } + ++current_tp; + } + + if (tpp) + { + if (ctf_event_id (tpp)) + { + warning (_("Unable to get tracepoint id.")); + *tpp = INT_MIN; + } + } + + return current_tp; +} + +/* Find traceframe that id is TP that follow current traceframe. + If success, return the num of traceframe. + If fail, return -1. */ + +static int +ctf_find_tp (int tp) +{ + while (1) + { + int id; + + if (bt_iter_next (bt_ctf_get_iter (iter)) < 0) + return -1; + ctf_event = bt_ctf_iter_read_event (iter); + if (!ctf_event) + { + ctf_goto_begin (); + return -1; + } + ++current_tp; + if (ctf_event_id (&id)) + warning (_("Unable to get tracepoint id.")); + else if (id == tp) + break; + } + + return current_tp; +} + +static void +ctf_open (char *dirname, int from_tty) +{ + target_preopen (from_tty); + if (!dirname) + error (_("No CTF directory specified.")); + + ctf_open_dir (dirname); + + push_target (&ctf_ops); +} + +static void +ctf_close (int quitting) +{ + ctf_close_dir (); +} + +static int +ctf_trace_find (enum trace_find_type type, int num, + ULONGEST addr1, ULONGEST addr2, int *tpp) +{ + int ret = -1; + + switch (type) + { + case tfind_number: + if (num < 0) + { + if (tpp) + *tpp = -1; + } + else + ret = ctf_find_num (num, tpp); + break; + + case tfind_tp: + ret = ctf_find_tp (num); + break; + } + + if (ret >= 0) + { + if (ctf_event_to_internalvar ()) + warning (_("Unable to add internal var of this frame.")); + } + + return ret; +} + +static const char * +ctf_get_current_tracepoint_name (void) +{ + if (ctf_event) + return bt_ctf_event_name (ctf_event); + + return NULL; +} + +static int +ctf_trace_dump (int from_tty) +{ + const struct definition *top_d; + struct definition const * const *list_d; + unsigned int list_d_count, i; + + if (!ctf_event) + return 1; + + top_d = bt_ctf_get_top_level_scope (ctf_event, BT_EVENT_FIELDS); + if (!top_d) + return 1; + if (bt_ctf_get_field_list (ctf_event, top_d, &list_d, &list_d_count)) + return 1; + + for (i = 0; i < list_d_count; i++) + { + char name[256]; + snprintf (name, 256, "$%s", bt_ctf_field_name (list_d[i])); + printf_filtered ("%s = ", name); + output_command (name, from_tty); + printf_filtered ("\n"); + } + + return 1; +} + +static int +ctf_has_all_memory (struct target_ops *ops) +{ + return 0; +} + +static int +ctf_has_memory (struct target_ops *ops) +{ + return 0; +} + +static int +ctf_has_stack (struct target_ops *ops) +{ + return 0; +} + +static int +ctf_has_registers (struct target_ops *ops) +{ + return 0; +} + +static int +ctf_thread_alive (struct target_ops *ops, ptid_t ptid) +{ + return 1; +} + +static void +init_ctf_ops (void) +{ + ctf_ops.to_shortname = "ctf"; + ctf_ops.to_longname = "CTF file"; + ctf_ops.to_doc = "Use a CTF directory as a target.\n\ +Specify the filename of the CTF directory."; + ctf_ops.to_open = ctf_open; + ctf_ops.to_close = ctf_close; + ctf_ops.to_trace_find = ctf_trace_find; + ctf_ops.to_get_current_tracepoint_name = ctf_get_current_tracepoint_name; + ctf_ops.to_trace_dump = ctf_trace_dump; + ctf_ops.to_stratum = process_stratum; + ctf_ops.to_has_all_memory = ctf_has_all_memory; + ctf_ops.to_has_memory = ctf_has_memory; + ctf_ops.to_has_stack = ctf_has_stack; + ctf_ops.to_has_registers = ctf_has_registers; + ctf_ops.to_thread_alive = ctf_thread_alive; + ctf_ops.to_magic = OPS_MAGIC; +} + +extern void _initialize_ctf (void); + +/* module initialization */ +void +_initialize_ctf (void) +{ + init_ctf_ops (); + + add_target (&ctf_ops); +} +#endif --- a/target.c +++ b/target.c @@ -694,6 +694,8 @@ update_current_target (void) INHERIT (to_set_disconnected_tracing, t); INHERIT (to_set_circular_trace_buffer, t); INHERIT (to_set_trace_notes, t); + INHERIT (to_get_current_tracepoint_name, t); + INHERIT (to_trace_dump, t); INHERIT (to_get_tib_address, t); INHERIT (to_set_permissions, t); INHERIT (to_static_tracepoint_marker_at, t); @@ -915,6 +917,12 @@ update_current_target (void) de_fault (to_set_trace_notes, (int (*) (char *, char *, char *)) return_zero); + de_fault (to_get_current_tracepoint_name, + (const char *(*) (void)) + return_zero); + de_fault (to_trace_dump, + (int (*) (int)) + return_zero); de_fault (to_get_tib_address, (int (*) (ptid_t, CORE_ADDR *)) tcomplain); --- a/target.h +++ b/target.h @@ -811,6 +811,17 @@ struct target_ops successful, 0 otherwise. */ int (*to_set_trace_notes) (char *user, char *notes, char* stopnotes); + /* Return name of current traceframe's tracepoint. + Return NULL if the target doesn't support it. */ + + const char *(*to_get_current_tracepoint_name) (void); + + /* Dump all the value of current traceframe. + Return fail if the target doesn't support it. Then GDB will + dump all the value of current traceframe with itself. */ + + int (*to_trace_dump) (int from_tty); + /* Return the processor core that thread PTID was last seen on. This information is updated only when: - update_thread_list is called @@ -1703,6 +1714,12 @@ extern char *target_fileio_read_stralloc #define target_set_trace_notes(user,notes,stopnotes) \ (*current_target.to_set_trace_notes) ((user), (notes), (stopnotes)) +#define target_get_current_tracepoint_name() \ + (*current_target.to_get_current_tracepoint_name) () + +#define target_trace_dump(from_tty) \ + (*current_target.to_trace_dump) (from_tty) + #define target_get_tib_address(ptid, addr) \ (*current_target.to_get_tib_address) ((ptid), (addr)) --- a/tracepoint.c +++ b/tracepoint.c @@ -2257,7 +2257,7 @@ tfind_1 (enum trace_find_type type, int below (correctly) decide to print out the source location of the trace frame. */ if (!(type == tfind_number && num == -1) - && (has_stack_frames () || traceframe_number >= 0)) + && has_stack_frames ()) old_frame_id = get_frame_id (get_current_frame ()); target_frameno = target_trace_find (type, num, addr1, addr2, @@ -2308,7 +2308,8 @@ tfind_1 (enum trace_find_type type, int tp = get_tracepoint_by_number_on_target (target_tracept); - reinit_frame_cache (); + if (has_stack_frames ()) + reinit_frame_cache (); target_dcache_invalidate (); set_tracepoint_num (tp ? tp->base.number : target_tracept); @@ -2318,10 +2319,13 @@ tfind_1 (enum trace_find_type type, int set_current_traceframe (target_frameno); - if (target_frameno == -1) - set_traceframe_context (NULL); - else - set_traceframe_context (get_current_frame ()); + if (has_stack_frames ()) + { + if (target_frameno == -1) + set_traceframe_context (NULL); + else + set_traceframe_context (get_current_frame ()); + } if (traceframe_number >= 0) { @@ -2355,21 +2359,30 @@ tfind_1 (enum trace_find_type type, int if (from_tty && (has_stack_frames () || traceframe_number >= 0)) { - enum print_what print_what; + const char *tp_name; - /* NOTE: in imitation of the step command, try to determine - whether we have made a transition from one function to - another. If so, we'll print the "stack frame" (ie. the new - function and it's arguments) -- otherwise we'll just show the - new source line. */ + tp_name = target_get_current_tracepoint_name (); + if (tp_name) + printf_filtered ("%s\n", tp_name); - if (frame_id_eq (old_frame_id, - get_frame_id (get_current_frame ()))) - print_what = SRC_LINE; - else - print_what = SRC_AND_LOC; + if (has_stack_frames ()) + { + enum print_what print_what; - print_stack_frame (get_selected_frame (NULL), 1, print_what); + /* NOTE: in imitation of the step command, try to determine + whether we have made a transition from one function to + another. If so, we'll print the "stack frame" (ie. the new + function and it's arguments) -- otherwise we'll just show the + new source line. */ + + if (frame_id_eq (old_frame_id, + get_frame_id (get_current_frame ()))) + print_what = SRC_LINE; + else + print_what = SRC_AND_LOC; + + print_stack_frame (get_selected_frame (NULL), 1, print_what); + } do_displays (); } } @@ -2899,6 +2912,9 @@ trace_dump_command (char *args, int from return; } + if (target_trace_dump (from_tty)) + return; + t = get_tracepoint (tracepoint_number); if (t == NULL)