[PATCH] Add CTF support to GDB [3/4] ctf target

Hui Zhu teawater@gmail.com
Wed Jan 23 05:54:00 GMT 2013


On Wed, Jan 16, 2013 at 11:12 PM, Abid, Hafiz <Hafiz_Abid@mentor.com> wrote:
> Hi Hui,
> Some minor issues that I noted.
>
> Many functions in your patch starts with bt_ctf_ like the function from libbabeltrace. So it is difficult to see which function comes from the library and which function is actually in GDB. I am not sure about the convention but it looks to me that it would make the code more readable if you renamed your functions. Bring them into GDB namespace.

I agree with you.  And it increase the Increased the possibility of
same name issue with babeltrace in the future.
So I change it to "ctf_".

>
>>+    error (_("Initialize libbabeltrace fail"));
>>+    error (_("Use libbabeltrace open \"%s\" fail"), dirname);
>>+      warning (_("get tracepoint id fail."));
> As Tom already pointed out, these messages can be improved. How about something like "Unable to get the tracepoint id"

Fixed.

>
>>+/* Add each variable of crrent traceframe to GDB as internalvar.  */
> current

Fixed.

>
>>+      warning (_("$%s is not support."), name);
> supported

Fixed.

>
>>+      if (bt_ctf_event_to_internalvar ())
>>+      warning (_("add internal var of this frame fail."));
> This warning message does not tell much. Perhaps it can be moved inside bt_ctf_event_to_internalvar where we have more context to provide more information. Also it needs to be re-phrased.

Sorry.  I didn't have good words for these 2 fail.  So I just change
warning to Unable to xxx...

>
> May be it is just me but indentation looks off at many places.
>
> Regards,
> Abid

Thanks,
Hui

2013-01-23  Hui Zhu  <hui_zhu@mentor.com>

	* aclocal.m4: Add PKG_PROG_PKG_CONFIG.
	* c-exp.y (lookup_enum): Rename to lookup_enum_gdb.
	* config.in (HAVE_LIBBABELTRACE): new macro.
	* configure: New option "--enable-ctf-target".
	* configure.ac: New option "--enable-ctf-target".
	* ctf.c (babeltrace/babeltrace.h, babeltrace/types.h,
	babeltrace/ctf/events.h, babeltrace/ctf/iterator.h): New includes.
	(ctx, iter, current_tp, ctf_event, ctf_ops): New variables.
	(ctf_close_dir, ctf_open_dir, ctf_find_field, ctf_event_id,
	ctf_def_to_val, ctf_event_to_internalvar, ctf_goto_begin,
	ctf_find_num, ctf_find_tp, ctf_open, ctf_close,
	ctf_trace_find, ctf_get_current_tracepoint_name, ctf_trace_dump,
	ctf_has_all_memory, ctf_has_memory, ctf_has_stack,
	ctf_has_registers, ctf_thread_alive, init_ctf_ops,
	_initialize_ctf): New functions.
	* gdbtypes.c (lookup_enum): Rename to lookup_enum_gdb.
	* python/py-type.c (typy_lookup_typename): Rename lookup_enum
	to lookup_enum_gdb.
	* symtab.h (lookup_enum): Rename to lookup_enum_gdb.
	* target.c (update_current_target): Add
	to_get_current_tracepoint_name and to_trace_dump.
	(update_current_target): Ditto.
	* target.h (target_ops): Add to_get_current_tracepoint_name and
	to_trace_dump.
	(target_get_current_tracepoint_name, target_trace_dump): New
	macro.
	* tracepoint.c (tfind_1): Add checks for has_stack_frames ().
	Call target_get_current_tracepoint_name to show the name of
	tracepoint.
	(trace_dump_command): Call target_trace_dump.

