From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15611 invoked by alias); 25 Mar 2013 09:54:21 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 15575 invoked by uid 89); 25 Mar 2013 09:54:08 -0000 X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL,BAYES_00,TW_CP,TW_EG autolearn=no version=3.3.1 Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 25 Mar 2013 09:54:00 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1UK46I-0000AI-CY from Yao_Qi@mentor.com ; Mon, 25 Mar 2013 02:53:58 -0700 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Mon, 25 Mar 2013 02:53:57 -0700 Received: from qiyao.dyndns.org (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.1.289.1; Mon, 25 Mar 2013 02:53:57 -0700 Message-ID: <51501E65.1020801@codesourcery.com> Date: Mon, 25 Mar 2013 13:33:00 -0000 From: Yao Qi User-Agent: Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130110 Thunderbird/17.0.2 MIME-Version: 1.0 To: Doug Evans CC: Tom Tromey , gdb-patches Subject: Re: [PATCH v3 03/15] Read CTF by the ctf target References: <1362800844-27940-1-git-send-email-yao@codesourcery.com> <1362800844-27940-4-git-send-email-yao@codesourcery.com> <871ubjawq8.fsf@fleche.redhat.com> <20802.2886.914505.51784@ruffy2.mtv.corp.google.com> In-Reply-To: <20802.2886.914505.51784@ruffy2.mtv.corp.google.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-SW-Source: 2013-03/txt/msg00926.txt.bz2 On 03/15/2013 01:39 AM, Doug Evans wrote: > Running ./configure --help I see expat provides a different means > for specifying the location. > > --with-expat include expat support (auto/yes/no) > --with-libexpat-prefix[=DIR] search for libexpat in DIR/include and DIR/lib > --without-libexpat-prefix don't search for libexpat in includedir and libdir > > Ideally we should be consistent. > > IIUC, expat support does this: > > AC_LIB_HAVE_LINKFLAGS([expat], [], [#include "expat.h"], > [XML_Parser p = XML_ParserCreate (0);]) Doug and Tom, I start to use AC_LIB_HAVE_LINKFLAGS in the new patch below, and the 'configure --help' is like this: --with-babeltrace include babeltrace support (auto/yes/no) --with-libbabeltrace-prefix[=DIR] search for libbabeltrace in DIR/include and DIR/lib --without-libbabeltrace-prefix don't search for libbabeltrace in includedir and libdir This version also includes several changes compared with the last one: - Update ctf_close because of the change in 'to_close' field of 'struct target_ops'. - Don't expose some variables out of tracepoint.c. Add and use functions to access them. - Remove some unnecessary target_ops hooks. I also test this patch with babeltrace 1.1.0 release which was released yesterday. Test looks right. I also build GDB with mingw32 and mingw-w64 cross gcc. Is it OK? -- Yao (齐尧) gdb: 2013-03-25 Hui Zhu Yao Qi * configure.ac: Check libbabeltrace is installed. * config.in: Regenerate. * configure: Regenerate. * Makefile.in (LIBBABELTRACE): New. (CLIBS): Add LIBBABELTRACE. * ctf.c (ctx, ctf_iter, trace_dirname): New. (ctf_destroy, ctf_open_dir, ctf_open): New. (ctf_close, ctf_files_info): New. (ctf_fetch_registers, ctf_xfer_partial): New. (ctf_get_trace_state_variable_value): New. (ctf_get_tpnum_from_frame_event): New. (ctf_get_traceframe_address): New. (ctf_trace_find, ctf_has_stack): New. (ctf_has_registers, ctf_traceframe_info, init_ctf_ops): New. (_initialize_ctf): New. * tracepoint.c (get_tracepoint_number): New (struct traceframe_info, trace_regblock_size): Move it to ... * tracepoint.h: ... here. (get_tracepoint_number): Declare it. --- gdb/Makefile.in | 6 +- gdb/config.in | 3 + gdb/configure | 535 +++++++++++++++++++++++++++++++++++++++ gdb/configure.ac | 41 +++ gdb/ctf.c | 743 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/tracepoint.c | 16 +- gdb/tracepoint.h | 13 + 7 files changed, 1346 insertions(+), 11 deletions(-) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 9bab01c..f474897 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -154,6 +154,10 @@ LIBEXPAT = @LIBEXPAT@ # Where is lzma? This will be empty if lzma was not available. LIBLZMA = @LIBLZMA@ +# Where is libbabeltrace? This will be empty if lbabeltrace was not +# available. +LIBBABELTRACE = @LIBBABELTRACE@ + WARN_CFLAGS = @WARN_CFLAGS@ WERROR_CFLAGS = @WERROR_CFLAGS@ GDB_WARN_CFLAGS = $(WARN_CFLAGS) @@ -475,7 +479,7 @@ INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(MH_LDFLAGS) $(LDFLAGS) $(CONFIG_ # LIBIBERTY appears twice on purpose. CLIBS = $(SIM) $(READLINE) $(OPCODES) $(BFD) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \ $(XM_CLIBS) $(NAT_CLIBS) $(GDBTKLIBS) @LIBS@ @PYTHON_LIBS@ \ - $(LIBEXPAT) $(LIBLZMA) \ + $(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) \ $(LIBIBERTY) $(WIN32LIBS) $(LIBGNU) CDEPS = $(XM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE_DEPS) \ $(OPCODES) $(INTL_DEPS) $(LIBIBERTY) $(CONFIG_DEPS) $(LIBGNU) diff --git a/gdb/config.in b/gdb/config.in index 9e21325..c4e8eaa 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -180,6 +180,9 @@ /* Define if your file defines LC_MESSAGES. */ #undef HAVE_LC_MESSAGES +/* Define if libbabeltrace is available */ +#undef HAVE_LIBBABELTRACE + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL diff --git a/gdb/configure b/gdb/configure index 0dd67f0..db4c023 100755 --- a/gdb/configure +++ b/gdb/configure @@ -592,6 +592,9 @@ enable_option_checking=no ac_subst_vars='LTLIBOBJS LIBOBJS GDB_NM_FILE +LTLIBBABELTRACE +LIBBABELTRACE +HAVE_LIBBABELTRACE frags target_subdir CONFIG_UNINSTALL @@ -819,6 +822,8 @@ with_x enable_sim enable_multi_ice enable_gdbserver +with_babeltrace +with_libbabeltrace_prefix ' ac_precious_vars='build_alias host_alias @@ -1532,6 +1537,9 @@ Optional Packages: --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tk directory containing tk configuration (tkConfig.sh) --with-x use the X Window System + --with-babeltrace include babeltrace support (auto/yes/no) + --with-libbabeltrace-prefix[=DIR] search for libbabeltrace in DIR/include and DIR/lib + --without-libbabeltrace-prefix don't search for libbabeltrace in includedir and libdir Some influential environment variables: CC C compiler command @@ -14093,6 +14101,533 @@ if test "$enable_gdbserver" = "yes" -a "$gdbserver_build_enabled" != "yes"; then as_fn_error "Automatic gdbserver build is not supported for this configuration" "$LINENO" 5 fi +# Check for babeltrace and babeltrace-ctf + +# Check whether --with-babeltrace was given. +if test "${with_babeltrace+set}" = set; then : + withval=$with_babeltrace; +else + with_babeltrace=auto +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use babeltrace" >&5 +$as_echo_n "checking whether to use babeltrace... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_babeltrace" >&5 +$as_echo "$with_babeltrace" >&6; } + +if test "x$with_babeltrace" = "xno"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: babletrace support disabled; GDB is unable to read CTF data." >&5 +$as_echo "$as_me: WARNING: babletrace support disabled; GDB is unable to read CTF data." >&2;} +else + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libbabeltrace-prefix was given. +if test "${with_libbabeltrace_prefix+set}" = set; then : + withval=$with_libbabeltrace_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/lib" + fi + fi + +fi + + LIBBABELTRACE= + LTLIBBABELTRACE= + INCBABELTRACE= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='babeltrace babeltrace-ctf' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBBABELTRACE="${LTLIBBABELTRACE}${LTLIBBABELTRACE:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + if test $use_additional = yes; then + if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then + found_dir="$additional_libdir" + found_so="$additional_libdir/lib$name.$shlibext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + else + if test -f "$additional_libdir/lib$name.$libext"; then + found_dir="$additional_libdir" + found_a="$additional_libdir/lib$name.$libext" + if test -f "$additional_libdir/lib$name.la"; then + found_la="$additional_libdir/lib$name.la" + fi + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBBABELTRACE; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then + found_dir="$dir" + found_so="$dir/lib$name.$shlibext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + else + if test -f "$dir/lib$name.$libext"; then + found_dir="$dir" + found_a="$dir/lib$name.$libext" + if test -f "$dir/lib$name.la"; then + found_la="$dir/lib$name.la" + fi + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBBABELTRACE="${LTLIBBABELTRACE}${LTLIBBABELTRACE:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$hardcode_direct" = yes; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$found_so" + else + if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBBABELTRACE; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }-L$found_dir" + fi + if test "$hardcode_minus_L" != no; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$found_so" + else + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$found_a" + else + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'` + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCBABELTRACE; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCBABELTRACE="${INCBABELTRACE}${INCBABELTRACE:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/lib"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/lib"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBBABELTRACE; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBBABELTRACE; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBBABELTRACE="${LTLIBBABELTRACE}${LTLIBBABELTRACE:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$dep" + LTLIBBABELTRACE="${LTLIBBABELTRACE}${LTLIBBABELTRACE:+ }$dep" + ;; + esac + done + fi + else + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }-l$name" + LTLIBBABELTRACE="${LTLIBBABELTRACE}${LTLIBBABELTRACE:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBBABELTRACE="${LIBBABELTRACE}${LIBBABELTRACE:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBBABELTRACE="${LTLIBBABELTRACE}${LTLIBBABELTRACE:+ }-R$found_dir" + done + fi + + + ac_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCBABELTRACE; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libbabeltrace" >&5 +$as_echo_n "checking for libbabeltrace... " >&6; } +if test "${ac_cv_libbabeltrace+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + ac_save_LIBS="$LIBS" + LIBS="$LIBS $LIBBABELTRACE" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + #include +int +main () +{ +struct bt_iter_pos *pos = bt_iter_get_pos (bt_ctf_get_iter (NULL)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_libbabeltrace=yes +else + ac_cv_libbabeltrace=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libbabeltrace" >&5 +$as_echo "$ac_cv_libbabeltrace" >&6; } + if test "$ac_cv_libbabeltrace" = yes; then + HAVE_LIBBABELTRACE=yes + +$as_echo "#define HAVE_LIBBABELTRACE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libbabeltrace" >&5 +$as_echo_n "checking how to link with libbabeltrace... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBBABELTRACE" >&5 +$as_echo "$LIBBABELTRACE" >&6; } + else + HAVE_LIBBABELTRACE=no + CPPFLAGS="$ac_save_CPPFLAGS" + LIBBABELTRACE= + LTLIBBABELTRACE= + fi + + + + + + + + if test "$HAVE_LIBBABELTRACE" != yes; then + if test "$wit_babeltrace" = yes; then + as_fn_error "babeltrace is missing or unusable" "$LINENO" 5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: babeltrace is missing or unusable; GDB is unable to read CTF data." >&5 +$as_echo "$as_me: WARNING: babeltrace is missing or unusable; GDB is unable to read CTF data." >&2;} + fi + else + # Check whether there is a function named 'lookup_enum' in + # babeltrace library. We can't use the babeltrace library + # in which function 'lookup_enum' is defined. This function + # is renamed to 'bt_lookup_enum' in recent babeltrace. + saved_LIBS=$LIBS + LIBS="$LIBS $LIBBABELTRACE" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken babeltrace" >&5 +$as_echo_n "checking for broken babeltrace... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +lookup_enum (NULL, NULL, 0) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; +$as_echo "#define HAVE_LIBBABELTRACE 0" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + LIBS=$save_LIBS + fi +fi + # If nativefile (NAT_FILE) is not set in config/*/*.m[ht] files, we link # to an empty version. diff --git a/gdb/configure.ac b/gdb/configure.ac index c17f587..874294b 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -2321,6 +2321,47 @@ if test "$enable_gdbserver" = "yes" -a "$gdbserver_build_enabled" != "yes"; then AC_MSG_ERROR(Automatic gdbserver build is not supported for this configuration) fi +# Check for babeltrace and babeltrace-ctf +AC_ARG_WITH(babeltrace, + AC_HELP_STRING([--with-babeltrace], [include babeltrace support (auto/yes/no)]), + [], [with_babeltrace=auto]) +AC_MSG_CHECKING([whether to use babeltrace]) +AC_MSG_RESULT([$with_babeltrace]) + +if test "x$with_babeltrace" = "xno"; then + AC_MSG_WARN([babletrace support disabled; GDB is unable to read CTF data.]) +else + AC_LIB_HAVE_LINKFLAGS([babeltrace], [babeltrace-ctf], + [#include + #include + #include ], + [struct bt_iter_pos *pos = bt_iter_get_pos (bt_ctf_get_iter (NULL));]) + + if test "$HAVE_LIBBABELTRACE" != yes; then + if test "$wit_babeltrace" = yes; then + AC_MSG_ERROR([babeltrace is missing or unusable]) + else + AC_MSG_WARN([babeltrace is missing or unusable; GDB is unable to read CTF data.]) + fi + else + # Check whether there is a function named 'lookup_enum' in + # babeltrace library. We can't use the babeltrace library + # in which function 'lookup_enum' is defined. This function + # is renamed to 'bt_lookup_enum' in recent babeltrace. + saved_LIBS=$LIBS + LIBS="$LIBS $LIBBABELTRACE" + + AC_MSG_CHECKING([for broken babeltrace]) + AC_TRY_LINK([#include ], + [lookup_enum (NULL, NULL, 0)], + [AC_MSG_RESULT([yes]); AC_DEFINE(HAVE_LIBBABELTRACE, 0, + [Define if libbabeltrace is available])], + [AC_MSG_RESULT([no])]) + + LIBS=$save_LIBS + fi +fi + # If nativefile (NAT_FILE) is not set in config/*/*.m[ht] files, we link # to an empty version. diff --git a/gdb/ctf.c b/gdb/ctf.c index 6b55986..99a7fef 100644 --- a/gdb/ctf.c +++ b/gdb/ctf.c @@ -24,6 +24,7 @@ #include "tracepoint.h" #include "regcache.h" #include "gdb_stat.h" +#include "exec.h" #include @@ -669,3 +670,745 @@ ctf_trace_file_writer_new (void) return (struct trace_file_writer *) writer; } + +#if HAVE_LIBBABELTRACE +/* Use libbabeltrace to read CTF data. The libbabeltrace provides + iterator to iterate over each event in CTF data and APIs to get + details of event and packet, so it is very convenient to use + libbabeltrace to access events in CTF. */ + +#include +#include +#include + +/* The struct pointer for current CTF directory. */ +static struct bt_context *ctx = NULL; +static struct bt_ctf_iter *ctf_iter = NULL; +/* The name of CTF directory. */ +static char *trace_dirname; + +static struct target_ops ctf_ops; + +/* Destroy ctf iterator and context. */ + +static void +ctf_destroy (void) +{ + if (ctf_iter != NULL) + { + bt_ctf_iter_destroy (ctf_iter); + ctf_iter = NULL; + } + if (ctx != NULL) + { + bt_context_put (ctx); + ctx = NULL; + } +} + +/* Open CTF trace data in DIRNAME. */ + +static void +ctf_open_dir (char *dirname) +{ + int ret; + struct bt_iter_pos begin_pos; + struct bt_iter_pos *pos; + + ctx = bt_context_create (); + if (ctx == NULL) + error (_("Unable to initialize libbabeltrace")); + ret = bt_context_add_trace (ctx, dirname, "ctf", NULL, NULL, NULL); + if (ret < 0) + { + ctf_destroy (); + error (_("Unable to use libbabeltrace open \"%s\""), dirname); + } + + begin_pos.type = BT_SEEK_BEGIN; + ctf_iter = bt_ctf_iter_create (ctx, &begin_pos, NULL); + if (ctf_iter == NULL) + { + ctf_destroy (); + error (_("Unable to use libbabeltrace open \"%s\""), dirname); + } + + /* Iterate over events, and look for an event for register block + to set trace_regblock_size. */ + + /* Save the current position. */ + pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); + gdb_assert (pos->type == BT_SEEK_RESTORE); + + while (1) + { + const char *name; + struct bt_ctf_event *event; + + event = bt_ctf_iter_read_event (ctf_iter); + + name = bt_ctf_event_name (event); + + if (name == NULL) + break; + else if (strcmp (name, "register") == 0) + { + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + const struct bt_definition *array + = bt_ctf_get_field (event, scope, "contents"); + + trace_regblock_size + = bt_ctf_get_array_len (bt_ctf_get_decl_from_def (array)); + } + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + } + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + +} + +/* This is the implementation of target_ops method to_open. Open CTF + trace data, read trace status, trace state variables and tracepoint + definitions from the first packet. Set the start position at the + second packet which contains events on trace blocks. */ + +static void +ctf_open (char *dirname, int from_tty) +{ + target_preopen (from_tty); + if (!dirname) + error (_("No CTF directory specified.")); + + ctf_open_dir (dirname); + + trace_dirname = xstrdup (dirname); + push_target (&ctf_ops); +} + +/* This is the implementation of target_ops method to_close. Destroy + CTF iterator and context. */ + +static void +ctf_close (void) +{ + ctf_destroy (); + xfree (trace_dirname); + trace_dirname = NULL; +} + +/* This is the implementation of target_ops method to_files_info. + Print the directory name of CTF trace data. */ + +static void +ctf_files_info (struct target_ops *t) +{ + printf_filtered ("\t`%s'\n", trace_dirname); +} + +/* This is the implementation of target_ops method to_fetch_registers. + Iterate over events whose name is "register" in current frame, + extract contents from events, and set REGCACHE with the contents. + If no matched events are found, mark registers unavailable. */ + +static void +ctf_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int offset, regn, regsize, pc_regno; + char *regs = NULL; + struct bt_ctf_event *event = NULL; + struct bt_iter_pos *pos; + + /* An uninitialized reg size says we're not going to be + successful at getting register blocks. */ + if (trace_regblock_size == 0) + return; + + /* Save the current position. */ + pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); + gdb_assert (pos->type == BT_SEEK_RESTORE); + + while (1) + { + const char *name; + struct bt_ctf_event *event1; + + event1 = bt_ctf_iter_read_event (ctf_iter); + + name = bt_ctf_event_name (event1); + + if (name == NULL || strcmp (name, "frame") == 0) + break; + else if (strcmp (name, "register") == 0) + { + event = event1; + break; + } + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + } + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + + if (event != NULL) + { + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + const struct bt_definition *array + = bt_ctf_get_field (event, scope, "contents"); + + regs = bt_ctf_get_char_array (array); + /* Assume the block is laid out in GDB register number order, + each register with the size that it has in GDB. */ + offset = 0; + for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) + { + regsize = register_size (gdbarch, regn); + /* Make sure we stay within block bounds. */ + if (offset + regsize >= trace_regblock_size) + break; + if (regcache_register_status (regcache, regn) == REG_UNKNOWN) + { + if (regno == regn) + { + regcache_raw_supply (regcache, regno, regs + offset); + break; + } + else if (regno == -1) + { + regcache_raw_supply (regcache, regn, regs + offset); + } + } + offset += regsize; + } + return; + } + + regs = alloca (trace_regblock_size); + + /* We get here if no register data has been found. Mark registers + as unavailable. */ + for (regn = 0; regn < gdbarch_num_regs (gdbarch); regn++) + regcache_raw_supply (regcache, regn, NULL); + + /* We can often usefully guess that the PC is going to be the same + as the address of the tracepoint. */ + pc_regno = gdbarch_pc_regnum (gdbarch); + if (pc_regno >= 0 && (regno == -1 || regno == pc_regno)) + { + struct tracepoint *tp = get_tracepoint (get_tracepoint_number ()); + + if (tp != NULL && tp->base.loc) + { + /* But don't try to guess if tracepoint is multi-location... */ + if (tp->base.loc->next != NULL) + { + warning (_("Tracepoint %d has multiple " + "locations, cannot infer $pc"), + tp->base.number); + return; + } + /* ... or does while-stepping. */ + if (tp->step_count > 0) + { + warning (_("Tracepoint %d does while-stepping, " + "cannot infer $pc"), + tp->base.number); + return; + } + + store_unsigned_integer (regs, register_size (gdbarch, pc_regno), + gdbarch_byte_order (gdbarch), + tp->base.loc->address); + regcache_raw_supply (regcache, pc_regno, regs); + } + } +} + +/* This is the implementation of target_ops method to_xfer_partial. + Iterate over events whose name is "memory" in + current frame, extract the address and length from events. If + OFFSET is within the range, read the contents from events to + READBUF. */ + +static LONGEST +ctf_xfer_partial (struct target_ops *ops, enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, ULONGEST offset, + LONGEST len) +{ + /* We're only doing regular memory for now. */ + if (object != TARGET_OBJECT_MEMORY) + return -1; + + if (readbuf == NULL) + error (_("ctf_xfer_partial: trace file is read-only")); + + if (get_traceframe_number () != -1) + { + struct bt_iter_pos *pos; + int i = 0; + + /* Save the current position. */ + pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); + gdb_assert (pos->type == BT_SEEK_RESTORE); + + /* Iterate through the traceframe's blocks, looking for + memory. */ + while (1) + { + ULONGEST maddr, amt; + uint16_t mlen; + enum bfd_endian byte_order + = gdbarch_byte_order (target_gdbarch ()); + const struct bt_definition *scope; + const struct bt_definition *def; + struct bt_ctf_event *event + = bt_ctf_iter_read_event (ctf_iter); + const char *name = bt_ctf_event_name (event); + + if (strcmp (name, "frame") == 0) + break; + else if (strcmp (name, "memory") != 0) + { + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + + continue; + } + + scope = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + + def = bt_ctf_get_field (event, scope, "address"); + maddr = bt_ctf_get_uint64 (def); + def = bt_ctf_get_field (event, scope, "length"); + mlen = (uint16_t) bt_ctf_get_uint64 (def); + + /* If the block includes the first part of the desired + range, return as much it has; GDB will re-request the + remainder, which might be in a different block of this + trace frame. */ + if (maddr <= offset && offset < (maddr + mlen)) + { + const struct bt_definition *array + = bt_ctf_get_field (event, scope, "contents"); + const struct bt_declaration *decl + = bt_ctf_get_decl_from_def (array); + gdb_byte *contents; + int k; + + contents = xmalloc (mlen); + + for (k = 0; k < mlen; k++) + { + const struct bt_definition *element + = bt_ctf_get_index (event, array, k); + + contents[k] = (gdb_byte) bt_ctf_get_uint64 (element); + } + + amt = (maddr + mlen) - offset; + if (amt > len) + amt = len; + + memcpy (readbuf, &contents[offset - maddr], amt); + + xfree (contents); + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + + return amt; + } + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + } + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + } + + /* It's unduly pedantic to refuse to look at the executable for + read-only pieces; so do the equivalent of readonly regions aka + QTro packet. */ + if (exec_bfd != NULL) + { + asection *s; + bfd_size_type size; + bfd_vma vma; + + for (s = exec_bfd->sections; s; s = s->next) + { + if ((s->flags & SEC_LOAD) == 0 + || (s->flags & SEC_READONLY) == 0) + continue; + + vma = s->vma; + size = bfd_get_section_size (s); + if (vma <= offset && offset < (vma + size)) + { + ULONGEST amt; + + amt = (vma + size) - offset; + if (amt > len) + amt = len; + + amt = bfd_get_section_contents (exec_bfd, s, + readbuf, offset - vma, amt); + return amt; + } + } + } + + /* Indicate failure to find the requested memory block. */ + return -1; +} + +/* This is the implementation of target_ops method + to_get_trace_state_variable_value. + Iterate over events whose name is "tsv" in current frame. When the + trace variable is found, set the value of it to *VAL and return + true, otherwise return false. */ + +static int +ctf_get_trace_state_variable_value (int tsvnum, LONGEST *val) +{ + struct bt_iter_pos *pos; + int found = 0; + + /* Save the current position. */ + pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); + gdb_assert (pos->type == BT_SEEK_RESTORE); + + /* Iterate through the traceframe's blocks, looking for 'V' + block. */ + while (1) + { + struct bt_ctf_event *event + = bt_ctf_iter_read_event (ctf_iter); + const char *name = bt_ctf_event_name (event); + + if (name == NULL || strcmp (name, "frame") == 0) + break; + else if (strcmp (name, "tsv") == 0) + { + const struct bt_definition *scope; + const struct bt_definition *def; + + scope = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + + def = bt_ctf_get_field (event, scope, "num"); + if (tsvnum == (int32_t) bt_ctf_get_uint64 (def)) + { + def = bt_ctf_get_field (event, scope, "val"); + *val = bt_ctf_get_uint64 (def); + + found = 1; + } + } + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + } + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + + return found; +} + +/* Return the tracepoint number in "frame" event. */ + +static int +ctf_get_tpnum_from_frame_event (struct bt_ctf_event *event) +{ + /* The packet context of events has a field "tpnum". */ + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, BT_STREAM_PACKET_CONTEXT); + uint64_t tpnum + = bt_ctf_get_uint64 (bt_ctf_get_field (event, scope, "tpnum")); + + return (int) tpnum; +} + +/* Return the address at which the current frame was collected. */ + +static ULONGEST +ctf_get_traceframe_address (void) +{ + struct bt_ctf_event *event = NULL; + struct bt_iter_pos *pos + = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); + ULONGEST addr = 0; + + gdb_assert (pos->type == BT_SEEK_RESTORE); + + while (1) + { + const char *name; + struct bt_ctf_event *event1; + + event1 = bt_ctf_iter_read_event (ctf_iter); + + name = bt_ctf_event_name (event1); + + if (name == NULL) + break; + else if (strcmp (name, "frame") == 0) + { + event = event1; + break; + } + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + } + + if (event != NULL) + { + int tpnum = ctf_get_tpnum_from_frame_event (event); + struct tracepoint *tp + = get_tracepoint_by_number_on_target (tpnum); + + if (tp && tp->base.loc) + addr = tp->base.loc->address; + } + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + + return addr; +} + +/* This is the implementation of target_ops method to_trace_find. + Iterate the events whose name is "frame", extract the tracepoint + number in it. Return traceframe number when matched. */ + +static int +ctf_trace_find (enum trace_find_type type, int num, + ULONGEST addr1, ULONGEST addr2, int *tpp) +{ + int ret = -1; + int tfnum = 0; + int found = 0; + struct bt_iter_pos pos; + + if (num == -1) + { + if (tpp != NULL) + *tpp = -1; + return -1; + } + + /* Set iterator back to the beginning. */ + pos.type = BT_SEEK_BEGIN; + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), &pos); + + while (1) + { + int id; + struct bt_ctf_event *event; + const char *name; + + event = bt_ctf_iter_read_event (ctf_iter); + + name = bt_ctf_event_name (event); + + if (event == NULL || name == NULL) + return -1; + + if (strcmp (name, "frame") == 0) + { + ULONGEST tfaddr; + + if (type == tfind_number) + { + /* Looking for a specific trace frame. */ + if (tfnum == num) + found = 1; + } + else + { + /* Start from the _next_ trace frame. */ + if (tfnum > get_traceframe_number ()) + { + switch (type) + { + case tfind_tp: + { + struct tracepoint *tp = get_tracepoint (num); + + if (tp != NULL + && (tp->number_on_target + == ctf_get_tpnum_from_frame_event (event))) + found = 1; + break; + } + case tfind_pc: + tfaddr = ctf_get_traceframe_address (); + if (tfaddr == addr1) + found = 1; + break; + case tfind_range: + tfaddr = ctf_get_traceframe_address (); + if (addr1 <= tfaddr && tfaddr <= addr2) + found = 1; + break; + case tfind_outside: + tfaddr = ctf_get_traceframe_address (); + if (!(addr1 <= tfaddr && tfaddr <= addr2)) + found = 1; + break; + default: + internal_error (__FILE__, __LINE__, _("unknown tfind type")); + } + } + } + if (found) + { + if (tpp != NULL) + *tpp = ctf_get_tpnum_from_frame_event (event); + + /* Skip the event "frame". */ + bt_iter_next (bt_ctf_get_iter (ctf_iter)); + + return tfnum; + } + tfnum++; + } + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + return -1; + } + + return -1; +} + +/* This is the implementation of target_ops method to_has_stack. + The target has a stack when GDB has already selected one trace + frame. */ + +static int +ctf_has_stack (struct target_ops *ops) +{ + return get_traceframe_number () != -1; +} + +/* This is the implementation of target_ops method to_has_registers. + The target has registers when GDB has already selected one trace + frame. */ + +static int +ctf_has_registers (struct target_ops *ops) +{ + return get_traceframe_number () != -1; +} + +/* This is the implementation of target_ops method to_traceframe_info. + Iterate the events whose name is "memory", in current + frame, extract memory range information, and return them in + traceframe_info. */ + +static struct traceframe_info * +ctf_traceframe_info (void) +{ + struct traceframe_info *info = XCNEW (struct traceframe_info); + const char *name; + struct bt_iter_pos *pos; + + /* Save the current position. */ + pos = bt_iter_get_pos (bt_ctf_get_iter (ctf_iter)); + gdb_assert (pos->type == BT_SEEK_RESTORE); + + do + { + struct bt_ctf_event *event + = bt_ctf_iter_read_event (ctf_iter); + + name = bt_ctf_event_name (event); + + if (name == NULL || strcmp (name, "register") == 0 + || strcmp (name, "frame") == 0) + ; + else if (strcmp (name, "memory") == 0) + { + const struct bt_definition *scope + = bt_ctf_get_top_level_scope (event, + BT_EVENT_FIELDS); + const struct bt_definition *def; + struct mem_range *r; + + r = VEC_safe_push (mem_range_s, info->memory, NULL); + def = bt_ctf_get_field (event, scope, "address"); + r->start = bt_ctf_get_uint64 (def); + + def = bt_ctf_get_field (event, scope, "length"); + r->length = (uint16_t) bt_ctf_get_uint64 (def); + } + else + warning (_("Unhandled trace block type (%s) " + "while building trace frame info."), + name); + + if (bt_iter_next (bt_ctf_get_iter (ctf_iter)) < 0) + break; + } + while (name != NULL && strcmp (name, "frame") != 0); + + /* Restore the position. */ + bt_iter_set_pos (bt_ctf_get_iter (ctf_iter), pos); + + return info; +} + +static void +init_ctf_ops (void) +{ + memset (&ctf_ops, 0, sizeof (ctf_ops)); + + 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_fetch_registers = ctf_fetch_registers; + ctf_ops.to_xfer_partial = ctf_xfer_partial; + ctf_ops.to_files_info = ctf_files_info; + ctf_ops.to_trace_find = ctf_trace_find; + ctf_ops.to_get_trace_state_variable_value + = ctf_get_trace_state_variable_value; + ctf_ops.to_stratum = process_stratum; + ctf_ops.to_has_stack = ctf_has_stack; + ctf_ops.to_has_registers = ctf_has_registers; + ctf_ops.to_traceframe_info = ctf_traceframe_info; + ctf_ops.to_magic = OPS_MAGIC; +} + +#endif + +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_ctf; + +/* module initialization */ +void +_initialize_ctf (void) +{ +#if HAVE_LIBBABELTRACE + init_ctf_ops (); + + add_target (&ctf_ops); +#endif +} diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 9a2425b..6a30f6f 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -126,14 +126,6 @@ extern void (*deprecated_readline_end_hook) (void); typedef struct trace_state_variable tsv_s; DEF_VEC_O(tsv_s); -/* An object describing the contents of a traceframe. */ - -struct traceframe_info -{ - /* Collected memory. */ - VEC(mem_range_s) *memory; -}; - static VEC(tsv_s) *tvariables; /* The next integer to assign to a variable. */ @@ -3302,8 +3294,6 @@ static const struct trace_file_write_ops tfile_write_ops = #define TRACE_WRITE_V_BLOCK(writer, num, val) \ writer->ops->frame_ops->write_v_block ((writer), (num), (val)) -extern int trace_regblock_size; - /* Save tracepoint data to file named FILENAME through WRITER. WRITER determines the trace file format. If TARGET_DOES_SAVE is non-zero, the save is performed on the target, otherwise GDB obtains all trace @@ -3740,6 +3730,12 @@ get_traceframe_number (void) return traceframe_number; } +int +get_tracepoint_number (void) +{ + return tracepoint_number; +} + /* Make the traceframe NUM be the current trace frame. Does nothing if NUM is already current. */ diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h index c7eef7b..bad8d49 100644 --- a/gdb/tracepoint.h +++ b/gdb/tracepoint.h @@ -24,6 +24,14 @@ #include "memrange.h" #include "gdb_vecs.h" +/* An object describing the contents of a traceframe. */ + +struct traceframe_info +{ + /* Collected memory. */ + VEC(mem_range_s) *memory; +}; + /* A trace state variable is a value managed by a target being traced. A trace state variable (or tsv for short) can be accessed and assigned to by tracepoint actions and conditionals, but is not @@ -142,6 +150,8 @@ struct trace_status *current_trace_status (void); extern char *default_collect; +extern int trace_regblock_size; + /* Struct to collect random info about tracepoints on the target. */ struct uploaded_tp @@ -324,6 +334,9 @@ extern void (*deprecated_trace_start_stop_hook) (int start, int from_tty); /* Returns the current traceframe number. */ extern int get_traceframe_number (void); +/* Returns the tracepoint number for current traceframe. */ +extern int get_tracepoint_number (void); + /* Make the traceframe NUM be the current GDB trace frame number, and do nothing more. In particular, this does not flush the register/frame caches or notify the target about the trace frame -- 1.7.7.6