>
> ________________________________________
> From: gdb-patches-owner@sourceware.org [gdb-patches-owner@sourceware.org] on behalf of Hui Zhu [teawater@gmail.com]
> Sent: Friday, December 21, 2012 8:22 AM
> To: Tom Tromey
> Cc: Qi, Yao; Zhu, Hui; gdb-patches ml
> Subject: Re: [PATCH] Add CTF support to GDB [3/4] ctf target
>
> On Fri, Nov 30, 2012 at 4:41 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>>> "Hui" == Hui Zhu <teawater@gmail.com> writes:
>>
>> Hui> --- a/configure.ac
>> Hui> +++ b/configure.ac
>> Hui> @@ -2306,6 +2306,134 @@ if test "$enable_gdbserver" = "yes" -a "
>> Hui>    AC_MSG_ERROR(Automatic gdbserver build is not supported for this configuration)
>> Hui>  fi
>>
>> Hui> +AC_ARG_ENABLE(ctf-target,
>> Hui> +AS_HELP_STRING([--enable-ctf-target],
>> Hui> +               [enable ctf target (yes/no/auto, default is auto)]),
>> Hui> +[case "${enableval}" in
>> Hui> +  yes| no|auto) ;;
>> Hui> +  *) AC_MSG_ERROR(bad value ${enableval} for --enable-ctf-target option) ;;
>> Hui> +esac],[enable_ctf_target=auto])
>> Hui> +
>> Hui> +if test "$enable_ctf_target" = "yes" || test "$enable_ctf_target" = "auto"; then
>> Hui> +  pkg_config_args=glib-2.0
>> Hui> +  for module in . gmodule
>> [...]
>>
>> This seems like an awful lot of code just to check for one library.
>> Does libbabeltrace not come with its own pkg-config file?
>> Or not link against its dependencies?
>>
>
> The developer of babeltrace added a patch to "provides a basic
> pkg-config file for libbabeltrace" after I sent request about that.
> So its trunk support pkg-config now.
> New patch support it now.
>
>> Hui> +static struct bt_context *ctx = NULL;
>> Hui> +static struct bt_ctf_iter *iter = NULL;
>> Hui> +static int current_tp;
>> Hui> +static struct bt_ctf_event *ctf_event;
>>
>> Comments.
>>
>> Most of this patch was impenetrable to me due to the general lack of
>> comments.
>
> I added comments to each function to this patch.
>
>>
>> Hui> +    error (_("Try to use libbabeltrace got error"));
>>
>> Please phrase differently.
>
> I change it to "Initialize libbabeltrace fail".
>
>>
>> Hui> +      error (_("Try to open \"%s\" got error"), dirname);
>>
>> Likewise.
>
> I change it to:
> error (_("Use libbabeltrace open \"%s\" fail"), dirname);
>
>>
>> Hui> +      if (strcmp (bt_ctf_field_name(list_d[i]), name) == 0)
>>
>> Missing a space before a paren.  This happens in a few spots.
>
> Fixed.
>
>>
>> Hui> +  /* XXX: some types are not support.  */
>>
>> How about an error in this case?
>> No new FIXME comments anyway.
>
> Removed.
> When this type is not support, GDB will output a warning for that.
>
>>
>> Hui> +extern void output_command (char *, int);
>>
>> Time for this to go into a header file.
>
> Fixed.
>
>>
>> Hui> --- a/target.h
>> Hui> +++ b/target.h
>> Hui> @@ -811,6 +811,10 @@ struct target_ops
>> Hui>         successful, 0 otherwise.  */
>> Hui>      int (*to_set_trace_notes) (char *user, char *notes, char* stopnotes);
>>
>> Hui> +    const char *(*to_get_current_tracepoint_name) (void);
>> Hui> +
>> Hui> +    int (*to_trace_dump) (int from_tty);
>>
>> These sorts of additions particularly need documentation.
>
> I change it to:
>     /* 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);
>
>>
>> Hui> +#define target_get_current_tracepoint_name() \
>> Hui> +(*current_target.to_get_current_tracepoint_name) ()
>> Hui> +
>> Hui> +#define target_trace_dump(from_tty) \
>> Hui> +(*current_target.to_trace_dump) (from_tty)
>>
>> Formatting.
>
> Fixed.
>
>>
>> Hui> --- a/tracepoint.c
>> Hui> +++ b/tracepoint.c
>> Hui> @@ -2243,7 +2243,7 @@ tfind_1 (enum trace_find_type type, int
>> Hui>       below (correctly) decide to print out the source location of the
>> Hui>       trace frame.  */
>> Hui>    if (!(type == tfind_number && num == -1)
>> Hui> -      && (has_stack_frames () || traceframe_number >= 0))
>> Hui> +      && has_stack_frames ())
>>
>> I'm curious about the rationale and impact of this change.
>
> I agree with this change looks odd.  But it is indispensable for this patch.
> According to my prev mail in this thread, maybe you had gotten that
> CTF format is not base on memory mode like tfild.  So it don't have
> frame or something like it.
>
> All this part of code is:
>   if (!(type == tfind_number && num == -1)
>       && (has_stack_frames () || traceframe_number >= 0))
>     old_frame_id = get_frame_id (get_current_frame ());
>
> target ctf cannot support "old_frame_id = get_frame_id
> (get_current_frame ());".  But traceframe_number >= 0 will let GDB
> call the line that target ctf don't support.
> And I don't think traceframe_number >= 0 is very import for "target
> remote" or "target tfile" that support tfind because both of them
> "has_stack_frames ()".
> So I remove "traceframe_number >= 0".
>
>>
>> Tom
>
> Thanks for your help.
>
> According to your comments.  I post a new patch.
>
> Merry Christmas!
>
> Best,
> Hui
>
> 2012-12-20  Hui Zhu  <hui_zhu@mentor.com>
>
>         * aclocal.m4: Add PKG_PROG_PKG_CONFIG.
>         * c-exp.y (lookup_enum): Rename to lookup_enum_gdb.
>         * config.in (HAVE_LIBBABELTRACE): new macro.
>         * configure: New option "--enable-ctf-target".
>         * configure.ac: New option "--enable-ctf-target".
>         * ctf.c (babeltrace/babeltrace.h, babeltrace/types.h,
>         babeltrace/ctf/events.h, babeltrace/ctf/iterator.h): New includes.
>         (ctx, iter, current_tp, ctf_event, ctf_ops): New variables.
>         (bt_ctf_close, bt_ctf_open, bt_ctf_find_field, bt_ctf_event_id,
>         bt_ctf_def_to_val, bt_ctf_event_to_internalvar, bt_ctf_goto_begin,
>         bt_ctf_find_num, bt_ctf_find_tp, ctf_open, ctf_close,
>         ctf_trace_find, ctf_get_current_tracepoint_name, ctf_trace_dump,
>         ctf_has_all_memory, ctf_has_memory, ctf_has_stack,
>         ctf_has_registers, ctf_thread_alive, init_ctf_ops,
>         _initialize_ctf): New functions.
>         * gdbtypes.c (lookup_enum): Rename to lookup_enum_gdb.
>         * python/py-type.c (typy_lookup_typename): Rename lookup_enum
>         to lookup_enum_gdb.
>         * symtab.h (lookup_enum): Rename to lookup_enum_gdb.
>         * target.c (update_current_target): Add
>         to_get_current_tracepoint_name and to_trace_dump.
>         (update_current_target): Ditto.
>         * target.h (target_ops): Add to_get_current_tracepoint_name and
>         to_trace_dump.
>         (target_get_current_tracepoint_name, target_trace_dump): New
>         macro.
>         * tracepoint.c (tfind_1): Add checks for has_stack_frames ().
>         Call target_get_current_tracepoint_name to show the name of
>         tracepoint.
>         (trace_dump_command): Call target_trace_dump.
-------------- next part --------------
--- 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 <link.h> 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 <babeltrace/babeltrace.h>
+#include <babeltrace/ctf/events.h>
+#include <babeltrace/ctf/iterator.h>
+
+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 <babeltrace/babeltrace.h>
+#include <babeltrace/ctf/events.h>
+#include <babeltrace/ctf/iterator.h>
+
+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 <ctype.h>
 
@@ -1338,3 +1339,479 @@ traceframe %d is dropped because type of
 
   do_cleanups (old_chain);
 }
+
+#ifdef HAVE_LIBBABELTRACE
+#include <babeltrace/babeltrace.h>
+#include <babeltrace/ctf/events.h>
+#include <babeltrace/ctf/iterator.h>
+
+/* 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)


More information about the Gdb-patches mailing list