public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/8] extend branch tracing to use ARM CoreSight traces
@ 2021-02-26  2:45 Zied Guermazi
  2021-02-26  2:45 ` [PATCH 1/8] configure gdb build system for supporting btrace on arm processors Zied Guermazi
                   ` (7 more replies)
  0 siblings, 8 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi

 This patch set adds support for branch tracing in GDB on arm platforms
 using coresight etm traces
 Branch tracing offers instructions and functions histories as well as
 execution record and replay (forwards and reverse debugging)
 this patch set was tested using the gdb.btrace testsuite on ARMv7 and ARMv8
 cortex A processors running linux operating system with coresight drivers.
 
 test results of gdb.btrace testsuite on ARMv8, variation unix
 # of expected passes		595
 # of unexpected failures	1
 # of unsupported tests	1

 test results of gdb.btrace testsuite on ARMv8 variation native-gdbserver
 # of expected passes		582
 # of unexpected failures	4
 # of unsupported tests	2
 
 test results of gdb.btrace testsuite  on ARMv7, variation unix
 
 test results of gdb.btrace testsuite on ARMv7 variation native-gdbserver

 
 known limitations:
 for arm v7 only
- some registers needed for breakpoint address calculation in forwards
  executions may be missing.
 for arm v7 and arm v8
- sometimes trace buffers are not flushed properly or flushed in
  the buffer of a different thread. this was observed
  in test scripts only.
- sometimes, in non-stop mode, while executing "stepi n" for two threads
  in parallel, a thread is hitting breakpoints intended for stepping
  the other one.
  Gdb recognizes that it is intended for the second thread,
  but decreases the step counter. leading to a stepping less than "n"
  times.
 patches are:

Zied Guermazi (8):
  configure gdb build system for supporting btrace on arm processors
  add btrace coresight related commands
  start/stop btrace with coresight etm and parse etm buffer. nat
    independant
  start/stop btrace with coresight etm and collect etm buffer on linux
    os
  fix issue: gdb hangs in the command following a commad returning with
    TARGET_WAITKIND_NO_HISTORY
  add support for coresight btrace via remote protocol
  adapt btrace testcases for arm target
  document btrace support for arm targets using coresight etm traces

 gdb/ChangeLog                                 | 143 +++
 gdb/Makefile.in                               |   5 +-
 gdb/NEWS                                      |  30 +
 gdb/aarch64-linux-nat.c                       |  71 +-
 gdb/arm-linux-nat.c                           |  66 ++
 gdb/btrace.c                                  | 951 +++++++++++++++++-
 gdb/btrace.h                                  |  20 +
 gdb/config.in                                 |   3 +
 gdb/configure                                 | 545 ++++++++++
 gdb/configure.nat                             |   4 +-
 gdb/doc/ChangeLog                             |   5 +
 gdb/doc/gdb.texinfo                           | 119 ++-
 gdb/features/btrace-conf.dtd                  |  10 +-
 gdb/features/btrace.dtd                       |  39 +-
 gdb/infrun.c                                  |   3 +-
 gdb/nat/linux-btrace.c                        | 450 ++++++++-
 gdb/nat/linux-btrace.h                        |  19 +
 gdb/record-btrace.c                           | 141 ++-
 gdb/record.c                                  |   2 +
 gdb/remote.c                                  |  66 +-
 .../gdb.btrace/aarch64-instruction_history.S  |  31 +
 .../gdb.btrace/aarch64-record_goto.S          | 400 ++++++++
 .../gdb.btrace/aarch64-tailcall-only.S        | 517 ++++++++++
 gdb/testsuite/gdb.btrace/aarch64-tailcall.S   | 409 ++++++++
 .../gdb.btrace/arm-instruction_history.S      |  31 +
 gdb/testsuite/gdb.btrace/arm-record_goto.S    | 433 ++++++++
 gdb/testsuite/gdb.btrace/arm-tailcall-only.S  | 504 ++++++++++
 gdb/testsuite/gdb.btrace/arm-tailcall.S       | 391 +++++++
 gdb/testsuite/gdb.btrace/buffer-size.exp      |  15 +-
 gdb/testsuite/gdb.btrace/delta.exp            |  10 +
 .../gdb.btrace/instruction_history.exp        | 107 +-
 gdb/testsuite/gdb.btrace/non-stop.exp         |  60 +-
 gdb/testsuite/gdb.btrace/record_goto.exp      | 241 +++--
 gdb/testsuite/gdb.btrace/stepi.exp            |  95 +-
 gdb/testsuite/gdb.btrace/tailcall-only.exp    |   8 +
 gdb/testsuite/gdb.btrace/tailcall.exp         |  46 +-
 ...on_history.S => x86-instruction_history.S} |   0
 gdb/testsuite/lib/gdb.exp                     |   2 +-
 gdb/top.c                                     |  10 +-
 gdbserver/ChangeLog                           |  17 +
 gdbserver/configure                           | 545 ++++++++++
 gdbserver/configure.srv                       |   4 +
 gdbserver/linux-low.cc                        | 103 +-
 gdbserver/server.cc                           |  34 +-
 gdbsupport/ChangeLog                          |  30 +
 gdbsupport/btrace-common.cc                   |  47 +
 gdbsupport/btrace-common.h                    | 130 ++-
 gdbsupport/common.m4                          |  39 +
 gdbsupport/configure                          | 545 ++++++++++
 49 files changed, 7335 insertions(+), 161 deletions(-)
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-instruction_history.S
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-record_goto.S
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-tailcall-only.S
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-tailcall.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-instruction_history.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-record_goto.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-tailcall-only.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-tailcall.S
 rename gdb/testsuite/gdb.btrace/{instruction_history.S => x86-instruction_history.S} (100%)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 1/8] configure gdb build system for supporting btrace on arm processors
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
@ 2021-02-26  2:45 ` Zied Guermazi
  2021-03-04 16:35   ` Metzger, Markus T
  2021-02-26  2:45 ` [PATCH 2/8] add btrace coresight related commands Zied Guermazi
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi


This patch adds the possibility to build GDB with support for branch tracing
using ARM CoreSight traces
new flag is --with-arm-cs

gdb/ChangeLog

	* Makefile.in LIBOPENCSD_C_API: set the flag.
	* config.in LIBOPENCSD_C_API: undefine it if
	libopenocsd library is available.
	* configure: Regenerated.
	* configure.nat: add nat/linux-btrace.o to the build
	for aarch64 and arm
	* top.c (print_gdb_configuration): add --with-arm-cs
	or --without-arm-cs according to the configuration.

gdbserver/ChangeLog
    * gdbserver/configure: Regenerated.

gdbsupport/ChangeLog

    * gdbsupport/common.m4: check --with-arm-cs configuration
    flag, perf_event and opencsd_c_api to set compilation flags.
    * gdbsupport/configure: Regenerated

---
 gdb/ChangeLog        |  11 +
 gdb/Makefile.in      |   5 +-
 gdb/config.in        |   3 +
 gdb/configure        | 545 +++++++++++++++++++++++++++++++++++++++++++
 gdb/configure.nat    |   4 +-
 gdb/top.c            |  10 +-
 gdbserver/ChangeLog  |   4 +
 gdbserver/configure  | 545 +++++++++++++++++++++++++++++++++++++++++++
 gdbsupport/ChangeLog |   6 +
 gdbsupport/common.m4 |  39 ++++
 gdbsupport/configure | 545 +++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 1713 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2ca7d3c6a05..7178c30affb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* Makefile.in LIBOPENCSD_C_API: set the flag.
+	* config.in LIBOPENCSD_C_API: undefine it if
+	libopenocsd library is available.
+	* configure: Regenerated.
+	* configure.nat: add nat/linux-btrace.o to the build
+	for aarch64 and arm
+	* top.c (print_gdb_configuration): add --with-arm-cs 
+	or --without-arm-cs according to the configuration.
+
 2021-02-24  Tom de Vries  <tdevries@suse.de>
 
 	PR symtab/27336
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ae89b85eb56..9120f4fa958 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -203,6 +203,9 @@ LIBXXHASH = @LIBXXHASH@
 # Where is libipt?  This will be empty if libipt was not available.
 LIBIPT = @LIBIPT@
 
+#where is libopencsd? this will be empty if libopencsd was not available
+LIBOPENCSD_C_API = @LIBOPENCSD_C_API@
+
 # Where is libgmp?
 LIBGMP = @LIBGMP@
 
@@ -636,7 +639,7 @@ CLIBS = $(SIM) $(READLINE) $(OPCODES) $(LIBCTF) $(BFD) $(ZLIB) \
         $(LIBSUPPORT) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
 	$(XM_CLIBS) $(GDBTKLIBS) \
 	@LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
-	$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) \
+	$(LIBEXPAT) $(LIBLZMA) $(LIBBABELTRACE) $(LIBIPT) $(LIBOPENCSD_C_API) \
 	$(WIN32LIBS) $(LIBGNU) $(LIBGNU_EXTRA_LIBS) $(LIBICONV) \
 	$(LIBMPFR) $(LIBGMP) $(SRCHIGH_LIBS) $(LIBXXHASH) $(PTHREAD_LIBS) \
 	$(DEBUGINFOD_LIBS)
diff --git a/gdb/config.in b/gdb/config.in
index 14a77c661d5..b343271d530 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -247,6 +247,9 @@
 /* Define if you have the mpfr library. */
 #undef HAVE_LIBMPFR
 
+/* Define if you have libopenocsd library. */
+#undef HAVE_LIBOPENCSD_C_API
+
 /* Define to 1 if you have the <libunwind-ia64.h> header file. */
 #undef HAVE_LIBUNWIND_IA64_H
 
diff --git a/gdb/configure b/gdb/configure
index 51b4d1921c5..be550544bc1 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -705,6 +705,9 @@ SYSTEM_GDBINIT
 TARGET_SYSTEM_ROOT
 CONFIG_LDFLAGS
 RDYNAMIC
+LTLIBOPENCSD_C_API
+LIBOPENCSD_C_API
+HAVE_LIBOPENCSD_C_API
 LTLIBIPT
 LIBIPT
 HAVE_LIBIPT
@@ -911,6 +914,9 @@ enable_source_highlight
 with_intel_pt
 with_libipt_prefix
 with_libipt_type
+with_arm_cs
+with_libopencsd_c_api_prefix
+with_libopencsd_c_api_type
 with_included_regex
 with_sysroot
 with_system_gdbinit
@@ -1661,6 +1667,11 @@ Optional Packages:
   --with-libipt-prefix[=DIR]  search for libipt in DIR/include and DIR/lib
   --without-libipt-prefix     don't search for libipt in includedir and libdir
   --with-libipt-type=TYPE     type of library to search for (auto/static/shared)
+  --with-arm-cs           include ARM CoreSight Processor Trace support
+                          (auto/yes/no)
+  --with-libopencsd_c_api-prefix[=DIR]  search for libopencsd_c_api in DIR/include and DIR/lib
+  --without-libopencsd_c_api-prefix     don't search for libopencsd_c_api in includedir and libdir
+  --with-libopencsd_c_api-type=TYPE     type of library to search for (auto/static/shared)
   --without-included-regex
                           don't use included regex; this is the default on
                           systems with version 2 of the GNU C library (use
@@ -15317,6 +15328,540 @@ fi
     fi
   fi
 
+  # ARM CoreSight trace       #
+
+
+# Check whether --with-arm_cs was given.
+if test "${with_arm_cs+set}" = set; then :
+  withval=$with_arm_cs;
+else
+  with_arm_cs=auto
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use ARM CoreSight Processor Trace " >&5
+$as_echo_n "checking whether to use ARM CoreSight Processor Trace ... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_arm_cs" >&5
+$as_echo "$with_arm_cs" >&6; }
+
+  if test "${with_arm_cs}" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable." >&2;}
+    HAVE_LIBOPENCSD=no
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #include <linux/perf_event.h>
+  #ifndef PERF_ATTR_SIZE_VER5
+  # error
+  #endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  perf_event=yes
+else
+  perf_event=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+    if test "$perf_event" != yes; then
+      if test "$" = yes; then
+        as_fn_error $? "linux/perf_event.h missing or too old" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable." >&2;}
+      fi
+    fi
+
+
+
+
+
+
+
+
+
+    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-libopencsd_c_api-prefix was given.
+if test "${with_libopencsd_c_api_prefix+set}" = set; then :
+  withval=$with_libopencsd_c_api_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
+
+
+# Check whether --with-libopencsd_c_api-type was given.
+if test "${with_libopencsd_c_api_type+set}" = set; then :
+  withval=$with_libopencsd_c_api_type;  with_libopencsd_c_api_type=$withval
+else
+   with_libopencsd_c_api_type=auto
+fi
+
+  lib_type=`eval echo \$with_libopencsd_c_api_type`
+
+      LIBOPENCSD_C_API=
+  LTLIBOPENCSD_C_API=
+  INCOPENCSD_C_API=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='opencsd_c_api '
+  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" || LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }$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" && test x$lib_type != xstatic; 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
+            elif test x$lib_type != xshared; then
+              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 $LTLIBOPENCSD_C_API; 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" && test x$lib_type != xstatic; 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
+                  elif test x$lib_type != xshared; then
+                    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
+                        LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-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
+                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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
+                                                      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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 $LIBOPENCSD_C_API; 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
+                      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_a"
+              else
+                                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-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 $INCOPENCSD_C_API; 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
+                                            INCOPENCSD_C_API="${INCOPENCSD_C_API}${INCOPENCSD_C_API:+ }-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 $LIBOPENCSD_C_API; 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
+                                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBOPENCSD_C_API; 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
+                                                        LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-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$,,'`
+                    ;;
+                  *)
+                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$dep"
+                    LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
+              LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l$name"
+              LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-l$name"
+            else
+              LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l:lib$name.$libext"
+              LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-l:lib$name.$libext"
+            fi
+          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"
+      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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"
+        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-R$found_dir"
+    done
+  fi
+
+
+        ac_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCOPENCSD_C_API; 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 libopencsd_c_api" >&5
+$as_echo_n "checking for libopencsd_c_api... " >&6; }
+if ${ac_cv_libopencsd_c_api+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIBOPENCSD_C_API"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "opencsd/c_api/opencsd_c_api.h"
+int
+main ()
+{
+ocsd_get_version();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_libopencsd_c_api=yes
+else
+  ac_cv_libopencsd_c_api=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_libopencsd_c_api" >&5
+$as_echo "$ac_cv_libopencsd_c_api" >&6; }
+  if test "$ac_cv_libopencsd_c_api" = yes; then
+    HAVE_LIBOPENCSD_C_API=yes
+
+$as_echo "#define HAVE_LIBOPENCSD_C_API 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libopencsd_c_api" >&5
+$as_echo_n "checking how to link with libopencsd_c_api... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBOPENCSD_C_API" >&5
+$as_echo "$LIBOPENCSD_C_API" >&6; }
+  else
+    HAVE_LIBOPENCSD_C_API=no
+            CPPFLAGS="$ac_save_CPPFLAGS"
+    LIBOPENCSD_C_API=
+    LTLIBOPENCSD_C_API=
+  fi
+
+
+
+
+
+
+    if test "$HAVE_LIBOPENCSD_C_API" != yes; then
+      if test "$" = yes; then
+        as_fn_error $? "libopencsd_c_api is missing or unusable" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable." >&2;}
+      fi
+    else
+      LIBS="$LIBS $LIBOPENCSD_C_API"
+    fi
+  fi
+
+
 
 $as_echo "#define _STRUCTURED_PROC 1" >>confdefs.h
 
diff --git a/gdb/configure.nat b/gdb/configure.nat
index 286975966da..c17b6697b05 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -235,7 +235,7 @@ case ${gdb_host} in
 		#  Host: AArch64 based machine running GNU/Linux
 		NATDEPFILES="${NATDEPFILES} aarch64-linux-nat.o \
 		aarch32-linux-nat.o nat/aarch64-linux-hw-point.o \
-		nat/aarch64-linux.o \
+		nat/aarch64-linux.o nat/linux-btrace.o \
 		nat/aarch64-sve-linux-ptrace.o"
 		;;
 	    arc)
@@ -245,7 +245,7 @@ case ${gdb_host} in
 	    arm)
 		# Host: ARM based machine running GNU/Linux
 		NATDEPFILES="${NATDEPFILES} arm-linux-nat.o \
-		aarch32-linux-nat.o"
+		aarch32-linux-nat.o nat/linux-btrace.o"
 		;;
 	    i386)
 		# Host: Intel 386 running GNU/Linux.
diff --git a/gdb/top.c b/gdb/top.c
index 3be95079654..a5aab3202c5 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1526,7 +1526,15 @@ This GDB was configured as follows:\n\
 	     --without-intel-pt\n\
 "));
 #endif
-
+#if HAVE_LIBOPENCSD_C_API
+    fprintf_filtered (stream, _("\
+             --with-arm-cs\n\
+"));
+#else
+    fprintf_filtered (stream, _("\
+             --without-arm-cs\n\
+"));
+#endif
 #if HAVE_LIBMPFR
   fprintf_filtered (stream, _("\
 	     --with-mpfr\n\
diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog
index 0e713cc6abb..bafdc7685c3 100644
--- a/gdbserver/ChangeLog
+++ b/gdbserver/ChangeLog
@@ -1,3 +1,7 @@
+2021-02-01  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* gdbserver/configure: Regenerated.
+
 2021-02-23  Simon Marchi  <simon.marchi@polymtl.ca>
 
 	* linux-low.cc (linux_process_target::filter_event): Return
diff --git a/gdbserver/configure b/gdbserver/configure
index 0db0ad3f4fb..0ded9a7cec7 100755
--- a/gdbserver/configure
+++ b/gdbserver/configure
@@ -656,6 +656,9 @@ am__leading_dot
 host_noncanonical
 target_noncanonical
 WIN32APILIBS
+LTLIBOPENCSD_C_API
+LIBOPENCSD_C_API
+HAVE_LIBOPENCSD_C_API
 LTLIBIPT
 LIBIPT
 HAVE_LIBIPT
@@ -751,6 +754,9 @@ with_gnu_ld
 enable_rpath
 with_libipt_prefix
 with_libipt_type
+with_arm_cs
+with_libopencsd_c_api_prefix
+with_libopencsd_c_api_type
 enable_unit_tests
 with_ust
 with_ust_include
@@ -1415,6 +1421,11 @@ Optional Packages:
   --with-libipt-prefix[=DIR]  search for libipt in DIR/include and DIR/lib
   --without-libipt-prefix     don't search for libipt in includedir and libdir
   --with-libipt-type=TYPE     type of library to search for (auto/static/shared)
+  --with-arm-cs           include ARM CoreSight Processor Trace support
+                          (auto/yes/no)
+  --with-libopencsd_c_api-prefix[=DIR]  search for libopencsd_c_api in DIR/include and DIR/lib
+  --without-libopencsd_c_api-prefix     don't search for libopencsd_c_api in includedir and libdir
+  --with-libopencsd_c_api-type=TYPE     type of library to search for (auto/static/shared)
   --with-ust=PATH       Specify prefix directory for the installed UST package
                           Equivalent to --with-ust-include=PATH/include
                           plus --with-ust-lib=PATH/lib
@@ -8623,6 +8634,540 @@ fi
     fi
   fi
 
+  # ARM CoreSight trace       #
+
+
+# Check whether --with-arm_cs was given.
+if test "${with_arm_cs+set}" = set; then :
+  withval=$with_arm_cs;
+else
+  with_arm_cs=auto
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use ARM CoreSight Processor Trace " >&5
+$as_echo_n "checking whether to use ARM CoreSight Processor Trace ... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_arm_cs" >&5
+$as_echo "$with_arm_cs" >&6; }
+
+  if test "${with_arm_cs}" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable." >&2;}
+    HAVE_LIBOPENCSD=no
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #include <linux/perf_event.h>
+  #ifndef PERF_ATTR_SIZE_VER5
+  # error
+  #endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  perf_event=yes
+else
+  perf_event=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+    if test "$perf_event" != yes; then
+      if test "$" = yes; then
+        as_fn_error $? "linux/perf_event.h missing or too old" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable." >&2;}
+      fi
+    fi
+
+
+
+
+
+
+
+
+
+    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-libopencsd_c_api-prefix was given.
+if test "${with_libopencsd_c_api_prefix+set}" = set; then :
+  withval=$with_libopencsd_c_api_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
+
+
+# Check whether --with-libopencsd_c_api-type was given.
+if test "${with_libopencsd_c_api_type+set}" = set; then :
+  withval=$with_libopencsd_c_api_type;  with_libopencsd_c_api_type=$withval
+else
+   with_libopencsd_c_api_type=auto
+fi
+
+  lib_type=`eval echo \$with_libopencsd_c_api_type`
+
+      LIBOPENCSD_C_API=
+  LTLIBOPENCSD_C_API=
+  INCOPENCSD_C_API=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='opencsd_c_api '
+  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" || LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }$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" && test x$lib_type != xstatic; 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
+            elif test x$lib_type != xshared; then
+              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 $LTLIBOPENCSD_C_API; 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" && test x$lib_type != xstatic; 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
+                  elif test x$lib_type != xshared; then
+                    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
+                        LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-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
+                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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
+                                                      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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 $LIBOPENCSD_C_API; 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
+                      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_a"
+              else
+                                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-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 $INCOPENCSD_C_API; 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
+                                            INCOPENCSD_C_API="${INCOPENCSD_C_API}${INCOPENCSD_C_API:+ }-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 $LIBOPENCSD_C_API; 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
+                                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBOPENCSD_C_API; 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
+                                                        LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-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$,,'`
+                    ;;
+                  *)
+                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$dep"
+                    LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
+              LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l$name"
+              LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-l$name"
+            else
+              LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l:lib$name.$libext"
+              LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-l:lib$name.$libext"
+            fi
+          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"
+      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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"
+        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-R$found_dir"
+    done
+  fi
+
+
+        ac_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCOPENCSD_C_API; 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 libopencsd_c_api" >&5
+$as_echo_n "checking for libopencsd_c_api... " >&6; }
+if ${ac_cv_libopencsd_c_api+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIBOPENCSD_C_API"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "opencsd/c_api/opencsd_c_api.h"
+int
+main ()
+{
+ocsd_get_version();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_libopencsd_c_api=yes
+else
+  ac_cv_libopencsd_c_api=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_libopencsd_c_api" >&5
+$as_echo "$ac_cv_libopencsd_c_api" >&6; }
+  if test "$ac_cv_libopencsd_c_api" = yes; then
+    HAVE_LIBOPENCSD_C_API=yes
+
+$as_echo "#define HAVE_LIBOPENCSD_C_API 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libopencsd_c_api" >&5
+$as_echo_n "checking how to link with libopencsd_c_api... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBOPENCSD_C_API" >&5
+$as_echo "$LIBOPENCSD_C_API" >&6; }
+  else
+    HAVE_LIBOPENCSD_C_API=no
+            CPPFLAGS="$ac_save_CPPFLAGS"
+    LIBOPENCSD_C_API=
+    LTLIBOPENCSD_C_API=
+  fi
+
+
+
+
+
+
+    if test "$HAVE_LIBOPENCSD_C_API" != yes; then
+      if test "$" = yes; then
+        as_fn_error $? "libopencsd_c_api is missing or unusable" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable." >&2;}
+      fi
+    else
+      LIBS="$LIBS $LIBOPENCSD_C_API"
+    fi
+  fi
+
+
 
 $as_echo "#define _STRUCTURED_PROC 1" >>confdefs.h
 
diff --git a/gdbsupport/ChangeLog b/gdbsupport/ChangeLog
index c8fa9e73148..f27b57c2fa9 100644
--- a/gdbsupport/ChangeLog
+++ b/gdbsupport/ChangeLog
@@ -1,3 +1,9 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* gdbsupport/common.m4: check --with-arm-cs configuration
+	flag, perf_event and opencsd_c_api to set compilation flags.
+	* gdbsupport/configure: Regenerated
+
 2021-02-05  Paul E. Murphy  <murphy@linux.ibm.com>
 
 	* common-defs.h (ATTRIBUTE_PRINTF): Rename
diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
index 3ed95dabc85..8d2f959e8f3 100644
--- a/gdbsupport/common.m4
+++ b/gdbsupport/common.m4
@@ -186,6 +186,45 @@ AC_DEFUN([GDB_AC_COMMON], [
     fi
   fi
 
+  # ARM CoreSight trace       #
+
+  AC_ARG_WITH(arm_cs,
+    AS_HELP_STRING([--with-arm-cs], [include ARM CoreSight Processor Trace support (auto/yes/no)]),
+    [], [with_arm_cs=auto])
+  AC_MSG_CHECKING([whether to use ARM CoreSight Processor Trace ])
+  AC_MSG_RESULT([$with_arm_cs])
+
+  if test "${with_arm_cs}" = no; then
+    AC_MSG_WARN([ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable.])
+    HAVE_LIBOPENCSD=no
+  else
+    AC_PREPROC_IFELSE([AC_LANG_SOURCE([[
+  #include <linux/perf_event.h>
+  #ifndef PERF_ATTR_SIZE_VER5
+  # error
+  #endif
+    ]])], [perf_event=yes], [perf_event=no])
+    if test "$perf_event" != yes; then
+      if test "$" = yes; then
+        AC_MSG_ERROR([linux/perf_event.h missing or too old])
+      else
+        AC_MSG_WARN([linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable.])
+      fi
+    fi
+
+    AC_LIB_HAVE_LINKFLAGS([opencsd_c_api], [], [#include "opencsd/c_api/opencsd_c_api.h"], [ocsd_get_version();])
+    if test "$HAVE_LIBOPENCSD_C_API" != yes; then
+      if test "$" = yes; then
+        AC_MSG_ERROR([libopencsd_c_api is missing or unusable])
+      else
+        AC_MSG_WARN([libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable.])
+      fi
+    else
+      LIBS="$LIBS $LIBOPENCSD_C_API"
+    fi
+  fi
+
+
   BFD_SYS_PROCFS_H
   if test "$ac_cv_header_sys_procfs_h" = yes; then
     BFD_HAVE_SYS_PROCFS_TYPE(gregset_t)
diff --git a/gdbsupport/configure b/gdbsupport/configure
index 9c5e59c5f10..bac558e4ea3 100755
--- a/gdbsupport/configure
+++ b/gdbsupport/configure
@@ -628,6 +628,9 @@ WERROR_CFLAGS
 WARN_CFLAGS
 SELFTEST_FALSE
 SELFTEST_TRUE
+LTLIBOPENCSD_C_API
+LIBOPENCSD_C_API
+HAVE_LIBOPENCSD_C_API
 LTLIBIPT
 LIBIPT
 HAVE_LIBIPT
@@ -772,6 +775,9 @@ with_gnu_ld
 enable_rpath
 with_libipt_prefix
 with_libipt_type
+with_arm_cs
+with_libopencsd_c_api_prefix
+with_libopencsd_c_api_type
 enable_unit_tests
 enable_werror
 enable_build_warnings
@@ -1436,6 +1442,11 @@ Optional Packages:
   --with-libipt-prefix[=DIR]  search for libipt in DIR/include and DIR/lib
   --without-libipt-prefix     don't search for libipt in includedir and libdir
   --with-libipt-type=TYPE     type of library to search for (auto/static/shared)
+  --with-arm-cs           include ARM CoreSight Processor Trace support
+                          (auto/yes/no)
+  --with-libopencsd_c_api-prefix[=DIR]  search for libopencsd_c_api in DIR/include and DIR/lib
+  --without-libopencsd_c_api-prefix     don't search for libopencsd_c_api in includedir and libdir
+  --with-libopencsd_c_api-type=TYPE     type of library to search for (auto/static/shared)
 
 Some influential environment variables:
   CC          C compiler command
@@ -9637,6 +9648,540 @@ fi
     fi
   fi
 
+  # ARM CoreSight trace       #
+
+
+# Check whether --with-arm_cs was given.
+if test "${with_arm_cs+set}" = set; then :
+  withval=$with_arm_cs;
+else
+  with_arm_cs=auto
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use ARM CoreSight Processor Trace " >&5
+$as_echo_n "checking whether to use ARM CoreSight Processor Trace ... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_arm_cs" >&5
+$as_echo "$with_arm_cs" >&6; }
+
+  if test "${with_arm_cs}" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: ARM CoreSight Processor Trace support disabled; CoreSight Tracing will be unavailable." >&2;}
+    HAVE_LIBOPENCSD=no
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #include <linux/perf_event.h>
+  #ifndef PERF_ATTR_SIZE_VER5
+  # error
+  #endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  perf_event=yes
+else
+  perf_event=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+    if test "$perf_event" != yes; then
+      if test "$" = yes; then
+        as_fn_error $? "linux/perf_event.h missing or too old" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: linux/perf_event.h missing or too old; CoreSight Tracing will be unavailable." >&2;}
+      fi
+    fi
+
+
+
+
+
+
+
+
+
+    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-libopencsd_c_api-prefix was given.
+if test "${with_libopencsd_c_api_prefix+set}" = set; then :
+  withval=$with_libopencsd_c_api_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
+
+
+# Check whether --with-libopencsd_c_api-type was given.
+if test "${with_libopencsd_c_api_type+set}" = set; then :
+  withval=$with_libopencsd_c_api_type;  with_libopencsd_c_api_type=$withval
+else
+   with_libopencsd_c_api_type=auto
+fi
+
+  lib_type=`eval echo \$with_libopencsd_c_api_type`
+
+      LIBOPENCSD_C_API=
+  LTLIBOPENCSD_C_API=
+  INCOPENCSD_C_API=
+  rpathdirs=
+  ltrpathdirs=
+  names_already_handled=
+  names_next_round='opencsd_c_api '
+  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" || LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$value"
+            eval value=\"\$LTLIB$uppername\"
+            test -z "$value" || LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }$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" && test x$lib_type != xstatic; 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
+            elif test x$lib_type != xshared; then
+              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 $LTLIBOPENCSD_C_API; 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" && test x$lib_type != xstatic; 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
+                  elif test x$lib_type != xshared; then
+                    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
+                        LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-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
+                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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
+                                                      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_so"
+                else
+                  if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+                                                            LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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 $LIBOPENCSD_C_API; 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
+                      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-L$found_dir"
+                    fi
+                    if test "$hardcode_minus_L" != no; then
+                                                                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_so"
+                    else
+                                                                                                                                                                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l$name"
+                    fi
+                  fi
+                fi
+              fi
+            else
+              if test "X$found_a" != "X"; then
+                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$found_a"
+              else
+                                                LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-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 $INCOPENCSD_C_API; 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
+                                            INCOPENCSD_C_API="${INCOPENCSD_C_API}${INCOPENCSD_C_API:+ }-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 $LIBOPENCSD_C_API; 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
+                                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-L$additional_libdir"
+                          fi
+                        fi
+                        haveit=
+                        for x in $LDFLAGS $LTLIBOPENCSD_C_API; 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
+                                                        LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-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$,,'`
+                    ;;
+                  *)
+                                        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$dep"
+                    LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }$dep"
+                    ;;
+                esac
+              done
+            fi
+          else
+                                                            if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
+              LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l$name"
+              LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-l$name"
+            else
+              LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }-l:lib$name.$libext"
+              LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-l:lib$name.$libext"
+            fi
+          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"
+      LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$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"
+        LIBOPENCSD_C_API="${LIBOPENCSD_C_API}${LIBOPENCSD_C_API:+ }$flag"
+      done
+    fi
+  fi
+  if test "X$ltrpathdirs" != "X"; then
+            for found_dir in $ltrpathdirs; do
+      LTLIBOPENCSD_C_API="${LTLIBOPENCSD_C_API}${LTLIBOPENCSD_C_API:+ }-R$found_dir"
+    done
+  fi
+
+
+        ac_save_CPPFLAGS="$CPPFLAGS"
+
+  for element in $INCOPENCSD_C_API; 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 libopencsd_c_api" >&5
+$as_echo_n "checking for libopencsd_c_api... " >&6; }
+if ${ac_cv_libopencsd_c_api+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS="$LIBS"
+    LIBS="$LIBS $LIBOPENCSD_C_API"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "opencsd/c_api/opencsd_c_api.h"
+int
+main ()
+{
+ocsd_get_version();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_libopencsd_c_api=yes
+else
+  ac_cv_libopencsd_c_api=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_libopencsd_c_api" >&5
+$as_echo "$ac_cv_libopencsd_c_api" >&6; }
+  if test "$ac_cv_libopencsd_c_api" = yes; then
+    HAVE_LIBOPENCSD_C_API=yes
+
+$as_echo "#define HAVE_LIBOPENCSD_C_API 1" >>confdefs.h
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libopencsd_c_api" >&5
+$as_echo_n "checking how to link with libopencsd_c_api... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBOPENCSD_C_API" >&5
+$as_echo "$LIBOPENCSD_C_API" >&6; }
+  else
+    HAVE_LIBOPENCSD_C_API=no
+            CPPFLAGS="$ac_save_CPPFLAGS"
+    LIBOPENCSD_C_API=
+    LTLIBOPENCSD_C_API=
+  fi
+
+
+
+
+
+
+    if test "$HAVE_LIBOPENCSD_C_API" != yes; then
+      if test "$" = yes; then
+        as_fn_error $? "libopencsd_c_api is missing or unusable" "$LINENO" 5
+      else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable." >&5
+$as_echo "$as_me: WARNING: libopencsd_c_api is missing or unusable; CoreSight Tracing will be unavailable." >&2;}
+      fi
+    else
+      LIBS="$LIBS $LIBOPENCSD_C_API"
+    fi
+  fi
+
+
 
 $as_echo "#define _STRUCTURED_PROC 1" >>confdefs.h
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 2/8] add btrace coresight related commands
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
  2021-02-26  2:45 ` [PATCH 1/8] configure gdb build system for supporting btrace on arm processors Zied Guermazi
@ 2021-02-26  2:45 ` Zied Guermazi
  2021-03-04 16:35   ` Metzger, Markus T
  2021-02-26  2:45 ` [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant Zied Guermazi
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi

This patch extends the commands needed for using branch tracing
with ARM CoreSight traces.
Those commands are:
set record btrace etm sink
set record btrace etm size
record btrace etm

gdb/ChangeLog

	* record-btrace.c (record_btrace_print_etm_conf): New.
	(record_btrace_print_conf): handle BTRACE_FORMAT_ETM.
	(cmd_record_btrace_etm_start): New.
	(cmd_record_btrace_start): handle starting ETM tracing.
	(cmd_show_record_btrace_cpu): extend for ARM cpus.
	(show_record_etm_buffer_size_value): New.
	(_initialize_record_btrace): add commands for ETM traces.
	(record_start): add starting ETM traces.

gdbsupport/ChangeLog

	* gdbsupport/btrace-common.h (btrace_format): add BTRACE_FORMAT_ETM
	to the enum.
	(btrace_cpu_vendor): add CV_ARM to the enum.
	(btrace_config_etm): new struct.
	(btrace_config): add btrace_config_etm etm.
	* gdbsupport/btrace-common.cc (btrace_format_string): add BTRACE_FORMAT_ETM.
	(btrace_format_short_string): add BTRACE_FORMAT_ETM.


---
 gdb/ChangeLog               |  11 ++++
 gdb/record-btrace.c         | 124 +++++++++++++++++++++++++++++++++++-
 gdb/record.c                |   2 +
 gdbsupport/ChangeLog        |  11 ++++
 gdbsupport/btrace-common.cc |   7 ++
 gdbsupport/btrace-common.h  |  26 +++++++-
 6 files changed, 177 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7178c30affb..46e7a2f2416 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,16 @@
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
+	* record-btrace.c (record_btrace_print_etm_conf): New.
+	* record-btrace.c (record_btrace_print_conf): handle BTRACE_FORMAT_ETM.
+	* record-btrace.c (cmd_record_btrace_etm_start): New.
+	* record-btrace.c (cmd_record_btrace_start): handle starting ETM tracing.
+	* record-btrace.c (cmd_show_record_btrace_cpu): extend for ARM cpus.
+	* record-btrace.c (show_record_etm_buffer_size_value): New.
+	* record-btrace.c (_initialize_record_btrace): add commands for ETM traces.
+	* record.c (record_start): add starting ETM traces.
+
+2021-02-02  Zied Guermazi  <zied.guermazi@trande.de>
+
 	* Makefile.in LIBOPENCSD_C_API: set the flag.
 	* config.in LIBOPENCSD_C_API: undefine it if
 	libopenocsd library is available.
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index d9cc7a3b6d8..39ac9aafc28 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -201,6 +201,10 @@ static struct cmd_list_element *show_record_btrace_bts_cmdlist;
 static struct cmd_list_element *set_record_btrace_pt_cmdlist;
 static struct cmd_list_element *show_record_btrace_pt_cmdlist;
 
+/* Command lists for "set/show record btrace etm".  */
+static struct cmd_list_element *set_record_btrace_etm_cmdlist;
+static struct cmd_list_element *show_record_btrace_etm_cmdlist;
+
 /* Command list for "set record btrace cpu".  */
 static struct cmd_list_element *set_record_btrace_cpu_cmdlist;
 
@@ -525,6 +529,22 @@ record_btrace_print_pt_conf (const struct btrace_config_pt *conf)
     }
 }
 
+/* Print an ARM Processor Trace configuration.  */
+
+static void
+record_btrace_print_etm_conf (const struct btrace_config_etm *conf)
+{
+  const char *suffix;
+  unsigned int size;
+
+  size = conf->size;
+  if (size > 0)
+    {
+      suffix = record_btrace_adjust_size (&size);
+      printf_unfiltered (_("Buffer size: %u%s.\n"), size, suffix);
+    }
+}
+
 /* Print a branch tracing configuration.  */
 
 static void
@@ -545,6 +565,10 @@ record_btrace_print_conf (const struct btrace_config *conf)
     case BTRACE_FORMAT_PT:
       record_btrace_print_pt_conf (&conf->pt);
       return;
+
+    case BTRACE_FORMAT_ETM:
+      record_btrace_print_etm_conf (&conf->etm);
+      return;
     }
 
   internal_error (__FILE__, __LINE__, _("Unknown branch trace format."));
@@ -2675,7 +2699,7 @@ record_btrace_target::stop (ptid_t ptid)
 	  tp->btrace.flags |= BTHR_STOP;
 	}
     }
- }
+}
 
 /* The can_execute_reverse method of target record-btrace.  */
 
@@ -2936,6 +2960,27 @@ cmd_record_btrace_pt_start (const char *args, int from_tty)
     }
 }
 
+/* Start recording in arm CoreSight ETM Trace format.  */
+
+static void
+cmd_record_btrace_etm_start (const char *args, int from_tty)
+{
+  if (args != NULL && *args != 0)
+    error (_("Invalid argument."));
+
+  record_btrace_conf.format = BTRACE_FORMAT_ETM;
+
+  try
+    {
+      execute_command ("target record-btrace", from_tty);
+    }
+  catch (const gdb_exception &exception)
+    {
+      record_btrace_conf.format = BTRACE_FORMAT_NONE;
+      throw;
+    }
+}
+
 /* Alias for "target record".  */
 
 static void
@@ -2950,10 +2995,18 @@ cmd_record_btrace_start (const char *args, int from_tty)
     {
       execute_command ("target record-btrace", from_tty);
     }
-  catch (const gdb_exception &exception)
+  catch (const gdb_exception &exception_pt)
     {
       record_btrace_conf.format = BTRACE_FORMAT_BTS;
 
+      try
+        {
+          execute_command ("target record-btrace", from_tty);
+        }
+      catch (const gdb_exception &exception_bts)
+        {
+          record_btrace_conf.format = BTRACE_FORMAT_ETM;
+
           try
             {
               execute_command ("target record-btrace", from_tty);
@@ -2964,8 +3017,10 @@ cmd_record_btrace_start (const char *args, int from_tty)
               throw;
             }
         }
+    }
 }
 
+
 /* The "show record btrace replay-memory-access" command.  */
 
 static void
@@ -3074,6 +3129,10 @@ cmd_show_record_btrace_cpu (const char *args, int from_tty)
                                record_btrace_cpu.model,
                                record_btrace_cpu.stepping);
           return;
+        case CV_ARM:
+          printf_unfiltered ("btrace cpu is 'ARM'.\n");
+
+          return;
 	}
     }
 
@@ -3102,6 +3161,17 @@ show_record_pt_buffer_size_value (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* The "record etm buffer-size" show value function.  */
+
+static void
+show_record_etm_buffer_size_value (struct ui_file *file, int from_tty,
+				   struct cmd_list_element *c,
+				   const char *value)
+{
+  fprintf_filtered (file, _("The record/replay etm buffer size is %s.\n"),
+		    value);
+}
+
 /* Initialize btrace commands.  */
 
 void _initialize_record_btrace ();
@@ -3165,6 +3235,22 @@ When set to \"none\", errata workarounds are disabled."),
 		  "set record btrace cpu ", 1,
 		  &set_record_btrace_cmdlist);
 
+  add_cmd ("etm", class_obscure, cmd_record_btrace_etm_start,
+	   _("\
+Start branch trace recording in arm CoreSight ETM Trace format.\n\n\
+This format may not be available on all processors."),
+	   &record_btrace_cmdlist);
+  add_alias_cmd ("etm", "btrace etm", class_obscure, 1, &record_cmdlist);
+
+  add_basic_prefix_cmd ("btrace", class_support,
+			_("Set record options."), &set_record_btrace_cmdlist,
+			"set record btrace ", 0, &set_record_cmdlist);
+
+  add_show_prefix_cmd ("btrace", class_support,
+		       _("Show record options."), &show_record_btrace_cmdlist,
+		       "show record btrace ", 0, &show_record_cmdlist);
+
+
   add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
 Automatically determine the cpu to be used for trace decode."),
 	   &set_record_btrace_cpu_cmdlist);
@@ -3226,6 +3312,39 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
 		  &set_record_btrace_pt_cmdlist,
 		  &show_record_btrace_pt_cmdlist);
 
+  add_basic_prefix_cmd ("etm", class_support,
+			_("Set record btrace etm options."),
+			&set_record_btrace_etm_cmdlist,
+			"set record btrace etm ", 0, &set_record_btrace_cmdlist);
+
+  add_show_prefix_cmd ("etm", class_support,
+		       _("Show record btrace etm options."),
+		       &show_record_btrace_etm_cmdlist,
+		       "show record btrace etm ", 0, &show_record_btrace_cmdlist);
+
+  add_setshow_uinteger_cmd ("buffer-size", no_class,
+			    &record_btrace_conf.etm.size,
+			    _("Set the record/replay etm buffer size."),
+			    _("Show the record/replay etm buffer size."), _("\
+Bigger buffers allow longer recording but also take more time to process \
+the recorded execution.\n\
+The actual buffer size may differ from the requested size.  Use \"info record\" \
+to see the actual buffer size."), NULL, show_record_etm_buffer_size_value,
+		  &set_record_btrace_etm_cmdlist,
+		  &show_record_btrace_etm_cmdlist);
+  add_setshow_string_cmd ("sink", no_class,
+                          &record_btrace_conf.etm.sink,
+                          _("Set the record/replay etm sink device."),
+                          _("Show the record/replay etm sink device."),
+                          _("\
+sink device is the device that intercepts etm traces and collects or routes \
+them out of SoC.\n\
+list of available sinks on linux targets are enumerated in the directory \
+\"/sys/bus/event_source/devices/cs_etm/sinks/\".\n\
+value \"default\" reverts it to default sink"),
+                  NULL, NULL,
+                  &set_record_btrace_etm_cmdlist,
+                  &show_record_btrace_etm_cmdlist);
   add_target (record_btrace_target_info, record_btrace_target_open);
 
   bfcache = htab_create_alloc (50, bfcache_hash, bfcache_eq, NULL,
@@ -3233,4 +3352,5 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
 
   record_btrace_conf.bts.size = 64 * 1024;
   record_btrace_conf.pt.size = 16 * 1024;
+  record_btrace_conf.etm.size = 8 * 1024;
 }
diff --git a/gdb/record.c b/gdb/record.c
index cd541b56f43..43e5bb0874f 100644
--- a/gdb/record.c
+++ b/gdb/record.c
@@ -118,6 +118,8 @@ record_start (const char *method, const char *format, int from_tty)
 	execute_command_to_string ("record btrace bts", from_tty, false);
       else if (strcmp (format, "pt") == 0)
 	execute_command_to_string ("record btrace pt", from_tty, false);
+      else if (strcmp (format, "etm") == 0)
+	execute_command_to_string ("record btrace etm", from_tty, false);
       else
 	error (_("Invalid format."));
     }
diff --git a/gdbsupport/ChangeLog b/gdbsupport/ChangeLog
index f27b57c2fa9..e14bdf109b3 100644
--- a/gdbsupport/ChangeLog
+++ b/gdbsupport/ChangeLog
@@ -1,3 +1,14 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* gdbsupport/btrace-common.h (btrace_format): add BTRACE_FORMAT_ETM 
+	to the enum.
+	* gdbsupport/btrace-common.h (btrace_cpu_vendor): add CV_ARM to the enum.
+	* gdbsupport/btrace-common.h (btrace_config_etm): new struct.
+	* gdbsupport/btrace-common.h (btrace_config): add btrace_config_etm etm.
+	* gdbsupport/btrace-common.cc (btrace_format_string): add BTRACE_FORMAT_ETM.
+	* gdbsupport/btrace-common.cc (btrace_format_short_string): add 
+	BTRACE_FORMAT_ETM.
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* gdbsupport/common.m4: check --with-arm-cs configuration
diff --git a/gdbsupport/btrace-common.cc b/gdbsupport/btrace-common.cc
index 4f9ef855e74..461f769ed51 100644
--- a/gdbsupport/btrace-common.cc
+++ b/gdbsupport/btrace-common.cc
@@ -36,6 +36,9 @@ btrace_format_string (enum btrace_format format)
 
     case BTRACE_FORMAT_PT:
       return _("Intel Processor Trace");
+    
+    case BTRACE_FORMAT_ETM:
+      return _("ARM Processor CoreSight ETM Trace");
   }
 
   internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
@@ -56,6 +59,10 @@ btrace_format_short_string (enum btrace_format format)
 
     case BTRACE_FORMAT_PT:
       return "pt";
+    
+    case BTRACE_FORMAT_ETM:
+      return "etm";
+
     }
 
   internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
index 26d26ec957f..7f3cabfde77 100644
--- a/gdbsupport/btrace-common.h
+++ b/gdbsupport/btrace-common.h
@@ -63,7 +63,10 @@ enum btrace_format
   BTRACE_FORMAT_BTS,
 
   /* Branch trace is in Intel Processor Trace format.  */
-  BTRACE_FORMAT_PT
+  BTRACE_FORMAT_PT,
+
+  /* Branch trace is ARM CoreSight ETM format.  */
+  BTRACE_FORMAT_ETM
 };
 
 /* An enumeration of cpu vendors.  */
@@ -77,7 +80,10 @@ enum btrace_cpu_vendor
   CV_INTEL,
 
   /* AMD.  */
-  CV_AMD
+  CV_AMD,
+
+  /* ARM. */
+  CV_ARM
 };
 
 /* A cpu identifier.  */
@@ -119,6 +125,18 @@ struct btrace_config_pt
   unsigned int size;
 };
 
+/* An ARM CoreSight ETM Trace configuration.  */
+
+struct btrace_config_etm
+{
+  /* The size of the branch trace buffer in bytes.
+
+     This is unsigned int and not size_t since it is registered as
+     control variable for "set record btrace etm buffer-size".  */
+  unsigned int size;
+  char *sink;
+};
+
 /* A branch tracing configuration.
 
    This describes the requested configuration as well as the actually
@@ -136,6 +154,10 @@ struct btrace_config
 
   /* The Intel Processor Trace format configuration.  */
   struct btrace_config_pt pt;
+
+  /* The ARM CoreSight ETM Trace configuration.  */
+  struct btrace_config_etm etm;
+
 };
 
 /* Branch trace in BTS format.  */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
  2021-02-26  2:45 ` [PATCH 1/8] configure gdb build system for supporting btrace on arm processors Zied Guermazi
  2021-02-26  2:45 ` [PATCH 2/8] add btrace coresight related commands Zied Guermazi
@ 2021-02-26  2:45 ` Zied Guermazi
  2021-03-04 16:35   ` Metzger, Markus T
  2021-02-26  2:45 ` [PATCH 4/8] start/stop btrace with coresight etm and collect etm buffer on linux os Zied Guermazi
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi

This patch extend branch tracing by adding the functions nedded
to start and stop tracing, as well decoding them. This patch is not 
providing an implementation of the mechanisms on the target. 

gdb/ChangeLog

	* btrace.c (ftrace_remove_last_insn): New.
	(cs_etm_get_etmv3_config): New.
	(cs_etm_get_etmv4_config): New.
	(cs_etm_update_btrace_with_inst_range): New.
	(cs_etm_update_btrace_with_exception): New.
	(cs_etm_update_btrace_with_trace_on): New.
	(cs_etm_trace_element_callback): New.
	(cs_etm_create_decoder): New.
	(cs_etm_free_decoder): New.
	(btrace_etm_readmem_callback): New.
	(cs_etm_add_mem_access_callback): New.
	(cs_etm_process_data_block): New.
	(btrace_print_all): New.
	(btrace_compute_ftrace_etm): New.
	(btrace_compute_ftrace_1): add handling of CoreSight traces.
	(btrace_enable): add error message if ETM unavailable.
	(btrace_stitch_trace): add handling of CoreSight traces.
	(maint_info_btrace_cmd): add handling of CoreSight trace format.
	* btrace.h (record_btrace_reg_entry): new.
	(btrace_insn): add a vector of record_btrace_reg_entry.
	* record-btrace.c (record_btrace_target::fetch_registers): fetch
	registers from insn->registers when available

gdbsupport/ChangeLog

	* btrace-common.h (cs_etmv3_trace_params): New
	(cs_etmv4_trace_params): New.
	(cs_etm_trace_params): New.
	(cs_etm_decoder_params): New
	(btrace_data_etm_config): New.
	(btrace_data_etm): New.
	(btrace_data): add a btrace_data_etm.
	* btrace-common.cc (btrace_data::fini): handle CoreSight traces.
	(btrace_data::empty): handle CoreSight traces.
	(btrace_data_append): handle CoreSight traces.


---
 gdb/ChangeLog               |  28 +-
 gdb/btrace.c                | 591 +++++++++++++++++++++++++++++++++++-
 gdb/btrace.h                |  20 ++
 gdb/record-btrace.c         |  21 +-
 gdbsupport/ChangeLog        |  27 +-
 gdbsupport/btrace-common.cc |  42 ++-
 gdbsupport/btrace-common.h  | 106 ++++++-
 7 files changed, 816 insertions(+), 19 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 46e7a2f2416..1b998ef2624 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,29 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* btrace.c (ftrace_remove_last_insn): New.
+	* btrace.c (cs_etm_get_etmv3_config): New.
+	* btrace.c (cs_etm_get_etmv4_config): New.
+	* btrace.c (cs_etm_update_btrace_with_inst_range): New.
+	* btrace.c (cs_etm_update_btrace_with_exception): New.
+	* btrace.c (cs_etm_update_btrace_with_trace_on): New.
+	* btrace.c (cs_etm_trace_element_callback): New.
+	* btrace.c (cs_etm_create_decoder): New.
+	* btrace.c (cs_etm_free_decoder): New.
+	* btrace.c (btrace_etm_readmem_callback): New.
+	* btrace.c (cs_etm_add_mem_access_callback): New.
+	* btrace.c (cs_etm_process_data_block): New.
+	* btrace.c (btrace_print_all): New.
+	* btrace.c (btrace_compute_ftrace_etm): New.
+	* btrace.c (btrace_compute_ftrace_1): add handling of CoreSight traces.
+	* btrace.c (btrace_enable): add error message if ETM unavailable.
+	* btrace.c (btrace_stitch_trace): add handling of CoreSight traces.
+	* btrace.c (maint_info_btrace_cmd): add handling of CoreSight trace 
+	format.
+	* btrace.h (record_btrace_reg_entry): new.
+	* btrace.h (btrace_insn): add a vector of record_btrace_reg_entry.
+	* record-btrace.c (record_btrace_target::fetch_registers): fetch 
+	registers from insn->registers when available
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* record-btrace.c (record_btrace_print_etm_conf): New.
@@ -9,7 +35,7 @@
 	* record-btrace.c (_initialize_record_btrace): add commands for ETM traces.
 	* record.c (record_start): add starting ETM traces.
 
-2021-02-02  Zied Guermazi  <zied.guermazi@trande.de>
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* Makefile.in LIBOPENCSD_C_API: set the flag.
 	* config.in LIBOPENCSD_C_API: undefine it if
diff --git a/gdb/btrace.c b/gdb/btrace.c
index c697f37f46c..dcb89964b81 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -227,6 +227,23 @@ ftrace_function_switched (const struct btrace_function *bfun,
   return 0;
 }
 
+#if defined (HAVE_LIBOPENCSD_C_API)
+
+/* set a record_btrace_reg_entry.  */
+
+static void
+btrace_reg_set (struct record_btrace_reg_entry *reg, 
+                const struct regcache *regcache, int regnum, const gdb_byte *value)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  reg->num = regnum;
+  reg->len = register_size (gdbarch, regnum);
+  memcpy(reg->buffer, value, reg->len);
+}
+
+#endif //defined (HAVE_LIBOPENCSD_C_API)
+
 /* Allocate and initialize a new branch trace function segment at the end of
    the trace.
    BTINFO is the branch trace information for the current thread.
@@ -257,6 +274,7 @@ ftrace_new_function (struct btrace_thread_info *btinfo,
     }
 
   btinfo->functions.emplace_back (mfun, fun, number, insn_offset, level);
+  ftrace_debug (&btinfo->functions.back (), "new function");
   return &btinfo->functions.back ();
 }
 
@@ -671,6 +689,32 @@ ftrace_update_insns (struct btrace_function *bfun, const btrace_insn &insn)
     ftrace_debug (bfun, "update insn");
 }
 
+#if defined (HAVE_LIBOPENCSD_C_API)
+  /* remove last instruction from BFUN's list.
+     This function is not generic and is granted to work properly
+     only if the same removed instruction will be added later.  */
+
+static void 
+ftrace_remove_last_insn (struct btrace_thread_info *btinfo)
+{
+  struct btrace_function  *bfun;
+
+  /* If we didn't have a function, we return.  */
+  if (btinfo->functions.empty ())
+    return;
+  /* If we had a gap before, we return.  */
+  bfun = &btinfo->functions.back ();
+  if (bfun->errcode != 0)
+    return;
+  if (!bfun->insn.empty ())
+    bfun->insn.pop_back ();
+  else
+    {
+      /* a valid function must have at least one insn  */
+      error (_("Attempt to remove last instruction from an empty function"));
+    }
+}
+#endif /* #if defined (HAVE_LIBOPENCSD_C_API)*/
 /* Classify the instruction at PC.  */
 
 static enum btrace_insn_class
@@ -1193,7 +1237,7 @@ pt_btrace_insn_flags (const struct pt_insn &insn)
 static btrace_insn
 pt_btrace_insn (const struct pt_insn &insn)
 {
-  return {(CORE_ADDR) insn.ip, (gdb_byte) insn.size,
+  return {(CORE_ADDR) insn.ip, (gdb_byte) insn.size,{},
     pt_reclassify_insn (insn.iclass),
     pt_btrace_insn_flags (insn)};
 }
@@ -1502,6 +1546,533 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
 
 #endif /* defined (HAVE_LIBIPT)  */
 
+#if defined (HAVE_LIBOPENCSD_C_API)
+
+struct cs_etm_decoder 
+{
+  /* The tree representing CoreSight architecture in the SoC.  */
+  dcd_tree_handle_t dcd_tree;
+  
+  /* Callback function to allow the decoder to access program memory.  */
+  Fn_MemAcc_CB mem_access;
+  
+  /* thread_info of traced thread.  */
+  struct thread_info *t_info;
+  
+  /* returned value of previously processed block.  */
+  ocsd_datapath_resp_t prev_return;
+  
+  /* ARM architecture version of associated core.  */
+  ocsd_arch_version_t arch_version;
+  
+  /* list of gaps in the execution record.  */
+  std::vector<unsigned int> &gaps;
+};
+
+/* fills a ocsd_etmv3_cfg from a cs_etm_trace_params  */
+
+static void 
+cs_etm_get_etmv3_config (const struct cs_etm_trace_params *params,
+                                   ocsd_etmv3_cfg *config)
+{
+  config->reg_idr = params->etmv3.reg_idr;
+  config->reg_ctrl = params->etmv3.reg_ctrl;
+  config->reg_ccer = params->etmv3.reg_ccer;
+  config->reg_trc_id = params->etmv3.reg_trc_id;
+  config->arch_ver = (ocsd_arch_version_t)params->arch_ver;
+  config->core_prof = (ocsd_core_profile_t)params->core_profile;
+}
+
+/* fills a ocsd_etmv4_cfg from a cs_etm_trace_params  */
+
+static void 
+cs_etm_get_etmv4_config (const struct cs_etm_trace_params *params,
+                                    ocsd_etmv4_cfg *config)
+{
+  config->reg_configr = params->etmv4.reg_configr;
+  config->reg_traceidr = params->etmv4.reg_traceidr;
+  config->reg_idr0 = params->etmv4.reg_idr0;
+  config->reg_idr1 = params->etmv4.reg_idr1;
+  config->reg_idr2 = params->etmv4.reg_idr2;
+  config->reg_idr8 = params->etmv4.reg_idr8;
+  config->reg_idr9 = 0;
+  config->reg_idr10 = 0;
+  config->reg_idr11 = 0;
+  config->reg_idr12 = 0;
+  config->reg_idr13 = 0;
+  config->arch_ver = (ocsd_arch_version_t)params->arch_ver;
+  config->core_prof = (ocsd_core_profile_t)params->core_profile;
+}
+
+#define ARM_PS_REGNUM  25               /* Contains processor status */
+
+/* update btrace in the case of an instruction range  */
+
+static void
+cs_etm_update_btrace_with_inst_range (const void *context, 
+                                     const ocsd_generic_trace_elem *elem)
+{
+  struct cs_etm_decoder *etm_decoder;
+  struct thread_info *tp;
+  struct btrace_thread_info *btinfo;
+  struct btrace_function *bfun;
+  struct btrace_insn insn;
+  CORE_ADDR pc;
+  int size;
+  struct gdbarch *gdbarch;
+  unsigned int cpsr;
+  struct record_btrace_reg_entry reg;
+
+  if (elem->elem_type == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
+    {
+      etm_decoder = (struct cs_etm_decoder *)context;
+      if (!etm_decoder->t_info )
+        return;
+      tp = etm_decoder->t_info;
+      btinfo = &tp->btrace;
+      gdbarch = target_gdbarch ();
+
+      pc = elem->st_addr;
+      for (int i = 0; i< elem->num_instr_range; i++)
+        {
+          insn.pc = pc;
+          try
+            {
+              size = gdb_insn_length (gdbarch, pc);
+            }
+          catch (const gdb_exception_error &err)
+            {
+              error (_("Failed to get the size of the instruction."));
+            }
+          bfun = ftrace_update_function (btinfo, pc );
+          insn.iclass=BTRACE_INSN_OTHER;
+          insn.size = size;
+          if (etm_decoder->arch_version == ARCH_V7)
+            {
+              switch(elem->isa)
+              {
+                case ocsd_isa_arm:
+                  cpsr = 0;
+                  break;
+                case ocsd_isa_thumb2:
+                  cpsr = 0x20;
+                  break;
+                case ocsd_isa_tee:
+                  cpsr = 0x1000020;
+                  break;
+                case ocsd_isa_jazelle:
+                  cpsr = 0x1000000;
+                  break;
+                default:
+                  cpsr = 0;
+              }
+              btrace_reg_set (&reg, get_thread_regcache(tp), 
+                              ARM_PS_REGNUM, (gdb_byte *)&cpsr);
+              insn.registers.push_back (reg);
+            }
+          if (i == elem->num_instr_range -1)
+            {
+              switch (elem->last_i_type)
+              {
+                case OCSD_INSTR_BR:
+                case OCSD_INSTR_BR_INDIRECT:
+                  switch (elem->last_i_subtype )
+                  {
+                    case OCSD_S_INSTR_V8_RET:
+                    case OCSD_S_INSTR_V8_ERET:
+                    case OCSD_S_INSTR_V7_IMPLIED_RET:
+                      insn.iclass=BTRACE_INSN_RETURN;
+                      break;
+                    case OCSD_S_INSTR_BR_LINK:
+                      insn.iclass=BTRACE_INSN_CALL;
+                      break;
+                    case OCSD_S_INSTR_NONE:
+                      insn.iclass=BTRACE_INSN_JUMP;
+                  }
+                  break;
+                    case OCSD_INSTR_ISB:
+                    case OCSD_INSTR_DSB_DMB:
+                    case OCSD_INSTR_WFI_WFE:
+                    case OCSD_INSTR_OTHER:
+                      insn.iclass=BTRACE_INSN_OTHER;
+                      break;
+                    default:
+                      break;
+              }
+            }
+          ftrace_update_insns (bfun, insn);
+          pc = pc + size;
+        }
+    }
+}
+#undef ARM_PS_REGNUM
+
+#define ARM_EXCEPTION_UNDEFINED_INSTRUCTION 9
+
+/* update btrace in the case of an exception  */
+
+static void
+cs_etm_update_btrace_with_exception (const void *context, 
+                                    const ocsd_generic_trace_elem *elem)
+{
+  struct cs_etm_decoder *etm_decoder;
+  struct thread_info *tp;
+  struct btrace_thread_info *btinfo;
+
+  etm_decoder = (struct cs_etm_decoder *)context;
+  if (!etm_decoder->t_info )
+    return;
+  tp = etm_decoder->t_info;
+  btinfo = &tp->btrace;
+  /* handle the implementation of breakpoints in gdb for arm (v7) architecture
+     using undefined instructions  */
+
+  if (etm_decoder->arch_version == ARCH_V7)
+    {
+      if (elem->elem_type==OCSD_GEN_TRC_ELEM_EXCEPTION)
+        {
+          if (elem->exception_number == ARM_EXCEPTION_UNDEFINED_INSTRUCTION)
+            {
+              DEBUG ("handle breakpoints implementation in gdb for armv7");
+              ftrace_remove_last_insn(btinfo);
+            }
+        }
+    }
+}
+#undef ARM_EXCEPTION_UNDEFINED_INSTRUCTION
+
+/* update btrace in the case of a trace on  */
+
+static void
+cs_etm_update_btrace_with_trace_on (const void *context,
+                                   const ocsd_generic_trace_elem *elem)
+{
+  struct cs_etm_decoder *etm_decoder;
+  struct thread_info *tp;
+  struct btrace_thread_info *btinfo;
+
+  etm_decoder = (struct cs_etm_decoder *)context;
+  if (!etm_decoder->t_info )
+    return;
+  tp = etm_decoder->t_info;
+  btinfo = &tp->btrace;
+
+  if (elem->elem_type==OCSD_GEN_TRC_ELEM_TRACE_ON)
+    {
+      if (elem->trace_on_reason != TRACE_ON_NORMAL)
+        ftrace_new_gap (btinfo, elem->trace_on_reason, etm_decoder->gaps);
+    }
+}
+
+/*  callback function when a ocsd_generic_trace_elem is emitted  */
+
+static ocsd_datapath_resp_t 
+cs_etm_trace_element_callback (const void *context,
+				const ocsd_trc_index_t indx,
+				const uint8_t trace_chan_id,
+				const ocsd_generic_trace_elem *elem)
+{
+  char str_buffer[128];
+  if(ocsd_gen_elem_str(elem, str_buffer,128) == OCSD_OK)
+    DEBUG("ETM trace_element: index= %d, channel= 0x%x, %s",
+          indx, trace_chan_id, str_buffer);
+  ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+  switch (elem->elem_type) {
+    case OCSD_GEN_TRC_ELEM_TRACE_ON:
+      cs_etm_update_btrace_with_trace_on(context, elem);
+      break;
+    case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
+      cs_etm_update_btrace_with_inst_range(context, elem);
+      break;
+    case OCSD_GEN_TRC_ELEM_EXCEPTION:
+      cs_etm_update_btrace_with_exception(context, elem);
+      break;
+    case OCSD_GEN_TRC_ELEM_UNKNOWN:
+    case OCSD_GEN_TRC_ELEM_EO_TRACE:
+    case OCSD_GEN_TRC_ELEM_NO_SYNC:
+    case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
+    case OCSD_GEN_TRC_ELEM_TIMESTAMP:
+    case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
+    case OCSD_GEN_TRC_ELEM_ADDR_NACC:
+    case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
+    case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
+    case OCSD_GEN_TRC_ELEM_EVENT:
+    case OCSD_GEN_TRC_ELEM_SWTRACE:
+    case OCSD_GEN_TRC_ELEM_CUSTOM:
+    default:
+      break;
+  }
+  return resp;
+}
+
+/* create a cs_etm_decoder and initialize it  */
+
+static bool
+cs_etm_create_decoder (struct cs_etm_trace_params *t_params,
+			struct cs_etm_decoder *decoder)
+{
+  const char *decoder_name;
+  ocsd_etmv3_cfg config_etmv3;
+  ocsd_etmv4_cfg trace_config_etmv4;
+  void *trace_config;
+  uint8_t csid;
+
+  switch (t_params->protocol) {
+    case CS_ETM_PROTO_ETMV3:
+    case CS_ETM_PROTO_PTM:
+      cs_etm_get_etmv3_config(t_params, &config_etmv3);
+      decoder_name = (t_params->protocol == CS_ETM_PROTO_ETMV3) ?
+          OCSD_BUILTIN_DCD_ETMV3 :
+          OCSD_BUILTIN_DCD_PTM;
+      trace_config = &config_etmv3;
+      decoder->arch_version = ARCH_V7;
+      break;
+    case CS_ETM_PROTO_ETMV4i:
+      cs_etm_get_etmv4_config(t_params, &trace_config_etmv4);
+      decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
+      trace_config = &trace_config_etmv4;
+      decoder->arch_version = ARCH_V8;
+      break;
+    default:
+      decoder->arch_version = ARCH_UNKNOWN;
+      return false;
+  }
+
+  if (ocsd_dt_create_decoder(decoder->dcd_tree,
+                             decoder_name,
+                             OCSD_CREATE_FLG_FULL_DECODER,
+                             trace_config, &csid))
+    return false;
+  if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
+                                 cs_etm_trace_element_callback,
+                                 decoder))
+    return false;
+  decoder->prev_return = OCSD_RESP_CONT;
+  return true;
+}
+
+/* allocate a cs_etm_decoder and initialize it  */
+
+static struct cs_etm_decoder *
+cs_etm_alloc_decoder (struct thread_info *tp, int num_cpu,
+                     struct cs_etm_decoder_params d_params,
+                     std::vector<cs_etm_trace_params> * t_params)
+{
+
+  dcd_tree_handle_t dcdtree_handle;
+  ocsd_dcd_tree_src_t src_type =OCSD_TRC_SRC_SINGLE;
+  uint32_t deformatterCfgFlags =0;
+  struct cs_etm_decoder *decoder;
+  int i;
+  bool ret;
+
+  if (d_params.formatted)
+    src_type = OCSD_TRC_SRC_FRAME_FORMATTED;
+  if (d_params.frame_aligned)
+    deformatterCfgFlags |= OCSD_DFRMTR_FRAME_MEM_ALIGN;
+  if (d_params.fsyncs)
+    deformatterCfgFlags |= OCSD_DFRMTR_HAS_FSYNCS;
+  if (d_params.hsyncs)
+    deformatterCfgFlags |= OCSD_DFRMTR_HAS_HSYNCS;
+  if (d_params.reset_on_4x_sync)
+    deformatterCfgFlags |= OCSD_DFRMTR_RESET_ON_4X_FSYNC; 
+
+  dcdtree_handle = ocsd_create_dcd_tree(src_type,
+                                        deformatterCfgFlags);
+
+  if (dcdtree_handle == C_API_INVALID_TREE_HANDLE)
+    return NULL;
+  decoder=(struct cs_etm_decoder*)xmalloc (sizeof(struct cs_etm_decoder));
+  decoder->dcd_tree = dcdtree_handle;
+
+  for (i = 0; i < num_cpu; i++) {
+      ret = cs_etm_create_decoder(&(t_params->at(i)),
+                                  decoder);
+      if (ret == false)
+        {
+          ocsd_destroy_dcd_tree(decoder->dcd_tree);
+          free(decoder);
+          return NULL;
+        }
+
+  }
+  decoder->t_info =tp;
+  return decoder;
+}
+
+/* free a cs_etm_decoder  */
+
+static void 
+cs_etm_free_decoder (struct cs_etm_decoder *decoder)
+{
+  if (!decoder)
+    return;
+
+  ocsd_destroy_dcd_tree(decoder->dcd_tree);
+  decoder->dcd_tree = NULL;
+  decoder->t_info = NULL;
+  free(decoder);
+}
+
+/* A callback function to allow the trace decoder to read the inferior's
+   memory.  */
+
+static uint32_t
+btrace_etm_readmem_callback (const void *p_context, const ocsd_vaddr_t address,
+                             const ocsd_mem_space_acc_t mem_space, 
+                             const uint32_t reqBytes, uint8_t *byteBuffer)
+{
+  int result, errcode;
+
+  result = (int) reqBytes;
+  try
+  {
+      errcode = target_read_code ((CORE_ADDR) address, byteBuffer, reqBytes);
+      if (errcode != 0)
+        result = 0;
+  }
+  catch (const gdb_exception_error &error)
+  {
+      result = 0;
+  }
+
+  return result;
+}
+
+/* add memory access callback to the decoder  */
+
+static ocsd_err_t
+cs_etm_add_mem_access_callback (struct cs_etm_decoder *decoder,
+                               CORE_ADDR start, CORE_ADDR end,
+                               Fn_MemAcc_CB p_cb_func)
+{
+  ocsd_err_t error;
+  error = ocsd_dt_add_callback_mem_acc(decoder->dcd_tree,
+                                       (ocsd_vaddr_t) start, (ocsd_vaddr_t) end,
+                                       OCSD_MEM_SPACE_ANY, p_cb_func, decoder);
+  if (error != OCSD_OK)
+    decoder->mem_access = p_cb_func;
+  return (error);
+
+}
+
+/* process an etm traces data block  */ 
+
+static int
+cs_etm_process_data_block (struct cs_etm_decoder *decoder,
+                          uint64_t index, const uint8_t *buf,
+                          size_t len, size_t *consumed)
+{
+  int ret = 0;
+  ocsd_datapath_resp_t cur = OCSD_RESP_CONT;
+  ocsd_datapath_resp_t prev_return = decoder->prev_return;
+  size_t processed = 0;
+  uint32_t count;
+
+  while (processed < len) {
+      if (OCSD_DATA_RESP_IS_WAIT(prev_return)) {
+          cur = ocsd_dt_process_data(decoder->dcd_tree,
+                                     OCSD_OP_FLUSH,
+                                     0,
+                                     0,
+                                     NULL,
+                                     NULL);
+      } else if (OCSD_DATA_RESP_IS_CONT(prev_return)) {
+          cur = ocsd_dt_process_data(decoder->dcd_tree,
+                                     OCSD_OP_DATA,
+                                     index + processed,
+                                     len - processed,
+                                     &buf[processed],
+                                     &count);
+          processed += count;
+      } else {
+          DEBUG_FTRACE ("ocsd_dt_process_data returned with %d.\n", cur);
+          ret = -EINVAL;
+          break;
+      }
+
+      /* Return to the input code if the packet buffer is full.
+         Flushing will get done once the packet buffer has been
+         processed. */
+      if (OCSD_DATA_RESP_IS_WAIT(cur))
+        break;
+
+      prev_return = cur;
+  }
+
+  decoder->prev_return = cur;
+  *consumed = processed;
+
+  return ret;
+}
+
+/* print all function in a btrace  */
+
+static void btrace_print_all (struct btrace_thread_info *btinfo)
+{
+  std::vector<btrace_function> functions;
+
+  functions = btinfo->functions;
+  for (const btrace_function &function : functions)
+    ftrace_debug (&function, "");
+}
+
+static void
+btrace_compute_ftrace_etm (struct thread_info *tp,
+                           const struct btrace_data_etm *btrace,
+                           std::vector<unsigned int> &gaps)
+{
+  struct btrace_thread_info *btinfo;
+  struct cs_etm_decoder *decoder;
+  int errcode;
+  ocsd_err_t ocsd_error;
+  size_t consumed;
+
+
+  DEBUG_FTRACE ("btrace->size is 0x%x for thread %s", 
+                (unsigned int)(btrace->size), print_thread_id (tp));
+  if (btrace->size == 0)
+    return;
+
+  btinfo = &tp->btrace;
+  if (btinfo->functions.empty ())
+    btinfo->level = 0;
+
+  decoder = cs_etm_alloc_decoder(tp,btrace->config.num_cpu,
+                                 btrace->config.etm_decoder_params,
+                                 btrace->config.etm_trace_params);
+  if (decoder == NULL)
+    error (_("Failed to allocate ARM CoreSight ETM Trace decoder."));
+
+  ocsd_error = cs_etm_add_mem_access_callback(decoder,
+                                              (CORE_ADDR)0x0L, (CORE_ADDR) -1L,
+                                              btrace_etm_readmem_callback);
+  if (ocsd_error!= OCSD_OK)
+    error (_("Failed to add CoreSight Trace decoder memory access callback."));
+
+  errcode = cs_etm_process_data_block(decoder,
+                                      0, btrace->data,
+                                      btrace->size, &consumed);
+  if (errcode!=0)
+    error (_("Failed to decode ARM CoreSight ETM Trace."));
+  ftrace_compute_global_level_offset (btinfo);
+  btrace_add_pc (tp);
+  btrace_print_all(btinfo);
+  cs_etm_free_decoder(decoder);
+
+}
+#else /*    defined (HAVE_LIBOPENCSD_C_API)    */
+
+static void
+btrace_compute_ftrace_etm (struct thread_info *tp,
+                           const struct btrace_data_etm *btrace,
+                           std::vector<unsigned int> &gaps)
+{
+
+  internal_error (__FILE__, __LINE__, _("Unexpected branch trace format."));
+}
+#endif /*    defined (HAVE_LIBOPENCSD_C_API)    */
+
 /* Compute the function branch trace from a block branch trace BTRACE for
    a thread given by BTINFO.  If CPU is not NULL, overwrite the cpu in the
    branch trace configuration.  This is currently only used for the PT
@@ -1531,6 +2102,10 @@ btrace_compute_ftrace_1 (struct thread_info *tp,
 
       btrace_compute_ftrace_pt (tp, &btrace->variant.pt, gaps);
       return;
+
+    case BTRACE_FORMAT_ETM:
+      btrace_compute_ftrace_etm (tp, &btrace->variant.etm, gaps);
+      return;
   }
 
   internal_error (__FILE__, __LINE__, _("Unknown branch trace format."));
@@ -1599,6 +2174,10 @@ btrace_enable (struct thread_info *tp, const struct btrace_config *conf)
   if (conf->format == BTRACE_FORMAT_PT)
     error (_("Intel Processor Trace support was disabled at compile time."));
 #endif /* !defined (HAVE_LIBIPT) */
+#if !defined (HAVE_LIBOPENCSD_C_API)
+  if (conf->format == BTRACE_FORMAT_ETM)
+    error (_("ARM CoreSight Trace support was disabled at compile time."));
+#endif /* !defined (HAVE_LIBOPENCSD_C_API) */
 
   DEBUG ("enable thread %s (%s)", print_thread_id (tp),
          target_pid_to_str (tp->ptid).c_str ());
@@ -1791,6 +2370,9 @@ btrace_stitch_trace (struct btrace_data *btrace, struct thread_info *tp)
     case BTRACE_FORMAT_PT:
       /* Delta reads are not supported.  */
       return -1;
+    case BTRACE_FORMAT_ETM:
+      /* Delta reads are not supported.  */
+      return -1;
   }
 
   internal_error (__FILE__, __LINE__, _("Unknown branch trace format."));
@@ -3413,6 +3995,11 @@ maint_info_btrace_cmd (const char *args, int from_tty)
       }
       break;
 #endif /* defined (HAVE_LIBIPT)  */
+#if defined (HAVE_LIBOPENCSD_C_API)
+    case BTRACE_FORMAT_ETM:
+      printf_unfiltered (_("Version: %s.\n"), ocsd_get_version_str());
+      break;
+#endif /* defined (HAVE_LIBOPENCSD_C_API) */
   }
 }
 
@@ -3487,7 +4074,7 @@ first."),
 	   maint_btrace_clear_packet_history_cmd,
 	    _("Clears the branch tracing packet history.\n\
 Discards the raw branch tracing data but not the execution history data."),
-	   &maint_btrace_cmdlist);
+&maint_btrace_cmdlist);
 
   add_cmd ("clear", class_maintenance, maint_btrace_clear_cmd,
 	    _("Clears the branch tracing data.\n\
diff --git a/gdb/btrace.h b/gdb/btrace.h
index 8f6ce32103d..5d734896632 100644
--- a/gdb/btrace.h
+++ b/gdb/btrace.h
@@ -34,6 +34,12 @@
 #  include <intel-pt.h>
 #endif
 
+#if defined (HAVE_LIBOPENCSD_C_API)
+#  include <opencsd/c_api/opencsd_c_api.h>
+#  include <opencsd/etmv4/trc_pkt_types_etmv4.h>
+#  include <opencsd/ocsd_if_types.h>
+#endif
+
 #include <vector>
 
 struct thread_info;
@@ -63,6 +69,17 @@ enum btrace_insn_flag
 };
 DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags);
 
+/* extend MAX_BTRACE_REGISTER_SIZE if targets with registers 
+bigger than 64 bits are considered  */
+#define MAX_BTRACE_REGISTER_SIZE 8 
+/* a register entry in btrace_insn*/
+struct record_btrace_reg_entry
+{
+  unsigned short num;
+  unsigned short len;
+  gdb_byte buffer[MAX_BTRACE_REGISTER_SIZE * sizeof (gdb_byte)]; 
+};
+
 /* A branch trace instruction.
 
    This represents a single instruction in a branch trace.  */
@@ -74,6 +91,9 @@ struct btrace_insn
   /* The size of this instruction in bytes.  */
   gdb_byte size;
 
+  /* a vector of registers */
+  std::vector<record_btrace_reg_entry> registers;
+
   /* The instruction class of this instruction.  */
   enum btrace_insn_class iclass;
 
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 39ac9aafc28..107abd7e653 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -1576,18 +1576,27 @@ record_btrace_target::fetch_registers (struct regcache *regcache, int regno)
       struct gdbarch *gdbarch;
       int pcreg;
 
+      insn = btrace_insn_get (replay);
+      gdb_assert (insn != NULL);
+      if (!insn->registers.empty())
+        {
+          for(int i = 0; i < insn->registers.size(); i++)
+            {
+              if (insn->registers.operator[](i).num==regno)
+                {
+                  regcache->raw_supply (regno, insn->registers.operator[](i).buffer);
+                  return;
+                }
+            }
+        }
       gdbarch = regcache->arch ();
       pcreg = gdbarch_pc_regnum (gdbarch);
       if (pcreg < 0)
         return;
-
-      /* We can only provide the PC register.  */
+      /* We can only provide the PC register here.  */
       if (regno >= 0 && regno != pcreg)
         return;
 
-      insn = btrace_insn_get (replay);
-      gdb_assert (insn != NULL);
-
       regcache->raw_supply (regno, &insn->pc);
     }
   else
@@ -3020,7 +3029,6 @@ cmd_record_btrace_start (const char *args, int from_tty)
     }
 }
 
-
 /* The "show record btrace replay-memory-access" command.  */
 
 static void
@@ -3250,7 +3258,6 @@ This format may not be available on all processors."),
 		       _("Show record options."), &show_record_btrace_cmdlist,
 		       "show record btrace ", 0, &show_record_cmdlist);
 
-
   add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
 Automatically determine the cpu to be used for trace decode."),
 	   &set_record_btrace_cpu_cmdlist);
diff --git a/gdbsupport/ChangeLog b/gdbsupport/ChangeLog
index e14bdf109b3..587bc08e58c 100644
--- a/gdbsupport/ChangeLog
+++ b/gdbsupport/ChangeLog
@@ -1,19 +1,32 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* btrace-common.h (cs_etmv3_trace_params): New 
+	* btrace-common.h (cs_etmv4_trace_params): New.
+	* btrace-common.h (cs_etm_trace_params): New.
+	* btrace-common.h (cs_etm_decoder_params): New 
+	* btrace-common.h (btrace_data_etm_config): New.
+	* btrace-common.h (btrace_data_etm): New.
+	* btrace-common.h (btrace_data): add a btrace_data_etm.
+	* btrace-common.cc (btrace_data::fini): handle CoreSight traces.
+	* btrace-common.cc (btrace_data::empty): handle CoreSight traces.
+	* btrace-common.cc (btrace_data_append): handle CoreSight traces.
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* gdbsupport/btrace-common.h (btrace_format): add BTRACE_FORMAT_ETM 
 	to the enum.
-	* gdbsupport/btrace-common.h (btrace_cpu_vendor): add CV_ARM to the enum.
-	* gdbsupport/btrace-common.h (btrace_config_etm): new struct.
-	* gdbsupport/btrace-common.h (btrace_config): add btrace_config_etm etm.
-	* gdbsupport/btrace-common.cc (btrace_format_string): add BTRACE_FORMAT_ETM.
-	* gdbsupport/btrace-common.cc (btrace_format_short_string): add 
+	* btrace-common.h (btrace_cpu_vendor): add CV_ARM to the enum.
+	* btrace-common.h (btrace_config_etm): new struct.
+	* btrace-common.h (btrace_config): add btrace_config_etm etm.
+	* btrace-common.cc (btrace_format_string): add BTRACE_FORMAT_ETM.
+	* btrace-common.cc (btrace_format_short_string): add 
 	BTRACE_FORMAT_ETM.
 
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
-	* gdbsupport/common.m4: check --with-arm-cs configuration
+	* common.m4: check --with-arm-cs configuration
 	flag, perf_event and opencsd_c_api to set compilation flags.
-	* gdbsupport/configure: Regenerated
+	* configure: Regenerated
 
 2021-02-05  Paul E. Murphy  <murphy@linux.ibm.com>
 
diff --git a/gdbsupport/btrace-common.cc b/gdbsupport/btrace-common.cc
index 461f769ed51..8e31c8a65dd 100644
--- a/gdbsupport/btrace-common.cc
+++ b/gdbsupport/btrace-common.cc
@@ -62,7 +62,6 @@ btrace_format_short_string (enum btrace_format format)
 
     case BTRACE_FORMAT_ETM:
       return "etm";
-
   }
 
   internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
@@ -87,6 +86,12 @@ btrace_data::fini ()
     case BTRACE_FORMAT_PT:
       xfree (variant.pt.data);
       return;
+
+    case BTRACE_FORMAT_ETM:
+      /* Variant.etm.data can be null if no new traces are collected.  */
+      if (variant.etm.data!=NULL)
+        xfree (variant.etm.data);
+      return;
   }
 
   internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
@@ -107,6 +112,9 @@ btrace_data::empty () const
 
     case BTRACE_FORMAT_PT:
       return (variant.pt.size == 0);
+
+    case BTRACE_FORMAT_ETM:
+      return (variant.etm.size == 0);
   }
 
   internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
@@ -192,6 +200,38 @@ btrace_data_append (struct btrace_data *dst,
               }
           }
           return 0;
+
+            case BTRACE_FORMAT_ETM:
+              switch (dst->format)
+              {
+                default:
+                  return -1;
+
+                case BTRACE_FORMAT_NONE:
+                  dst->format = BTRACE_FORMAT_ETM;
+                  dst->variant.etm.data = NULL;
+                  dst->variant.etm.size = 0;
+
+                  /* fall-through.  */
+                case BTRACE_FORMAT_ETM:
+                  {
+                    gdb_byte *data;
+                    size_t size;
+
+                    size = src->variant.etm.size + dst->variant.etm.size;
+                    data = (gdb_byte *) xmalloc (size);
+
+                    memcpy (data, dst->variant.etm.data, dst->variant.etm.size);
+                    memcpy (data + dst->variant.etm.size, src->variant.etm.data,
+                            src->variant.etm.size);
+
+                    xfree (dst->variant.etm.data);
+
+                    dst->variant.etm.data = data;
+                    dst->variant.etm.size = size;
+                  }
+              }
+              return 0;
   }
 
   internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
index 7f3cabfde77..5bc6f8dbd0f 100644
--- a/gdbsupport/btrace-common.h
+++ b/gdbsupport/btrace-common.h
@@ -157,7 +157,6 @@ struct btrace_config
 
   /* The ARM CoreSight ETM Trace configuration.  */
   struct btrace_config_etm etm;
-
 };
 
 /* Branch trace in BTS format.  */
@@ -189,6 +188,108 @@ struct btrace_data_pt
   size_t size;
 };
 
+/* Parameters needed for decoding ETMv3 traces.
+   See open source coresight trace decoder library (opencsd)
+   for further details.  */
+struct cs_etmv3_trace_params {
+  uint32_t reg_ctrl;
+  uint32_t reg_trc_id;
+  uint32_t reg_ccer;
+  uint32_t reg_idr;
+};
+
+/* Parameters needed for decoding ETMv4 traces.
+   See open source coresight trace decoder library (opencsd)
+   for further details.  */
+struct cs_etmv4_trace_params {
+  uint32_t reg_idr0;
+  uint32_t reg_idr1;
+  uint32_t reg_idr2;
+  uint32_t reg_idr8;
+  uint32_t reg_configr;
+  uint32_t reg_traceidr;
+};
+
+/* The following enums are indexed starting with 1 to align with the
+   open source coresight trace decoder library (opencsd).  */
+enum {
+  CS_ETM_PROTO_ETMV3 = 1,
+  CS_ETM_PROTO_ETMV4i,
+  CS_ETM_PROTO_ETMV4d,
+  CS_ETM_PROTO_PTM,
+};
+
+/* The following enum must be aligned with the
+   open source coresight trace decoder library (opencsd).  */
+
+/* Core Architecture Version  */
+enum {
+    ARCHITECTURE_UNKNOWN,   /* unknown architecture  */
+    ARCHITECTURE_CUSTOM,    /* None ARM, custom architecture  */
+    ARCHITECTURE_V7,        /* V7 architecture  */
+    ARCHITECTURE_V8,        /* V8 architecture  */
+    ARCHITECTURE_V8r3,      /* V8.3 architecture  */
+};
+
+/* The following enum must be aligned with the
+   open source coresight trace decoder library (opencsd).  */
+
+/* Core Profile  */
+enum {
+    PROFILE_UNKNOWN,     /* Unknown profile  */
+    PROFILE_CORTEX_M,    /* Cortex-M profile  */
+    PROFILE_CORTEX_R,    /* Cortex-R profile  */
+    PROFILE_CORTEX_A,    /* Cortex-A profile  */
+    PROFILE_CUSTOM,      /* None ARM, custom arch profile  */
+};
+
+/* parameters of trace source  */
+struct cs_etm_trace_params {
+  struct btrace_cpu cpu;
+  int arch_ver;
+  int core_profile;
+  int protocol;
+  union {
+    struct cs_etmv3_trace_params etmv3;
+    struct cs_etmv4_trace_params etmv4;
+  };
+};
+
+/* parameters of trace sink/decoder  */
+struct cs_etm_decoder_params {
+  uint8_t formatted    :1,
+  fsyncs           :1,
+  hsyncs           :1,
+  frame_aligned    :1,
+  reset_on_4x_sync :1,
+  __res            :3;
+};
+
+/* Configuration information to go with the etm trace data.  */
+struct btrace_data_etm_config
+{
+  /* The number of cpu (trace sources).  */
+  int    num_cpu;
+  std::vector<struct cs_etm_trace_params> *etm_trace_params;
+  struct cs_etm_decoder_params etm_decoder_params;
+};
+
+/* Branch trace in arm Processor Trace format.  */
+struct btrace_data_etm
+{
+  /* Some configuration information to go with the data.  */
+  struct btrace_data_etm_config config;
+
+  /* The trace data.  */
+  gdb_byte *data;
+
+  /* The size of DATA in bytes.  */
+  size_t size;
+
+  /* trace id for this thread. set to 0xFF to ignore it during parsing  */
+  int trace_id;
+};
+
 /* The branch trace data.  */
 struct btrace_data
 {
@@ -226,6 +327,9 @@ struct btrace_data
 
     /* Format == BTRACE_FORMAT_PT.  */
     struct btrace_data_pt pt;
+    
+    /* Format == BTRACE_FORMAT_ETM.  */
+    struct btrace_data_etm etm;
   } variant;
 
 private:
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 4/8] start/stop btrace with coresight etm and collect etm buffer on linux os
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
                   ` (2 preceding siblings ...)
  2021-02-26  2:45 ` [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant Zied Guermazi
@ 2021-02-26  2:45 ` Zied Guermazi
  2021-02-26  2:45 ` [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY Zied Guermazi
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi


This patch implement the lower layer for starting ad stopping 
ARM CoreSight tracing on linux targets for arm and aarch64

gdb/ChangeLog

	* nat/linux-btrace.h (btrace_tinfo_etm): New.
	(btrace_target_info): add etm.
	* nat/linux-btrace.c (perf_event_read_available): New.
	(linux_enable_bts): get page size from sysconf.
	(linux_enable_pt): get page size from sysconf.
	(perf_event_etm_event_type): New.
	(perf_event_etm_event_sink): New.
	(linux_enable_etm): New.
	(linux_enable_btrace): add enabling etm traces.
	(linux_disable_bts): get page size from sysconf.
	(linux_disable_pt): get page size from sysconf.
	(linux_disable_etm): New.
	(linux_disable_btrace): add disabling etm traces.
	(get_cpu_count): New.
	(cs_etm_is_etmv4): New.
	(cs_etm_get_register): New.
	(coresight_get_trace_id): New.
	(fill_etm_trace_params): New.
	(linux_fill_btrace_etm_config): New.
	(linux_read_etm): New.
	(linux_read_btrace): add reading etm traces.
	* arm-linux-nat.c (arm_linux_nat_target::enable_btrace): New.
	(arm_linux_nat_target::disable_btrace): New.
	(arm_linux_nat_target::teardown_btrace): New.
	(arm_linux_nat_target::read_btrace): New.
	(arm_linux_nat_target::btrace_conf): New.
	* aarch64-linux-nat.c (aarch64_linux_nat_target::enable_btrace): New.
	(aarch64_linux_nat_target::disable_btrace): New.
	(aarch64_linux_nat_target::teardown_btrace): New.
	(aarch64_linux_nat_target::read_btrace): New.
	(aarch64_linux_nat_target::btrace_conf): New.

---
 gdb/ChangeLog           |  34 +++
 gdb/aarch64-linux-nat.c |  71 ++++++-
 gdb/arm-linux-nat.c     |  66 ++++++
 gdb/nat/linux-btrace.c  | 450 ++++++++++++++++++++++++++++++++++++++--
 gdb/nat/linux-btrace.h  |  19 ++
 5 files changed, 626 insertions(+), 14 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1b998ef2624..a84671bf344 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,37 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* nat/linux-btrace.h (btrace_tinfo_etm): New.
+	* nat/linux-btrace.h (btrace_target_info): add etm.
+	* nat/linux-btrace.c (perf_event_read_available): New.
+	* nat/linux-btrace.c (linux_enable_bts): get page size from sysconf.
+	* nat/linux-btrace.c (linux_enable_pt): get page size from sysconf.
+	* nat/linux-btrace.c (perf_event_etm_event_type): New.
+	* nat/linux-btrace.c (perf_event_etm_event_sink): New.
+	* nat/linux-btrace.c (linux_enable_etm): New.
+	* nat/linux-btrace.c (linux_enable_btrace): add enabling etm traces.
+	* nat/linux-btrace.c (linux_disable_bts): get page size from sysconf.
+	* nat/linux-btrace.c (linux_disable_pt): get page size from sysconf.
+	* nat/linux-btrace.c (linux_disable_etm): New.
+	* nat/linux-btrace.c (linux_disable_btrace): add disabling etm traces.
+	* nat/linux-btrace.c (get_cpu_count): New.
+	* nat/linux-btrace.c (cs_etm_is_etmv4): New.
+	* nat/linux-btrace.c (cs_etm_get_register): New.
+	* nat/linux-btrace.c (coresight_get_trace_id): New.
+	* nat/linux-btrace.c (fill_etm_trace_params): New.
+	* nat/linux-btrace.c (linux_fill_btrace_etm_config): New.
+	* nat/linux-btrace.c (linux_read_etm): New.
+	* nat/linux-btrace.c (linux_read_btrace): add reading etm traces.
+	* arm-linux-nat.c (arm_linux_nat_target::enable_btrace): New.
+	* arm-linux-nat.c (arm_linux_nat_target::disable_btrace): New.
+	* arm-linux-nat.c (arm_linux_nat_target::teardown_btrace): New.
+	* arm-linux-nat.c (arm_linux_nat_target::read_btrace): New.
+	* arm-linux-nat.c (arm_linux_nat_target::btrace_conf): New.
+	* aarch64-linux-nat.c (aarch64_linux_nat_target::enable_btrace): New.
+	* aarch64-linux-nat.c (aarch64_linux_nat_target::disable_btrace): New.
+	* aarch64-linux-nat.c (aarch64_linux_nat_target::teardown_btrace): New.
+	* aarch64-linux-nat.c (aarch64_linux_nat_target::read_btrace): New.
+	* aarch64-linux-nat.c (aarch64_linux_nat_target::btrace_conf): New.
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* btrace.c (ftrace_remove_last_insn): New.
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 0cae91b569c..a5ac4c80f47 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -35,6 +35,7 @@
 #include "nat/aarch64-linux.h"
 #include "nat/aarch64-linux-hw-point.h"
 #include "nat/aarch64-sve-linux-ptrace.h"
+#include "nat/linux-btrace.h"
 
 #include "elf/external.h"
 #include "elf/common.h"
@@ -84,6 +85,16 @@ class aarch64_linux_nat_target final : public linux_nat_target
   /* Override the GNU/Linux post attach hook.  */
   void post_attach (int pid) override;
 
+  /*override branch tracing  */
+  struct btrace_target_info *enable_btrace (ptid_t ptid,
+                                            const struct btrace_config *conf) override;
+  void disable_btrace (struct btrace_target_info *tinfo) override;
+  void teardown_btrace (struct btrace_target_info *tinfo) override;
+  enum btrace_error read_btrace (struct btrace_data *data,
+                                 struct btrace_target_info *btinfo,
+                                 enum btrace_read_type type) override;
+  const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
+
   /* These three defer to common nat/ code.  */
   void low_new_thread (struct lwp_info *lp) override
   { aarch64_linux_new_thread (lp); }
@@ -591,7 +602,7 @@ aarch64_linux_nat_target::low_new_fork (struct lwp_info *parent,
   child_state = aarch64_get_debug_reg_state (child_pid);
   *child_state = *parent_state;
 }
-\f
+
 
 /* Called by libthread_db.  Returns a pointer to the thread local
    storage (or its descriptor).  */
@@ -605,7 +616,7 @@ ps_get_thread_area (struct ps_prochandle *ph,
 
   return aarch64_ps_get_thread_area (ph, lwpid, idx, base, is_64bit_p);
 }
-\f
+
 
 /* Implement the "post_startup_inferior" target_ops method.  */
 
@@ -632,6 +643,62 @@ aarch64_linux_nat_target::post_attach (int pid)
   linux_nat_target::post_attach (pid);
 }
 
+/* Enable branch tracing.  */
+
+struct btrace_target_info *
+aarch64_linux_nat_target::enable_btrace (ptid_t ptid,
+                                         const struct btrace_config *conf)
+{
+  struct btrace_target_info *tinfo = nullptr;
+  try
+    {
+      tinfo = linux_enable_btrace (ptid, conf);
+    }
+  catch (const gdb_exception_error &exception)
+    {
+      error (_("Could not enable branch tracing for %s: %s"),
+             target_pid_to_str (ptid).c_str (), exception.what ());
+    }
+
+  return tinfo;
+}
+
+/* Disable branch tracing.  */
+
+void
+aarch64_linux_nat_target::disable_btrace (struct btrace_target_info *tinfo)
+{
+  enum btrace_error errcode = linux_disable_btrace (tinfo);
+
+  if (errcode != BTRACE_ERR_NONE)
+    error (_("Could not disable branch tracing."));
+}
+
+/* Teardown branch tracing.  */
+
+void
+aarch64_linux_nat_target::teardown_btrace (struct btrace_target_info *tinfo)
+{
+  /* Ignore errors.  */
+  linux_disable_btrace (tinfo);
+}
+
+enum btrace_error
+aarch64_linux_nat_target::read_btrace (struct btrace_data *data,
+                                       struct btrace_target_info *btinfo,
+                                       enum btrace_read_type type)
+{
+  return linux_read_btrace (data, btinfo, type);
+}
+
+/* See to_btrace_conf in target.h.  */
+
+const struct btrace_config *
+aarch64_linux_nat_target::btrace_conf (const struct btrace_target_info *btinfo)
+{
+  return linux_btrace_conf (btinfo);
+}
+
 /* Implement the "read_description" target_ops method.  */
 
 const struct target_desc *
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index 662dade0a12..18befac6a65 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -39,6 +39,7 @@
 #include <sys/procfs.h>
 
 #include "nat/linux-ptrace.h"
+#include "nat/linux-btrace.h"
 #include "linux-tdep.h"
 
 /* Prototypes for supply_gregset etc.  */
@@ -95,6 +96,15 @@ class arm_linux_nat_target final : public linux_nat_target
 
   const struct target_desc *read_description () override;
 
+  struct btrace_target_info *enable_btrace (ptid_t ptid,
+                                            const struct btrace_config *conf) override;
+  void disable_btrace (struct btrace_target_info *tinfo) override;
+  void teardown_btrace (struct btrace_target_info *tinfo) override;
+  enum btrace_error read_btrace (struct btrace_data *data,
+                                 struct btrace_target_info *btinfo,
+                                 enum btrace_read_type type) override;
+  const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
+
   /* Override linux_nat_target low methods.  */
 
   /* Handle thread creation and exit.  */
@@ -1190,6 +1200,62 @@ arm_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
   return start <= addr && start + length - 1 >= addr;
 }
 
+/* Enable branch tracing.  */
+
+struct btrace_target_info *
+arm_linux_nat_target::enable_btrace (ptid_t ptid,
+                                     const struct btrace_config *conf)
+{
+  struct btrace_target_info *tinfo = nullptr;
+  try
+    {
+      tinfo = linux_enable_btrace (ptid, conf);
+    }
+  catch (const gdb_exception_error &exception)
+    {
+      error (_("Could not enable branch tracing for %s: %s"),
+             target_pid_to_str (ptid).c_str (), exception.what ());
+    }
+
+  return tinfo;
+}
+
+/* Disable branch tracing.  */
+
+void
+arm_linux_nat_target::disable_btrace (struct btrace_target_info *tinfo)
+{
+  enum btrace_error errcode = linux_disable_btrace (tinfo);
+
+  if (errcode != BTRACE_ERR_NONE)
+    error (_("Could not disable branch tracing."));
+}
+
+/* Teardown branch tracing.  */
+
+void
+arm_linux_nat_target::teardown_btrace (struct btrace_target_info *tinfo)
+{
+  /* Ignore errors.  */
+  linux_disable_btrace (tinfo);
+}
+
+enum btrace_error
+arm_linux_nat_target::read_btrace (struct btrace_data *data,
+                                   struct btrace_target_info *btinfo,
+                                   enum btrace_read_type type)
+{
+  return linux_read_btrace (data, btinfo, type);
+}
+
+/* See to_btrace_conf in target.h.  */
+
+const struct btrace_config *
+arm_linux_nat_target::btrace_conf (const struct btrace_target_info *btinfo)
+{
+  return linux_btrace_conf (btinfo);
+}
+
 /* Handle thread creation.  We need to copy the breakpoints and watchpoints
    in the parent thread to the child thread.  */
 void
diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
index 324f7ef0407..e8f74158784 100644
--- a/gdb/nat/linux-btrace.c
+++ b/gdb/nat/linux-btrace.c
@@ -159,6 +159,67 @@ perf_event_read (const struct perf_event_buffer *pev, __u64 data_head,
   return buffer;
 }
 
+/* Copy available bytes from PEV ending at DATA_HEAD, updates *psize
+   gives back *data: a pointer to the memory holding the copy.
+
+   The caller is responsible for freeing the data memory.  */
+static void
+perf_event_read_available (struct perf_event_buffer *pev, gdb_byte **data,
+                           size_t *psize)
+{
+  const gdb_byte *begin, *end, *start, *stop;
+  gdb_byte *buffer;
+  size_t buffer_size;
+  __u64 data_tail, data_head;
+
+  if (psize == NULL)
+    {
+      *data = NULL;
+      return ;
+    }
+
+  buffer_size = *(pev->data_head) - pev->last_head;
+
+  if (buffer_size >pev->size)
+    buffer_size = pev->size;
+
+  data_head = *(pev->data_head);
+  data_tail = *(pev->data_head) - buffer_size;
+
+  /* If we ask for more data than we seem to have, we wrap around and read
+     data from the end of the buffer.  This is already handled by the %
+     BUFFER_SIZE operation, below.  Here, we just need to make sure that we
+     don't underflow.
+
+     Note that this is perfectly OK for perf event buffers where data_head
+     doesn'grow indefinitely and instead wraps around to remain within the
+     buffer's boundaries.  */
+
+  gdb_assert (buffer_size <= data_head);
+
+  begin = pev->mem;
+  start = begin + data_tail % pev->size;
+  stop = begin + data_head % pev->size;
+
+  buffer = (gdb_byte *) xmalloc (buffer_size);
+
+  if (start < stop)
+    {
+      memcpy (buffer, start, stop - start);
+    }
+  else
+    {
+      end = begin + pev->size;
+
+      memcpy (buffer, start, end - start);
+      memcpy (buffer + (end - start), begin, stop - begin);
+    }
+  pev->last_head = *(pev->data_head);
+  *psize = buffer_size;
+  *data = buffer;
+  return ;
+}
+
 /* Copy the perf event buffer data from PEV.
    Store a pointer to the copy into DATA and its size in SIZE.  */
 
@@ -483,10 +544,11 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
   scoped_fd fd (syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0));
   if (fd.get () < 0)
     diagnose_perf_event_open_fail ();
+  long page_size = sysconf(_SC_PAGESIZE);
 
   /* Convert the requested size in bytes to pages (rounding up).  */
-  pages = ((size_t) conf->size / PAGE_SIZE
-	   + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
+  pages = ((size_t) conf->size / page_size
+	   + ((conf->size % page_size) == 0 ? 0 : 1));
   /* We need at least one page.  */
   if (pages == 0)
     pages = 1;
@@ -505,17 +567,17 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
       size_t length;
       __u64 data_size;
 
-      data_size = (__u64) pages * PAGE_SIZE;
+      data_size = (__u64) pages * page_size;
 
       /* Don't ask for more than we can represent in the configuration.  */
       if ((__u64) UINT_MAX < data_size)
 	continue;
 
       size = (size_t) data_size;
-      length = size + PAGE_SIZE;
+      length = size + page_size;
 
       /* Check for overflows.  */
-      if ((__u64) length != data_size + PAGE_SIZE)
+      if ((__u64) length != data_size + page_size)
 	continue;
 
       errno = 0;
@@ -530,7 +592,7 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
 
   struct perf_event_mmap_page *header = (struct perf_event_mmap_page *)
         data.get ();
-  data_offset = PAGE_SIZE;
+  data_offset = page_size;
 
 #if defined (PERF_ATTR_SIZE_VER5)
   if (offsetof (struct perf_event_mmap_page, data_size) <= header->size)
@@ -613,7 +675,8 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
     diagnose_perf_event_open_fail ();
 
   /* Allocate the configuration page. */
-  scoped_mmap data (nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
+  long page_size = sysconf(_SC_PAGESIZE);
+  scoped_mmap data (nullptr, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
 		    fd.get (), 0);
   if (data.get () == MAP_FAILED)
     error (_("Failed to map trace user page: %s."), safe_strerror (errno));
@@ -624,8 +687,8 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
   header->aux_offset = header->data_offset + header->data_size;
 
   /* Convert the requested size in bytes to pages (rounding up).  */
-  pages = ((size_t) conf->size / PAGE_SIZE
-	   + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
+  pages = ((size_t) conf->size / page_size
+	   + ((conf->size % page_size) == 0 ? 0 : 1));
   /* We need at least one page.  */
   if (pages == 0)
     pages = 1;
@@ -644,7 +707,7 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
       size_t length;
       __u64 data_size;
 
-      data_size = (__u64) pages * PAGE_SIZE;
+      data_size = (__u64) pages * page_size;
 
       /* Don't ask for more than we can represent in the configuration.  */
       if ((__u64) UINT_MAX < data_size)
@@ -689,6 +752,152 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
 
 #endif /* !defined (PERF_ATTR_SIZE_VER5) */
 
+/* Determine the etm event type.  */
+
+static int
+perf_event_etm_event_type ()
+{
+  static const char filename[] = "/sys/bus/event_source/devices/cs_etm/type";
+
+  errno = 0;
+  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+  if (file.get () == nullptr)
+    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
+
+  int type, found = fscanf (file.get (), "%d", &type);
+  if (found != 1)
+    error (_("Failed to read the ETM event type from %s."), filename);
+
+  return type;
+}
+
+
+static unsigned int
+perf_event_etm_event_sink (const struct btrace_config_etm *conf)
+{
+  char filename[PATH_MAX];
+
+  sprintf( filename, "/sys/bus/event_source/devices/cs_etm/sinks/%s",conf->sink );
+  errno = 0;
+  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+  if (file.get () == nullptr)
+    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
+
+  unsigned int sink;
+  int  found = fscanf (file.get (), "0x%x", &sink);
+  if (found != 1)
+    error (_("Failed to read the ETM sink from %s."), filename);
+
+  return sink;
+}
+
+/* Enable arm CoreSight ETM tracing.  */
+
+static struct btrace_target_info *
+linux_enable_etm (ptid_t ptid, const struct btrace_config_etm *conf)
+{
+  struct btrace_tinfo_etm *etm;
+  size_t pages;
+  int pid, pg;
+
+  pid = ptid.lwp ();
+  if (pid == 0)
+    pid = ptid.pid ();
+
+  gdb::unique_xmalloc_ptr<btrace_target_info> tinfo
+    (XCNEW (btrace_target_info));
+  tinfo->ptid = ptid;
+
+  tinfo->conf.format = BTRACE_FORMAT_ETM;
+  etm = &tinfo->variant.etm;
+
+  etm->attr.type = perf_event_etm_event_type ();
+  etm->attr.size = sizeof (etm->attr);
+
+  etm->attr.sample_type = PERF_SAMPLE_CPU;
+  etm->attr.read_format = PERF_FORMAT_ID;
+  etm->attr.sample_id_all = 1;
+  etm->attr.enable_on_exec = 1;
+  etm->attr.exclude_kernel = 1;
+  etm->attr.exclude_hv = 1;
+  etm->attr.exclude_idle = 1;
+  if (conf->sink != nullptr)
+    {
+      if (strcmp (conf->sink, "default")!=0)
+        etm->attr.config2 = perf_event_etm_event_sink(conf);
+    }
+
+  errno = 0;
+  scoped_fd fd (syscall (SYS_perf_event_open, &etm->attr, pid, -1, -1, 0));
+  if (fd.get () < 0)
+    diagnose_perf_event_open_fail ();
+
+  /* Allocate the configuration page. */
+  long page_size = sysconf(_SC_PAGESIZE);
+  scoped_mmap data (nullptr, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+		    fd.get (), 0);
+  if (data.get () == MAP_FAILED)
+    error (_("Failed to map trace user page: %s."), safe_strerror (errno));
+
+  struct perf_event_mmap_page *header = (struct perf_event_mmap_page *)
+    data.get ();
+
+  header->aux_offset = header->data_offset + header->data_size;
+  /* Convert the requested size in bytes to pages (rounding up).  */
+  pages = ((size_t) conf->size / page_size
+	   + ((conf->size % page_size) == 0 ? 0 : 1));
+  /* We need at least one page.  */
+  if (pages == 0)
+    pages = 1;
+
+  /* The buffer size can be requested in powers of two pages.  Adjust PAGES
+     to the next power of two.  */
+  for (pg = 0; pages != ((size_t) 1 << pg); ++pg)
+    if ((pages & ((size_t) 1 << pg)) != 0)
+      pages += ((size_t) 1 << pg);
+
+  /* We try to allocate the requested size.
+     If that fails, try to get as much as we can.  */
+  scoped_mmap aux;
+  for (; pages > 0; pages >>= 1)
+    {
+      size_t length;
+      __u64 data_size;
+      data_size = (__u64) pages * page_size;
+
+      /* Don't ask for more than we can represent in the configuration.  */
+      if ((__u64) UINT_MAX < data_size)
+	continue;
+
+      length = (size_t) data_size;
+
+      /* Check for overflows.  */
+      if ((__u64) length != data_size)
+	continue;
+
+      header->aux_size = data_size;
+
+      errno = 0;
+      aux.reset (nullptr, length, PROT_READ, MAP_SHARED, fd.get (),
+		 header->aux_offset);
+      if (aux.get () != MAP_FAILED)
+	break;
+    }
+  if (pages == 0)
+    error (_("Failed to map trace buffer: %s."), safe_strerror (errno));
+
+  etm->etm.size = aux.size ();
+  etm->etm.mem = (const uint8_t *) aux.release ();
+  etm->etm.data_head = &header->aux_head;
+  etm->etm.last_head = header->aux_tail;
+  etm->header = (struct perf_event_mmap_page *) data.release ();
+  gdb_assert (etm->header == header);
+  etm->file = fd.release ();
+
+  tinfo->conf.etm.size = (unsigned int) etm->etm.size;
+  return tinfo.release ();
+}
+
 /* See linux-btrace.h.  */
 
 struct btrace_target_info *
@@ -707,6 +916,10 @@ linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 
     case BTRACE_FORMAT_PT:
       return linux_enable_pt (ptid, &conf->pt);
+
+    case BTRACE_FORMAT_ETM:
+      return linux_enable_etm (ptid, &conf->etm);
+
     }
 }
 
@@ -715,7 +928,8 @@ linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 static enum btrace_error
 linux_disable_bts (struct btrace_tinfo_bts *tinfo)
 {
-  munmap((void *) tinfo->header, tinfo->bts.size + PAGE_SIZE);
+  long page_size = sysconf(_SC_PAGESIZE);
+  munmap((void *) tinfo->header, tinfo->bts.size + page_size);
   close (tinfo->file);
 
   return BTRACE_ERR_NONE;
@@ -726,8 +940,22 @@ linux_disable_bts (struct btrace_tinfo_bts *tinfo)
 static enum btrace_error
 linux_disable_pt (struct btrace_tinfo_pt *tinfo)
 {
+  long page_size = sysconf(_SC_PAGESIZE);
   munmap((void *) tinfo->pt.mem, tinfo->pt.size);
-  munmap((void *) tinfo->header, PAGE_SIZE);
+  munmap((void *) tinfo->header, page_size);
+  close (tinfo->file);
+
+  return BTRACE_ERR_NONE;
+}
+
+/* Disable arm CoreSight ETM tracing.  */
+
+static enum btrace_error
+linux_disable_etm (struct btrace_tinfo_etm *tinfo)
+{
+  long page_size = sysconf(_SC_PAGESIZE);
+  munmap((void *) tinfo->etm.mem, tinfo->etm.size);
+  munmap((void *) tinfo->header, page_size);
   close (tinfo->file);
 
   return BTRACE_ERR_NONE;
@@ -753,6 +981,10 @@ linux_disable_btrace (struct btrace_target_info *tinfo)
     case BTRACE_FORMAT_PT:
       errcode = linux_disable_pt (&tinfo->variant.pt);
       break;
+
+    case BTRACE_FORMAT_ETM:
+      errcode = linux_disable_etm (&tinfo->variant.etm);
+      break;
     }
 
   if (errcode == BTRACE_ERR_NONE)
@@ -898,6 +1130,192 @@ linux_read_pt (struct btrace_data_pt *btrace,
   internal_error (__FILE__, __LINE__, _("Unknown btrace read type."));
 }
 
+/* return the number of CPUs that are present  */
+
+static int 
+get_cpu_count(void)
+{
+  static const char filename[] = "/sys/devices/system/cpu/present";
+  int length;
+  char * buffer;
+  int cpu_count;
+
+  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+  if (file.get () == nullptr)
+    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
+
+  fseek (file.get (), 0, SEEK_END);
+  length = ftell (file.get ());
+  fseek (file.get (), 0, SEEK_SET);
+  buffer = (char*) xmalloc (length+1);
+
+  length = fread (buffer, 1, length, file.get());
+  buffer[length]='\0';
+  while (--length) 
+    {
+      if ((buffer[length] == ',') || (buffer[length] == '-')) 
+        {
+	  length++;
+	  break;
+        }
+    }
+  if (sscanf(&buffer[length], "%d", &cpu_count) < 1)
+    error (_("Failed to get cpu count in %s: %s."), 
+	     buffer, safe_strerror (errno));
+
+  cpu_count ++;
+  return (cpu_count);
+}
+
+/* check if the etm is an etmv4  */
+
+static bool 
+cs_etm_is_etmv4( int cpu)
+{
+  char filename[PATH_MAX];
+  sprintf(filename, 
+	  "/sys/bus/event_source/devices/cs_etm/cpu%d/trcidr/trcidr0",
+	  cpu);
+  errno = 0;
+  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+  if (file.get () == nullptr)
+    return false;
+
+  return true;
+}
+
+/* get etm configuration register from sys filesystem  */
+
+static uint32_t 
+cs_etm_get_register(int cpu, const char *path)
+{
+  char filename[PATH_MAX];
+  uint32_t val = 0;
+
+  /* Get coresight register from sysfs  */
+  sprintf(filename,
+	  "/sys/bus/event_source/devices/cs_etm/cpu%d/%s",
+	  cpu, path );
+  errno = 0;
+  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
+  if (file.get () == nullptr)
+    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
+
+  int  found = fscanf (file.get (), "0x%x", &val);
+  if (found != 1)
+    error (_("Failed to read coresight register from %s."), filename);
+  return val;
+}
+
+#define CORESIGHT_ETM_PMU_SEED  0x10
+
+/* calculate trace_id for this cpu
+to be kept aligned with coresight-pmu.h  */
+
+static inline int 
+coresight_get_trace_id(int cpu)
+{
+  return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
+}
+
+
+/* PTMs ETMIDR [11:8] set to b0011  */
+#define ETMIDR_PTM_VERSION 0x00000300
+
+/* collect and fill etm trace parameter  */
+
+static void 
+fill_etm_trace_params (struct cs_etm_trace_params *etm_trace_params, int cpu)
+{
+  if (cs_etm_is_etmv4 (cpu) == true)
+    {
+      etm_trace_params->arch_ver = ARCHITECTURE_V8;
+      etm_trace_params->core_profile = PROFILE_CORTEX_A;
+      etm_trace_params->protocol = CS_ETM_PROTO_ETMV4i;
+      /* this is the parameter passed in etm->attr.config in the call to 
+         perf_event_open remapped according to linux/coresight-pmu.h  */
+      etm_trace_params->etmv4.reg_configr = 0;
+      etm_trace_params->etmv4.reg_idr0 = 
+	cs_etm_get_register(cpu, "trcidr/trcidr0");
+      etm_trace_params->etmv4.reg_idr1 = 
+	cs_etm_get_register(cpu, "trcidr/trcidr1");
+      etm_trace_params->etmv4.reg_idr2 = 
+	cs_etm_get_register(cpu, "trcidr/trcidr2");
+      etm_trace_params->etmv4.reg_idr8 = 
+	cs_etm_get_register(cpu, "trcidr/trcidr8");
+      etm_trace_params->etmv4.reg_traceidr = coresight_get_trace_id(cpu);
+    }
+  else
+    {
+      etm_trace_params->arch_ver = ARCHITECTURE_V7;
+      etm_trace_params->core_profile = PROFILE_CORTEX_A;
+      etm_trace_params->protocol = 
+	(etm_trace_params->etmv3.reg_idr & ETMIDR_PTM_VERSION) == ETMIDR_PTM_VERSION?
+	CS_ETM_PROTO_PTM:CS_ETM_PROTO_ETMV3;
+      etm_trace_params->etmv3.reg_ccer = 
+	cs_etm_get_register(cpu, "mgmt/etmccer");
+      etm_trace_params->etmv3.reg_ctrl = 
+	cs_etm_get_register(cpu, "mgmt/etmcr");
+      etm_trace_params->etmv3.reg_idr = 
+	cs_etm_get_register(cpu, "mgmt/etmidr");
+      etm_trace_params->etmv3.reg_trc_id = 
+	cs_etm_get_register(cpu, "traceid");
+    }
+}
+
+static void
+linux_fill_btrace_etm_config (struct btrace_target_info *tinfo,
+			       struct btrace_data_etm_config *conf)
+{
+
+  cs_etm_trace_params etm_trace_params;
+  conf->num_cpu = get_cpu_count();
+  conf->etm_trace_params=new std::vector<cs_etm_trace_params>;
+  for (int i = 0; i<conf->num_cpu; i++)
+    {
+      fill_etm_trace_params (&etm_trace_params,i);
+      conf->etm_trace_params->push_back(etm_trace_params);
+    }
+
+  conf->etm_decoder_params.formatted = 1;
+  conf->etm_decoder_params.fsyncs = 0;
+  conf->etm_decoder_params.hsyncs = 1;
+  conf->etm_decoder_params.frame_aligned = 0;
+  conf->etm_decoder_params.reset_on_4x_sync = 1;
+}
+
+static enum btrace_error
+linux_read_etm (struct btrace_data_etm *btrace,
+                struct btrace_target_info *tinfo,
+                enum btrace_read_type type)
+{
+  struct perf_event_buffer *etm;
+  etm = &tinfo->variant.etm.etm;
+
+  linux_fill_btrace_etm_config (tinfo, &btrace->config);
+
+  switch (type)
+    {
+    case BTRACE_READ_DELTA:
+      /* We don't support delta reads.  The data head (i.e. aux_head) wraps
+	 around to stay inside the aux buffer.  */
+      return BTRACE_ERR_NOT_SUPPORTED;
+
+    case BTRACE_READ_NEW:
+      if (!perf_event_new_data (etm))
+	return BTRACE_ERR_NONE;
+
+      /* Fall through.  */
+    case BTRACE_READ_ALL:
+      etm->last_head=0;
+      perf_event_read_available (etm, &(btrace->data),&(btrace->size));
+      return BTRACE_ERR_NONE;
+    }
+
+  internal_error (__FILE__, __LINE__, _("Unkown btrace read type."));
+}
+
+
 /* See linux-btrace.h.  */
 
 enum btrace_error
@@ -924,6 +1342,14 @@ linux_read_btrace (struct btrace_data *btrace,
       btrace->variant.pt.size = 0;
 
       return linux_read_pt (&btrace->variant.pt, tinfo, type);
+
+    case BTRACE_FORMAT_ETM:
+      /* We read btrace in arm CoreSight ETM Trace format.  */
+      btrace->format = BTRACE_FORMAT_ETM;
+      btrace->variant.etm.data = NULL;
+      btrace->variant.etm.size = 0;
+
+      return linux_read_etm (&btrace->variant.etm, tinfo, type);
     }
 
   internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
index 607182da144..60b8b29b7f6 100644
--- a/gdb/nat/linux-btrace.h
+++ b/gdb/nat/linux-btrace.h
@@ -78,6 +78,22 @@ struct btrace_tinfo_pt
   /* The trace perf event buffer.  */
   struct perf_event_buffer pt;
 };
+
+/* Branch trace target information for arm CoreSight ETM Trace. */
+struct btrace_tinfo_etm
+{
+  /* The Linux perf_event configuration for collecting the branch trace.  */
+  struct perf_event_attr attr;
+
+  /* The perf event file.  */
+  int file;
+
+  /* The perf event configuration page. */
+  volatile struct perf_event_mmap_page *header;
+
+  /* The trace perf event buffer.  */
+  struct perf_event_buffer etm;
+};
 #endif /* HAVE_LINUX_PERF_EVENT_H */
 
 /* Branch trace target information per thread.  */
@@ -98,6 +114,9 @@ struct btrace_target_info
 
     /* CONF.FORMAT == BTRACE_FORMAT_PT.  */
     struct btrace_tinfo_pt pt;
+
+    /* CONF.FORMAT == BTRACE_FORMAT_ETM.  */
+    struct btrace_tinfo_etm etm;
   } variant;
 #endif /* HAVE_LINUX_PERF_EVENT_H */
 };
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
                   ` (3 preceding siblings ...)
  2021-02-26  2:45 ` [PATCH 4/8] start/stop btrace with coresight etm and collect etm buffer on linux os Zied Guermazi
@ 2021-02-26  2:45 ` Zied Guermazi
  2021-02-26  7:12   ` Aktemur, Tankut Baris
  2021-02-26  2:46 ` [PATCH 6/8] add support for coresight btrace via remote protocol Zied Guermazi
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi

This patch fixes an issue observed with btrace when replaying the execution.
The issue was observed on ARMv7 processors.
To reproduce the issue needs to replay in forward direction 
until he reaches the end of history, then replay backwards 
(e.g a reverse-next) and then replay forwards. gdb hangs and the user
can not issue new commands.

gdb/ChangeLog

	* infrun.c (set_step_over_info): add debug print.
	(handle_inferior_event): clear step over info 
	in case TARGET_WAITKIND_NO_HISTORY

---
 gdb/ChangeLog | 6 ++++++
 gdb/infrun.c  | 3 ++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a84671bf344..15dee4eb29b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* infrun.c (set_step_over_info): add debug print.
+	* infrun.c (handle_inferior_event): clear step over info.
+	in case TARGET_WAITKIND_NO_HISTORY
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* nat/linux-btrace.h (btrace_tinfo_etm): New.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index a271220b261..a483307d7a3 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1308,6 +1308,7 @@ set_step_over_info (const address_space *aspace, CORE_ADDR address,
 		    int nonsteppable_watchpoint_p,
 		    int thread)
 {
+  infrun_debug_printf ("infrun: set_step_over_info\n");
   step_over_info.aspace = aspace;
   step_over_info.address = address;
   step_over_info.nonsteppable_watchpoint_p = nonsteppable_watchpoint_p;
@@ -5536,7 +5537,7 @@ handle_inferior_event (struct execution_control_state *ecs)
       delete_just_stopped_threads_single_step_breakpoints ();
       ecs->event_thread->suspend.stop_pc
 	= regcache_read_pc (get_thread_regcache (inferior_thread ()));
-
+      clear_step_over_info ();
       if (handle_stop_requested (ecs))
 	return;
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 6/8] add support for coresight btrace via remote protocol
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
                   ` (4 preceding siblings ...)
  2021-02-26  2:45 ` [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY Zied Guermazi
@ 2021-02-26  2:46 ` Zied Guermazi
  2021-02-26  2:46 ` [PATCH 7/8] adapt btrace testcases for arm target Zied Guermazi
  2021-02-26  2:46 ` [PATCH 8/8] document btrace support for arm targets using coresight etm traces Zied Guermazi
  7 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi


This patch extends the remote protocol to use ARM CoreSight traces for btrace.
This patch adds the capabilities enumeration as well as the required protocol
extentions for configuring traces collection, starting and stopping tracing,
and transferring the traces as well as the parameters needed for decoding them.

gdb/ChangeLog

	* btrace.c (check_xml_btrace_version): add version 1.1
	* btrace.c (parse_xml_btrace_etm_config_source_config_cpu_etmv4_config):
	New.
	* btrace.c (parse_xml_btrace_etm_config_source_config_cpu_etmv3_config):
	New.
	* btrace.c (parse_xml_btrace_etm_config_source_config_cpu_etm_config):
	New.
	* btrace.c (parse_xml_btrace_etm_config_source_config): New.
	* btrace.c (dump_config): New.
	* btrace.c (parse_xml_btrace_etm_config_source_config_end): New.
	* btrace.c (parse_xml_btrace_etm_config_sink_config): New.
	* btrace.c (parse_xml_btrace_etm_raw): New.
	* btrace.c (parse_xml_btrace_etm): New.
	* btrace.c (parse_xml_btrace_conf_etm): New.
	* btrace.dtd: add etm data and decoding parameters.
	* btrace-conf.dtd: add etm configuration.
	* remote.c (remote_target::btrace_sync_conf): add etm configuration.
	* remote.c(remote_target::enable_btrace): add coresight etm.
	* remote.c (_initialize_remote): add etm related packets.

gdbserver/ChangeLog

	* configure.srv: add btrace for aarch64*-*-linux* and arm*-*-linux*.
	* linux-low.c (linux_low_encode_etm_config): New.
	* linux-low.c (linux_process_target::read_btrace): encode CoreSight
	traces and relative decoding parameters.
	* linux-low.c (linux_process_target::read_btrace_conf): encode
	CoreSight configuration.
	* server.cc (handle_btrace_enable_etm): New.
	* server.cc (handle_btrace_general_set): add etm handling.
	* server.cc (handle_btrace_conf_general_set): add etm handling.
	* server.cc (supported_btrace_packets): add etm related packets.

---
 gdb/ChangeLog                |  22 +++
 gdb/btrace.c                 | 360 ++++++++++++++++++++++++++++++++++-
 gdb/features/btrace-conf.dtd |  10 +-
 gdb/features/btrace.dtd      |  39 +++-
 gdb/remote.c                 |  66 ++++++-
 gdbserver/ChangeLog          |  13 ++
 gdbserver/configure.srv      |   4 +
 gdbserver/linux-low.cc       | 103 +++++++++-
 gdbserver/server.cc          |  34 +++-
 9 files changed, 639 insertions(+), 12 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 15dee4eb29b..30f45a62cd5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,25 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* btrace.c (check_xml_btrace_version): add version 1.1
+	* btrace.c (parse_xml_btrace_etm_config_source_config_cpu_etmv4_config):
+	New.
+	* btrace.c (parse_xml_btrace_etm_config_source_config_cpu_etmv3_config):
+	New.
+	* btrace.c (parse_xml_btrace_etm_config_source_config_cpu_etm_config):
+	New.
+	* btrace.c (parse_xml_btrace_etm_config_source_config): New.
+	* btrace.c (dump_config): New.
+	* btrace.c (parse_xml_btrace_etm_config_source_config_end): New.
+	* btrace.c (parse_xml_btrace_etm_config_sink_config): New.
+	* btrace.c (parse_xml_btrace_etm_raw): New.
+	* btrace.c (parse_xml_btrace_etm): New.
+	* btrace.c (parse_xml_btrace_conf_etm): New.
+	* btrace.dtd: add etm data and decoding parameters.
+	* btrace-conf.dtd: add etm configuration.
+	* remote.c (remote_target::btrace_sync_conf): add etm configuration.
+	* remote.c(remote_target::enable_btrace): add coresight etm.
+	* remote.c (_initialize_remote): add etm related packets.
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* infrun.c (set_step_over_info): add debug print.
diff --git a/gdb/btrace.c b/gdb/btrace.c
index dcb89964b81..ded539e94f6 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -2597,7 +2597,7 @@ check_xml_btrace_version (struct gdb_xml_parser *parser,
   const char *version
   = (const char *) xml_find_attribute (attributes, "version")->value.get ();
 
-  if (strcmp (version, "1.0") != 0)
+  if ((strcmp (version, "1.0") != 0) && (strcmp (version, "1.1") != 0))
     gdb_xml_error (parser, _("Unsupported btrace version: \"%s\""), version);
 }
 
@@ -2732,6 +2732,238 @@ parse_xml_btrace_pt (struct gdb_xml_parser *parser,
   btrace->variant.pt.size = 0;
 }
 
+/* Parse a btrace etm "cpu-etm-config-etmv4_config" xml record.  */
+
+static void
+parse_xml_btrace_etm_config_source_config_cpu_etmv4_config (
+                                struct gdb_xml_parser *parser,
+                                const struct gdb_xml_element *element,
+                                void *user_data,
+                                std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_data *btrace;
+  struct gdb_xml_value *reg_idr0;
+  struct gdb_xml_value *reg_idr1;
+  struct gdb_xml_value *reg_idr2;
+  struct gdb_xml_value *reg_idr8;
+  struct gdb_xml_value *reg_configr;
+  struct gdb_xml_value *reg_traceidr;
+  cs_etm_trace_params *etm_trace_params;
+
+  DEBUG ("parse_xml_btrace_etm_config_source_config_cpu_etmv4_config");
+
+  btrace = (struct btrace_data *) user_data;
+  etm_trace_params = & (btrace->variant.etm.config.etm_trace_params->back());
+
+  reg_idr0
+    = xml_find_attribute (attributes, "reg_idr0");
+  reg_idr1
+    = xml_find_attribute (attributes, "reg_idr1");
+  reg_idr2
+    = xml_find_attribute (attributes, "reg_idr2");
+  reg_idr8
+    = xml_find_attribute (attributes, "reg_idr8");
+  reg_configr
+    = xml_find_attribute (attributes, "reg_configr");
+  reg_traceidr
+    = xml_find_attribute (attributes, "reg_traceidr");
+
+  etm_trace_params->etmv4.reg_idr0
+    = (unsigned int) *(ULONGEST *)reg_idr0->value.get ();
+  etm_trace_params->etmv4.reg_idr1
+    = (unsigned int) *(ULONGEST *)reg_idr1->value.get ();
+  etm_trace_params->etmv4.reg_idr2
+    = (unsigned int) *(ULONGEST *)reg_idr2->value.get ();
+  etm_trace_params->etmv4.reg_idr8
+    = (unsigned int) *(ULONGEST *)reg_idr8->value.get ();
+  etm_trace_params->etmv4.reg_configr
+    = (unsigned int) *(ULONGEST *)reg_configr->value.get ();
+  etm_trace_params->etmv4.reg_traceidr
+    = (unsigned int) *(ULONGEST *)reg_traceidr->value.get ();
+
+}
+
+/* Parse a btrace etm "cpu-etm-config-etmv3_config" xml record.  */
+
+static void
+parse_xml_btrace_etm_config_source_config_cpu_etmv3_config (
+                                struct gdb_xml_parser *parser,
+                                const struct gdb_xml_element *element,
+                                void *user_data,
+                                std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_data *btrace;
+  struct gdb_xml_value *reg_ctrl;
+  struct gdb_xml_value *reg_trc_id;
+  struct gdb_xml_value *reg_ccer;
+  struct gdb_xml_value *reg_idr;
+
+  cs_etm_trace_params *etm_trace_params;
+
+  DEBUG ("parse_xml_btrace_etm_config_source_config_cpu_etmv3_config");
+
+  btrace = (struct btrace_data *) user_data;
+  etm_trace_params = & (btrace->variant.etm.config.etm_trace_params->back());
+
+  reg_ctrl
+    = xml_find_attribute (attributes, "reg_ctrl");
+  reg_trc_id
+    = xml_find_attribute (attributes, "reg_trc_id");
+  reg_ccer
+    = xml_find_attribute (attributes, "reg_ccer");
+  reg_idr
+    = xml_find_attribute (attributes, "reg_idr");
+
+  etm_trace_params->etmv3.reg_ctrl 
+    = (unsigned int) *(ULONGEST *) reg_ctrl->value.get ();
+  etm_trace_params->etmv3.reg_trc_id
+    = (unsigned int) *(ULONGEST *)reg_trc_id->value.get ();
+  etm_trace_params->etmv3.reg_ccer
+    = (unsigned int) *(ULONGEST *)reg_ccer->value.get ();
+  etm_trace_params->etmv3.reg_idr
+    = (unsigned int) *(ULONGEST *)reg_idr->value.get ();
+}
+
+
+/* Parse a btrace etm "cpu-etm-config" xml record.  */
+
+static void
+parse_xml_btrace_etm_config_source_config_cpu_etm_config (struct gdb_xml_parser *parser,
+                                const struct gdb_xml_element *element,
+                                void *user_data,
+                                std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_data *btrace;
+  struct gdb_xml_value *arch_ver;
+  struct gdb_xml_value *core_prof;
+  struct gdb_xml_value *protocol;
+  cs_etm_trace_params etm_trace_params;
+
+  DEBUG ("parse_xml_btrace_etm_config_source_config_cpu_etm_config");
+
+  btrace = (struct btrace_data *) user_data;
+
+  arch_ver
+    = xml_find_attribute (attributes, "arch_ver");
+  core_prof
+    = xml_find_attribute (attributes, "core_prof");
+  protocol
+    = xml_find_attribute (attributes, "protocol");
+
+  etm_trace_params.arch_ver=(int) *(ULONGEST *) arch_ver->value.get ();
+  etm_trace_params.core_profile=(int) *(ULONGEST *)core_prof->value.get ();
+  etm_trace_params.protocol=(int) *(ULONGEST *)protocol->value.get ();
+
+  btrace->variant.etm.config.etm_trace_params->push_back(etm_trace_params);
+}
+
+/* Parse a btrace etm "source-config" xml record.  */
+
+static void
+parse_xml_btrace_etm_config_source_config (struct gdb_xml_parser *parser,
+                                const struct gdb_xml_element *element,
+                                void *user_data,
+                                std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_data *btrace;
+  struct gdb_xml_value *trace_id;
+
+  DEBUG ("parse_xml_btrace_etm_config_source_config");
+  btrace = (struct btrace_data *) user_data;
+
+  trace_id = xml_find_attribute (attributes, "trace_id");
+  if (trace_id != NULL)
+    btrace->variant.etm.trace_id 
+      = (unsigned int) *(ULONGEST *) trace_id->value.get ();
+  btrace->variant.etm.config.etm_trace_params 
+    = new std::vector<cs_etm_trace_params>;
+}
+
+/* get the number of cpus  */
+static void
+parse_xml_btrace_etm_config_source_config_end(struct gdb_xml_parser *,
+      const struct gdb_xml_element *,
+      void *user_data, const char *body_text)
+{
+  struct btrace_data *btrace;
+
+  DEBUG ("parse_xml_btrace_etm_config_source_config_end");
+  btrace = (struct btrace_data *) user_data;
+
+  btrace->variant.etm.config.num_cpu
+    = btrace->variant.etm.config.etm_trace_params->size();
+}
+
+/* Parse a btrace etm "sink-config" xml record.  */
+
+static void
+parse_xml_btrace_etm_config_sink_config (struct gdb_xml_parser *parser,
+                                const struct gdb_xml_element *element,
+                                void *user_data,
+                                std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_data *btrace;
+  //const char *sink_id;
+  DEBUG ("parse_xml_btrace_etm_config_sink_config");
+  ULONGEST *formatted, *fsyncs, *hsyncs, *frame_aligned, *reset_on_4x_sync;
+  /*sink_id =
+      (const char *) xml_find_attribute (attributes, "sink_id")->value.get ();*/
+  formatted
+  = (ULONGEST *) xml_find_attribute (attributes, "formatted")->value.get ();
+  fsyncs
+  = (ULONGEST *) xml_find_attribute (attributes, "fsyncs")->value.get ();
+  hsyncs
+  = (ULONGEST *) xml_find_attribute (attributes, "hsyncs")->value.get ();
+  frame_aligned
+  = (ULONGEST *) xml_find_attribute (attributes, "frame_aligned")->value.get ();
+  reset_on_4x_sync
+  = (ULONGEST *) xml_find_attribute (attributes, "reset_on_4x_sync")->value.get ();
+
+  btrace = (struct btrace_data *) user_data;
+
+  btrace->variant.etm.config.etm_decoder_params.formatted
+    = *formatted;
+  btrace->variant.etm.config.etm_decoder_params.fsyncs
+    = *fsyncs;
+  btrace->variant.etm.config.etm_decoder_params.hsyncs
+    = *hsyncs;
+  btrace->variant.etm.config.etm_decoder_params.frame_aligned
+    = *frame_aligned;
+  btrace->variant.etm.config.etm_decoder_params.reset_on_4x_sync
+    = *reset_on_4x_sync;
+}
+
+
+/* Parse a btrace etm "raw" xml record.  */
+
+static void
+parse_xml_btrace_etm_raw (struct gdb_xml_parser *parser,
+                         const struct gdb_xml_element *element,
+                         void *user_data, const char *body_text)
+{
+  struct btrace_data *btrace;
+  DEBUG ("parse_xml_btrace_etm_raw");
+  btrace = (struct btrace_data *) user_data;
+  parse_xml_raw (parser, body_text, &btrace->variant.etm.data,
+                 &btrace->variant.etm.size);
+}
+
+/* Parse a btrace "etm" xml record.  */
+
+static void
+parse_xml_btrace_etm (struct gdb_xml_parser *parser,
+                     const struct gdb_xml_element *element,
+                     void *user_data,
+                     std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_data *btrace;
+  DEBUG ("parse_xml_btrace_etm");
+  btrace = (struct btrace_data *) user_data;
+  btrace->format = BTRACE_FORMAT_ETM;
+  btrace->variant.etm.data = NULL;
+  btrace->variant.etm.size = 0;
+}
+
 static const struct gdb_xml_attribute block_attributes[] = {
     { "begin", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
     { "end", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
@@ -2759,6 +2991,92 @@ static const struct gdb_xml_element btrace_pt_children[] = {
         { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
 };
 
+static const struct gdb_xml_attribute 
+  btrace_etm_config_source_config_cpu_config_etmv3_config_attributes[] = {
+    { "reg_ctrl", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_trc_id", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_ccer", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_idr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute 
+  btrace_etm_config_source_config_cpu_config_etmv4_config_attributes[] = {
+    { "reg_idr0", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_idr1", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_idr2", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_idr8", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_configr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reg_traceidr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element
+  btrace_etm_config_source_config_cpu_etm_config_children[] = {
+    { "etmv3-config",
+        btrace_etm_config_source_config_cpu_config_etmv3_config_attributes, 
+        NULL, GDB_XML_EF_OPTIONAL,
+        parse_xml_btrace_etm_config_source_config_cpu_etmv3_config, NULL },
+    { "etmv4-config",
+        btrace_etm_config_source_config_cpu_config_etmv4_config_attributes,
+        NULL, GDB_XML_EF_OPTIONAL,
+        parse_xml_btrace_etm_config_source_config_cpu_etmv4_config, NULL },
+    { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute
+  btrace_etm_config_source_config_etm_config_attributes[] = {
+    { "cpu_id", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "arch_ver", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "core_prof", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "protocol", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element
+  btrace_etm_config_source_config_children[] = {
+    { "cpu-etm-config", btrace_etm_config_source_config_etm_config_attributes,
+        btrace_etm_config_source_config_cpu_etm_config_children,
+        GDB_XML_EF_REPEATABLE,
+        parse_xml_btrace_etm_config_source_config_cpu_etm_config, NULL },
+    { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute
+  btrace_etm_config_sink_config_attributes[] = {
+    { "sink_id", GDB_XML_AF_OPTIONAL, NULL, NULL },
+    { "formatted", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "fsyncs", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "hsyncs", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "frame_aligned", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { "reset_on_4x_sync", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+    { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute
+  btrace_etm_config_source_config_attributes[] = {
+    { "trace_id", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+    { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element btrace_etm_config_children[] = {
+    { "source-config", btrace_etm_config_source_config_attributes,
+        btrace_etm_config_source_config_children, GDB_XML_EF_NONE,
+        parse_xml_btrace_etm_config_source_config,
+        parse_xml_btrace_etm_config_source_config_end },
+    { "sink-config", btrace_etm_config_sink_config_attributes, NULL,
+        GDB_XML_EF_NONE, parse_xml_btrace_etm_config_sink_config, NULL },
+    { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element btrace_etm_children[] = {
+    { "etm-config", NULL, btrace_etm_config_children, GDB_XML_EF_NONE, NULL,
+        NULL },
+    { "raw", NULL, NULL, GDB_XML_EF_OPTIONAL, NULL,
+        parse_xml_btrace_etm_raw },
+    { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
 static const struct gdb_xml_attribute btrace_attributes[] = {
     { "version", GDB_XML_AF_NONE, NULL, NULL },
     { NULL, GDB_XML_AF_NONE, NULL, NULL }
@@ -2767,8 +3085,10 @@ static const struct gdb_xml_attribute btrace_attributes[] = {
 static const struct gdb_xml_element btrace_children[] = {
     { "block", block_attributes, NULL,
         GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, parse_xml_btrace_block, NULL },
-        { "pt", NULL, btrace_pt_children, GDB_XML_EF_OPTIONAL, parse_xml_btrace_pt,
-            NULL },
+    { "pt", NULL, btrace_pt_children, GDB_XML_EF_OPTIONAL,
+        parse_xml_btrace_pt, NULL },
+    { "etm", NULL, btrace_etm_children, GDB_XML_EF_OPTIONAL,
+        parse_xml_btrace_etm, NULL },
     { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
 };
 
@@ -2849,6 +3169,32 @@ parse_xml_btrace_conf_pt (struct gdb_xml_parser *parser,
     conf->pt.size = (unsigned int) *(ULONGEST *) size->value.get ();
 }
 
+/* Parse a btrace-conf "etm" xml record.  */
+
+static void
+parse_xml_btrace_conf_etm (struct gdb_xml_parser *parser,
+                          const struct gdb_xml_element *element,
+                          void *user_data,
+                          std::vector<gdb_xml_value> &attributes)
+{
+  struct btrace_config *conf;
+  struct gdb_xml_value *size;
+  struct gdb_xml_value *sink;
+
+  DEBUG ("parse_xml_btrace_conf_etm");
+  conf = (struct btrace_config *) user_data;
+  conf->format = BTRACE_FORMAT_ETM;
+  conf->etm.size = 0;
+
+  size = xml_find_attribute (attributes, "size");
+  if (size != NULL)
+    conf->etm.size = (unsigned int) *(ULONGEST *) size->value.get ();
+
+  sink = xml_find_attribute (attributes, "sink");
+  if (sink != NULL)
+    conf->etm.sink = (char*) sink->value.get (); 
+}
+
 static const struct gdb_xml_attribute btrace_conf_pt_attributes[] = {
     { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
     { NULL, GDB_XML_AF_NONE, NULL, NULL }
@@ -2859,11 +3205,19 @@ static const struct gdb_xml_attribute btrace_conf_bts_attributes[] = {
     { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
+static const struct gdb_xml_attribute btrace_conf_etm_attributes[] = {
+    { "size", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+    { "sink", GDB_XML_AF_OPTIONAL, NULL, NULL },
+    { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
 static const struct gdb_xml_element btrace_conf_children[] = {
     { "bts", btrace_conf_bts_attributes, NULL, GDB_XML_EF_OPTIONAL,
         parse_xml_btrace_conf_bts, NULL },
     { "pt", btrace_conf_pt_attributes, NULL, GDB_XML_EF_OPTIONAL,
         parse_xml_btrace_conf_pt, NULL },
+    { "etm", btrace_conf_etm_attributes, NULL, GDB_XML_EF_OPTIONAL,
+        parse_xml_btrace_conf_etm, NULL },
     { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
 };
 
diff --git a/gdb/features/btrace-conf.dtd b/gdb/features/btrace-conf.dtd
index 4b060bb408c..7334d035f34 100644
--- a/gdb/features/btrace-conf.dtd
+++ b/gdb/features/btrace-conf.dtd
@@ -4,11 +4,17 @@
      are permitted in any medium without royalty provided the copyright
      notice and this notice are preserved.  -->
 
-<!ELEMENT btrace-conf	(bts?, pt?)>
-<!ATTLIST btrace-conf	version	CDATA	#FIXED "1.0">
+<!ELEMENT btrace-conf	(bts?, pt?, etm?)>
+<!ATTLIST btrace-conf	version	(1.0|1.1) #REQUIRED>
 
 <!ELEMENT bts	EMPTY>
 <!ATTLIST bts	size	CDATA	#IMPLIED>
 
 <!ELEMENT pt	EMPTY>
 <!ATTLIST pt	size	CDATA	#IMPLIED>
+
+<!ELEMENT etm	EMPTY>
+<!ATTLIST etm   size    CDATA   #IMPLIED
+                sink	CDATA   #IMPLIED
+                filter  CDATA   #IMPLIED
+                config  CDATA   #IMPLIED>
diff --git a/gdb/features/btrace.dtd b/gdb/features/btrace.dtd
index 9bb930d7d3b..5c2bb6755ad 100644
--- a/gdb/features/btrace.dtd
+++ b/gdb/features/btrace.dtd
@@ -4,8 +4,8 @@
      are permitted in any medium without royalty provided the copyright
      notice and this notice are preserved.  -->
 
-<!ELEMENT btrace  (block* | pt)>
-<!ATTLIST btrace  version CDATA   #FIXED "1.0">
+<!ELEMENT btrace  (block* | pt | etm)>
+<!ATTLIST btrace  version (1.0|1.1) #REQUIRED>
 
 <!ELEMENT block        EMPTY>
 <!ATTLIST block        begin  CDATA   #REQUIRED
@@ -21,4 +21,39 @@
               model    CDATA #REQUIRED
               stepping CDATA #REQUIRED>
 
+<!ELEMENT etm (etm-config?, raw?)>
+
+<!ELEMENT etm-config (source-config, sink-config)>
+
+<!ELEMENT source-config   (cpu-etm-config+)>
+<!ATTLIST source-config    trace_id         CDATA #IMPLIED>
+
+<!ELEMENT cpu-etm-config  (etmv3-config|etmv4-config)>
+<!ATTLIST cpu-etm-config   cpu_id           CDATA #REQUIRED
+                           arch_ver         CDATA #REQUIRED
+                           core_prof        CDATA #REQUIRED
+                           protocol         CDATA #REQUIRED>
+
+<!ELEMENT etmv3-config     EMPTY>
+<!ATTLIST etmv3-config     reg_ctrl         CDATA #REQUIRED
+                           reg_trc_id       CDATA #REQUIRED
+                           reg_ccer         CDATA #REQUIRED
+                           reg_idr          CDATA #REQUIRED>
+
+<!ELEMENT etmv4-config     EMPTY>
+<!ATTLIST etmv4-config     reg_idr0         CDATA #REQUIRED
+                           reg_idr1         CDATA #REQUIRED
+                           reg_idr2         CDATA #REQUIRED
+                           reg_idr8         CDATA #REQUIRED
+                           reg_configr      CDATA #REQUIRED
+                           reg_traceidr     CDATA #REQUIRED>
+
+<!ELEMENT sink-config      EMPTY>
+<!ATTLIST sink-config      sink_id           CDATA #IMPLIED
+                           formatted         CDATA #REQUIRED
+                           fsyncs            CDATA #REQUIRED
+                           hsyncs            CDATA #REQUIRED
+                           frame_aligned     CDATA #REQUIRED
+                           reset_on_4x_sync  CDATA #REQUIRED>
+
 <!ELEMENT raw (#PCDATA)>
diff --git a/gdb/remote.c b/gdb/remote.c
index 2c85bdcffbc..6e8b9bd8211 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -2167,6 +2167,15 @@ enum {
   /* Support TARGET_WAITKIND_NO_RESUMED.  */
   PACKET_no_resumed,
 
+  /* Support for the Qbtrace-etm packet.  */
+  PACKET_Qbtrace_etm,
+
+  /* Support for the Qbtrace-conf:etm:size packet.  */
+  PACKET_Qbtrace_conf_etm_size,
+
+  /* Support for the Qbtrace-conf:etm:sink packet.  */
+  PACKET_Qbtrace_conf_etm_sink,
+
   PACKET_MAX
 };
 
@@ -5302,6 +5311,12 @@ static const struct protocol_feature remote_protocol_features[] = {
   { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported },
   { "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents },
   { "no-resumed", PACKET_DISABLE, remote_supported_packet, PACKET_no_resumed },
+  { "Qbtrace:etm", PACKET_DISABLE, remote_supported_packet,
+    PACKET_Qbtrace_etm },
+  { "Qbtrace-conf:etm:size", PACKET_DISABLE, remote_supported_packet,
+    PACKET_Qbtrace_conf_etm_size },
+  { "Qbtrace-conf:etm:sink", PACKET_DISABLE, remote_supported_packet,
+    PACKET_Qbtrace_conf_etm_sink },
 };
 
 static char *remote_support_xml;
@@ -13882,6 +13897,28 @@ remote_target::btrace_sync_conf (const btrace_config *conf)
 
       rs->btrace_config.pt.size = conf->pt.size;
     }
+
+  packet = &remote_protocol_packets[PACKET_Qbtrace_conf_etm_size];
+  if (packet_config_support (packet) == PACKET_ENABLE
+      && conf->etm.size != rs->btrace_config.etm.size)
+    {
+      pos = buf;
+      pos += xsnprintf (pos, endbuf - pos, "%s=0x%x", packet->name,
+                        conf->etm.size);
+
+      putpkt (buf);
+      getpkt (&rs->buf, 0);
+
+      if (packet_ok (buf, packet) == PACKET_ERROR)
+        {
+          if (buf[0] == 'E' && buf[1] == '.')
+            error (_("Failed to configure the trace buffer size: %s"), buf + 2);
+          else
+            error (_("Failed to configure the trace buffer size."));
+        }
+
+      rs->btrace_config.etm.size = conf->etm.size;
+    }
 }
 
 /* Read the current thread's btrace configuration from the target and
@@ -13903,7 +13940,7 @@ remote_target::remote_btrace_maybe_reopen ()
 {
   struct remote_state *rs = get_remote_state ();
   int btrace_target_pushed = 0;
-#if !defined (HAVE_LIBIPT)
+#if !defined (HAVE_LIBIPT) || !defined (HAVE_LIBOPENCSD_C_API)
   int warned = 0;
 #endif
 
@@ -13938,6 +13975,20 @@ remote_target::remote_btrace_maybe_reopen ()
         }
 #endif /* !defined (HAVE_LIBIPT) */
 
+#if !defined (HAVE_LIBOPENCSD_C_API)
+      if (rs->btrace_config.format == BTRACE_FORMAT_ETM)
+        {
+          if (!warned)
+            {
+              warned = 1;
+              warning (_("Target is recording using ARM CoreSight Processor Trace "
+                         "but support was disabled at compile time."));
+            }
+
+          continue;
+        }
+#endif /* !defined (HAVE_LIBOPENCSD_C_API) */
+
       /* Push target, once, but before anything else happens.  This way our
 	 changes to the threads will be cleaned up by unpushing the target
 	 in case btrace_read_config () throws.  */
@@ -13975,6 +14026,10 @@ remote_target::enable_btrace (ptid_t ptid, const struct btrace_config *conf)
       case BTRACE_FORMAT_PT:
 	packet = &remote_protocol_packets[PACKET_Qbtrace_pt];
 	break;
+
+      case BTRACE_FORMAT_ETM:
+	packet = &remote_protocol_packets[PACKET_Qbtrace_etm];
+	break;
     }
 
   if (packet == NULL || packet_config_support (packet) != PACKET_ENABLE)
@@ -14883,6 +14938,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_no_resumed],
 			 "N stop reply", "no-resumed-stop-reply", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_etm],
+			 "Qbtrace:etm", "enable-btrace-etm", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_etm_size],
+			 "Qbtrace-conf:etm:size", "btrace-conf-etm-size", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_etm_sink],
+			 "Qbtrace-conf:etm:sink", "btrace-conf-etm-sink", 0);
+
   /* Assert that we've registered "set remote foo-packet" commands
      for all packet configs.  */
   {
diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog
index bafdc7685c3..2c80dfbe079 100644
--- a/gdbserver/ChangeLog
+++ b/gdbserver/ChangeLog
@@ -1,3 +1,16 @@
+2021-02-06  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* configure.srv: add btrace for aarch64*-*-linux* and arm*-*-linux*.
+	* linux-low.c (linux_low_encode_etm_config): New.
+	* linux-low.c (linux_process_target::read_btrace): encode CoreSight
+	traces and relative decoding parameters.
+	* linux-low.c (linux_process_target::read_btrace_conf): encode 
+	CoreSight configuration.
+	* server.cc (handle_btrace_enable_etm): New.
+	* server.cc (handle_btrace_general_set): add etm handling.
+	* server.cc (handle_btrace_conf_general_set): add etm handling.
+	* server.cc (supported_btrace_packets): add etm related packets.
+
 2021-02-01  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* gdbserver/configure: Regenerated.
diff --git a/gdbserver/configure.srv b/gdbserver/configure.srv
index 833ad27c4c4..5f900d80d66 100644
--- a/gdbserver/configure.srv
+++ b/gdbserver/configure.srv
@@ -54,12 +54,14 @@ case "${gdbserver_host}" in
 			srv_tgtobj="$srv_tgtobj arch/aarch64.o"
 			srv_tgtobj="$srv_tgtobj linux-aarch64-tdesc.o"
 			srv_tgtobj="$srv_tgtobj nat/aarch64-sve-linux-ptrace.o"
+			srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
 			srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			ipa_obj="linux-aarch64-ipa.o"
 			ipa_obj="${ipa_obj} linux-aarch64-tdesc-ipa.o"
 			ipa_obj="${ipa_obj} arch/aarch64-ipa.o"
+			srv_linux_btrace=yes
 			;;
   aarch64*-*-netbsd*)	srv_regobj=""
 			srv_tgtobj="netbsd-low.o netbsd-aarch64-low.o fork-child.o"
@@ -82,6 +84,7 @@ case "${gdbserver_host}" in
 			srv_tgtobj="$srv_tgtobj linux-arm-tdesc.o"
 			srv_tgtobj="$srv_tgtobj linux-aarch32-low.o"
 			srv_tgtobj="$srv_tgtobj linux-aarch32-tdesc.o"
+			srv_tgtobj="${srv_tgtobj} nat/linux-btrace.o"
 			srv_tgtobj="${srv_tgtobj} arch/aarch32.o"
 			srv_tgtobj="${srv_tgtobj} arch/arm.o"
 			srv_tgtobj="${srv_tgtobj} arch/arm-linux.o"
@@ -89,6 +92,7 @@ case "${gdbserver_host}" in
 			srv_linux_usrregs=yes
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
+			srv_linux_btrace=yes
 			;;
   i[34567]86-*-cygwin*)	srv_regobj=""
 			srv_tgtobj="x86-low.o nat/x86-dregs.o win32-low.o"
diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc
index 0baac013129..ac5db7e8c03 100644
--- a/gdbserver/linux-low.cc
+++ b/gdbserver/linux-low.cc
@@ -6994,6 +6994,75 @@ linux_low_encode_pt_config (struct buffer *buffer,
   buffer_grow_str (buffer, "</pt-config>\n");
 }
 
+/* Encode ARM CoreSight Processor Trace configuration.  */
+
+static void
+linux_low_encode_etm_config (struct buffer *buffer,
+			    const struct btrace_data_etm_config *config)
+{
+  int architecture;
+  buffer_grow_str (buffer, "<etm-config>\n");
+  buffer_grow_str (buffer, "<source-config>\n");
+  for (int i=0; i< config->num_cpu;i++)
+  {
+    if ((config->etm_trace_params->at(i).protocol == CS_ETM_PROTO_ETMV3)
+        ||(config->etm_trace_params->at(i).protocol == CS_ETM_PROTO_PTM))
+      {
+        architecture = ARCHITECTURE_V7;
+      }
+    else if (config->etm_trace_params->at(i).protocol == CS_ETM_PROTO_ETMV4i)
+      {
+         architecture = ARCHITECTURE_V8;
+      }
+    else
+      {
+        architecture = ARCHITECTURE_UNKNOWN;
+      }
+
+    buffer_xml_printf (buffer,"<cpu-etm-config arch_ver=\"0x%x\" "
+        "core_prof=\"0x%x\" cpu_id=\"0x%x\" protocol=\"0x%x\">\n",
+			  architecture, PROFILE_CORTEX_A,
+			  i, config->etm_trace_params->at(i).protocol);
+    if (architecture == ARCHITECTURE_V7)
+    {
+
+      buffer_xml_printf (buffer, 
+        "<etmv3-config reg_idr=\"0x%x\" reg_ctrl=\"0x%x\" "
+        "reg_ccer=\"0x%x\" reg_trc_id=\"0x%x\"/>\n",
+			  config->etm_trace_params->at(i).etmv3.reg_idr,
+			  config->etm_trace_params->at(i).etmv3.reg_ctrl,
+			  config->etm_trace_params->at(i).etmv3.reg_ccer,
+			  config->etm_trace_params->at(i).etmv3.reg_trc_id);
+    }
+    if (architecture == ARCHITECTURE_V8)
+    {
+      buffer_xml_printf (buffer, 
+        "<etmv4-config reg_idr0=\"0x%x\" reg_idr1=\"0x%x\" "
+        "reg_idr2=\"0x%x\" reg_idr8=\"0x%x\" "
+			  "reg_configr=\"0x%x\" reg_traceidr=\"0x%x\"/>\n",
+			  config->etm_trace_params->at(i).etmv4.reg_idr0,
+			  config->etm_trace_params->at(i).etmv4.reg_idr1,
+			  config->etm_trace_params->at(i).etmv4.reg_idr2,
+			  config->etm_trace_params->at(i).etmv4.reg_idr8,
+			  config->etm_trace_params->at(i).etmv4.reg_configr,
+			  config->etm_trace_params->at(i).etmv4.reg_traceidr);
+    }
+    buffer_xml_printf (buffer,"</cpu-etm-config>\n");
+
+  }
+  buffer_grow_str (buffer,"</source-config>\n");
+  buffer_xml_printf (buffer, 
+    "<sink-config  formatted=\"0x%x\" "
+		"fsyncs=\"0x%x\" hsyncs=\"0x%x\" "
+		"frame_aligned=\"0x%x\" reset_on_4x_sync=\"0x%x\"/>\n",
+		config->etm_decoder_params.formatted,
+		config->etm_decoder_params.fsyncs,
+		config->etm_decoder_params.hsyncs,
+		config->etm_decoder_params.frame_aligned,
+		config->etm_decoder_params.reset_on_4x_sync);
+  buffer_grow_str (buffer,"</etm-config>\n");
+}
+
 /* Encode a raw buffer.  */
 
 static void
@@ -7048,7 +7117,7 @@ linux_process_target::read_btrace (btrace_target_info *tinfo,
 
     case BTRACE_FORMAT_BTS:
       buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
-      buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+      buffer_grow_str (buffer, "<btrace version=\"1.1\">\n");
 
       for (const btrace_block &block : *btrace.variant.bts.blocks)
 	buffer_xml_printf (buffer, "<block begin=\"0x%s\" end=\"0x%s\"/>\n",
@@ -7059,7 +7128,7 @@ linux_process_target::read_btrace (btrace_target_info *tinfo,
 
     case BTRACE_FORMAT_PT:
       buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
-      buffer_grow_str (buffer, "<btrace version=\"1.0\">\n");
+      buffer_grow_str (buffer, "<btrace version=\"1.1\">\n");
       buffer_grow_str (buffer, "<pt>\n");
 
       linux_low_encode_pt_config (buffer, &btrace.variant.pt.config);
@@ -7071,6 +7140,20 @@ linux_process_target::read_btrace (btrace_target_info *tinfo,
       buffer_grow_str0 (buffer, "</btrace>\n");
       break;
 
+    case BTRACE_FORMAT_ETM:
+      buffer_grow_str (buffer, "<!DOCTYPE btrace SYSTEM \"btrace.dtd\">\n");
+      buffer_grow_str (buffer, "<btrace version=\"1.1\">\n");
+      buffer_grow_str (buffer, "<etm>\n");
+
+      linux_low_encode_etm_config (buffer, &btrace.variant.etm.config);
+
+      linux_low_encode_raw (buffer, btrace.variant.etm.data,
+			    btrace.variant.etm.size);
+
+      buffer_grow_str (buffer, "</etm>\n");
+      buffer_grow_str0 (buffer, "</btrace>\n");
+      break;
+
     default:
       buffer_grow_str0 (buffer, "E.Unsupported Trace Format.");
       return -1;
@@ -7088,7 +7171,7 @@ linux_process_target::read_btrace_conf (const btrace_target_info *tinfo,
   const struct btrace_config *conf;
 
   buffer_grow_str (buffer, "<!DOCTYPE btrace-conf SYSTEM \"btrace-conf.dtd\">\n");
-  buffer_grow_str (buffer, "<btrace-conf version=\"1.0\">\n");
+  buffer_grow_str (buffer, "<btrace-conf version=\"1.1\">\n");
 
   conf = linux_btrace_conf (tinfo);
   if (conf != NULL)
@@ -7109,6 +7192,20 @@ linux_process_target::read_btrace_conf (const btrace_target_info *tinfo,
 	  buffer_xml_printf (buffer, " size=\"0x%x\"", conf->pt.size);
 	  buffer_xml_printf (buffer, "/>\n");
 	  break;
+
+	case BTRACE_FORMAT_ETM:
+	  buffer_xml_printf (buffer, "<etm");
+	  buffer_xml_printf (buffer, " size=\"0x%x\"", conf->etm.size);
+	  if (conf->etm.sink !=NULL)
+	    {
+	      buffer_xml_printf (buffer, " sink=\"%s\"", conf->etm.sink);
+	    }
+	  else
+	    {
+	      buffer_xml_printf (buffer, " sink=\"default\"");
+	    }
+	  buffer_xml_printf (buffer, "/>\n");
+	  break;
 	}
     }
 
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
index a5497e93cee..d0c619d2178 100644
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -424,6 +424,18 @@ handle_btrace_enable_pt (struct thread_info *thread)
   thread->btrace = target_enable_btrace (thread->id, &current_btrace_conf);
 }
 
+/* Handle btrace enabling in ARM CoreSight Trace format.  */
+
+static void
+handle_btrace_enable_etm (struct thread_info *thread)
+{
+  if (thread->btrace != NULL)
+    error (_("Btrace already enabled."));
+
+  current_btrace_conf.format = BTRACE_FORMAT_ETM;
+  thread->btrace = target_enable_btrace (thread->id, &current_btrace_conf);
+}
+
 /* Handle btrace disabling.  */
 
 static void
@@ -473,10 +485,12 @@ handle_btrace_general_set (char *own_buf)
 	handle_btrace_enable_bts (thread);
       else if (strcmp (op, "pt") == 0)
 	handle_btrace_enable_pt (thread);
+      else if (strcmp (op, "etm") == 0)
+	handle_btrace_enable_etm (thread);
       else if (strcmp (op, "off") == 0)
 	handle_btrace_disable (thread);
       else
-	error (_("Bad Qbtrace operation.  Use bts, pt, or off."));
+	error (_("Bad Qbtrace operation.  Use bts, pt, etm, or off."));
 
       write_ok (own_buf);
     }
@@ -546,6 +560,21 @@ handle_btrace_conf_general_set (char *own_buf)
 
       current_btrace_conf.pt.size = (unsigned int) size;
     }
+  else if (strncmp (op, "etm:size=", strlen ("etm:size=")) == 0)
+    {
+      unsigned long size;
+      char *endp = NULL;
+        
+      errno = 0;
+      size = strtoul (op + strlen ("etm:size="), &endp, 16);
+      if (endp == NULL || *endp != 0 || errno != 0 || size > UINT_MAX)
+        {
+          strcpy (own_buf, "E.Bad size value.");
+          return -1;
+        }
+       
+      current_btrace_conf.etm.size = (unsigned int) size;
+    }
   else
     {
       strcpy (own_buf, "E.Bad Qbtrace configuration option.");
@@ -2084,6 +2113,9 @@ supported_btrace_packets (char *buf)
   strcat (buf, ";Qbtrace-conf:bts:size+");
   strcat (buf, ";Qbtrace:pt+");
   strcat (buf, ";Qbtrace-conf:pt:size+");
+  strcat (buf, ";Qbtrace:etm+");
+  strcat (buf, ";Qbtrace-conf:etm:size+");
+  strcat (buf, ";Qbtrace-conf:etm:sink+");
   strcat (buf, ";Qbtrace:off+");
   strcat (buf, ";qXfer:btrace:read+");
   strcat (buf, ";qXfer:btrace-conf:read+");
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 7/8] adapt btrace testcases for arm target
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
                   ` (5 preceding siblings ...)
  2021-02-26  2:46 ` [PATCH 6/8] add support for coresight btrace via remote protocol Zied Guermazi
@ 2021-02-26  2:46 ` Zied Guermazi
  2021-02-26  2:46 ` [PATCH 8/8] document btrace support for arm targets using coresight etm traces Zied Guermazi
  7 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi


This patch extends the test suite for btrace to cover using
ARM CoreSight traces.


gdb/ChangeLog
	* testsuite/lib/gdb.exp (skip_btrace_tests): enable btrace tests
	for arm.
	* testsuite/gdb.btrace/buffer-size.exp: enable btrace tests
	and adapt test for arm.
	* testsuite/gdb.btrace/delta.exp (check_trace): enable btrace tests
	and adapt test for arm.
	* testsuite/gdb.btrace/instruction_history.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/instruction_history.S: renamed to
	x86-instruction_history.S
	* testsuite/gdb.btrace/aarch64-instruction_history.S: New.
	* testsuite/gdb.btrace/arm-instruction_history.S: New
	* testsuite/gdb.btrace/non-stop.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/reconnect.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/record_goto.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/aarch64-record_goto.S: New.
	* testsuite/gdb.btrace/arm-record_goto.S: New.
	* testsuite/gdb.btrace/stepi.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/tailcall.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/aarch64-tailcall.S: New.
	* testsuite/gdb.btrace/arm-tailcall.S: New.
	* testsuite/gdb.btrace/tailcall-only.exp: enable btrace tests
	and adapt tests for arm.
	* testsuite/gdb.btrace/aarch64-tailcall-only.S: New.
	* testsuite/gdb.btrace/arm-tailcall-only.S: New.

---
 gdb/ChangeLog                                 |  33 ++
 .../gdb.btrace/aarch64-instruction_history.S  |  31 ++
 .../gdb.btrace/aarch64-record_goto.S          | 400 ++++++++++++++
 .../gdb.btrace/aarch64-tailcall-only.S        | 517 ++++++++++++++++++
 gdb/testsuite/gdb.btrace/aarch64-tailcall.S   | 409 ++++++++++++++
 .../gdb.btrace/arm-instruction_history.S      |  31 ++
 gdb/testsuite/gdb.btrace/arm-record_goto.S    | 433 +++++++++++++++
 gdb/testsuite/gdb.btrace/arm-tailcall-only.S  | 504 +++++++++++++++++
 gdb/testsuite/gdb.btrace/arm-tailcall.S       | 391 +++++++++++++
 gdb/testsuite/gdb.btrace/buffer-size.exp      |  15 +-
 gdb/testsuite/gdb.btrace/delta.exp            |  10 +
 .../gdb.btrace/instruction_history.exp        | 107 +++-
 gdb/testsuite/gdb.btrace/non-stop.exp         |  60 +-
 gdb/testsuite/gdb.btrace/record_goto.exp      | 241 ++++++--
 gdb/testsuite/gdb.btrace/stepi.exp            |  95 +++-
 gdb/testsuite/gdb.btrace/tailcall-only.exp    |   8 +
 gdb/testsuite/gdb.btrace/tailcall.exp         |  46 +-
 ...on_history.S => x86-instruction_history.S} |   0
 gdb/testsuite/lib/gdb.exp                     |   2 +-
 19 files changed, 3215 insertions(+), 118 deletions(-)
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-instruction_history.S
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-record_goto.S
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-tailcall-only.S
 create mode 100644 gdb/testsuite/gdb.btrace/aarch64-tailcall.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-instruction_history.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-record_goto.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-tailcall-only.S
 create mode 100644 gdb/testsuite/gdb.btrace/arm-tailcall.S
 rename gdb/testsuite/gdb.btrace/{instruction_history.S => x86-instruction_history.S} (100%)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 30f45a62cd5..285a467043f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,36 @@
+2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* testsuite/lib/gdb.exp (skip_btrace_tests): enable btrace tests
+	for arm.
+	* testsuite/gdb.btrace/buffer-size.exp: enable btrace tests
+	and adapt test for arm.
+	* testsuite/gdb.btrace/delta.exp (check_trace): enable btrace tests
+	and adapt test for arm.
+	* testsuite/gdb.btrace/instruction_history.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/instruction_history.S: renamed to
+	x86-instruction_history.S
+	* testsuite/gdb.btrace/aarch64-instruction_history.S: New.
+	* testsuite/gdb.btrace/arm-instruction_history.S: New
+	* testsuite/gdb.btrace/non-stop.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/reconnect.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/record_goto.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/aarch64-record_goto.S: New.
+	* testsuite/gdb.btrace/arm-record_goto.S: New.
+	* testsuite/gdb.btrace/stepi.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/tailcall.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/aarch64-tailcall.S: New.
+	* testsuite/gdb.btrace/arm-tailcall.S: New.
+	* testsuite/gdb.btrace/tailcall-only.exp: enable btrace tests
+	and adapt tests for arm.
+	* testsuite/gdb.btrace/aarch64-tailcall-only.S: New.
+	* testsuite/gdb.btrace/arm-tailcall-only.S: New.
+
 2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
 
 	* btrace.c (check_xml_btrace_version): add version 1.1
diff --git a/gdb/testsuite/gdb.btrace/aarch64-instruction_history.S b/gdb/testsuite/gdb.btrace/aarch64-instruction_history.S
new file mode 100644
index 00000000000..66490e3b23e
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/aarch64-instruction_history.S
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013-2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+.arch armv8-a
+.text
+.globl loop
+.type  loop, %function
+loop:
+	mov x0, #2 /* bp.1 */
+L1:
+	cmp x0, #0
+	beq L2
+	subs x0, x0, #1
+	b L1
+L2:
+	ret /* bp.2 */
+
+
diff --git a/gdb/testsuite/gdb.btrace/aarch64-record_goto.S b/gdb/testsuite/gdb.btrace/aarch64-record_goto.S
new file mode 100644
index 00000000000..be832eeb4c1
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/aarch64-record_goto.S
@@ -0,0 +1,400 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013-2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated on an armv8 machine using:
+   gcc -S -dA -g record_goto.c -o aarch64-record_goto.S  */
+
+	.arch armv8-a
+	.file	"record_goto.c"
+	.text
+.Ltext0:
+	.align	2
+	.global	fun1
+	//.tune generic
+	.type	fun1, %function
+fun1:
+.LFB0:
+	.file 1 "record_goto.c"
+	// record_goto.c:22:1
+	.loc 1 22 1
+	.cfi_startproc
+// BLOCK 2 seq:0
+// PRED: ENTRY (FALLTHRU)
+	// record_goto.c:23:1
+	.loc 1 23 1
+	nop
+// SUCC: EXIT [always] 
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	fun1, .-fun1
+	.align	2
+	.global	fun2
+	.type	fun2, %function
+fun2:
+.LFB1:
+	// record_goto.c:27:1
+	.loc 1 27 1
+	.cfi_startproc
+// BLOCK 2 seq:0
+// PRED: ENTRY (FALLTHRU)
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	mov	x29, sp
+	// record_goto.c:28:3
+	.loc 1 28 3
+	bl	fun1
+	// record_goto.c:29:1
+	.loc 1 29 1
+	nop
+	ldp	x29, x30, [sp], 16
+	.cfi_restore 30
+	.cfi_restore 29
+	.cfi_def_cfa_offset 0
+// SUCC: EXIT [always] 
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	fun2, .-fun2
+	.align	2
+	.global	fun3
+	.type	fun3, %function
+fun3:
+.LFB2:
+	// record_goto.c:33:1
+	.loc 1 33 1
+	.cfi_startproc
+// BLOCK 2 seq:0
+// PRED: ENTRY (FALLTHRU)
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	mov	x29, sp
+	// record_goto.c:34:3
+	.loc 1 34 3
+	bl	fun1
+	// record_goto.c:35:3
+	.loc 1 35 3
+	bl	fun2
+	// record_goto.c:36:1
+	.loc 1 36 1
+	nop
+	ldp	x29, x30, [sp], 16
+	.cfi_restore 30
+	.cfi_restore 29
+	.cfi_def_cfa_offset 0
+// SUCC: EXIT [always] 
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	fun3, .-fun3
+	.align	2
+	.global	fun4
+	.type	fun4, %function
+fun4:
+.LFB3:
+	// record_goto.c:40:1
+	.loc 1 40 1
+	.cfi_startproc
+// BLOCK 2 seq:0
+// PRED: ENTRY (FALLTHRU)
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	mov	x29, sp
+	// record_goto.c:41:3
+	.loc 1 41 3
+	bl	fun1
+	// record_goto.c:42:3
+	.loc 1 42 3
+	bl	fun2
+	// record_goto.c:43:3
+	.loc 1 43 3
+	bl	fun3
+	// record_goto.c:44:1
+	.loc 1 44 1
+	nop
+	ldp	x29, x30, [sp], 16
+	.cfi_restore 30
+	.cfi_restore 29
+	.cfi_def_cfa_offset 0
+// SUCC: EXIT [always] 
+	ret
+	.cfi_endproc
+.LFE3:
+	.size	fun4, .-fun4
+	.align	2
+	.global	main
+	.type	main, %function
+main:
+.LFB4:
+	// record_goto.c:48:1
+	.loc 1 48 1
+	.cfi_startproc
+// BLOCK 2 seq:0
+// PRED: ENTRY (FALLTHRU)
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	mov	x29, sp
+	// record_goto.c:49:3
+	.loc 1 49 3
+	bl	fun4
+	// record_goto.c:50:10
+	.loc 1 50 10
+	mov	w0, 0
+	// record_goto.c:51:1
+	.loc 1 51 1
+	ldp	x29, x30, [sp], 16
+	.cfi_restore 30
+	.cfi_restore 29
+	.cfi_def_cfa_offset 0
+// SUCC: EXIT [always] 
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.4byte	0xb7	// Length of Compilation Unit Info
+	.2byte	0x4	// DWARF version number
+	.4byte	.Ldebug_abbrev0	// Offset Into Abbrev. Section
+	.byte	0x8	// Pointer Size (in bytes)
+	.uleb128 0x1	// (DIE (0xb) DW_TAG_compile_unit)
+	.4byte	.LASF4	// DW_AT_producer: "GNU C17 10.2.1 20201224 -mlittle-endian -mabi=lp64 -g -fasynchronous-unwind-tables"
+	.byte	0xc	// DW_AT_language
+	.4byte	.LASF5	// DW_AT_name: "record_goto.c"
+	.4byte	.LASF6	// DW_AT_comp_dir: "/home/linaro/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+	.8byte	.Ltext0	// DW_AT_low_pc
+	.8byte	.Letext0-.Ltext0	// DW_AT_high_pc
+	.4byte	.Ldebug_line0	// DW_AT_stmt_list
+	.uleb128 0x2	// (DIE (0x2d) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF7	// DW_AT_name: "main"
+	.byte	0x1	// DW_AT_decl_file (record_goto.c)
+	.byte	0x2f	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x4b	// DW_AT_type
+	.8byte	.LFB4	// DW_AT_low_pc
+	.8byte	.LFE4-.LFB4	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x3	// (DIE (0x4b) DW_TAG_base_type)
+	.byte	0x4	// DW_AT_byte_size
+	.byte	0x5	// DW_AT_encoding
+	.ascii "int\0"	// DW_AT_name
+	.uleb128 0x4	// (DIE (0x52) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF0	// DW_AT_name: "fun4"
+	.byte	0x1	// DW_AT_decl_file (record_goto.c)
+	.byte	0x27	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.8byte	.LFB3	// DW_AT_low_pc
+	.8byte	.LFE3-.LFB3	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x4	// (DIE (0x6c) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF1	// DW_AT_name: "fun3"
+	.byte	0x1	// DW_AT_decl_file (record_goto.c)
+	.byte	0x20	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.8byte	.LFB2	// DW_AT_low_pc
+	.8byte	.LFE2-.LFB2	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x4	// (DIE (0x86) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF2	// DW_AT_name: "fun2"
+	.byte	0x1	// DW_AT_decl_file (record_goto.c)
+	.byte	0x1a	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.8byte	.LFB1	// DW_AT_low_pc
+	.8byte	.LFE1-.LFB1	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x5	// (DIE (0xa0) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF3	// DW_AT_name: "fun1"
+	.byte	0x1	// DW_AT_decl_file (record_goto.c)
+	.byte	0x15	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.8byte	.LFB0	// DW_AT_low_pc
+	.8byte	.LFE0-.LFB0	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.byte	0	// end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	// (abbrev code)
+	.uleb128 0x11	// (TAG: DW_TAG_compile_unit)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x25	// (DW_AT_producer)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x13	// (DW_AT_language)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x1b	// (DW_AT_comp_dir)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x10	// (DW_AT_stmt_list)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0	// DW_children_no
+	.uleb128 0x3f	// (DW_AT_external)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2116	// (DW_AT_GNU_all_tail_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	// (abbrev code)
+	.uleb128 0x24	// (TAG: DW_TAG_base_type)
+	.byte	0	// DW_children_no
+	.uleb128 0xb	// (DW_AT_byte_size)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3e	// (DW_AT_encoding)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0x8	// (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0	// DW_children_no
+	.uleb128 0x3f	// (DW_AT_external)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2116	// (DW_AT_GNU_all_tail_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0	// DW_children_no
+	.uleb128 0x3f	// (DW_AT_external)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.4byte	0x2c	// Length of Address Ranges Info
+	.2byte	0x2	// DWARF aranges version
+	.4byte	.Ldebug_info0	// Offset of Compilation Unit Info
+	.byte	0x8	// Size of Address
+	.byte	0	// Size of Segment Descriptor
+	.2byte	0	// Pad to 16 byte boundary
+	.2byte	0
+	.8byte	.Ltext0	// Address
+	.8byte	.Letext0-.Ltext0	// Length
+	.8byte	0
+	.8byte	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF5:
+	.string	"record_goto.c"
+.LASF4:
+	.string	"GNU C17 10.2.1 20201224 -mlittle-endian -mabi=lp64 -g -fasynchronous-unwind-tables"
+.LASF3:
+	.string	"fun1"
+.LASF2:
+	.string	"fun2"
+.LASF0:
+	.string	"fun4"
+.LASF6:
+	.string	"/home/linaro/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+.LASF7:
+	.string	"main"
+.LASF1:
+	.string	"fun3"
+	.ident	"GCC: (Debian 10.2.1-3) 10.2.1 20201224"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.btrace/aarch64-tailcall-only.S b/gdb/testsuite/gdb.btrace/aarch64-tailcall-only.S
new file mode 100644
index 00000000000..1822385b85f
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/aarch64-tailcall-only.S
@@ -0,0 +1,517 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2016-2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated on an armv8 machine using:
+   gcc -m32 -S -O2 -dA -g tailcall-only.c -o aarch64-tailcall-only.S
+ */
+
+	.arch armv8-a
+	.file	"tailcall-only.c"
+	.text
+.Ltext0:
+	.align	2
+	.p2align 4,,11
+	//.tune generic
+	.type	bar_1, %function
+bar_1:
+.LFB0:
+	.file 1 "tailcall-only.c"
+	// tailcall-only.c:22:1
+	.loc 1 22 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall-only.c:23:3
+	.loc 1 23 3 view .LVU1
+	// tailcall-only.c:24:1
+	.loc 1 24 1 is_stmt 0 view .LVU2
+	mov	w0, 42
+// SUCC: EXIT [always]  count:1073741824 (estimated locally)
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	bar_1, .-bar_1
+	.align	2
+	.p2align 4,,11
+	.type	bar, %function
+bar:
+.LFB1:
+	// tailcall-only.c:28:1
+	.loc 1 28 1 is_stmt 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall-only.c:29:3
+	.loc 1 29 3 view .LVU4
+// SUCC: EXIT [always]  count:1073741824 (estimated locally) (ABNORMAL,SIBCALL)
+	// tailcall-only.c:29:10
+	.loc 1 29 10 is_stmt 0 view .LVU5
+	b	bar_1
+.LVL0:
+	.cfi_endproc
+.LFE1:
+	.size	bar, .-bar
+	.align	2
+	.p2align 4,,11
+	.type	foo_1, %function
+foo_1:
+.LFB2:
+	// tailcall-only.c:34:1
+	.loc 1 34 1 is_stmt 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall-only.c:35:3
+	.loc 1 35 3 view .LVU7
+// SUCC: EXIT [always]  count:1073741824 (estimated locally) (ABNORMAL,SIBCALL)
+	// tailcall-only.c:35:10
+	.loc 1 35 10 is_stmt 0 view .LVU8
+	b	bar
+.LVL1:
+	.cfi_endproc
+.LFE2:
+	.size	foo_1, .-foo_1
+	.align	2
+	.p2align 4,,11
+	.type	foo, %function
+foo:
+.LFB3:
+	// tailcall-only.c:40:1
+	.loc 1 40 1 is_stmt 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall-only.c:41:3
+	.loc 1 41 3 view .LVU10
+// SUCC: EXIT [always]  count:1073741824 (estimated locally) (ABNORMAL,SIBCALL)
+	// tailcall-only.c:41:10
+	.loc 1 41 10 is_stmt 0 view .LVU11
+	b	foo_1
+.LVL2:
+	.cfi_endproc
+.LFE3:
+	.size	foo, .-foo
+	.section	.text.startup,"ax",@progbits
+	.align	2
+	.p2align 4,,11
+	.global	main
+	.type	main, %function
+main:
+.LFB4:
+	// tailcall-only.c:46:1
+	.loc 1 46 1 is_stmt 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall-only.c:47:3
+	.loc 1 47 3 view .LVU13
+	// tailcall-only.c:49:3
+	.loc 1 49 3 view .LVU14
+	// tailcall-only.c:46:1
+	.loc 1 46 1 is_stmt 0 view .LVU15
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	mov	x29, sp
+	// tailcall-only.c:49:12
+	.loc 1 49 12 view .LVU16
+	bl	foo
+.LVL3:
+	// DEBUG answer => x0
+	// tailcall-only.c:50:3
+	.loc 1 50 3 is_stmt 1 view .LVU17
+	// DEBUG answer => x0+0x1
+	// tailcall-only.c:52:3
+	.loc 1 52 3 view .LVU18
+	// tailcall-only.c:53:1
+	.loc 1 53 1 is_stmt 0 view .LVU19
+	add	w0, w0, 1
+.LVL4:
+	// DEBUG answer => x0
+	// tailcall-only.c:53:1
+	.loc 1 53 1 view .LVU20
+	ldp	x29, x30, [sp], 16
+	.cfi_restore 30
+	.cfi_restore 29
+	.cfi_def_cfa_offset 0
+// SUCC: EXIT [always]  count:1073741824 (estimated locally)
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.4byte	0x11f	// Length of Compilation Unit Info
+	.2byte	0x4	// DWARF version number
+	.4byte	.Ldebug_abbrev0	// Offset Into Abbrev. Section
+	.byte	0x8	// Pointer Size (in bytes)
+	.uleb128 0x1	// (DIE (0xb) DW_TAG_compile_unit)
+	.4byte	.LASF1	// DW_AT_producer: "GNU C17 10.2.1 20201224 -mlittle-endian -mabi=lp64 -g -O2 -fasynchronous-unwind-tables"
+	.byte	0xc	// DW_AT_language
+	.4byte	.LASF2	// DW_AT_name: "tailcall-only.c"
+	.4byte	.LASF3	// DW_AT_comp_dir: "/home/linaro/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+	.4byte	.Ldebug_ranges0+0	// DW_AT_ranges
+	.8byte	0	// DW_AT_low_pc
+	.4byte	.Ldebug_line0	// DW_AT_stmt_list
+	.uleb128 0x2	// (DIE (0x29) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF4	// DW_AT_name: "main"
+	.byte	0x1	// DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2d	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB4	// DW_AT_low_pc
+	.8byte	.LFE4-.LFB4	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.4byte	0x6d	// DW_AT_sibling
+	.uleb128 0x3	// (DIE (0x4b) DW_TAG_variable)
+	.4byte	.LASF5	// DW_AT_name: "answer"
+	.byte	0x1	// DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2f	// DW_AT_decl_line
+	.byte	0x7	// DW_AT_decl_column
+	.4byte	0x6d	// DW_AT_type
+	.4byte	.LLST0	// DW_AT_location
+	.4byte	.LVUS0	// DW_AT_GNU_locviews
+	.uleb128 0x4	// (DIE (0x5f) DW_TAG_GNU_call_site)
+	.8byte	.LVL3	// DW_AT_low_pc
+	.4byte	0x74	// DW_AT_abstract_origin
+	.byte	0	// end of children of DIE 0x29
+	.uleb128 0x5	// (DIE (0x6d) DW_TAG_base_type)
+	.byte	0x4	// DW_AT_byte_size
+	.byte	0x5	// DW_AT_encoding
+	.ascii "int\0"	// DW_AT_name
+	.uleb128 0x6	// (DIE (0x74) DW_TAG_subprogram)
+	.ascii "foo\0"	// DW_AT_name
+	.byte	0x1	// DW_AT_decl_file (tailcall-only.c)
+	.byte	0x27	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB3	// DW_AT_low_pc
+	.8byte	.LFE3-.LFB3	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.4byte	0xa4	// DW_AT_sibling
+	.uleb128 0x7	// (DIE (0x96) DW_TAG_GNU_call_site)
+	.8byte	.LVL2	// DW_AT_low_pc
+			// DW_AT_GNU_tail_call
+	.4byte	0xa4	// DW_AT_abstract_origin
+	.byte	0	// end of children of DIE 0x74
+	.uleb128 0x8	// (DIE (0xa4) DW_TAG_subprogram)
+	.4byte	.LASF0	// DW_AT_name: "foo_1"
+	.byte	0x1	// DW_AT_decl_file (tailcall-only.c)
+	.byte	0x21	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB2	// DW_AT_low_pc
+	.8byte	.LFE2-.LFB2	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.4byte	0xd4	// DW_AT_sibling
+	.uleb128 0x7	// (DIE (0xc6) DW_TAG_GNU_call_site)
+	.8byte	.LVL1	// DW_AT_low_pc
+			// DW_AT_GNU_tail_call
+	.4byte	0xd4	// DW_AT_abstract_origin
+	.byte	0	// end of children of DIE 0xa4
+	.uleb128 0x6	// (DIE (0xd4) DW_TAG_subprogram)
+	.ascii "bar\0"	// DW_AT_name
+	.byte	0x1	// DW_AT_decl_file (tailcall-only.c)
+	.byte	0x1b	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB1	// DW_AT_low_pc
+	.8byte	.LFE1-.LFB1	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.4byte	0x104	// DW_AT_sibling
+	.uleb128 0x7	// (DIE (0xf6) DW_TAG_GNU_call_site)
+	.8byte	.LVL0	// DW_AT_low_pc
+			// DW_AT_GNU_tail_call
+	.4byte	0x104	// DW_AT_abstract_origin
+	.byte	0	// end of children of DIE 0xd4
+	.uleb128 0x9	// (DIE (0x104) DW_TAG_subprogram)
+	.4byte	.LASF6	// DW_AT_name: "bar_1"
+	.byte	0x1	// DW_AT_decl_file (tailcall-only.c)
+	.byte	0x15	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB0	// DW_AT_low_pc
+	.8byte	.LFE0-.LFB0	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.byte	0	// end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	// (abbrev code)
+	.uleb128 0x11	// (TAG: DW_TAG_compile_unit)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x25	// (DW_AT_producer)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x13	// (DW_AT_language)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x1b	// (DW_AT_comp_dir)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x55	// (DW_AT_ranges)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x10	// (DW_AT_stmt_list)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x3f	// (DW_AT_external)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x1	// (DW_AT_sibling)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	// (abbrev code)
+	.uleb128 0x34	// (TAG: DW_TAG_variable)
+	.byte	0	// DW_children_no
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x2	// (DW_AT_location)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.uleb128 0x2137	// (DW_AT_GNU_locviews)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	// (abbrev code)
+	.uleb128 0x4109	// (TAG: DW_TAG_GNU_call_site)
+	.byte	0	// DW_children_no
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x31	// (DW_AT_abstract_origin)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	// (abbrev code)
+	.uleb128 0x24	// (TAG: DW_TAG_base_type)
+	.byte	0	// DW_children_no
+	.uleb128 0xb	// (DW_AT_byte_size)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3e	// (DW_AT_encoding)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0x8	// (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0x8	// (DW_FORM_string)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x1	// (DW_AT_sibling)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	// (abbrev code)
+	.uleb128 0x4109	// (TAG: DW_TAG_GNU_call_site)
+	.byte	0	// DW_children_no
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x2115	// (DW_AT_GNU_tail_call)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x31	// (DW_AT_abstract_origin)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x1	// (DW_AT_sibling)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0	// DW_children_no
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LVUS0:
+	.uleb128 .LVU17	// View list begin (*.LVUS0)
+	.uleb128 .LVU18	// View list end (*.LVUS0)
+	.uleb128 .LVU18	// View list begin (*.LVUS0)
+	.uleb128 .LVU20	// View list end (*.LVUS0)
+	.uleb128 .LVU20	// View list begin (*.LVUS0)
+	.uleb128 0	// View list end (*.LVUS0)
+.LLST0:
+	.8byte	.LVL3	// Location list begin address (*.LLST0)
+	.8byte	.LVL3	// Location list end address (*.LLST0)
+	.2byte	0x1	// Location expression size
+	.byte	0x50	// DW_OP_reg0
+	.8byte	.LVL3	// Location list begin address (*.LLST0)
+	.8byte	.LVL4	// Location list end address (*.LLST0)
+	.2byte	0x3	// Location expression size
+	.byte	0x70	// DW_OP_breg0
+	.sleb128 1
+	.byte	0x9f	// DW_OP_stack_value
+	.8byte	.LVL4	// Location list begin address (*.LLST0)
+	.8byte	.LFE4	// Location list end address (*.LLST0)
+	.2byte	0x1	// Location expression size
+	.byte	0x50	// DW_OP_reg0
+	.8byte	0	// Location list terminator begin (*.LLST0)
+	.8byte	0	// Location list terminator end (*.LLST0)
+	.section	.debug_aranges,"",@progbits
+	.4byte	0x3c	// Length of Address Ranges Info
+	.2byte	0x2	// DWARF aranges version
+	.4byte	.Ldebug_info0	// Offset of Compilation Unit Info
+	.byte	0x8	// Size of Address
+	.byte	0	// Size of Segment Descriptor
+	.2byte	0	// Pad to 16 byte boundary
+	.2byte	0
+	.8byte	.Ltext0	// Address
+	.8byte	.Letext0-.Ltext0	// Length
+	.8byte	.LFB4	// Address
+	.8byte	.LFE4-.LFB4	// Length
+	.8byte	0
+	.8byte	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.8byte	.Ltext0	// Offset 0
+	.8byte	.Letext0
+	.8byte	.LFB4	// Offset 0x10
+	.8byte	.LFE4
+	.8byte	0
+	.8byte	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF6:
+	.string	"bar_1"
+.LASF2:
+	.string	"tailcall-only.c"
+.LASF3:
+	.string	"/home/linaro/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+.LASF5:
+	.string	"answer"
+.LASF4:
+	.string	"main"
+.LASF1:
+	.string	"GNU C17 10.2.1 20201224 -mlittle-endian -mabi=lp64 -g -O2 -fasynchronous-unwind-tables"
+.LASF0:
+	.string	"foo_1"
+	.ident	"GCC: (Debian 10.2.1-3) 10.2.1 20201224"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.btrace/aarch64-tailcall.S b/gdb/testsuite/gdb.btrace/aarch64-tailcall.S
new file mode 100644
index 00000000000..a6b01cbccea
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/aarch64-tailcall.S
@@ -0,0 +1,409 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013-2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated on an armv8 machine using:
+   gcc -S -O2 -dA -g tailcall.c -o aarch64-tailcall.S  */
+
+	.arch armv8-a
+	.file	"tailcall.c"
+	.text
+.Ltext0:
+	.align	2
+	.p2align 4,,11
+	//.tune generic
+	.type	bar, %function
+bar:
+.LFB0:
+	.file 1 "tailcall.c"
+	// tailcall.c:22:1
+	.loc 1 22 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall.c:23:3
+	.loc 1 23 3 view .LVU1
+	// tailcall.c:24:1
+	.loc 1 24 1 is_stmt 0 view .LVU2
+	mov	w0, 42
+// SUCC: EXIT [always]  count:1073741824 (estimated locally)
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	bar, .-bar
+	.align	2
+	.p2align 4,,11
+	.type	foo, %function
+foo:
+.LFB1:
+	// tailcall.c:28:1
+	.loc 1 28 1 is_stmt 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall.c:29:3
+	.loc 1 29 3 view .LVU4
+// SUCC: EXIT [always]  count:1073741824 (estimated locally) (ABNORMAL,SIBCALL)
+	// tailcall.c:29:10
+	.loc 1 29 10 is_stmt 0 view .LVU5
+	b	bar
+.LVL0:
+	.cfi_endproc
+.LFE1:
+	.size	foo, .-foo
+	.section	.text.startup,"ax",@progbits
+	.align	2
+	.p2align 4,,11
+	.global	main
+	.type	main, %function
+main:
+.LFB2:
+	// tailcall.c:34:1
+	.loc 1 34 1 is_stmt 1 view -0
+	.cfi_startproc
+// BLOCK 2, count:1073741824 (estimated locally) seq:0
+// PRED: ENTRY [always]  count:1073741824 (estimated locally) (FALLTHRU)
+	// tailcall.c:35:3
+	.loc 1 35 3 view .LVU7
+	// tailcall.c:37:3
+	.loc 1 37 3 view .LVU8
+	// tailcall.c:34:1
+	.loc 1 34 1 is_stmt 0 view .LVU9
+	stp	x29, x30, [sp, -16]!
+	.cfi_def_cfa_offset 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
+	mov	x29, sp
+	// tailcall.c:37:12
+	.loc 1 37 12 view .LVU10
+	bl	foo
+.LVL1:
+	// DEBUG answer => x0
+	// tailcall.c:38:3
+	.loc 1 38 3 is_stmt 1 view .LVU11
+	// DEBUG answer => x0+0x1
+	// tailcall.c:40:3
+	.loc 1 40 3 view .LVU12
+	// tailcall.c:41:1
+	.loc 1 41 1 is_stmt 0 view .LVU13
+	add	w0, w0, 1
+.LVL2:
+	// DEBUG answer => x0
+	// tailcall.c:41:1
+	.loc 1 41 1 view .LVU14
+	ldp	x29, x30, [sp], 16
+	.cfi_restore 30
+	.cfi_restore 29
+	.cfi_def_cfa_offset 0
+// SUCC: EXIT [always]  count:1073741824 (estimated locally)
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.4byte	0xbf	// Length of Compilation Unit Info
+	.2byte	0x4	// DWARF version number
+	.4byte	.Ldebug_abbrev0	// Offset Into Abbrev. Section
+	.byte	0x8	// Pointer Size (in bytes)
+	.uleb128 0x1	// (DIE (0xb) DW_TAG_compile_unit)
+	.4byte	.LASF0	// DW_AT_producer: "GNU C17 10.2.1 20201224 -mlittle-endian -mabi=lp64 -g -O2 -fasynchronous-unwind-tables"
+	.byte	0xc	// DW_AT_language
+	.4byte	.LASF1	// DW_AT_name: "tailcall.c"
+	.4byte	.LASF2	// DW_AT_comp_dir: "/home/linaro/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+	.4byte	.Ldebug_ranges0+0	// DW_AT_ranges
+	.8byte	0	// DW_AT_low_pc
+	.4byte	.Ldebug_line0	// DW_AT_stmt_list
+	.uleb128 0x2	// (DIE (0x29) DW_TAG_subprogram)
+			// DW_AT_external
+	.4byte	.LASF3	// DW_AT_name: "main"
+	.byte	0x1	// DW_AT_decl_file (tailcall.c)
+	.byte	0x21	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB2	// DW_AT_low_pc
+	.8byte	.LFE2-.LFB2	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.4byte	0x6d	// DW_AT_sibling
+	.uleb128 0x3	// (DIE (0x4b) DW_TAG_variable)
+	.4byte	.LASF4	// DW_AT_name: "answer"
+	.byte	0x1	// DW_AT_decl_file (tailcall.c)
+	.byte	0x23	// DW_AT_decl_line
+	.byte	0x7	// DW_AT_decl_column
+	.4byte	0x6d	// DW_AT_type
+	.4byte	.LLST0	// DW_AT_location
+	.4byte	.LVUS0	// DW_AT_GNU_locviews
+	.uleb128 0x4	// (DIE (0x5f) DW_TAG_GNU_call_site)
+	.8byte	.LVL1	// DW_AT_low_pc
+	.4byte	0x74	// DW_AT_abstract_origin
+	.byte	0	// end of children of DIE 0x29
+	.uleb128 0x5	// (DIE (0x6d) DW_TAG_base_type)
+	.byte	0x4	// DW_AT_byte_size
+	.byte	0x5	// DW_AT_encoding
+	.ascii "int\0"	// DW_AT_name
+	.uleb128 0x6	// (DIE (0x74) DW_TAG_subprogram)
+	.ascii "foo\0"	// DW_AT_name
+	.byte	0x1	// DW_AT_decl_file (tailcall.c)
+	.byte	0x1b	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB1	// DW_AT_low_pc
+	.8byte	.LFE1-.LFB1	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.4byte	0xa4	// DW_AT_sibling
+	.uleb128 0x7	// (DIE (0x96) DW_TAG_GNU_call_site)
+	.8byte	.LVL0	// DW_AT_low_pc
+			// DW_AT_GNU_tail_call
+	.4byte	0xa4	// DW_AT_abstract_origin
+	.byte	0	// end of children of DIE 0x74
+	.uleb128 0x8	// (DIE (0xa4) DW_TAG_subprogram)
+	.ascii "bar\0"	// DW_AT_name
+	.byte	0x1	// DW_AT_decl_file (tailcall.c)
+	.byte	0x15	// DW_AT_decl_line
+	.byte	0x1	// DW_AT_decl_column
+			// DW_AT_prototyped
+	.4byte	0x6d	// DW_AT_type
+	.8byte	.LFB0	// DW_AT_low_pc
+	.8byte	.LFE0-.LFB0	// DW_AT_high_pc
+	.uleb128 0x1	// DW_AT_frame_base
+	.byte	0x9c	// DW_OP_call_frame_cfa
+			// DW_AT_GNU_all_call_sites
+	.byte	0	// end of children of DIE 0xb
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	// (abbrev code)
+	.uleb128 0x11	// (TAG: DW_TAG_compile_unit)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x25	// (DW_AT_producer)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x13	// (DW_AT_language)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x1b	// (DW_AT_comp_dir)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x55	// (DW_AT_ranges)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x10	// (DW_AT_stmt_list)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x3f	// (DW_AT_external)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x1	// (DW_AT_sibling)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	// (abbrev code)
+	.uleb128 0x34	// (TAG: DW_TAG_variable)
+	.byte	0	// DW_children_no
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0xe	// (DW_FORM_strp)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x2	// (DW_AT_location)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.uleb128 0x2137	// (DW_AT_GNU_locviews)
+	.uleb128 0x17	// (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	// (abbrev code)
+	.uleb128 0x4109	// (TAG: DW_TAG_GNU_call_site)
+	.byte	0	// DW_children_no
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x31	// (DW_AT_abstract_origin)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	// (abbrev code)
+	.uleb128 0x24	// (TAG: DW_TAG_base_type)
+	.byte	0	// DW_children_no
+	.uleb128 0xb	// (DW_AT_byte_size)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3e	// (DW_AT_encoding)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0x8	// (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0x1	// DW_children_yes
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0x8	// (DW_FORM_string)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x1	// (DW_AT_sibling)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	// (abbrev code)
+	.uleb128 0x4109	// (TAG: DW_TAG_GNU_call_site)
+	.byte	0	// DW_children_no
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x2115	// (DW_AT_GNU_tail_call)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x31	// (DW_AT_abstract_origin)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	// (abbrev code)
+	.uleb128 0x2e	// (TAG: DW_TAG_subprogram)
+	.byte	0	// DW_children_no
+	.uleb128 0x3	// (DW_AT_name)
+	.uleb128 0x8	// (DW_FORM_string)
+	.uleb128 0x3a	// (DW_AT_decl_file)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x3b	// (DW_AT_decl_line)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x39	// (DW_AT_decl_column)
+	.uleb128 0xb	// (DW_FORM_data1)
+	.uleb128 0x27	// (DW_AT_prototyped)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.uleb128 0x49	// (DW_AT_type)
+	.uleb128 0x13	// (DW_FORM_ref4)
+	.uleb128 0x11	// (DW_AT_low_pc)
+	.uleb128 0x1	// (DW_FORM_addr)
+	.uleb128 0x12	// (DW_AT_high_pc)
+	.uleb128 0x7	// (DW_FORM_data8)
+	.uleb128 0x40	// (DW_AT_frame_base)
+	.uleb128 0x18	// (DW_FORM_exprloc)
+	.uleb128 0x2117	// (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	// (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LVUS0:
+	.uleb128 .LVU11	// View list begin (*.LVUS0)
+	.uleb128 .LVU12	// View list end (*.LVUS0)
+	.uleb128 .LVU12	// View list begin (*.LVUS0)
+	.uleb128 .LVU14	// View list end (*.LVUS0)
+	.uleb128 .LVU14	// View list begin (*.LVUS0)
+	.uleb128 0	// View list end (*.LVUS0)
+.LLST0:
+	.8byte	.LVL1	// Location list begin address (*.LLST0)
+	.8byte	.LVL1	// Location list end address (*.LLST0)
+	.2byte	0x1	// Location expression size
+	.byte	0x50	// DW_OP_reg0
+	.8byte	.LVL1	// Location list begin address (*.LLST0)
+	.8byte	.LVL2	// Location list end address (*.LLST0)
+	.2byte	0x3	// Location expression size
+	.byte	0x70	// DW_OP_breg0
+	.sleb128 1
+	.byte	0x9f	// DW_OP_stack_value
+	.8byte	.LVL2	// Location list begin address (*.LLST0)
+	.8byte	.LFE2	// Location list end address (*.LLST0)
+	.2byte	0x1	// Location expression size
+	.byte	0x50	// DW_OP_reg0
+	.8byte	0	// Location list terminator begin (*.LLST0)
+	.8byte	0	// Location list terminator end (*.LLST0)
+	.section	.debug_aranges,"",@progbits
+	.4byte	0x3c	// Length of Address Ranges Info
+	.2byte	0x2	// DWARF aranges version
+	.4byte	.Ldebug_info0	// Offset of Compilation Unit Info
+	.byte	0x8	// Size of Address
+	.byte	0	// Size of Segment Descriptor
+	.2byte	0	// Pad to 16 byte boundary
+	.2byte	0
+	.8byte	.Ltext0	// Address
+	.8byte	.Letext0-.Ltext0	// Length
+	.8byte	.LFB2	// Address
+	.8byte	.LFE2-.LFB2	// Length
+	.8byte	0
+	.8byte	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.8byte	.Ltext0	// Offset 0
+	.8byte	.Letext0
+	.8byte	.LFB2	// Offset 0x10
+	.8byte	.LFE2
+	.8byte	0
+	.8byte	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"GNU C17 10.2.1 20201224 -mlittle-endian -mabi=lp64 -g -O2 -fasynchronous-unwind-tables"
+.LASF2:
+	.string	"/home/linaro/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+.LASF4:
+	.string	"answer"
+.LASF1:
+	.string	"tailcall.c"
+.LASF3:
+	.string	"main"
+	.ident	"GCC: (Debian 10.2.1-3) 10.2.1 20201224"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.btrace/arm-instruction_history.S b/gdb/testsuite/gdb.btrace/arm-instruction_history.S
new file mode 100644
index 00000000000..e73ddaa9be9
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/arm-instruction_history.S
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013-2021 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+.arm
+.text
+.globl loop
+.type  loop, %function
+loop:
+	movs r0, #2 /* bp.1 */
+L1:
+	cmp r0, #0
+	beq L2
+	subs r0, r0, #1
+	b L1
+L2:
+	bx lr /* bp.2 */
+
diff --git a/gdb/testsuite/gdb.btrace/arm-record_goto.S b/gdb/testsuite/gdb.btrace/arm-record_goto.S
new file mode 100644
index 00000000000..2d3a2f0c8de
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/arm-record_goto.S
@@ -0,0 +1,433 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013-2019 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated on an armv7 machine using:
+   gcc -S -dA -g record_goto.c -o arm-record_goto.S  */
+
+	.arch armv7-a
+	.eabi_attribute 28, 1	@ Tag_ABI_VFP_args
+	.eabi_attribute 20, 1	@ Tag_ABI_FP_denormal
+	.eabi_attribute 21, 1	@ Tag_ABI_FP_exceptions
+	.eabi_attribute 23, 3	@ Tag_ABI_FP_number_model
+	.eabi_attribute 24, 1	@ Tag_ABI_align8_needed
+	.eabi_attribute 25, 1	@ Tag_ABI_align8_preserved
+	.eabi_attribute 26, 2	@ Tag_ABI_enum_size
+	.eabi_attribute 30, 6	@ Tag_ABI_optimization_goals
+	.eabi_attribute 34, 1	@ Tag_CPU_unaligned_access
+	.eabi_attribute 18, 4	@ Tag_ABI_PCS_wchar_t
+	.file	"record_goto.c"
+	.text
+.Ltext0:
+	.cfi_sections	.debug_frame
+	.align	1
+	.global	fun1
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	fun1, %function
+fun1:
+.LFB0:
+	.file 1 "record_goto.c"
+	@ record_goto.c:22
+	.loc 1 22 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 1, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 seq:0
+@ PRED: ENTRY (FALLTHRU)
+	push	{r7}
+	.cfi_def_cfa_offset 4
+	.cfi_offset 7, -4
+	add	r7, sp, #0
+	.cfi_def_cfa_register 7
+	@ record_goto.c:23
+	.loc 1 23 0
+	nop
+	mov	sp, r7
+	.cfi_def_cfa_register 13
+	@ sp needed
+	ldr	r7, [sp], #4
+	.cfi_restore 7
+	.cfi_def_cfa_offset 0
+@ SUCC: EXIT [100.0%] 
+	bx	lr
+	.cfi_endproc
+.LFE0:
+	.size	fun1, .-fun1
+	.align	1
+	.global	fun2
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	fun2, %function
+fun2:
+.LFB1:
+	@ record_goto.c:27
+	.loc 1 27 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 1, uses_anonymous_args = 0
+@ BLOCK 2 seq:0
+@ PRED: ENTRY (FALLTHRU)
+	push	{r7, lr}
+	.cfi_def_cfa_offset 8
+	.cfi_offset 7, -8
+	.cfi_offset 14, -4
+	add	r7, sp, #0
+	.cfi_def_cfa_register 7
+	@ record_goto.c:28
+	.loc 1 28 0
+	bl	fun1(PLT)
+	@ record_goto.c:29
+	.loc 1 29 0
+	nop
+@ SUCC: EXIT [100.0%] 
+	pop	{r7, pc}
+	.cfi_endproc
+.LFE1:
+	.size	fun2, .-fun2
+	.align	1
+	.global	fun3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	fun3, %function
+fun3:
+.LFB2:
+	@ record_goto.c:33
+	.loc 1 33 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 1, uses_anonymous_args = 0
+@ BLOCK 2 seq:0
+@ PRED: ENTRY (FALLTHRU)
+	push	{r7, lr}
+	.cfi_def_cfa_offset 8
+	.cfi_offset 7, -8
+	.cfi_offset 14, -4
+	add	r7, sp, #0
+	.cfi_def_cfa_register 7
+	@ record_goto.c:34
+	.loc 1 34 0
+	bl	fun1(PLT)
+	@ record_goto.c:35
+	.loc 1 35 0
+	bl	fun2(PLT)
+	@ record_goto.c:36
+	.loc 1 36 0
+	nop
+@ SUCC: EXIT [100.0%] 
+	pop	{r7, pc}
+	.cfi_endproc
+.LFE2:
+	.size	fun3, .-fun3
+	.align	1
+	.global	fun4
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	fun4, %function
+fun4:
+.LFB3:
+	@ record_goto.c:40
+	.loc 1 40 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 1, uses_anonymous_args = 0
+@ BLOCK 2 seq:0
+@ PRED: ENTRY (FALLTHRU)
+	push	{r7, lr}
+	.cfi_def_cfa_offset 8
+	.cfi_offset 7, -8
+	.cfi_offset 14, -4
+	add	r7, sp, #0
+	.cfi_def_cfa_register 7
+	@ record_goto.c:41
+	.loc 1 41 0
+	bl	fun1(PLT)
+	@ record_goto.c:42
+	.loc 1 42 0
+	bl	fun2(PLT)
+	@ record_goto.c:43
+	.loc 1 43 0
+	bl	fun3(PLT)
+	@ record_goto.c:44
+	.loc 1 44 0
+	nop
+@ SUCC: EXIT [100.0%] 
+	pop	{r7, pc}
+	.cfi_endproc
+.LFE3:
+	.size	fun4, .-fun4
+	.align	1
+	.global	main
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	main, %function
+main:
+.LFB4:
+	@ record_goto.c:48
+	.loc 1 48 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 1, uses_anonymous_args = 0
+@ BLOCK 2 seq:0
+@ PRED: ENTRY (FALLTHRU)
+	push	{r7, lr}
+	.cfi_def_cfa_offset 8
+	.cfi_offset 7, -8
+	.cfi_offset 14, -4
+	add	r7, sp, #0
+	.cfi_def_cfa_register 7
+	@ record_goto.c:49
+	.loc 1 49 0
+	bl	fun4(PLT)
+	@ record_goto.c:50
+	.loc 1 50 0
+	movs	r3, #0
+	@ record_goto.c:51
+	.loc 1 51 0
+	mov	r0, r3
+@ SUCC: EXIT [100.0%] 
+	pop	{r7, pc}
+	.cfi_endproc
+.LFE4:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",%progbits
+.Ldebug_info0:
+	.4byte	0x82	@ Length of Compilation Unit Info
+	.2byte	0x4	@ DWARF version number
+	.4byte	.Ldebug_abbrev0	@ Offset Into Abbrev. Section
+	.byte	0x4	@ Pointer Size (in bytes)
+	.uleb128 0x1	@ (DIE (0xb) DW_TAG_compile_unit)
+	.4byte	.LASF4	@ DW_AT_producer: "GNU C11 7.4.0 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb -mtls-dialect=gnu -g -fstack-protector-strong"
+	.byte	0xc	@ DW_AT_language
+	.4byte	.LASF5	@ DW_AT_name: "record_goto.c"
+	.4byte	.LASF6	@ DW_AT_comp_dir: "/home/ubuntu/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+	.4byte	.Ltext0	@ DW_AT_low_pc
+	.4byte	.Letext0-.Ltext0	@ DW_AT_high_pc
+	.4byte	.Ldebug_line0	@ DW_AT_stmt_list
+	.uleb128 0x2	@ (DIE (0x25) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF7	@ DW_AT_name: "main"
+	.byte	0x1	@ DW_AT_decl_file (record_goto.c)
+	.byte	0x2f	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x3a	@ DW_AT_type
+	.4byte	.LFB4	@ DW_AT_low_pc
+	.4byte	.LFE4-.LFB4	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x3	@ (DIE (0x3a) DW_TAG_base_type)
+	.byte	0x4	@ DW_AT_byte_size
+	.byte	0x5	@ DW_AT_encoding
+	.ascii "int\0"	@ DW_AT_name
+	.uleb128 0x4	@ (DIE (0x41) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF0	@ DW_AT_name: "fun4"
+	.byte	0x1	@ DW_AT_decl_file (record_goto.c)
+	.byte	0x27	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	.LFB3	@ DW_AT_low_pc
+	.4byte	.LFE3-.LFB3	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x4	@ (DIE (0x52) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF1	@ DW_AT_name: "fun3"
+	.byte	0x1	@ DW_AT_decl_file (record_goto.c)
+	.byte	0x20	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	.LFB2	@ DW_AT_low_pc
+	.4byte	.LFE2-.LFB2	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x4	@ (DIE (0x63) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF2	@ DW_AT_name: "fun2"
+	.byte	0x1	@ DW_AT_decl_file (record_goto.c)
+	.byte	0x1a	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	.LFB1	@ DW_AT_low_pc
+	.4byte	.LFE1-.LFB1	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_tail_call_sites
+	.uleb128 0x5	@ (DIE (0x74) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF3	@ DW_AT_name: "fun1"
+	.byte	0x1	@ DW_AT_decl_file (record_goto.c)
+	.byte	0x15	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	.LFB0	@ DW_AT_low_pc
+	.4byte	.LFE0-.LFB0	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.byte	0	@ end of children of DIE 0xb
+	.section	.debug_abbrev,"",%progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	@ (abbrev code)
+	.uleb128 0x11	@ (TAG: DW_TAG_compile_unit)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x25	@ (DW_AT_producer)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x13	@ (DW_AT_language)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x1b	@ (DW_AT_comp_dir)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x10	@ (DW_AT_stmt_list)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3f	@ (DW_AT_external)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2116	@ (DW_AT_GNU_all_tail_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	@ (abbrev code)
+	.uleb128 0x24	@ (TAG: DW_TAG_base_type)
+	.byte	0	@ DW_children_no
+	.uleb128 0xb	@ (DW_AT_byte_size)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3e	@ (DW_AT_encoding)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0x8	@ (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3f	@ (DW_AT_external)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2116	@ (DW_AT_GNU_all_tail_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3f	@ (DW_AT_external)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",%progbits
+	.4byte	0x1c	@ Length of Address Ranges Info
+	.2byte	0x2	@ DWARF Version
+	.4byte	.Ldebug_info0	@ Offset of Compilation Unit Info
+	.byte	0x4	@ Size of Address
+	.byte	0	@ Size of Segment Descriptor
+	.2byte	0	@ Pad to 8 byte boundary
+	.2byte	0
+	.4byte	.Ltext0	@ Address
+	.4byte	.Letext0-.Ltext0	@ Length
+	.4byte	0
+	.4byte	0
+	.section	.debug_line,"",%progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",%progbits,1
+.LASF5:
+	.ascii	"record_goto.c\000"
+.LASF2:
+	.ascii	"fun2\000"
+.LASF6:
+	.ascii	"/home/ubuntu/development/gdb/binutils-gdb/gdb/tests"
+	.ascii	"uite/gdb.btrace\000"
+.LASF4:
+	.ascii	"GNU C11 7.4.0 -march=armv7-a -mfloat-abi=hard -mfpu"
+	.ascii	"=vfpv3-d16 -mthumb -mtls-dialect=gnu -g -fstack-pro"
+	.ascii	"tector-strong\000"
+.LASF0:
+	.ascii	"fun4\000"
+.LASF3:
+	.ascii	"fun1\000"
+.LASF7:
+	.ascii	"main\000"
+.LASF1:
+	.ascii	"fun3\000"
+	.ident	"GCC: (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) 7.4.0"
+	.section	.note.GNU-stack,"",%progbits
diff --git a/gdb/testsuite/gdb.btrace/arm-tailcall-only.S b/gdb/testsuite/gdb.btrace/arm-tailcall-only.S
new file mode 100644
index 00000000000..b7f4e4a3fce
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/arm-tailcall-only.S
@@ -0,0 +1,504 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2016-2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated on an armv7 machine using:
+   gcc -S -O2 -dA -g tailcall-only.c -o arm-tailcall-only.S  */
+
+	.eabi_attribute 28, 1	@ Tag_ABI_VFP_args
+	.eabi_attribute 20, 1	@ Tag_ABI_FP_denormal
+	.eabi_attribute 21, 1	@ Tag_ABI_FP_exceptions
+	.eabi_attribute 23, 3	@ Tag_ABI_FP_number_model
+	.eabi_attribute 24, 1	@ Tag_ABI_align8_needed
+	.eabi_attribute 25, 1	@ Tag_ABI_align8_preserved
+	.eabi_attribute 26, 2	@ Tag_ABI_enum_size
+	.eabi_attribute 30, 2	@ Tag_ABI_optimization_goals
+	.eabi_attribute 34, 1	@ Tag_CPU_unaligned_access
+	.eabi_attribute 18, 4	@ Tag_ABI_PCS_wchar_t
+	.file	"tailcall-only.c"
+	.text
+.Ltext0:
+	.cfi_sections	.debug_frame
+	.align	1
+	.p2align 2,,3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	bar_1, %function
+bar_1:
+.LFB0:
+	.file 1 "tailcall-only.c"
+	@ tailcall-only.c:22
+	.loc 1 22 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+	@ tailcall-only.c:24
+	.loc 1 24 0
+	movs	r0, #42
+@ SUCC: EXIT [100.0%] 
+	bx	lr
+	.cfi_endproc
+.LFE0:
+	.size	bar_1, .-bar_1
+	.align	1
+	.p2align 2,,3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	bar, %function
+bar:
+.LFB1:
+	@ tailcall-only.c:28
+	.loc 1 28 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+@ SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+	@ tailcall-only.c:29
+	.loc 1 29 0
+	b	bar_1(PLT)
+.LVL0:
+	.cfi_endproc
+.LFE1:
+	.size	bar, .-bar
+	.align	1
+	.p2align 2,,3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	foo_1, %function
+foo_1:
+.LFB2:
+	@ tailcall-only.c:34
+	.loc 1 34 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+@ SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+	@ tailcall-only.c:35
+	.loc 1 35 0
+	b	bar(PLT)
+.LVL1:
+	.cfi_endproc
+.LFE2:
+	.size	foo_1, .-foo_1
+	.align	1
+	.p2align 2,,3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	foo, %function
+foo:
+.LFB3:
+	@ tailcall-only.c:40
+	.loc 1 40 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+@ SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+	@ tailcall-only.c:41
+	.loc 1 41 0
+	b	foo_1(PLT)
+.LVL2:
+	.cfi_endproc
+.LFE3:
+	.size	foo, .-foo
+	.section	.text.startup,"ax",%progbits
+	.align	1
+	.p2align 2,,3
+	.global	main
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	main, %function
+main:
+.LFB4:
+	@ tailcall-only.c:46
+	.loc 1 46 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+	push	{r3, lr}
+	.cfi_def_cfa_offset 8
+	.cfi_offset 3, -8
+	.cfi_offset 14, -4
+	@ tailcall-only.c:49
+	.loc 1 49 0
+	bl	foo(PLT)
+.LVL3:
+	@ tailcall-only.c:53
+	.loc 1 53 0
+	adds	r0, r0, #1
+.LVL4:
+@ SUCC: EXIT [100.0%] 
+	pop	{r3, pc}
+	.cfi_endproc
+.LFE4:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",%progbits
+.Ldebug_info0:
+	.4byte	0xd9	@ Length of Compilation Unit Info
+	.2byte	0x4	@ DWARF version number
+	.4byte	.Ldebug_abbrev0	@ Offset Into Abbrev. Section
+	.byte	0x4	@ Pointer Size (in bytes)
+	.uleb128 0x1	@ (DIE (0xb) DW_TAG_compile_unit)
+	.4byte	.LASF1	@ DW_AT_producer: "GNU C11 7.4.0 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb -mtls-dialect=gnu -g -O2 -fstack-protector-strong"
+	.byte	0xc	@ DW_AT_language
+	.4byte	.LASF2	@ DW_AT_name: "tailcall-only.c"
+	.4byte	.LASF3	@ DW_AT_comp_dir: "/home/ubuntu/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+	.4byte	.Ldebug_ranges0+0	@ DW_AT_ranges
+	.4byte	0	@ DW_AT_low_pc
+	.4byte	.Ldebug_line0	@ DW_AT_stmt_list
+	.uleb128 0x2	@ (DIE (0x25) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF4	@ DW_AT_name: "main"
+	.byte	0x1	@ DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2d	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB4	@ DW_AT_low_pc
+	.4byte	.LFE4-.LFB4	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.4byte	0x57	@ DW_AT_sibling
+	.uleb128 0x3	@ (DIE (0x3e) DW_TAG_variable)
+	.4byte	.LASF5	@ DW_AT_name: "answer"
+	.byte	0x1	@ DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2f	@ DW_AT_decl_line
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LLST0	@ DW_AT_location
+	.uleb128 0x4	@ (DIE (0x4d) DW_TAG_GNU_call_site)
+	.4byte	.LVL3	@ DW_AT_low_pc
+	.4byte	0x5e	@ DW_AT_abstract_origin
+	.byte	0	@ end of children of DIE 0x25
+	.uleb128 0x5	@ (DIE (0x57) DW_TAG_base_type)
+	.byte	0x4	@ DW_AT_byte_size
+	.byte	0x5	@ DW_AT_encoding
+	.ascii "int\0"	@ DW_AT_name
+	.uleb128 0x6	@ (DIE (0x5e) DW_TAG_subprogram)
+	.ascii "foo\0"	@ DW_AT_name
+	.byte	0x1	@ DW_AT_decl_file (tailcall-only.c)
+	.byte	0x27	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB3	@ DW_AT_low_pc
+	.4byte	.LFE3-.LFB3	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.4byte	0x81	@ DW_AT_sibling
+	.uleb128 0x7	@ (DIE (0x77) DW_TAG_GNU_call_site)
+	.4byte	.LVL2	@ DW_AT_low_pc
+			@ DW_AT_GNU_tail_call
+	.4byte	0x81	@ DW_AT_abstract_origin
+	.byte	0	@ end of children of DIE 0x5e
+	.uleb128 0x8	@ (DIE (0x81) DW_TAG_subprogram)
+	.4byte	.LASF0	@ DW_AT_name: "foo_1"
+	.byte	0x1	@ DW_AT_decl_file (tailcall-only.c)
+	.byte	0x21	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB2	@ DW_AT_low_pc
+	.4byte	.LFE2-.LFB2	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.4byte	0xa4	@ DW_AT_sibling
+	.uleb128 0x7	@ (DIE (0x9a) DW_TAG_GNU_call_site)
+	.4byte	.LVL1	@ DW_AT_low_pc
+			@ DW_AT_GNU_tail_call
+	.4byte	0xa4	@ DW_AT_abstract_origin
+	.byte	0	@ end of children of DIE 0x81
+	.uleb128 0x6	@ (DIE (0xa4) DW_TAG_subprogram)
+	.ascii "bar\0"	@ DW_AT_name
+	.byte	0x1	@ DW_AT_decl_file (tailcall-only.c)
+	.byte	0x1b	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB1	@ DW_AT_low_pc
+	.4byte	.LFE1-.LFB1	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.4byte	0xc7	@ DW_AT_sibling
+	.uleb128 0x7	@ (DIE (0xbd) DW_TAG_GNU_call_site)
+	.4byte	.LVL0	@ DW_AT_low_pc
+			@ DW_AT_GNU_tail_call
+	.4byte	0xc7	@ DW_AT_abstract_origin
+	.byte	0	@ end of children of DIE 0xa4
+	.uleb128 0x9	@ (DIE (0xc7) DW_TAG_subprogram)
+	.4byte	.LASF6	@ DW_AT_name: "bar_1"
+	.byte	0x1	@ DW_AT_decl_file (tailcall-only.c)
+	.byte	0x15	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB0	@ DW_AT_low_pc
+	.4byte	.LFE0-.LFB0	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.byte	0	@ end of children of DIE 0xb
+	.section	.debug_abbrev,"",%progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	@ (abbrev code)
+	.uleb128 0x11	@ (TAG: DW_TAG_compile_unit)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x25	@ (DW_AT_producer)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x13	@ (DW_AT_language)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x1b	@ (DW_AT_comp_dir)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x55	@ (DW_AT_ranges)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x10	@ (DW_AT_stmt_list)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x3f	@ (DW_AT_external)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x1	@ (DW_AT_sibling)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	@ (abbrev code)
+	.uleb128 0x34	@ (TAG: DW_TAG_variable)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x2	@ (DW_AT_location)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	@ (abbrev code)
+	.uleb128 0x4109	@ (TAG: DW_TAG_GNU_call_site)
+	.byte	0	@ DW_children_no
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x31	@ (DW_AT_abstract_origin)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	@ (abbrev code)
+	.uleb128 0x24	@ (TAG: DW_TAG_base_type)
+	.byte	0	@ DW_children_no
+	.uleb128 0xb	@ (DW_AT_byte_size)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3e	@ (DW_AT_encoding)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0x8	@ (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0x8	@ (DW_FORM_string)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x1	@ (DW_AT_sibling)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	@ (abbrev code)
+	.uleb128 0x4109	@ (TAG: DW_TAG_GNU_call_site)
+	.byte	0	@ DW_children_no
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x2115	@ (DW_AT_GNU_tail_call)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x31	@ (DW_AT_abstract_origin)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x1	@ (DW_AT_sibling)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x9	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",%progbits
+.Ldebug_loc0:
+.LLST0:
+	.4byte	.LVL3	@ Location list begin address (*.LLST0)
+	.4byte	.LVL4	@ Location list end address (*.LLST0)
+	.2byte	0x3	@ Location expression size
+	.byte	0x70	@ DW_OP_breg0
+	.sleb128 1
+	.byte	0x9f	@ DW_OP_stack_value
+	.4byte	.LVL4	@ Location list begin address (*.LLST0)
+	.4byte	.LFE4	@ Location list end address (*.LLST0)
+	.2byte	0x1	@ Location expression size
+	.byte	0x50	@ DW_OP_reg0
+	.4byte	0	@ Location list terminator begin (*.LLST0)
+	.4byte	0	@ Location list terminator end (*.LLST0)
+	.section	.debug_aranges,"",%progbits
+	.4byte	0x24	@ Length of Address Ranges Info
+	.2byte	0x2	@ DWARF Version
+	.4byte	.Ldebug_info0	@ Offset of Compilation Unit Info
+	.byte	0x4	@ Size of Address
+	.byte	0	@ Size of Segment Descriptor
+	.2byte	0	@ Pad to 8 byte boundary
+	.2byte	0
+	.4byte	.Ltext0	@ Address
+	.4byte	.Letext0-.Ltext0	@ Length
+	.4byte	.LFB4	@ Address
+	.4byte	.LFE4-.LFB4	@ Length
+	.4byte	0
+	.4byte	0
+	.section	.debug_ranges,"",%progbits
+.Ldebug_ranges0:
+	.4byte	.Ltext0	@ Offset 0
+	.4byte	.Letext0
+	.4byte	.LFB4	@ Offset 0x8
+	.4byte	.LFE4
+	.4byte	0
+	.4byte	0
+	.section	.debug_line,"",%progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",%progbits,1
+.LASF2:
+	.ascii	"tailcall-only.c\000"
+.LASF5:
+	.ascii	"answer\000"
+.LASF1:
+	.ascii	"GNU C11 7.4.0 -march=armv7-a -mfloat-abi=hard -mfpu"
+	.ascii	"=vfpv3-d16 -mthumb -mtls-dialect=gnu -g -O2 -fstack"
+	.ascii	"-protector-strong\000"
+.LASF4:
+	.ascii	"main\000"
+.LASF6:
+	.ascii	"bar_1\000"
+.LASF3:
+	.ascii	"/home/ubuntu/development/gdb/binutils-gdb/gdb/tests"
+	.ascii	"uite/gdb.btrace\000"
+.LASF0:
+	.ascii	"foo_1\000"
+	.ident	"GCC: (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) 7.4.0"
+	.section	.note.GNU-stack,"",%progbits
diff --git a/gdb/testsuite/gdb.btrace/arm-tailcall.S b/gdb/testsuite/gdb.btrace/arm-tailcall.S
new file mode 100644
index 00000000000..125b614524a
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/arm-tailcall.S
@@ -0,0 +1,391 @@
+ /* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013-2020 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+   This file has been generated on an armv7 machine using:
+   gcc -S -O2 -dA -g tailcall.c -o arm-tailcall.S  */
+
+	.eabi_attribute 28, 1	@ Tag_ABI_VFP_args
+	.eabi_attribute 20, 1	@ Tag_ABI_FP_denormal
+	.eabi_attribute 21, 1	@ Tag_ABI_FP_exceptions
+	.eabi_attribute 23, 3	@ Tag_ABI_FP_number_model
+	.eabi_attribute 24, 1	@ Tag_ABI_align8_needed
+	.eabi_attribute 25, 1	@ Tag_ABI_align8_preserved
+	.eabi_attribute 26, 2	@ Tag_ABI_enum_size
+	.eabi_attribute 30, 2	@ Tag_ABI_optimization_goals
+	.eabi_attribute 34, 1	@ Tag_CPU_unaligned_access
+	.eabi_attribute 18, 4	@ Tag_ABI_PCS_wchar_t
+	.file	"tailcall.c"
+	.text
+.Ltext0:
+	.cfi_sections	.debug_frame
+	.align	1
+	.p2align 2,,3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	bar, %function
+bar:
+.LFB0:
+	.file 1 "tailcall.c"
+	@ tailcall.c:22
+	.loc 1 22 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+	@ tailcall.c:24
+	.loc 1 24 0
+	movs	r0, #42
+@ SUCC: EXIT [100.0%] 
+	bx	lr
+	.cfi_endproc
+.LFE0:
+	.size	bar, .-bar
+	.align	1
+	.p2align 2,,3
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	foo, %function
+foo:
+.LFB1:
+	@ tailcall.c:28
+	.loc 1 28 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+	@ link register save eliminated.
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+@ SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+	@ tailcall.c:29
+	.loc 1 29 0
+	b	bar(PLT)
+.LVL0:
+	.cfi_endproc
+.LFE1:
+	.size	foo, .-foo
+	.section	.text.startup,"ax",%progbits
+	.align	1
+	.p2align 2,,3
+	.global	main
+	.syntax unified
+	.thumb
+	.thumb_func
+	.fpu vfpv3-d16
+	.type	main, %function
+main:
+.LFB2:
+	@ tailcall.c:34
+	.loc 1 34 0
+	.cfi_startproc
+	@ args = 0, pretend = 0, frame = 0
+	@ frame_needed = 0, uses_anonymous_args = 0
+@ BLOCK 2 freq:10000 seq:0
+@ PRED: ENTRY [100.0%]  (FALLTHRU)
+	push	{r3, lr}
+	.cfi_def_cfa_offset 8
+	.cfi_offset 3, -8
+	.cfi_offset 14, -4
+	@ tailcall.c:37
+	.loc 1 37 0
+	bl	foo(PLT)
+.LVL1:
+	@ tailcall.c:41
+	.loc 1 41 0
+	adds	r0, r0, #1
+.LVL2:
+@ SUCC: EXIT [100.0%] 
+	pop	{r3, pc}
+	.cfi_endproc
+.LFE2:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",%progbits
+.Ldebug_info0:
+	.4byte	0x93	@ Length of Compilation Unit Info
+	.2byte	0x4	@ DWARF version number
+	.4byte	.Ldebug_abbrev0	@ Offset Into Abbrev. Section
+	.byte	0x4	@ Pointer Size (in bytes)
+	.uleb128 0x1	@ (DIE (0xb) DW_TAG_compile_unit)
+	.4byte	.LASF0	@ DW_AT_producer: "GNU C11 7.4.0 -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mthumb -mtls-dialect=gnu -g -O2 -fstack-protector-strong"
+	.byte	0xc	@ DW_AT_language
+	.4byte	.LASF1	@ DW_AT_name: "tailcall.c"
+	.4byte	.LASF2	@ DW_AT_comp_dir: "/home/ubuntu/development/gdb/binutils-gdb/gdb/testsuite/gdb.btrace"
+	.4byte	.Ldebug_ranges0+0	@ DW_AT_ranges
+	.4byte	0	@ DW_AT_low_pc
+	.4byte	.Ldebug_line0	@ DW_AT_stmt_list
+	.uleb128 0x2	@ (DIE (0x25) DW_TAG_subprogram)
+			@ DW_AT_external
+	.4byte	.LASF3	@ DW_AT_name: "main"
+	.byte	0x1	@ DW_AT_decl_file (tailcall.c)
+	.byte	0x21	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB2	@ DW_AT_low_pc
+	.4byte	.LFE2-.LFB2	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.4byte	0x57	@ DW_AT_sibling
+	.uleb128 0x3	@ (DIE (0x3e) DW_TAG_variable)
+	.4byte	.LASF4	@ DW_AT_name: "answer"
+	.byte	0x1	@ DW_AT_decl_file (tailcall.c)
+	.byte	0x23	@ DW_AT_decl_line
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LLST0	@ DW_AT_location
+	.uleb128 0x4	@ (DIE (0x4d) DW_TAG_GNU_call_site)
+	.4byte	.LVL1	@ DW_AT_low_pc
+	.4byte	0x5e	@ DW_AT_abstract_origin
+	.byte	0	@ end of children of DIE 0x25
+	.uleb128 0x5	@ (DIE (0x57) DW_TAG_base_type)
+	.byte	0x4	@ DW_AT_byte_size
+	.byte	0x5	@ DW_AT_encoding
+	.ascii "int\0"	@ DW_AT_name
+	.uleb128 0x6	@ (DIE (0x5e) DW_TAG_subprogram)
+	.ascii "foo\0"	@ DW_AT_name
+	.byte	0x1	@ DW_AT_decl_file (tailcall.c)
+	.byte	0x1b	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB1	@ DW_AT_low_pc
+	.4byte	.LFE1-.LFB1	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.4byte	0x81	@ DW_AT_sibling
+	.uleb128 0x7	@ (DIE (0x77) DW_TAG_GNU_call_site)
+	.4byte	.LVL0	@ DW_AT_low_pc
+			@ DW_AT_GNU_tail_call
+	.4byte	0x81	@ DW_AT_abstract_origin
+	.byte	0	@ end of children of DIE 0x5e
+	.uleb128 0x8	@ (DIE (0x81) DW_TAG_subprogram)
+	.ascii "bar\0"	@ DW_AT_name
+	.byte	0x1	@ DW_AT_decl_file (tailcall.c)
+	.byte	0x15	@ DW_AT_decl_line
+			@ DW_AT_prototyped
+	.4byte	0x57	@ DW_AT_type
+	.4byte	.LFB0	@ DW_AT_low_pc
+	.4byte	.LFE0-.LFB0	@ DW_AT_high_pc
+	.uleb128 0x1	@ DW_AT_frame_base
+	.byte	0x9c	@ DW_OP_call_frame_cfa
+			@ DW_AT_GNU_all_call_sites
+	.byte	0	@ end of children of DIE 0xb
+	.section	.debug_abbrev,"",%progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	@ (abbrev code)
+	.uleb128 0x11	@ (TAG: DW_TAG_compile_unit)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x25	@ (DW_AT_producer)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x13	@ (DW_AT_language)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x1b	@ (DW_AT_comp_dir)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x55	@ (DW_AT_ranges)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x10	@ (DW_AT_stmt_list)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x3f	@ (DW_AT_external)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x1	@ (DW_AT_sibling)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	@ (abbrev code)
+	.uleb128 0x34	@ (TAG: DW_TAG_variable)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0xe	@ (DW_FORM_strp)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x2	@ (DW_AT_location)
+	.uleb128 0x17	@ (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	@ (abbrev code)
+	.uleb128 0x4109	@ (TAG: DW_TAG_GNU_call_site)
+	.byte	0	@ DW_children_no
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x31	@ (DW_AT_abstract_origin)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	@ (abbrev code)
+	.uleb128 0x24	@ (TAG: DW_TAG_base_type)
+	.byte	0	@ DW_children_no
+	.uleb128 0xb	@ (DW_AT_byte_size)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3e	@ (DW_AT_encoding)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0x8	@ (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0x1	@ DW_children_yes
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0x8	@ (DW_FORM_string)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x1	@ (DW_AT_sibling)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	@ (abbrev code)
+	.uleb128 0x4109	@ (TAG: DW_TAG_GNU_call_site)
+	.byte	0	@ DW_children_no
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x2115	@ (DW_AT_GNU_tail_call)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x31	@ (DW_AT_abstract_origin)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	@ (abbrev code)
+	.uleb128 0x2e	@ (TAG: DW_TAG_subprogram)
+	.byte	0	@ DW_children_no
+	.uleb128 0x3	@ (DW_AT_name)
+	.uleb128 0x8	@ (DW_FORM_string)
+	.uleb128 0x3a	@ (DW_AT_decl_file)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x3b	@ (DW_AT_decl_line)
+	.uleb128 0xb	@ (DW_FORM_data1)
+	.uleb128 0x27	@ (DW_AT_prototyped)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.uleb128 0x49	@ (DW_AT_type)
+	.uleb128 0x13	@ (DW_FORM_ref4)
+	.uleb128 0x11	@ (DW_AT_low_pc)
+	.uleb128 0x1	@ (DW_FORM_addr)
+	.uleb128 0x12	@ (DW_AT_high_pc)
+	.uleb128 0x6	@ (DW_FORM_data4)
+	.uleb128 0x40	@ (DW_AT_frame_base)
+	.uleb128 0x18	@ (DW_FORM_exprloc)
+	.uleb128 0x2117	@ (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	@ (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"",%progbits
+.Ldebug_loc0:
+.LLST0:
+	.4byte	.LVL1	@ Location list begin address (*.LLST0)
+	.4byte	.LVL2	@ Location list end address (*.LLST0)
+	.2byte	0x3	@ Location expression size
+	.byte	0x70	@ DW_OP_breg0
+	.sleb128 1
+	.byte	0x9f	@ DW_OP_stack_value
+	.4byte	.LVL2	@ Location list begin address (*.LLST0)
+	.4byte	.LFE2	@ Location list end address (*.LLST0)
+	.2byte	0x1	@ Location expression size
+	.byte	0x50	@ DW_OP_reg0
+	.4byte	0	@ Location list terminator begin (*.LLST0)
+	.4byte	0	@ Location list terminator end (*.LLST0)
+	.section	.debug_aranges,"",%progbits
+	.4byte	0x24	@ Length of Address Ranges Info
+	.2byte	0x2	@ DWARF Version
+	.4byte	.Ldebug_info0	@ Offset of Compilation Unit Info
+	.byte	0x4	@ Size of Address
+	.byte	0	@ Size of Segment Descriptor
+	.2byte	0	@ Pad to 8 byte boundary
+	.2byte	0
+	.4byte	.Ltext0	@ Address
+	.4byte	.Letext0-.Ltext0	@ Length
+	.4byte	.LFB2	@ Address
+	.4byte	.LFE2-.LFB2	@ Length
+	.4byte	0
+	.4byte	0
+	.section	.debug_ranges,"",%progbits
+.Ldebug_ranges0:
+	.4byte	.Ltext0	@ Offset 0
+	.4byte	.Letext0
+	.4byte	.LFB2	@ Offset 0x8
+	.4byte	.LFE2
+	.4byte	0
+	.4byte	0
+	.section	.debug_line,"",%progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",%progbits,1
+.LASF0:
+	.ascii	"GNU C11 7.4.0 -march=armv7-a -mfloat-abi=hard -mfpu"
+	.ascii	"=vfpv3-d16 -mthumb -mtls-dialect=gnu -g -O2 -fstack"
+	.ascii	"-protector-strong\000"
+.LASF4:
+	.ascii	"answer\000"
+.LASF1:
+	.ascii	"tailcall.c\000"
+.LASF2:
+	.ascii	"/home/ubuntu/development/gdb/binutils-gdb/gdb/tests"
+	.ascii	"uite/gdb.btrace\000"
+.LASF3:
+	.ascii	"main\000"
+	.ident	"GCC: (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) 7.4.0"
+	.section	.note.GNU-stack,"",%progbits
diff --git a/gdb/testsuite/gdb.btrace/buffer-size.exp b/gdb/testsuite/gdb.btrace/buffer-size.exp
index ea4e36c1593..77d7b77852a 100644
--- a/gdb/testsuite/gdb.btrace/buffer-size.exp
+++ b/gdb/testsuite/gdb.btrace/buffer-size.exp
@@ -32,10 +32,17 @@ if ![runto_main] {
     return -1
 }
 
-gdb_test_no_output "set record btrace bts buffer-size 1"
-gdb_test_no_output "set record btrace pt buffer-size 1"
-gdb_test "show record btrace bts buffer-size" "The record/replay bts buffer size is 1\.\r"
-gdb_test "show record btrace pt buffer-size" "The record/replay pt buffer size is 1\.\r"
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    gdb_test_no_output "set record btrace bts buffer-size 1"
+    gdb_test_no_output "set record btrace pt buffer-size 1"
+    gdb_test "show record btrace bts buffer-size" "The record/replay bts buffer size is 1\.\r"
+    gdb_test "show record btrace pt buffer-size" "The record/replay pt buffer size is 1\.\r"
+}
+
+if {[istarget "arm*-*-*"]|| [istarget "aarch64*-*-*"]} {
+    gdb_test_no_output "set record btrace etm buffer-size 1"
+    gdb_test "show record btrace etm buffer-size" "The record/replay etm buffer size is 1\.\r"
+}
 
 gdb_test_no_output "record btrace"
 gdb_test "info record" [multi_line \
diff --git a/gdb/testsuite/gdb.btrace/delta.exp b/gdb/testsuite/gdb.btrace/delta.exp
index 9f6d741c013..2c8bada2065 100644
--- a/gdb/testsuite/gdb.btrace/delta.exp
+++ b/gdb/testsuite/gdb.btrace/delta.exp
@@ -58,8 +58,18 @@ proc check_trace {} {
     "Recording format: .*" \
     "Recorded 1 instructions in 1 functions \\\(0 gaps\\\) for .*" \
     ]
+  if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
     gdb_test "record instruction-history /f 1" \
       "1\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tmov *\\\$0x0,%eax\r"
+  }
+  if { [istarget "arm*-*-*"] } {
+    gdb_test "record instruction-history /f 1" \
+      "1\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tmovs\tr3, #0\r"
+  }
+  if { [istarget "aarch64*-*-*"]} {
+    gdb_test "record instruction-history /f 1" \
+      "1\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tmov\tw0, #0x0.*\r"
+  }
   gdb_test "record function-call-history /c 1" "1\tmain"
 }
 
diff --git a/gdb/testsuite/gdb.btrace/instruction_history.exp b/gdb/testsuite/gdb.btrace/instruction_history.exp
index 403085c083f..76fcadb9ac2 100644
--- a/gdb/testsuite/gdb.btrace/instruction_history.exp
+++ b/gdb/testsuite/gdb.btrace/instruction_history.exp
@@ -21,8 +21,14 @@ if { [skip_btrace_tests] } {
     unsupported "target does not support record-btrace"
     return -1
 }
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
+  standard_testfile instruction_history.c x86-instruction_history.S
+} elseif { [istarget "arm*-*-*"] } {
+  standard_testfile instruction_history.c arm-instruction_history.S
+} elseif { [istarget "aarch64*-*-*"]} {
+  standard_testfile instruction_history.c aarch64-instruction_history.S
+}
 
-standard_testfile .c .S
 if [prepare_for_testing "failed to prepare" $testfile "$srcfile $srcfile2" {debug}] {
     return -1
 }
@@ -68,39 +74,128 @@ if { $traced != 11 } {
 }
 
 # test that we see the expected instructions
-gdb_test "record instruction-history 3,7" [multi_line \
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
+  gdb_test "record instruction-history 3,7" [multi_line \
     "3\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "4\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tdec    %eax" \
     "5\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tjmp    0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "6\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tcmp    \\\$0x0,%eax" \
     "7\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
     ]
+}
+if { [istarget "arm*-*-*"] } {
+  gdb_test "record instruction-history 3,7" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>" \
+    "4\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tsubs\tr0, r0, #1" \
+    "5\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>" \
+    "6\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tcmp\tr0, #0" \
+    "7\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>\r" \
+    ]
+}
+if { [istarget "aarch64*-*-*"]} {
+  gdb_test "record instruction-history 3,7" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>.*" \
+    "4\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tsubs\tx0, x0, #0x1.*" \
+    "5\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>.*" \
+    "6\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tcmp\tx0, #0x0.*" \
+    "7\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>.*\r" \
+    ]
+}
 
-gdb_test "record instruction-history /f 3,+5" [multi_line \
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
+  gdb_test "record instruction-history /f 3,+5" [multi_line \
     "3\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "4\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tdec    %eax" \
     "5\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tjmp    0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "6\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp    \\\$0x0,%eax" \
     "7\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
     ]
+}
+if { [istarget "arm*-*-*"] } {
+  gdb_test "record instruction-history /f 3,+5" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>" \
+    "4\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tsubs\tr0, r0, #1" \
+    "5\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>" \
+    "6\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp\tr0, #0" \
+    "7\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>\r" \
+    ]
+}
+if { [istarget "aarch64*-*-*"]} {
+  gdb_test "record instruction-history /f 3,+5" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>.*" \
+    "4\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tsubs\tx0, x0, #0x1.*" \
+    "5\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>.*" \
+    "6\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp\tx0, #0x0.*" \
+    "7\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>.*\r" \
+    ]
+}
 
-gdb_test "record instruction-history /p 7,-5" [multi_line \
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
+  gdb_test "record instruction-history /p 7,-5" [multi_line \
     "3\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "4\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tdec    %eax" \
     "5\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tjmp    0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "6\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tcmp    \\\$0x0,%eax" \
     "7\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
     ]
+}
+if { [istarget "arm*-*-*"] } {
+  gdb_test "record instruction-history /p 7,-5" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>" \
+    "4\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tsubs\tr0, r0, #1" \
+    "5\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>" \
+    "6\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tcmp\tr0, #0" \
+    "7\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>\r" \
+    ]
+}
+if { [istarget "aarch64*-*-*"]} {
+  gdb_test "record instruction-history /p 7,-5" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>.*" \
+    "4\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tsubs\tx0, x0, #0x1.*" \
+    "5\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>.*" \
+    "6\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tcmp\tx0, #0x0.*" \
+    "7\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>.*\r" \
+    ]
+}
 
-gdb_test "record instruction-history /pf 3,7" [multi_line \
+
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
+  gdb_test "record instruction-history /pf 3,7" [multi_line \
     "3\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "4\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tdec    %eax" \
     "5\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tjmp    0x\[0-9a-f\]+ <loop\\+\[0-9\]+>" \
     "6\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp    \\\$0x0,%eax" \
     "7\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r" \
     ]
+}
+if { [istarget "arm*-*-*"] } {
+  gdb_test "record instruction-history /pf 3,7" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>" \
+    "4\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tsubs\tr0, r0, #1" \
+    "5\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>" \
+    "6\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp\tr0, #0" \
+    "7\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>\r" \
+    ]
+}
+if { [istarget "aarch64*-*-*"]} {
+  gdb_test "record instruction-history /pf 3,7" [multi_line \
+    "3\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\\.eq\t0x\[0-9a-f\]+ <L2>.*" \
+    "4\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tsubs\tx0, x0, #0x1.*" \
+    "5\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\t0x\[0-9a-f\]+ <L1>.*" \
+    "6\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tcmp\tx0, #0x0.*" \
+    "7\t   0x\[0-9a-f\]+ <\\+\[0-9\]+>:\tb\\.eq\t0x\[0-9a-f\]+ <L2>.*\r" \
+    ]
+}
 
-gdb_test "record instruction-history 3,3" "3\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r"
+if { [istarget "i?86-*-*"] || [istarget "x86_64-*-*"] } {
+  gdb_test "record instruction-history 3,3" "3\t   0x\[0-9a-f\]+ <loop\\+\[0-9\]+>:\tje     0x\[0-9a-f\]+ <loop\\+\[0-9\]+>\r"
+}
+if { [istarget "arm*-*-*"] } {
+  gdb_test "record instruction-history 3,3" "3\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tbeq\t0x\[0-9a-f\]+ <L2>\r"
+}
+if { [istarget "aarch64*-*-*"]} {
+  gdb_test "record instruction-history 3,3" "3\t   0x\[0-9a-f\]+ <L1\\+\[0-9\]+>:\tb\.eq\t0x\[0-9a-f\]+ <L2>  // b\.none\r"
+}
 
 # the following tests are checking the iterators
 # to avoid lots of regexps, we just check the number of lines that
diff --git a/gdb/testsuite/gdb.btrace/non-stop.exp b/gdb/testsuite/gdb.btrace/non-stop.exp
index 40cced7a8bb..58459de5359 100644
--- a/gdb/testsuite/gdb.btrace/non-stop.exp
+++ b/gdb/testsuite/gdb.btrace/non-stop.exp
@@ -31,6 +31,12 @@ save_vars { GDBFLAGS } {
     clean_restart $testfile
 }
 
+if {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    set loop_position 2
+} elseif {[istarget "arm*-*-*"] || [istarget "aarch64*-*-*"]} {
+    set loop_position 3
+}
+
 if ![runto_main] {
     untested "failed to run to main"
     return -1
@@ -111,87 +117,99 @@ gdb_test "thread apply all info rec" ".*"
 gdb_test "info threads" ".*"
 
 with_test_prefix "navigate" {
-    gdb_test "thread apply 1 record goto 2" "$loop_line"
-    gdb_test "thread apply 2 record goto 4" "$loop_line"
+    gdb_test "thread apply 1 record goto $loop_position" "$loop_line"
+    gdb_test "thread apply 2 record goto [expr {$loop_position + 2}]" "$loop_line"
     gdb_test "thread apply 1 info record" \
-        ".*Replay in progress\.  At instruction 2\." "thread 1 at insn 2"
+        ".*Replay in progress\.  At instruction $loop_position\." "thread 1 at insn $loop_position"
     gdb_test "thread apply 2 info record" \
-        ".*Replay in progress\.  At instruction 4\." "thread 2 at insn 4"
+        ".*Replay in progress\.  At instruction [expr {$loop_position + 2}]\." "thread 2 at insn [expr {$loop_position + 2}]"
 
-    gdb_test "thread apply all record goto 5" "$loop_line"
+    gdb_test "thread apply all record goto [expr {$loop_position + 3}]" "$loop_line"
     gdb_test "thread apply 1 info record" \
-        ".*Replay in progress\.  At instruction 5\." "thread 1 at insn 5"
+        ".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\." "thread 1 at insn [expr {$loop_position + 3}]"
     gdb_test "thread apply 2 info record" \
-        ".*Replay in progress\.  At instruction 5\." "thread 2 at insn 5"
+        ".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\." "thread 2 at insn [expr {$loop_position + 3}]"
 }
 
 with_test_prefix "step" {
+    with_test_prefix "fixture" {
+	gdb_test "thread apply 1 record goto [expr {$loop_position + 3}]" ".*"
+	gdb_test "thread apply 2 record goto [expr {$loop_position + 3}]" ".*"
+    }
     with_test_prefix "thread 1" {
         gdb_test "thread apply 1 stepi 2" "$loop_line"
         gdb_test "thread apply 1 info record" \
-            ".*Replay in progress\.  At instruction 7\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 5}]\."
         gdb_test "thread apply 2 info record" \
-            ".*Replay in progress\.  At instruction 5\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\."
     }
 
     with_test_prefix "thread 2" {
         gdb_test "thread apply 2 stepi 3" "$loop_line"
         gdb_test "thread apply 1 info record" \
-            ".*Replay in progress\.  At instruction 7\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 5}]\."
         gdb_test "thread apply 2 info record" \
-            ".*Replay in progress\.  At instruction 8\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 6}]\."
     }
 
     with_test_prefix "all" {
         gdb_cont_to all "stepi 4" "$loop_line" 2
         gdb_test "thread apply 1 info record" \
-            ".*Replay in progress\.  At instruction 11\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 9}]\."
         gdb_test "thread apply 2 info record" \
-            ".*Replay in progress\.  At instruction 12\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 10}]\."
     }
 }
 
 with_test_prefix "reverse-step" {
+    with_test_prefix "fixture" {
+        gdb_test "thread apply 1 record goto [expr {$loop_position + 9}]" ".*"
+        gdb_test "thread apply 2 record goto [expr {$loop_position + 10}]" ".*"
+    }
     with_test_prefix "thread 1" {
         gdb_test "thread apply 1 reverse-stepi 2" "$loop_line"
         gdb_test "thread apply 1 info record" \
-            ".*Replay in progress\.  At instruction 9\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 7}]\."
         gdb_test "thread apply 2 info record" \
-            ".*Replay in progress\.  At instruction 12\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 10}]\."
     }
 
     with_test_prefix "thread 2" {
         gdb_test "thread apply 2 reverse-stepi 3" "$loop_line"
         gdb_test "thread apply 1 info record" \
-            ".*Replay in progress\.  At instruction 9\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 7}]\."
         gdb_test "thread apply 2 info record" \
-            ".*Replay in progress\.  At instruction 9\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 7}]\."
     }
 
     with_test_prefix "all" {
         gdb_cont_to all "reverse-stepi 4" "$loop_line" 2
         gdb_test "thread apply 1 info record" \
-            ".*Replay in progress\.  At instruction 5\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\."
         gdb_test "thread apply 2 info record" \
-            ".*Replay in progress\.  At instruction 5\."
+            ".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\."
     }
 }
 
 with_test_prefix "continue" {
+    with_test_prefix "fixture" {
+	gdb_test "thread apply 1 record goto [expr {$loop_position + 3}]" ".*"
+	gdb_test "thread apply 2 record goto [expr {$loop_position + 3}]" ".*"
+    }
     with_test_prefix "thread 1" {
 	with_test_prefix "continue" {
 	    gdb_cont_to_no_history 1 "continue" 1
 	    gdb_test "thread apply 1 info record" \
 		".*Recorded \[0-9\]+ instructions \[^\\\r\\\n\]*"
 	    gdb_test "thread apply 2 info record" \
-		".*Replay in progress\.  At instruction 5\."
+		".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\."
 	}
 	with_test_prefix "reverse-continue" {
 	    gdb_cont_to_no_history 1 "reverse-continue" 1
 	    gdb_test "thread apply 1 info record" \
 		".*Replay in progress\.  At instruction 1\."
 	    gdb_test "thread apply 2 info record" \
-		".*Replay in progress\.  At instruction 5\."
+		".*Replay in progress\.  At instruction [expr {$loop_position + 3}]\."
 	}
     }
 
diff --git a/gdb/testsuite/gdb.btrace/record_goto.exp b/gdb/testsuite/gdb.btrace/record_goto.exp
index 75d76da1c7f..a04983a4859 100644
--- a/gdb/testsuite/gdb.btrace/record_goto.exp
+++ b/gdb/testsuite/gdb.btrace/record_goto.exp
@@ -41,6 +41,10 @@ if [info exists COMPILE] {
 	} else {
 		standard_testfile i686-record_goto.S
 	}
+} elseif {[istarget "arm*-*-*"]} {
+	standard_testfile arm-record_goto.S
+} elseif {[istarget "aarch64*-*-*"]} {
+	standard_testfile aarch64-record_goto.S
 } else {
     unsupported "target architecture not supported"
     return -1
@@ -50,6 +54,126 @@ if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] {
     return -1
 }
 
+if {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    set function_positions(0) 19
+    set function_positions(1) 27
+    set function_positions(2) 2
+    set function_positions(end) 40
+    set function_positions(3) 39
+
+    set sequence_begin(1) 1
+    set sequence_end(1) 1
+    set sequence_begin(2) 2
+    set sequence_end(2) 4
+    set sequence_begin(3) 5
+    set sequence_end(3) 8
+    set sequence_begin(4) 9
+    set sequence_end(4) 9
+    set sequence_begin(5) 10
+    set sequence_end(5) 12
+    set sequence_begin(6) 13
+    set sequence_end(6) 16
+    set sequence_begin(7) 17
+    set sequence_end(7) 18
+    set sequence_begin(8) 19
+    set sequence_end(8) 19
+    set sequence_begin(9) 20
+    set sequence_end(9) 22
+    set sequence_begin(10) 23
+    set sequence_end(10) 26
+    set sequence_begin(11) 27
+    set sequence_end(11) 27
+    set sequence_begin(12) 28
+    set sequence_end(12) 30
+    set sequence_begin(13) 31
+    set sequence_end(13) 34
+    set sequence_begin(14) 35
+    set sequence_end(14) 36
+    set sequence_begin(15) 37
+    set sequence_end(15) 38
+    set sequence_begin(16) 39
+    set sequence_end(16) 40
+
+} elseif {[istarget "arm*-*-*"]} {
+    set function_positions(0) 23
+    set function_positions(1) 33
+    set function_positions(2) 2
+    set function_positions(end) 48
+    set function_positions(3) 47
+
+    set sequence_begin(1) 1
+    set sequence_end(1) 1
+    set sequence_begin(2) 2
+    set sequence_end(2) 4
+    set sequence_begin(3) 5
+    set sequence_end(3) 10
+    set sequence_begin(4) 11
+    set sequence_end(4) 11
+    set sequence_begin(5) 12
+    set sequence_end(5) 14
+    set sequence_begin(6) 15
+    set sequence_end(6) 20
+    set sequence_begin(7) 21
+    set sequence_end(7) 22
+    set sequence_begin(8) 23
+    set sequence_end(8) 23
+    set sequence_begin(9) 24
+    set sequence_end(9) 26
+    set sequence_begin(10) 27
+    set sequence_end(10) 32
+    set sequence_begin(11) 33
+    set sequence_end(11) 33
+    set sequence_begin(12) 34
+    set sequence_end(12) 36
+    set sequence_begin(13) 37
+    set sequence_end(13) 42
+    set sequence_begin(14) 43
+    set sequence_end(14) 44
+    set sequence_begin(15) 45
+    set sequence_end(15) 46
+    set sequence_begin(16) 47
+    set sequence_end(16) 48
+} elseif {[istarget "aarch64*-*-*"]} {
+    set function_positions(0) 16
+    set function_positions(1) 22
+    set function_positions(2) 2
+    set function_positions(end) 36
+    set function_positions(3) 35
+
+    set sequence_begin(1) 1
+    set sequence_end(1) 1
+    set sequence_begin(2) 2
+    set sequence_end(2) 4
+    set sequence_begin(3) 5
+    set sequence_end(3) 6
+    set sequence_begin(4) 7
+    set sequence_end(4) 7
+    set sequence_begin(5) 8
+    set sequence_end(5) 10
+    set sequence_begin(6) 11
+    set sequence_end(6) 12
+    set sequence_begin(7) 13
+    set sequence_end(7) 15
+    set sequence_begin(8) 16
+    set sequence_end(8) 16
+    set sequence_begin(9) 17
+    set sequence_end(9) 19
+    set sequence_begin(10) 20
+    set sequence_end(10) 21
+    set sequence_begin(11) 22
+    set sequence_end(11) 22
+    set sequence_begin(12) 23
+    set sequence_end(12) 25
+    set sequence_begin(13) 26
+    set sequence_end(13) 27
+    set sequence_begin(14) 28
+    set sequence_end(14) 30
+    set sequence_begin(15) 31
+    set sequence_end(15) 33
+    set sequence_begin(16) 34
+    set sequence_end(16) 36
+}
+
 if ![runto_main] {
     untested "failed to run to main"
     return -1
@@ -65,43 +189,43 @@ gdb_test "next"
 
 # start by listing all functions
 gdb_test "record function-call-history /ci 1, +20" [multi_line \
-  "1\tmain\tinst 1,1" \
-  "2\t  fun4\tinst 2,4" \
-  "3\t    fun1\tinst 5,8" \
-  "4\t  fun4\tinst 9,9" \
-  "5\t    fun2\tinst 10,12" \
-  "6\t      fun1\tinst 13,16" \
-  "7\t    fun2\tinst 17,18" \
-  "8\t  fun4\tinst 19,19" \
-  "9\t    fun3\tinst 20,22" \
-  "10\t      fun1\tinst 23,26" \
-  "11\t    fun3\tinst 27,27" \
-  "12\t      fun2\tinst 28,30" \
-  "13\t        fun1\tinst 31,34" \
-  "14\t      fun2\tinst 35,36" \
-  "15\t    fun3\tinst 37,38" \
-  "16\t  fun4\tinst 39,40" \
+  "1\tmain\tinst $sequence_begin(1),$sequence_end(1)" \
+  "2\t  fun4\tinst $sequence_begin(2),$sequence_end(2)" \
+  "3\t    fun1\tinst $sequence_begin(3),$sequence_end(3)" \
+  "4\t  fun4\tinst $sequence_begin(4),$sequence_end(4)" \
+  "5\t    fun2\tinst $sequence_begin(5),$sequence_end(5)" \
+  "6\t      fun1\tinst $sequence_begin(6),$sequence_end(6)" \
+  "7\t    fun2\tinst $sequence_begin(7),$sequence_end(7)" \
+  "8\t  fun4\tinst $sequence_begin(8),$sequence_end(8)" \
+  "9\t    fun3\tinst $sequence_begin(9),$sequence_end(9)" \
+  "10\t      fun1\tinst $sequence_begin(10),$sequence_end(10)" \
+  "11\t    fun3\tinst $sequence_begin(11),$sequence_end(11)" \
+  "12\t      fun2\tinst $sequence_begin(12),$sequence_end(12)" \
+  "13\t        fun1\tinst $sequence_begin(13),$sequence_end(13)" \
+  "14\t      fun2\tinst $sequence_begin(14),$sequence_end(14)" \
+  "15\t    fun3\tinst $sequence_begin(15),$sequence_end(15)" \
+  "16\t  fun4\tinst $sequence_begin(16),$sequence_end(16)" \
   ]
 
 # let's see if we can go back in history
-gdb_test "record goto 19" ".*fun4 \\(\\) at record_goto.c:43.*"
+gdb_test "record goto $function_positions(0)" ".*fun4 \\(\\) at record_goto.c:43.*"
 
 # the function call history should start at the new location
 gdb_test "record function-call-history /ci" [multi_line \
-  "8\t  fun4\tinst 19,19" \
-  "9\t    fun3\tinst 20,22" \
-  "10\t      fun1\tinst 23,26" \
-  ] "function-call-history from 19 forwards"
+  "8\t  fun4\tinst $sequence_begin(8),$sequence_end(8)" \
+  "9\t    fun3\tinst $sequence_begin(9),$sequence_end(9)" \
+  "10\t      fun1\tinst $sequence_begin(10),$sequence_end(10)" \
+  ] "function-call-history from $function_positions(0) forwards"
 
 # the instruction history should start at the new location
 gdb_test "record instruction-history" [multi_line \
-  "19.*" \
-  "20.*" \
-  "21.*" \
-  ] "instruction-history from 19 forwards"
+  "$function_positions(0).*" \
+  "[expr {$function_positions(0) + 1}].*" \
+  "[expr {$function_positions(0) + 2}].*" \
+  ] "instruction-history from $function_positions(0) forwards"
 
 # let's go to another place in the history
-gdb_test "record goto 27" ".*fun3 \\(\\) at record_goto.c:35.*"
+gdb_test "record goto $function_positions(1)" ".*fun3 \\(\\) at record_goto.c:35.*"
 
 # check the back trace at that location
 gdb_test "backtrace" [multi_line \
@@ -117,26 +241,26 @@ gdb_test "up" ".*main.*at record_goto.c:49.*" "up to main"
 
 # the function call history should start at the new location
 gdb_test "record function-call-history /ci -" [multi_line \
-  "9\t    fun3\tinst 20,22" \
-  "10\t      fun1\tinst 23,26" \
-  "11\t    fun3\tinst 27,27" \
-  ] "function-call-history from 27 backwards"
+  "9\t    fun3\tinst $sequence_begin(9),$sequence_end(9)" \
+  "10\t      fun1\tinst $sequence_begin(10),$sequence_end(10)" \
+  "11\t    fun3\tinst $sequence_begin(11),$sequence_end(11)" \
+  ] "function-call-history from $function_positions(1) backwards"
 
 # the instruction history should start at the new location
 gdb_test "record instruction-history -" [multi_line \
-  "25.*" \
-  "26.*" \
-  "27.*" \
-  ] "instruction-history from 27 backwards"
+  "[expr {$function_positions(1) - 2}].*" \
+  "[expr {$function_positions(1) - 1}].*" \
+  "$function_positions(1).*" \
+  ] "instruction-history from $function_positions(1) backwards"
 
 # test that we can go to the begin of the trace
 gdb_test "record goto begin" ".*main \\(\\) at record_goto.c:49.*"
 
 # check that we're filling up the context correctly
 gdb_test "record function-call-history /ci -" [multi_line \
-  "1\tmain\tinst 1,1" \
-  "2\t  fun4\tinst 2,4" \
-  "3\t    fun1\tinst 5,8" \
+  "1\tmain\tinst $sequence_begin(1),$sequence_end(1)" \
+  "2\t  fun4\tinst $sequence_begin(2),$sequence_end(2)" \
+  "3\t    fun1\tinst $sequence_begin(3),$sequence_end(3)" \
   ] "function-call-history from begin backwards"
 
 # check that we're filling up the context correctly
@@ -147,52 +271,53 @@ gdb_test "record instruction-history -" [multi_line \
   ] "instruction-history from begin backwards"
 
 # we should get the exact same history from the first instruction
-gdb_test "record goto 2" ".*fun4 \\(\\) at record_goto.c:40.*"
+gdb_test "record goto $function_positions(2)" ".*fun4 \\(\\) at record_goto.c:40.*"
 
 # check that we're filling up the context correctly
 gdb_test "record function-call-history /ci -" [multi_line \
-  "1\tmain\tinst 1,1" \
-  "2\t  fun4\tinst 2,4" \
-  "3\t    fun1\tinst 5,8\r" \
-  ] "function-call-history from 2 backwards"
+  "1\tmain\tinst $sequence_begin(1),$sequence_end(1)" \
+  "2\t  fun4\tinst $sequence_begin(2),$sequence_end(2)" \
+  "3\t    fun1\tinst $sequence_begin(3),$sequence_end(3)\r" \
+  ] "function-call-history from $function_positions(2) backwards"
 
 # check that we're filling up the context correctly
 gdb_test "record instruction-history -" [multi_line \
   "1.*" \
   "2.*" \
   "3.*" \
-  ] "instruction-history from 2 backwards"
+  ] "instruction-history from $function_positions(2) backwards"
 
 # check that we can go to the end of the trace
 gdb_test "record goto end" ".*main \\(\\) at record_goto.c:50.*"
 
 # check that we're filling up the context correctly
 gdb_test "record function-call-history /ci" [multi_line \
-  "14\t      fun2\tinst 35,36" \
-  "15\t    fun3\tinst 37,38" \
-  "16\t  fun4\tinst 39,40" \
+  "14\t      fun2\tinst $sequence_begin(14),$sequence_end(14)" \
+  "15\t    fun3\tinst $sequence_begin(15),$sequence_end(15)" \
+  "16\t  fun4\tinst $sequence_begin(16),$sequence_end(16)" \
   ] "function-call-history from end forwards"
 
 # check that we're filling up the context correctly
+#adapt it for arm, last instruction is  at pos 48
 gdb_test "record instruction-history" [multi_line \
-  "38.*" \
-  "39.*" \
-  "40.*\r" \
+  "[expr {$function_positions(end) - 2}].*" \
+  "[expr {$function_positions(end) - 1}].*" \
+  "$function_positions(end).*\r" \
   ] "instruction-history from end forwards"
 
 # we should get the exact same history from the second to last instruction
-gdb_test "record goto 39" ".*fun4 \\(\\) at record_goto.c:44.*"
+gdb_test "record goto $function_positions(3)" ".*fun4 \\(\\) at record_goto.c:44.*"
 
 # check that we're filling up the context correctly
 gdb_test "record function-call-history /ci" [multi_line \
-  "14\t      fun2\tinst 35,36" \
-  "15\t    fun3\tinst 37,38" \
-  "16\t  fun4\tinst 39,40\r" \
-  ] "function-call-history from 39 forwards"
+  "14\t      fun2\tinst $sequence_begin(14),$sequence_end(14)" \
+  "15\t    fun3\tinst $sequence_begin(15),$sequence_end(15)" \
+  "16\t  fun4\tinst $sequence_begin(16),$sequence_end(16)\r" \
+  ] "function-call-history from $function_positions(3) forwards"
 
 # check that we're filling up the context correctly
 gdb_test "record instruction-history" [multi_line \
-  "38.*" \
-  "39.*" \
-  "40.*\r" \
-  ] "instruction-history from 39 forwards"
+  "[expr {$function_positions(3) - 1}].*" \
+  "$function_positions(3).*" \
+  "[expr {$function_positions(3) + 1}].*\r" \
+  ] "instruction-history from $function_positions(3) forwards"
diff --git a/gdb/testsuite/gdb.btrace/stepi.exp b/gdb/testsuite/gdb.btrace/stepi.exp
index bfb680bb30d..5b37d17ba0e 100644
--- a/gdb/testsuite/gdb.btrace/stepi.exp
+++ b/gdb/testsuite/gdb.btrace/stepi.exp
@@ -39,6 +39,10 @@ if [info exists COMPILE] {
 	} else {
 		standard_testfile i686-record_goto.S
 	}
+} elseif {[istarget "arm*-*-*"]} {
+	standard_testfile arm-record_goto.S
+} elseif {[istarget "aarch64*-*-*"]} {
+	standard_testfile aarch64-record_goto.S
 } else {
     unsupported "target architecture not supported"
     return -1
@@ -48,6 +52,56 @@ if [prepare_for_testing "failed to prepare" $testfile $srcfile] {
     return -1
 }
 
+if {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    set instructions_count 40
+    set instruction_position(0) 39
+    set instruction_position(1) 40
+    set instruction_position(2) 1
+    set instruction_position(3) 1
+    set instruction_position(4) 22
+    set instruction_position(5) 23
+    set instruction_position(6) 22
+    set instruction_position(7) 27
+    set instruction_position(8) 22
+    set instruction_position(9) 1
+    set instruction_position(10) 1
+    set instruction_position(11) 1
+    set instruction_position(12) 2
+    set instruction_position(13) 1
+} elseif {[istarget "arm*-*-*"]} {
+    set instructions_count 48
+    set instruction_position(0) 47
+    set instruction_position(1) 48
+    set instruction_position(2) 1
+    set instruction_position(3) 1
+    set instruction_position(4) 26
+    set instruction_position(5) 27
+    set instruction_position(6) 26
+    set instruction_position(7) 33
+    set instruction_position(8) 26
+    set instruction_position(9) 1
+    set instruction_position(10) 1
+    set instruction_position(11) 1
+    set instruction_position(12) 2
+    set instruction_position(13) 1
+} elseif {[istarget "aarch64*-*-*"]} {
+    set instructions_count 36
+    set instruction_position(0) 35
+    set instruction_position(1) 36
+    set instruction_position(2) 1
+    set instruction_position(3) 1
+    set instruction_position(4) 19
+    set instruction_position(5) 20
+    set instruction_position(6) 19
+    set instruction_position(7) 22
+    set instruction_position(8) 19
+    set instruction_position(9) 1
+    set instruction_position(10) 1
+    set instruction_position(11) 1
+    set instruction_position(12) 2
+    set instruction_position(13) 1
+}
+
 if ![runto_main] {
     untested "failed to run to main"
     return -1
@@ -56,10 +110,11 @@ if ![runto_main] {
 global gdb_prompt
 
 proc check_replay_at { insn } {
+  global instructions_count
   gdb_test "info record" [multi_line \
     "Active record target: record-btrace" \
     ".*" \
-    "Recorded 40 instructions in 16 functions \\\(0 gaps\\\) for .*" \
+    "Recorded $instructions_count instructions in 16 functions \\\(0 gaps\\\) for .*" \
     "Replay in progress\.  At instruction $insn\." \
     ] "check replay at $insn"
 }
@@ -74,15 +129,14 @@ with_test_prefix "record" {
 with_test_prefix "fetch" {
     gdb_test "reverse-stepi" ".*fun4\.5.*" "reverse-stepi.1"
     gdb_test "reverse-stepi" ".*fun4\.5.*" "reverse-stepi.2"
-
     # let's check where we are in the trace
-    check_replay_at 39
+    check_replay_at $instruction_position(0) 
 }
 
 # let's step forward and check again
 with_test_prefix "stepi" {
     gdb_test "stepi" ".*fun4\.5.*"
-    check_replay_at 40
+    check_replay_at $instruction_position(1) 
 }
 
 # with the next step, we stop replaying
@@ -91,14 +145,17 @@ with_test_prefix "end" {
     gdb_test "info record" [multi_line \
       "Active record target: record-btrace" \
       ".*" \
-      "Recorded 40 instructions in 16 functions \\\(0 gaps\\\) for \[^\\\r\\\n\]*" \
+      "Recorded $instructions_count instructions in 16 functions \\\(0 gaps\\\) for \[^\\\r\\\n\]*" \
   ] 
 }
 
+#recover from a missing lr register in arm
+gdb_test "record goto end"
+
 # let's try nexti
 with_test_prefix "reverse-nexti.1" {
     gdb_test "reverse-nexti" ".*main\.2.*"
-    check_replay_at 1
+    check_replay_at $instruction_position(2)
 }
 
 # we can't reverse-nexti any further
@@ -106,7 +163,7 @@ with_test_prefix "reverse-nexti.2" {
     gdb_test "reverse-nexti" \
 	"No more reverse-execution history\.\r\n.*main\.2.*" \
 	"reverse-nexti.2"
-    check_replay_at 1
+    check_replay_at $instruction_position(3)
 }
 
 # but we can step back again
@@ -115,32 +172,32 @@ with_test_prefix "nexti" {
     gdb_test "info record" [multi_line \
       "Active record target: record-btrace" \
       ".*" \
-      "Recorded 40 instructions in 16 functions \\\(0 gaps\\\) for \[^\\\r\\\n\]*" \
+      "Recorded $instructions_count instructions in 16 functions \\\(0 gaps\\\) for \[^\\\r\\\n\]*" \
 			       ]
 }
 
 # let's step from a goto position somewhere in the middle
 with_test_prefix "goto" {
-    gdb_test "record goto 22" ".*fun3\.2.*"
-    with_test_prefix "goto 22" { check_replay_at 22 }
+    gdb_test "record goto $instruction_position(4) " ".*fun3\.2.*"
+    with_test_prefix "goto $instruction_position(4) " { check_replay_at $instruction_position(4)  }
 
     gdb_test "stepi" ".*fun1\.1.*" "stepi.3"
-    with_test_prefix "stepi to 23" { check_replay_at 23 }
+    with_test_prefix "stepi to $instruction_position(5)" { check_replay_at $instruction_position(5) }
 
     gdb_test "reverse-stepi" ".*fun3\.2.*" "reverse-stepi.3"
-    with_test_prefix "reverse-stepi to 22" { check_replay_at 22 }
+    with_test_prefix "reverse-stepi to $instruction_position(6)" { check_replay_at $instruction_position(6) }
 
     gdb_test "nexti" ".*fun3\.3.*"
-    with_test_prefix "nexti to 27" { check_replay_at 27 }
+    with_test_prefix "nexti to $instruction_position(7) " { check_replay_at $instruction_position(7)  }
 
     gdb_test "reverse-nexti" ".*fun3\.2.*" "reverse-nexti.3"
-    with_test_prefix "reverse-nexti to 22" { check_replay_at 22 }
+    with_test_prefix "reverse-nexti to $instruction_position(8)" { check_replay_at $instruction_position(8) }
 }
 
 # let's try to step off the left end
 with_test_prefix "goto begin" {
     gdb_test "record goto begin" ".*main\.2.*"
-    check_replay_at 1
+    check_replay_at $instruction_position(9)
 
     with_test_prefix "reverse-stepi" {
 	gdb_test "reverse-stepi" \
@@ -149,7 +206,7 @@ with_test_prefix "goto begin" {
 	gdb_test "reverse-stepi" \
 	    "No more reverse-execution history\.\r\n.*main\.2.*" \
 	    "reverse-stepi.2"
-	check_replay_at 1
+	check_replay_at $instruction_position(10)
     }
 
     with_test_prefix "reverse-nexti" {
@@ -159,13 +216,13 @@ with_test_prefix "goto begin" {
 	gdb_test "reverse-nexti" \
 	    "No more reverse-execution history\.\r\n.*main\.2.*" \
 	    "reverse-nexti.2"
-	check_replay_at 1
+	check_replay_at $instruction_position(11)
     }
 
     # we can step forward, though
     with_test_prefix "stepi" {
 	gdb_test "stepi" ".*fun4\.1.*"
-	check_replay_at 2
+	check_replay_at $instruction_position(12)
     }
 }
 
@@ -178,5 +235,5 @@ with_test_prefix "reverse-stepi" {
     gdb_test "reverse-stepi" \
 	"No more reverse-execution history\.\r\n.*main\.2.*" \
 	"reverse-stepi.3"
-    check_replay_at 1
+    check_replay_at $instruction_position(13)
 }
diff --git a/gdb/testsuite/gdb.btrace/tailcall-only.exp b/gdb/testsuite/gdb.btrace/tailcall-only.exp
index 510f90c9d5e..7e449ee38da 100644
--- a/gdb/testsuite/gdb.btrace/tailcall-only.exp
+++ b/gdb/testsuite/gdb.btrace/tailcall-only.exp
@@ -43,6 +43,10 @@ if [info exists COMPILE] {
 	} else {
 		standard_testfile i686-tailcall-only.S
 	}
+} elseif { [istarget "arm*-*-*"] } {
+  standard_testfile arm-tailcall-only.S
+} elseif {[istarget "aarch64*-*-*"]} {
+  standard_testfile aarch64-tailcall-only.S
 } else {
     unsupported "target architecture not supported"
     return -1
@@ -62,6 +66,10 @@ gdb_test_no_output "set record function-call-history-size 0"
 
 # trace foo
 gdb_test "step" ".*" "prepare for recording"
+# make sure we get out of function epilogue
+if { [istarget "arm*-*-*"] } {
+  gdb_test "stepi"
+}
 gdb_test_no_output "record btrace"
 gdb_test "stepi 4" ".*" "record branch trace"
 
diff --git a/gdb/testsuite/gdb.btrace/tailcall.exp b/gdb/testsuite/gdb.btrace/tailcall.exp
index 07a3ec103f4..602a9ed6fba 100644
--- a/gdb/testsuite/gdb.btrace/tailcall.exp
+++ b/gdb/testsuite/gdb.btrace/tailcall.exp
@@ -40,6 +40,10 @@ if [info exists COMPILE] {
 	} else {
 		standard_testfile i686-tailcall.S
 	}
+} elseif { [istarget "arm*-*-*"] } {
+  standard_testfile arm-tailcall.S
+} elseif { [istarget "aarch64*-*-*"] } {
+  standard_testfile aarch64-tailcall.S
 } else {
     unsupported "target architecture not supported"
     return -1
@@ -48,6 +52,20 @@ if [info exists COMPILE] {
 if [prepare_for_testing "failed to prepare" $testfile $srcfile $opts] {
     return -1
 }
+
+if {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    set bar_return_line 24
+    set bar_return_position 4
+    set main_return_line 38
+} elseif {[istarget "arm*-*-*"]} {
+    set bar_return_line 24
+    set bar_return_position 5
+    set main_return_line 41
+    } elseif {[istarget "aarch64*-*-*"]} {
+    set bar_return_line 23
+    set bar_return_position 6
+    set main_return_line 40
+}
 if ![runto_main] {
     untested "failed to run to main"
     return -1
@@ -58,7 +76,17 @@ gdb_test_no_output "set record function-call-history-size 0"
 
 # trace the call to foo
 gdb_test_no_output "record btrace"
-gdb_test "next 2"
+
+# make sure we get out of function epilogue
+if {[istarget "i?86-*-*"] || [istarget "x86_64-*-*"]} {
+    gdb_test "next 2"
+} elseif {[istarget "arm*-*-*"]} {
+  gdb_test "next 2"
+  gdb_test "stepi"
+} elseif {[istarget "aarch64*-*-*"]} {
+  gdb_test "next"
+  gdb_test "stepi"
+}
 
 # show the flat branch trace
 gdb_test "record function-call-history 1" [multi_line \
@@ -77,11 +105,11 @@ gdb_test "record function-call-history /c 1" [multi_line \
   ] "indented"
 
 # go into bar
-gdb_test "record goto 4" ".*bar \\(\\) at .*tailcall.c:24\r\n.*"
+gdb_test "record goto $bar_return_position" ".*bar \\(\\) at .*tailcall.c:$bar_return_line\r\n.*"
 
 # check the backtrace
 gdb_test "backtrace" [multi_line \
-  "#0.*bar \\(\\) at tailcall.c:24" \
+  "#0.*bar \\(\\) at tailcall.c:$bar_return_line" \
   "#1.*foo \\(\\) at tailcall.c:29" \
   "#2.*main \\(\\) at tailcall.c:37" \
   "Backtrace stopped: not enough registers or memory available to unwind further" \
@@ -93,23 +121,23 @@ gdb_test "up" "#2\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" "up to main"
 gdb_test "down" "#1\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" "down to foo"
 
 # test stepping into and out of tailcalls.
-gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
+gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:$main_return_line\r\n.*" \
     "finish.1"
-gdb_test "reverse-step" "\[^\r\n\]*bar \\(\\) at tailcall.c:24\r\n.*" \
+gdb_test "reverse-step" "\[^\r\n\]*bar \\(\\) at tailcall.c:$bar_return_line\r\n.*" \
     "reverse-step.1"
 gdb_test "reverse-finish" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
     "reverse-finish.1"
 gdb_test "reverse-step" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
     "reverse-step.2"
-gdb_test "next" "\[^\r\n\]*38.*" \
+gdb_test "next" "\[^\r\n\]*$main_return_line.*" \
     "next.1"
 gdb_test "reverse-next" "\[^\r\n\]*main \\(\\) at tailcall.c:37\r\n.*" \
     "reverse-next.1"
 gdb_test "step" "\[^\r\n\]*foo \\(\\) at tailcall.c:29\r\n.*" \
     "step.1"
-gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
+gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:$main_return_line\r\n.*" \
     "finish.2"
-gdb_test "reverse-step" "\[^\r\n\]*bar \\(\\) at tailcall.c:24\r\n.*" \
+gdb_test "reverse-step" "\[^\r\n\]*bar \\(\\) at tailcall.c:$bar_return_line\r\n.*" \
     "reverse-step.3"
-gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:38\r\n.*" \
+gdb_test "finish" "\[^\r\n\]*main \\(\\) at tailcall.c:$main_return_line\r\n.*" \
     "finish.3"
diff --git a/gdb/testsuite/gdb.btrace/instruction_history.S b/gdb/testsuite/gdb.btrace/x86-instruction_history.S
similarity index 100%
rename from gdb/testsuite/gdb.btrace/instruction_history.S
rename to gdb/testsuite/gdb.btrace/x86-instruction_history.S
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 60f84d22aad..b7b11deab57 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -3232,7 +3232,7 @@ gdb_caching_proc skip_btrace_tests {
     global srcdir subdir gdb_prompt inferior_exited_re
 
     set me "skip_btrace_tests"
-    if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+    if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] && ![istarget "arm*-*-*"] && ![istarget "aarch64*-*-*"]} {
         verbose "$me:  target does not support btrace, returning 1" 2
         return 1
     }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 8/8] document btrace support for arm targets using coresight etm traces
  2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
                   ` (6 preceding siblings ...)
  2021-02-26  2:46 ` [PATCH 7/8] adapt btrace testcases for arm target Zied Guermazi
@ 2021-02-26  2:46 ` Zied Guermazi
  2021-02-26  7:36   ` Eli Zaretskii
  7 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-02-26  2:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi

This patch documents the extensions done in GDB to enable using
ARM Coresight traces for btrace.

gdb/doc/ChangeLog

	* gdb.texinfo: Document extending btrace to support
	ARM CoreSight traces commands and packets
	* gdb/NEWS: list new commands and new remote packets


---
 gdb/NEWS            |  30 +++++++++++
 gdb/doc/ChangeLog   |   5 ++
 gdb/doc/gdb.texinfo | 119 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 153 insertions(+), 1 deletion(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 7f5a745d0c0..b0caef1688c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -2,6 +2,7 @@
 	     (Organized release by release)
 
 *** Changes since GDB 10
+* Record btrace now  supports using ARM CoreSight ETM traces.
 
 * Building GDB now requires GMP (The GNU Multiple Precision Arithmetic
   Library).
@@ -35,6 +36,21 @@
 
 * New commands
 
+record btrace etm
+record etm
+  Start branch trace recording using ARM CoreSight trace format (ETM).
+
+set|show record btrace etm buffer-size
+  Set and show the size of the ring buffer used for branch tracing in
+  ETM format.
+  The obtained size may differ from the requested size.  Use "info
+  record" to see the obtained buffer size.
+
+set|show record btrace etm sink
+  Set and show the trace sink used for branch tracing in
+  ETM format.
+  use default to revert it to default sink
+
 set debug event-loop
 show debug event-loop
   Control the display of debug output about GDB's event loop.
@@ -98,6 +114,20 @@ maintenance info sections
 
 ARM Symbian			arm*-*-symbianelf*
 
+* New remote packets
+
+Qbtrace:etm
+  Enable ARM CoreSight ETM Trace-based branch tracing for the current
+  process.  The remote stub reports support for this packet to GDB's
+  qSupported query.
+
+Qbtrace-conf:etm:size
+  Set the requested ring buffer size for branch tracing in
+  ARM CoreSight ETM Trace format.
+
+Qbtrace-conf:etm:sink
+  Set the trace sink for branch tracing in ARM CoreSight ETM Trace format.
+
 *** Changes in GDB 10
 
 * There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index add31a0cc39..b4b9faa20d5 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2021-02-08  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* gdb.texinfo: Document extending btrace to support
+	ARM CoreSight traces commands and packets
+
 2021-02-24  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* gdb.texinfo (Files): Document new 'maint info target-sections'
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 80ccf74a049..c68a258463d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7371,15 +7371,19 @@ For architecture environments that support process record and replay,
 @kindex record btrace
 @kindex record btrace bts
 @kindex record btrace pt
+@kindex record btrace etm
 @kindex record bts
 @kindex record pt
+@kindex record etm
 @kindex rec
 @kindex rec full
 @kindex rec btrace
 @kindex rec btrace bts
 @kindex rec btrace pt
+@kindex rec btrace etm
 @kindex rec bts
 @kindex rec pt
+@kindex rec etm
 @item record @var{method}
 This command starts the process record and replay target.  The
 recording method can be specified as parameter.  Without a parameter
@@ -7393,7 +7397,7 @@ replay implementation.  This method allows replaying and reverse
 execution.
 
 @item btrace @var{format}
-Hardware-supported instruction recording, supported on Intel
+Hardware-supported instruction recording, supported on Intel and ARM
 processors.  This method does not record data.  Further, the data is
 collected in a ring buffer so old data will be overwritten when the
 buffer is full.  It allows limited reverse execution.  Variables and
@@ -7427,6 +7431,13 @@ Decoding the recorded execution trace, on the other hand, is more
 expensive than decoding @acronym{BTS} trace.  This is mostly due to the
 increased number of instructions to process.  You should increase the
 buffer-size with care.
+
+@item etm
+@cindex ARM CoreSight ETM Trace 
+Use the @dfn{ARM CoreSight ETM Trace} recording format.  In this
+format, the processor stores the execution trace in a compressed form
+that is afterwards decoded by @value{GDBN}.
+
 @end table
 
 Not all recording formats may be available on all processors.
@@ -7574,6 +7585,11 @@ and to read-write memory.  Beware that the accessed memory corresponds
 to the live target and not necessarily to the current replay
 position.
 
+@item set record btrace etm sink @var{sink}
+Set ARM CoreSight ETM sink to collect traces. 
+possible values for @var{sink} can be found by listing the folder 
+/sys/bus/event_source/devices/cs_etm/sinks/
+
 @item set record btrace cpu @var{identifier}
 Set the processor to be used for enabling workarounds for processor
 errata when decoding the trace.
@@ -7637,6 +7653,9 @@ Recorded 84872 instructions in 3189 functions (0 gaps) for thread 1 (...).
 @item show record btrace replay-memory-access
 Show the current setting of @code{replay-memory-access}.
 
+@item show record btrace etm sink 
+show ARM CoreSight ETM sink . 
+
 @item show record btrace cpu
 Show the processor to be used for enabling trace decode errata
 workarounds.
@@ -7688,6 +7707,29 @@ also need longer to process the branch trace data before it can be used.
 Show the current setting of the requested ring buffer size for branch
 tracing in Intel Processor Trace format.
 
+@kindex set record btrace etm
+@item set record btrace etm buffer-size @var{size}
+@itemx set record btrace etm buffer-size unlimited
+Set the requested ring buffer size for branch tracing in ARM 
+CoreSight ETM Trace format.  Default is 16KB.
+
+If @var{size} is a positive number, then @value{GDBN} will try to
+allocate a buffer of at least @var{size} bytes for each new thread
+that uses the btrace recording method and the Intel Processor Trace
+format.  The actually obtained buffer size may differ from the
+requested @var{size}.  Use the @code{info record} command to see the
+actual buffer size for each thread.
+
+If @var{limit} is @code{unlimited} or zero, @value{GDBN} will try to
+allocate a buffer of 4MB.
+
+Bigger buffers mean longer traces.  On the other hand, @value{GDBN} will
+also need longer to process the branch trace data before it can be used.
+
+@item show record btrace etm buffer-size @var{size}
+Show the current setting of the requested ring buffer size for branch
+tracing in ARM CoreSight ETM Trace format.
+
 @kindex info record
 @item info record
 Show various statistics about the recording depending on the recording
@@ -7739,6 +7781,12 @@ For the @code{pt} recording format, it also shows:
 @item
 Size of the perf ring buffer.
 @end itemize
+
+For the @code{etm} recording format, it also shows:
+@itemize @bullet
+@item
+Size of the perf ring buffer.
+@end itemize
 @end table
 
 @kindex record delete
@@ -38628,6 +38676,17 @@ Newer packets have higher numbers.  The oldest packet has number zero.
 The packet's offset in the trace stream.
 @item Packet opcode and payload
 @end table
+
+@item etm
+For the ARM CoreSight ETM Trace recording format, print a list of
+ARM CoreSight ETM Trace packets.  For each packet, the following
+information is printed:
+
+@table @asis
+@item Packet number
+Newer packets have higher numbers.  The oldest packet has number zero.
+@item Packet opcode and payload
+@end table
 @end table
 
 @kindex maint btrace clear-packet-history
@@ -41659,6 +41718,21 @@ These are the currently defined stub features and their properties:
 @tab @samp{-}
 @tab No
 
+@item @samp{Qbtrace:etm}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
+@item @samp{Qbtrace-conf:etm:size}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
+
+@item @samp{Qbtrace-conf:etm:sink}
+@tab Yes
+@tab @samp{-}
+@tab Yes
 @end multitable
 
 These are the currently defined stub features, in more detail:
@@ -41873,6 +41947,15 @@ The remote stub understands the @samp{QThreadEvents} packet.
 @item no-resumed
 The remote stub reports the @samp{N} stop reply.
 
+@item Qbtrace:etm
+The remote stub understands the @samp{Qbtrace:etm} packet.
+
+@item Qbtrace-conf:etm:size
+The remote stub understands the @samp{Qbtrace-conf:etm:size} packet.
+
+@item Qbtrace-conf:etm:sink
+The remote stub understands the @samp{Qbtrace-conf:etm:sink} packet.
+
 @end table
 
 @item qSymbol::
@@ -42335,6 +42418,40 @@ The ring buffer size has been set.
 A badly formed request or an error was encountered.
 @end table
 
+@item Qbtrace:etm
+Enable branch tracing for the current thread using ARM CoreSight ETM Trace.
+
+Reply:
+@table @samp
+@item OK
+Branch tracing has been enabled.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace-conf:etm:size=@var{value}
+Set the requested ring buffer size for new threads that use the
+btrace recording method in etm format.
+
+Reply:
+@table @samp
+@item OK
+The ring buffer size has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace-conf:etm:sink=@var{value}
+Set the requested trace sink for new threads that use the
+btrace recording method in etm format.
+
+Reply:
+@table @samp
+@item OK
+The ring buffer size has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
 @end table
 
 @node Architecture-Specific Protocol Details
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY
  2021-02-26  2:45 ` [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY Zied Guermazi
@ 2021-02-26  7:12   ` Aktemur, Tankut Baris
  2021-03-10 20:39     ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Aktemur, Tankut Baris @ 2021-02-26  7:12 UTC (permalink / raw)
  To: Zied Guermazi, gdb-patches

On Friday, February 26, 2021 3:46 AM, Zied Guermazi wrote:
> This patch fixes an issue observed with btrace when replaying the execution.
> The issue was observed on ARMv7 processors.
> To reproduce the issue needs to replay in forward direction
> until he reaches the end of history, then replay backwards
> (e.g a reverse-next) and then replay forwards. gdb hangs and the user
> can not issue new commands.
> 
> gdb/ChangeLog
> 
> 	* infrun.c (set_step_over_info): add debug print.
> 	(handle_inferior_event): clear step over info
> 	in case TARGET_WAITKIND_NO_HISTORY
> 
> ---
>  gdb/ChangeLog | 6 ++++++
>  gdb/infrun.c  | 3 ++-
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index a84671bf344..15dee4eb29b 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,9 @@
> +2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
> +
> +	* infrun.c (set_step_over_info): add debug print.
> +	* infrun.c (handle_inferior_event): clear step over info.
> +	in case TARGET_WAITKIND_NO_HISTORY
> +
>  2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
> 
>  	* nat/linux-btrace.h (btrace_tinfo_etm): New.
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index a271220b261..a483307d7a3 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -1308,6 +1308,7 @@ set_step_over_info (const address_space *aspace, CORE_ADDR address,
>  		    int nonsteppable_watchpoint_p,
>  		    int thread)
>  {
> +  infrun_debug_printf ("infrun: set_step_over_info\n");

The debug printf function already prints "infrun", the function name,
and the newline.  Just

  infrun_debug_printf ("enter");

is most likely sufficient.

-Baris


Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 8/8] document btrace support for arm targets using coresight etm traces
  2021-02-26  2:46 ` [PATCH 8/8] document btrace support for arm targets using coresight etm traces Zied Guermazi
@ 2021-02-26  7:36   ` Eli Zaretskii
  2021-03-10 20:36     ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Eli Zaretskii @ 2021-02-26  7:36 UTC (permalink / raw)
  To: Zied Guermazi; +Cc: gdb-patches

> From: Zied Guermazi <zied.guermazi@trande.de>
> Date: Fri, 26 Feb 2021 03:46:02 +0100
> Cc: Zied Guermazi <zied.guermazi@trande.de>
> 
> This patch documents the extensions done in GDB to enable using
> ARM Coresight traces for btrace.
> 
> gdb/doc/ChangeLog
> 
> 	* gdb.texinfo: Document extending btrace to support
> 	ARM CoreSight traces commands and packets

This should mention in parentheses the names of the modified @node's
(as if each node were a function).

> 	* gdb/NEWS: list new commands and new remote packets

This goes into a different ChangeLog file, gdb/ChangeLog.

> +set|show record btrace etm sink
> +  Set and show the trace sink used for branch tracing in
> +  ETM format.
> +  use default to revert it to default sink
     ^^^^^^^^^^^
The last sentence should begin with a capital "U".
Also, the sentence is not very clear: what do you mean by "use default"?
And I don't think I see this aspect described in the manual, did I
miss something?

> +@item etm
> +@cindex ARM CoreSight ETM Trace 
> +Use the @dfn{ARM CoreSight ETM Trace} recording format.  In this
> +format, the processor stores the execution trace in a compressed form
> +that is afterwards decoded by @value{GDBN}.

Please tell here what does "ETM" stand for (AFAIU, it stands for
"Embedded Trace Macrocell").  We should explain the acronyms in the
manual.

> +@item set record btrace etm sink @var{sink}
> +Set ARM CoreSight ETM sink to collect traces. 
> +possible values for @var{sink} can be found by listing the folder 
> +/sys/bus/event_source/devices/cs_etm/sinks/

"possible" should be "Possible", with a capital "P".
Instead of "folder", please use "file", and please give the file name
the @file markup.

> +@item show record btrace etm sink 
> +show ARM CoreSight ETM sink . 
   ^^^^                       ^^
Capitalize "show", and delete that extra blank before the period.

> +@item etm
> +For the ARM CoreSight ETM Trace recording format, print a list of

This is very far from the description of the ETM tracking support, so
please add here a cross-reference to that description.

> +@item @samp{Qbtrace:etm}

Same here.

Thanks.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 1/8] configure gdb build system for supporting btrace on arm processors
  2021-02-26  2:45 ` [PATCH 1/8] configure gdb build system for supporting btrace on arm processors Zied Guermazi
@ 2021-03-04 16:35   ` Metzger, Markus T
  2021-03-10 22:09     ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Metzger, Markus T @ 2021-03-04 16:35 UTC (permalink / raw)
  To: Zied Guermazi; +Cc: gdb-patches

Hello Zied,

> gdb/ChangeLog
> 
> 	* Makefile.in LIBOPENCSD_C_API: set the flag.
> 	* config.in LIBOPENCSD_C_API: undefine it if
> 	libopenocsd library is available.

This file is auto-generated.


> diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
> index 3ed95dabc85..8d2f959e8f3 100644
> --- a/gdbsupport/common.m4
> +++ b/gdbsupport/common.m4
> @@ -186,6 +186,45 @@ AC_DEFUN([GDB_AC_COMMON], [

[...]


> +    if test "$perf_event" != yes; then
> +      if test "$" = yes; then

Should this be $with_arm_cs?

> +        AC_MSG_ERROR([linux/perf_event.h missing or too old])
> +      else
> +        AC_MSG_WARN([linux/perf_event.h missing or too old; CoreSight Tracing will
> be unavailable.])
> +      fi
> +    fi
> +
> +    AC_LIB_HAVE_LINKFLAGS([opencsd_c_api], [], [#include
> "opencsd/c_api/opencsd_c_api.h"], [ocsd_get_version();])
> +    if test "$HAVE_LIBOPENCSD_C_API" != yes; then
> +      if test "$" = yes; then

Also here.

> +        AC_MSG_ERROR([libopencsd_c_api is missing or unusable])
> +      else
> +        AC_MSG_WARN([libopencsd_c_api is missing or unusable; CoreSight Tracing
> will be unavailable.])
> +      fi
> +    else
> +      LIBS="$LIBS $LIBOPENCSD_C_API"
> +    fi
> +  fi
> +
> +
>    BFD_SYS_PROCFS_H
>    if test "$ac_cv_header_sys_procfs_h" = yes; then
>      BFD_HAVE_SYS_PROCFS_TYPE(gregset_t)

Regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 2/8] add btrace coresight related commands
  2021-02-26  2:45 ` [PATCH 2/8] add btrace coresight related commands Zied Guermazi
@ 2021-03-04 16:35   ` Metzger, Markus T
       [not found]     ` <8a71a9a3-ad14-b716-6d86-ece063061b02@trande.de>
  0 siblings, 1 reply; 27+ messages in thread
From: Metzger, Markus T @ 2021-03-04 16:35 UTC (permalink / raw)
  To: Zied Guermazi; +Cc: gdb-patches, Eli Zaretskii

Hello Zied,

> This patch extends the commands needed for using branch tracing
> with ARM CoreSight traces.
> Those commands are:
> set record btrace etm sink
> set record btrace etm size
> record btrace etm

You'd want to describe them in gdb/doc/gdb.texinfo and announce the
new commands in gdb/NEWS.


> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
> index d9cc7a3b6d8..39ac9aafc28 100644
> --- a/gdb/record-btrace.c
> +++ b/gdb/record-btrace.c
> @@ -525,6 +529,22 @@ record_btrace_print_pt_conf (const struct
> btrace_config_pt *conf)
>      }
>  }
> 
> +/* Print an ARM Processor Trace configuration.  */
> +
> +static void
> +record_btrace_print_etm_conf (const struct btrace_config_etm *conf)
> +{
> +  const char *suffix;
> +  unsigned int size;

The surrounding code is old.  New code should declare variables when
they are first used.


> +    case BTRACE_FORMAT_ETM:
> +      record_btrace_print_etm_conf (&conf->etm);

You may want to use a const & parameter, instead.


> @@ -2936,6 +2960,27 @@ cmd_record_btrace_pt_start (const char *args, int
> from_tty)
>      }
>  }
> 
> +/* Start recording in arm CoreSight ETM Trace format.  */
> +
> +static void
> +cmd_record_btrace_etm_start (const char *args, int from_tty)
> +{
> +  if (args != NULL && *args != 0)

nullptr instead of NULL.


> @@ -2950,10 +2995,18 @@ cmd_record_btrace_start (const char *args, int
> from_tty)
>      {
>        execute_command ("target record-btrace", from_tty);
>      }
> -  catch (const gdb_exception &exception)
> +  catch (const gdb_exception &exception_pt)
>      {
>        record_btrace_conf.format = BTRACE_FORMAT_BTS;
> 
> +      try
> +        {
> +          execute_command ("target record-btrace", from_tty);
> +        }
> +      catch (const gdb_exception &exception_bts)
> +        {
> +          record_btrace_conf.format = BTRACE_FORMAT_ETM;
> +

We could look at the architecture to avoid trying PT and BTS first on ARM.
Not sure it matters in practice.


> @@ -3074,6 +3129,10 @@ cmd_show_record_btrace_cpu (const char *args, int
> from_tty)
>                                 record_btrace_cpu.model,
>                                 record_btrace_cpu.stepping);
>            return;
> +        case CV_ARM:

Please leave an empty line before the new case.


> +          printf_unfiltered ("btrace cpu is 'ARM'.\n");

The idea behind 'set record btrace cpu' is to allow the user to overwrite
the cpu identifier for enabling errata workarounds.  The main use-case is
when libipt does not know the cpu so it cannot enable workarounds
automatically.


> @@ -3165,6 +3235,22 @@ When set to \"none\", errata workarounds are
> disabled."),
>  		  "set record btrace cpu ", 1,
>  		  &set_record_btrace_cmdlist);
> 
> +  add_cmd ("etm", class_obscure, cmd_record_btrace_etm_start,
> +	   _("\
> +Start branch trace recording in arm CoreSight ETM Trace format.\n\n\

Isn't ARM typically spelled with capital letters?


> +This format may not be available on all processors."),
> +	   &record_btrace_cmdlist);
> +  add_alias_cmd ("etm", "btrace etm", class_obscure, 1, &record_cmdlist);

This alias wasn't mentioned in the list of new commands.


> +  add_basic_prefix_cmd ("btrace", class_support,
> +			_("Set record options."), &set_record_btrace_cmdlist,
> +			"set record btrace ", 0, &set_record_cmdlist);
> +
> +  add_show_prefix_cmd ("btrace", class_support,
> +		       _("Show record options."), &show_record_btrace_cmdlist,
> +		       "show record btrace ", 0, &show_record_cmdlist);

There already are such prefix commands.


> @@ -3226,6 +3312,39 @@ to see the actual buffer size."), NULL,


> +The actual buffer size may differ from the requested size.  Use \"info record\" \
> +to see the actual buffer size."), NULL, show_record_etm_buffer_size_value,
> +		  &set_record_btrace_etm_cmdlist,
> +		  &show_record_btrace_etm_cmdlist);

Please add an empty line here.

> +  add_setshow_string_cmd ("sink", no_class,
> +                          &record_btrace_conf.etm.sink,
> +                          _("Set the record/replay etm sink device."),
> +                          _("Show the record/replay etm sink device."),
> +                          _("\
> +sink device is the device that intercepts etm traces and collects or routes \

Please start with a capital letter.  Would etm be spelled ETM in the description?

> +them out of SoC.\n\

Is there a 'the' missing in front of SoC?

> +list of available sinks on linux targets are enumerated in the directory \
> +\"/sys/bus/event_source/devices/cs_etm/sinks/\".\n\
> +value \"default\" reverts it to default sink"),

Is 'revert' the right term, here?


> diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
> index 26d26ec957f..7f3cabfde77 100644
> --- a/gdbsupport/btrace-common.h
> +++ b/gdbsupport/btrace-common.h
> @@ -77,7 +80,10 @@ enum btrace_cpu_vendor
>    CV_INTEL,
> 
>    /* AMD.  */
> -  CV_AMD
> +  CV_AMD,
> +
> +  /* ARM. */
> +  CV_ARM

Does ARM also use model/family/stepping to identify their CPUs?

If not, please also extend struct btrace_cpu to make it a union
tagged with the vendor field.


> @@ -119,6 +125,18 @@ struct btrace_config_pt
>    unsigned int size;
>  };
> 
> +/* An ARM CoreSight ETM Trace configuration.  */
> +
> +struct btrace_config_etm
> +{
> +  /* The size of the branch trace buffer in bytes.
> +
> +     This is unsigned int and not size_t since it is registered as
> +     control variable for "set record btrace etm buffer-size".  */
> +  unsigned int size;
> +  char *sink;

Please leave an empty line and add a comment for 'sink'.

Regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-02-26  2:45 ` [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant Zied Guermazi
@ 2021-03-04 16:35   ` Metzger, Markus T
  2021-03-11  0:12     ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Metzger, Markus T @ 2021-03-04 16:35 UTC (permalink / raw)
  To: Zied Guermazi, gdb-patches

Hello Zied,

> This patch extend branch tracing by adding the functions nedded
> to start and stop tracing, as well decoding them. This patch is not

Start/stop was already added by 2/8.


> providing an implementation of the mechanisms on the target.

What does 'mechanism' refer to?


> diff --git a/gdb/btrace.c b/gdb/btrace.c
> index c697f37f46c..dcb89964b81 100644
> --- a/gdb/btrace.c
> +++ b/gdb/btrace.c
> @@ -227,6 +227,23 @@ ftrace_function_switched (const struct btrace_function
> *bfun,
>    return 0;
>  }
> 
> +#if defined (HAVE_LIBOPENCSD_C_API)
> +
> +/* set a record_btrace_reg_entry.  */

Capital first letter.

> +
> +static void
> +btrace_reg_set (struct record_btrace_reg_entry *reg,
> +                const struct regcache *regcache, int regnum, const gdb_byte *value)
> +{
> +  struct gdbarch *gdbarch = regcache->arch ();
> +
> +  reg->num = regnum;
> +  reg->len = register_size (gdbarch, regnum);
> +  memcpy(reg->buffer, value, reg->len);
> +}
> +
> +#endif //defined (HAVE_LIBOPENCSD_C_API)

I think there should be a space after //.


> @@ -257,6 +274,7 @@ ftrace_new_function (struct btrace_thread_info *btinfo,
>      }
> 
>    btinfo->functions.emplace_back (mfun, fun, number, insn_offset, level);
> +  ftrace_debug (&btinfo->functions.back (), "new function");
>    return &btinfo->functions.back ();

Please leave empty lines.  How about a local variable to hold the pointer now
that it is used in two places?

 
> @@ -671,6 +689,32 @@ ftrace_update_insns (struct btrace_function *bfun, const
> btrace_insn &insn)
>      ftrace_debug (bfun, "update insn");
>  }
> 
> +#if defined (HAVE_LIBOPENCSD_C_API)
> +  /* remove last instruction from BFUN's list.

Capital first letter.  You may use empty lines in comments, too, to structure
them.

> +     This function is not generic and is granted to work properly
> +     only if the same removed instruction will be added later.  */
> +
> +static void
> +ftrace_remove_last_insn (struct btrace_thread_info *btinfo)
> +{
> +  struct btrace_function  *bfun;

Please declare below when it is initialized.

> +
> +  /* If we didn't have a function, we return.  */
> +  if (btinfo->functions.empty ())
> +    return;

Please use empty lines to structure the code.

> +  /* If we had a gap before, we return.  */
> +  bfun = &btinfo->functions.back ();
> +  if (bfun->errcode != 0)
> +    return;
> +  if (!bfun->insn.empty ())
> +    bfun->insn.pop_back ();
> +  else
> +    {
> +      /* a valid function must have at least one insn  */
> +      error (_("Attempt to remove last instruction from an empty function"));

Should this be internal_error?


> @@ -1502,6 +1546,533 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
> 
>  #endif /* defined (HAVE_LIBIPT)  */
> 
> +#if defined (HAVE_LIBOPENCSD_C_API)
> +
> +struct cs_etm_decoder

Please add a comment describing the structure.


> +#define ARM_PS_REGNUM  25               /* Contains processor status */

This is already defined in arch/arm.h.  Please include that header instead
of defining it here, again.

> +
> +/* update btrace in the case of an instruction range  */
> +
> +static void
> +cs_etm_update_btrace_with_inst_range (const void *context,
> +                                     const ocsd_generic_trace_elem *elem)

The indentation seems off.  You might want to run some GNU style
checker or install one as pre-commit hook.


> +  struct cs_etm_decoder *etm_decoder;
> +  struct thread_info *tp;
> +  struct btrace_thread_info *btinfo;
> +  struct btrace_function *bfun;
> +  struct btrace_insn insn;
> +  CORE_ADDR pc;
> +  int size;
> +  struct gdbarch *gdbarch;
> +  unsigned int cpsr;
> +  struct record_btrace_reg_entry reg;

Please declare at first use.

> +
> +  if (elem->elem_type == OCSD_GEN_TRC_ELEM_INSTR_RANGE)

I looked for an else but didn't find one.  It may be better to turn this into

    if (elem->elem_type != OCSD_GEN_TRC_ELEM_INSTR_RANGE)
      return;

> +    {
> +      etm_decoder = (struct cs_etm_decoder *)context;
> +      if (!etm_decoder->t_info )

GNU style requires explicit comparison against nullptr.  Also, there's
an additional space before ')'.

> +        return;

Please add an empty line here to structure the code.

> +      tp = etm_decoder->t_info;
> +      btinfo = &tp->btrace;
> +      gdbarch = target_gdbarch ();
> +
> +      pc = elem->st_addr;
> +      for (int i = 0; i< elem->num_instr_range; i++)
> +        {
> +          insn.pc = pc;
> +          try
> +            {
> +              size = gdb_insn_length (gdbarch, pc);
> +            }
> +          catch (const gdb_exception_error &err)
> +            {
> +              error (_("Failed to get the size of the instruction."));
> +            }
> +          bfun = ftrace_update_function (btinfo, pc );

Additional space before ')'.

> +          insn.iclass=BTRACE_INSN_OTHER;
> +          insn.size = size;
> +          if (etm_decoder->arch_version == ARCH_V7)
> +            {
> +              switch(elem->isa)
> +              {

Indentation seems off.  Indent two more spaces.

Indentation uses 8-wide tabs and spaces.

> +                case ocsd_isa_arm:
> +                  cpsr = 0;
> +                  break;

Please add an empty line between cases.

> +                case ocsd_isa_thumb2:
> +                  cpsr = 0x20;
> +                  break;
> +                case ocsd_isa_tee:
> +                  cpsr = 0x1000020;
> +                  break;
> +                case ocsd_isa_jazelle:
> +                  cpsr = 0x1000000;
> +                  break;
> +                default:
> +                  cpsr = 0;
> +              }

It might make sense to turn this if into a small helper function.

> +              btrace_reg_set (&reg, get_thread_regcache(tp),

Space before '('.

> +                              ARM_PS_REGNUM, (gdb_byte *)&cpsr);
> +              insn.registers.push_back (reg);
> +            }
> +          if (i == elem->num_instr_range -1)
> +            {
> +              switch (elem->last_i_type)
> +              {
> +                case OCSD_INSTR_BR:
> +                case OCSD_INSTR_BR_INDIRECT:
> +                  switch (elem->last_i_subtype )
> +                  {
> +                    case OCSD_S_INSTR_V8_RET:
> +                    case OCSD_S_INSTR_V8_ERET:
> +                    case OCSD_S_INSTR_V7_IMPLIED_RET:
> +                      insn.iclass=BTRACE_INSN_RETURN;
> +                      break;
> +                    case OCSD_S_INSTR_BR_LINK:
> +                      insn.iclass=BTRACE_INSN_CALL;
> +                      break;
> +                    case OCSD_S_INSTR_NONE:
> +                      insn.iclass=BTRACE_INSN_JUMP;
> +                  }
> +                  break;
> +                    case OCSD_INSTR_ISB:
> +                    case OCSD_INSTR_DSB_DMB:
> +                    case OCSD_INSTR_WFI_WFE:
> +                    case OCSD_INSTR_OTHER:
> +                      insn.iclass=BTRACE_INSN_OTHER;
> +                      break;
> +                    default:
> +                      break;
> +              }

This switch could be a small helper function, too.

> +            }
> +          ftrace_update_insns (bfun, insn);
> +          pc = pc + size;
> +        }
> +    }
> +}
> +#undef ARM_PS_REGNUM
> +
> +#define ARM_EXCEPTION_UNDEFINED_INSTRUCTION 9

Should this go into arch/arm.h?


> +          if (elem->exception_number ==
> ARM_EXCEPTION_UNDEFINED_INSTRUCTION)
> +            {
> +              DEBUG ("handle breakpoints implementation in gdb for armv7");
> +              ftrace_remove_last_insn(btinfo);

Could we detect this before we added the instruction?


> +static void
> +cs_etm_update_btrace_with_trace_on (const void *context,
> +                                   const ocsd_generic_trace_elem *elem)
> +{
> +  struct cs_etm_decoder *etm_decoder;
> +  struct thread_info *tp;
> +  struct btrace_thread_info *btinfo;
> +
> +  etm_decoder = (struct cs_etm_decoder *)context;
> +  if (!etm_decoder->t_info )
> +    return;
> +  tp = etm_decoder->t_info;
> +  btinfo = &tp->btrace;
> +
> +  if (elem->elem_type==OCSD_GEN_TRC_ELEM_TRACE_ON)

Should we rather assert this?  Also for similar functions above.

> +static ocsd_datapath_resp_t
> +cs_etm_trace_element_callback (const void *context,
> +				const ocsd_trc_index_t indx,
> +				const uint8_t trace_chan_id,
> +				const ocsd_generic_trace_elem *elem)
> +{
> +  char str_buffer[128];
> +  if(ocsd_gen_elem_str(elem, str_buffer,128) == OCSD_OK)

Space between if and ( and between _str and (.

> +    DEBUG("ETM trace_element: index= %d, channel= 0x%x, %s",
> +          indx, trace_chan_id, str_buffer);

Please add empty lines to structure the code. 

> +  ocsd_datapath_resp_t resp = OCSD_RESP_CONT;

This is not changed in the switch.  We could just return
OCSD_RESP_CONT ...

> +  switch (elem->elem_type) {
> +    case OCSD_GEN_TRC_ELEM_TRACE_ON:
> +      cs_etm_update_btrace_with_trace_on(context, elem);
> +      break;
> +    case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
> +      cs_etm_update_btrace_with_inst_range(context, elem);
> +      break;
> +    case OCSD_GEN_TRC_ELEM_EXCEPTION:
> +      cs_etm_update_btrace_with_exception(context, elem);
> +      break;
> +    case OCSD_GEN_TRC_ELEM_UNKNOWN:
> +    case OCSD_GEN_TRC_ELEM_EO_TRACE:
> +    case OCSD_GEN_TRC_ELEM_NO_SYNC:
> +    case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
> +    case OCSD_GEN_TRC_ELEM_TIMESTAMP:
> +    case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
> +    case OCSD_GEN_TRC_ELEM_ADDR_NACC:
> +    case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
> +    case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
> +    case OCSD_GEN_TRC_ELEM_EVENT:
> +    case OCSD_GEN_TRC_ELEM_SWTRACE:
> +    case OCSD_GEN_TRC_ELEM_CUSTOM:
> +    default:
> +      break;
> +  }
> +  return resp;

... here.


> +static bool
> +cs_etm_create_decoder (struct cs_etm_trace_params *t_params,
> +			struct cs_etm_decoder *decoder)
> +{
> +  const char *decoder_name;
> +  ocsd_etmv3_cfg config_etmv3;
> +  ocsd_etmv4_cfg trace_config_etmv4;
> +  void *trace_config;
> +  uint8_t csid;
> +
> +  switch (t_params->protocol) {

The { goes onto the next line.


> +    default:
> +      decoder->arch_version = ARCH_UNKNOWN;
> +      return false;

Wouldn't it make more sense to error () or return an error code?
There are different things that can go wrong, it seems.


> +  if (dcdtree_handle == C_API_INVALID_TREE_HANDLE)
> +    return NULL;
> +  decoder=(struct cs_etm_decoder*)xmalloc (sizeof(struct cs_etm_decoder));

How about new?

There are spaces missing in several places in this line.

> +  decoder->dcd_tree = dcdtree_handle;
> +
> +  for (i = 0; i < num_cpu; i++) {
> +      ret = cs_etm_create_decoder(&(t_params->at(i)),
> +                                  decoder);

Is this overwriting the same decoder object?

> +      if (ret == false)
> +        {
> +          ocsd_destroy_dcd_tree(decoder->dcd_tree);
> +          free(decoder);

Do we need to undo anything for the other cpus from 0 to i-1?

There's a cs_etm_free_decoder function defined below.  Should
this be called to free the decoder?


> +  result = (int) reqBytes;
> +  try
> +  {
> +      errcode = target_read_code ((CORE_ADDR) address, byteBuffer, reqBytes);
> +      if (errcode != 0)
> +        result = 0;
> +  }
> +  catch (const gdb_exception_error &error)
> +  {
> +      result = 0;
> +  }
> +
> +  return result;

That construct was needed for the old TRY and CATCH macros.  We should meanwhile
be OK to return from try and catch statements.


> +static ocsd_err_t
> +cs_etm_add_mem_access_callback (struct cs_etm_decoder *decoder,
> +                               CORE_ADDR start, CORE_ADDR end,
> +                               Fn_MemAcc_CB p_cb_func)
> +{
> +  ocsd_err_t error;
> +  error = ocsd_dt_add_callback_mem_acc(decoder->dcd_tree,
> +                                       (ocsd_vaddr_t) start, (ocsd_vaddr_t) end,
> +                                       OCSD_MEM_SPACE_ANY, p_cb_func, decoder);
> +  if (error != OCSD_OK)
> +    decoder->mem_access = p_cb_func;

Should this be

    if (error == OCSD_OK)


> +  return (error);

The () should not be necessary.


> +  while (processed < len) {
> +      if (OCSD_DATA_RESP_IS_WAIT(prev_return)) {
> +          cur = ocsd_dt_process_data(decoder->dcd_tree,
> +                                     OCSD_OP_FLUSH,
> +                                     0,
> +                                     0,
> +                                     NULL,
> +                                     NULL);

Those arguments should all fit onto one line.


> +/* print all function in a btrace  */
> +
> +static void btrace_print_all (struct btrace_thread_info *btinfo)

Break after function type.  Name goes onto next line.

> +{
> +  std::vector<btrace_function> functions;
> +
> +  functions = btinfo->functions;

Do we even need that local variable?

 
>    DEBUG ("enable thread %s (%s)", print_thread_id (tp),
>           target_pid_to_str (tp->ptid).c_str ());
> @@ -1791,6 +2370,9 @@ btrace_stitch_trace (struct btrace_data *btrace, struct
> thread_info *tp)
>      case BTRACE_FORMAT_PT:
>        /* Delta reads are not supported.  */
>        return -1;
> +    case BTRACE_FORMAT_ETM:

Please add an empty line before a new case.


> @@ -3487,7 +4074,7 @@ first."),
>  	   maint_btrace_clear_packet_history_cmd,
>  	    _("Clears the branch tracing packet history.\n\
>  Discards the raw branch tracing data but not the execution history data."),
> -	   &maint_btrace_cmdlist);
> +&maint_btrace_cmdlist);

Unrelated change.


> diff --git a/gdb/btrace.h b/gdb/btrace.h
> index 8f6ce32103d..5d734896632 100644
> --- a/gdb/btrace.h
> +++ b/gdb/btrace.h
> @@ -63,6 +69,17 @@ enum btrace_insn_flag
>  };
>  DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags);
> 
> +/* extend MAX_BTRACE_REGISTER_SIZE if targets with registers
> +bigger than 64 bits are considered  */
> +#define MAX_BTRACE_REGISTER_SIZE 8
> +/* a register entry in btrace_insn*/
> +struct record_btrace_reg_entry
> +{
> +  unsigned short num;
> +  unsigned short len;
> +  gdb_byte buffer[MAX_BTRACE_REGISTER_SIZE * sizeof (gdb_byte)];
> +};

Please add comments to all fields.


> @@ -74,6 +91,9 @@ struct btrace_insn
>    /* The size of this instruction in bytes.  */
>    gdb_byte size;
> 
> +  /* a vector of registers */
> +  std::vector<record_btrace_reg_entry> registers;

This is very expensive.  We will have lots of btrace_insn objects.

Do we need those registers on all ARM instructions?

If yes, we need to see how we can make others that don't need them
not pay the price.
If no, we need to look into a better way of providing those registers;
maybe inside the btrace_insn stream as special types of instructions.


> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
> index 39ac9aafc28..107abd7e653 100644
> --- a/gdb/record-btrace.c
> +++ b/gdb/record-btrace.c
> @@ -3020,7 +3029,6 @@ cmd_record_btrace_start (const char *args, int from_tty)
>      }
>  }
> 
> -

Hmmm, I do not see two empty lines at that location.

>  /* The "show record btrace replay-memory-access" command.  */
> 
>  static void
> @@ -3250,7 +3258,6 @@ This format may not be available on all processors."),
>  		       _("Show record options."), &show_record_btrace_cmdlist,
>  		       "show record btrace ", 0, &show_record_cmdlist);
> 
> -

Same here.

>    add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
>  Automatically determine the cpu to be used for trace decode."),
>  	   &set_record_btrace_cpu_cmdlist);
> diff --git a/gdbsupport/btrace-common.cc b/gdbsupport/btrace-common.cc
> index 461f769ed51..8e31c8a65dd 100644
> --- a/gdbsupport/btrace-common.cc
> +++ b/gdbsupport/btrace-common.cc
> @@ -62,7 +62,6 @@ btrace_format_short_string (enum btrace_format format)
> 
>      case BTRACE_FORMAT_ETM:
>        return "etm";
> -

Could this be leftovers from a previous patch in the series?

>    }
> 
>    internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
> @@ -87,6 +86,12 @@ btrace_data::fini ()
>      case BTRACE_FORMAT_PT:
>        xfree (variant.pt.data);
>        return;
> +
> +    case BTRACE_FORMAT_ETM:
> +      /* Variant.etm.data can be null if no new traces are collected.  */
> +      if (variant.etm.data!=NULL)

Spaces around !=.

 
> diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
> index 7f3cabfde77..5bc6f8dbd0f 100644
> --- a/gdbsupport/btrace-common.h
> +++ b/gdbsupport/btrace-common.h
> @@ -189,6 +188,108 @@ struct btrace_data_pt
>    size_t size;
>  };
> 
> +/* Parameters needed for decoding ETMv3 traces.
> +   See open source coresight trace decoder library (opencsd)
> +   for further details.  */
> +struct cs_etmv3_trace_params {
> +  uint32_t reg_ctrl;
> +  uint32_t reg_trc_id;
> +  uint32_t reg_ccer;
> +  uint32_t reg_idr;
> +};

Please describe all the fields in comments.

> +/* The following enums are indexed starting with 1 to align with the
> +   open source coresight trace decoder library (opencsd).  */
> +enum {
> +  CS_ETM_PROTO_ETMV3 = 1,
> +  CS_ETM_PROTO_ETMV4i,
> +  CS_ETM_PROTO_ETMV4d,
> +  CS_ETM_PROTO_PTM,

And all the enumeration constants.


> +/* The following enum must be aligned with the
> +   open source coresight trace decoder library (opencsd).  */

Could we get them from a header file?


> +/* The following enum must be aligned with the
> +   open source coresight trace decoder library (opencsd).  */

And those, as well?


I noticed a number of style issues in this patch.  I have not pointed out
all of them.  Would it be possible to run a GNU style checker on this
patch series and fix anything that it finds?

We need to discuss how to handle register values inside the btrace_insn
stream.  I'd suggest we close that before reviewing the rest of this patch
series.


Regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 8/8] document btrace support for arm targets using coresight etm traces
  2021-02-26  7:36   ` Eli Zaretskii
@ 2021-03-10 20:36     ` Zied Guermazi
  0 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-03-10 20:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

hi Eli

thanks for your review. below is the status of the changed, the result 
will be published in the v2 of the patchset.

Kind Regards.

Zied Guermazi


On 26.02.21 08:36, Eli Zaretskii wrote:
>> From: Zied Guermazi <zied.guermazi@trande.de>
>> Date: Fri, 26 Feb 2021 03:46:02 +0100
>> Cc: Zied Guermazi <zied.guermazi@trande.de>
>>
>> This patch documents the extensions done in GDB to enable using
>> ARM Coresight traces for btrace.
>>
>> gdb/doc/ChangeLog
>>
>> 	* gdb.texinfo: Document extending btrace to support
>> 	ARM CoreSight traces commands and packets
> This should mention in parentheses the names of the modified @node's
> (as if each node were a function).
[Zied] changed accordingly.
>
>> 	* gdb/NEWS: list new commands and new remote packets
> This goes into a different ChangeLog file, gdb/ChangeLog.
[Zied] done
>
>> +set|show record btrace etm sink
>> +  Set and show the trace sink used for branch tracing in
>> +  ETM format.
>> +  use default to revert it to default sink
>       ^^^^^^^^^^^
> The last sentence should begin with a capital "U".
> Also, the sentence is not very clear: what do you mean by "use default"?
> And I don't think I see this aspect described in the manual, did I
> miss something?
[Zied] done. this aspect is described in @node Process Record and Replay
>
>> +@item etm
>> +@cindex ARM CoreSight ETM Trace
>> +Use the @dfn{ARM CoreSight ETM Trace} recording format.  In this
>> +format, the processor stores the execution trace in a compressed form
>> +that is afterwards decoded by @value{GDBN}.
> Please tell here what does "ETM" stand for (AFAIU, it stands for
> "Embedded Trace Macrocell").  We should explain the acronyms in the
> manual.
[Zied] done.
>
>> +@item set record btrace etm sink @var{sink}
>> +Set ARM CoreSight ETM sink to collect traces.
>> +possible values for @var{sink} can be found by listing the folder
>> +/sys/bus/event_source/devices/cs_etm/sinks/
> "possible" should be "Possible", with a capital "P".
> Instead of "folder", please use "file", and please give the file name
> the @file markup.

[Zied] Changed to

"On @sc{gnu}/Linux systems, possible values for @var{sink} are the name 
of the
files in the directory @file{/sys/bus/event_source/devices/cs_etm/sinks/}.

Use the value @kbd{default} to reset it to default sink."

>
>> +@item show record btrace etm sink
>> +show ARM CoreSight ETM sink .
>     ^^^^                       ^^
> Capitalize "show", and delete that extra blank before the period.
[Zied] done.
>
>> +@item etm
>> +For the ARM CoreSight ETM Trace recording format, print a list of
> This is very far from the description of the ETM tracking support, so
> please add here a cross-reference to that description.
[Zied] done
>
>> +@item @samp{Qbtrace:etm}
> Same here.
[Zied] alignment of the table is not kept when the cross reference is 
added there. it is added in the section below.
>
> Thanks.
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY
  2021-02-26  7:12   ` Aktemur, Tankut Baris
@ 2021-03-10 20:39     ` Zied Guermazi
  0 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-03-10 20:39 UTC (permalink / raw)
  To: Aktemur, Tankut Baris, gdb-patches

hi Baris,

Thanks for your review. The  line is changed to

infrun_debug_printf ("setting step over info");

to keep in pair with

infrun_debug_printf ("clearing step over info"); .

Change will be made available in the version 2 of the patch set

Kind Regards

Zied Guermazi


On 26.02.21 08:12, Aktemur, Tankut Baris wrote:
> On Friday, February 26, 2021 3:46 AM, Zied Guermazi wrote:
>> This patch fixes an issue observed with btrace when replaying the execution.
>> The issue was observed on ARMv7 processors.
>> To reproduce the issue needs to replay in forward direction
>> until he reaches the end of history, then replay backwards
>> (e.g a reverse-next) and then replay forwards. gdb hangs and the user
>> can not issue new commands.
>>
>> gdb/ChangeLog
>>
>> 	* infrun.c (set_step_over_info): add debug print.
>> 	(handle_inferior_event): clear step over info
>> 	in case TARGET_WAITKIND_NO_HISTORY
>>
>> ---
>>   gdb/ChangeLog | 6 ++++++
>>   gdb/infrun.c  | 3 ++-
>>   2 files changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
>> index a84671bf344..15dee4eb29b 100644
>> --- a/gdb/ChangeLog
>> +++ b/gdb/ChangeLog
>> @@ -1,3 +1,9 @@
>> +2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
>> +
>> +	* infrun.c (set_step_over_info): add debug print.
>> +	* infrun.c (handle_inferior_event): clear step over info.
>> +	in case TARGET_WAITKIND_NO_HISTORY
>> +
>>   2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
>>
>>   	* nat/linux-btrace.h (btrace_tinfo_etm): New.
>> diff --git a/gdb/infrun.c b/gdb/infrun.c
>> index a271220b261..a483307d7a3 100644
>> --- a/gdb/infrun.c
>> +++ b/gdb/infrun.c
>> @@ -1308,6 +1308,7 @@ set_step_over_info (const address_space *aspace, CORE_ADDR address,
>>   		    int nonsteppable_watchpoint_p,
>>   		    int thread)
>>   {
>> +  infrun_debug_printf ("infrun: set_step_over_info\n");
> The debug printf function already prints "infrun", the function name,
> and the newline.  Just
>
>    infrun_debug_printf ("enter");
>
> is most likely sufficient.
>
> -Baris
>
>
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 1/8] configure gdb build system for supporting btrace on arm processors
  2021-03-04 16:35   ` Metzger, Markus T
@ 2021-03-10 22:09     ` Zied Guermazi
  0 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-03-10 22:09 UTC (permalink / raw)
  To: Metzger, Markus T; +Cc: gdb-patches

hi Markus,

thank for reviewing the patch set. Below is the status of the changes, 
the result will be published in the v2 of the patch set.

On 04.03.21 17:35, Metzger, Markus T wrote:
> Hello Zied,
>
>> gdb/ChangeLog
>>
>> 	* Makefile.in LIBOPENCSD_C_API: set the flag.
>> 	* config.in LIBOPENCSD_C_API: undefine it if
>> 	libopenocsd library is available.
> This file is auto-generated.
[Zied] pending: issue in generating the files with automake on my Ubuntu 
machine. The issue was published in gdb@sourceware.org
>
>
>> diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
>> index 3ed95dabc85..8d2f959e8f3 100644
>> --- a/gdbsupport/common.m4
>> +++ b/gdbsupport/common.m4
>> @@ -186,6 +186,45 @@ AC_DEFUN([GDB_AC_COMMON], [
> [...]
>
>
>> +    if test "$perf_event" != yes; then
>> +      if test "$" = yes; then
> Should this be $with_arm_cs?
[Zied] yes, issue fixed.
>
>> +        AC_MSG_ERROR([linux/perf_event.h missing or too old])
>> +      else
>> +        AC_MSG_WARN([linux/perf_event.h missing or too old; CoreSight Tracing will
>> be unavailable.])
>> +      fi
>> +    fi
>> +
>> +    AC_LIB_HAVE_LINKFLAGS([opencsd_c_api], [], [#include
>> "opencsd/c_api/opencsd_c_api.h"], [ocsd_get_version();])
>> +    if test "$HAVE_LIBOPENCSD_C_API" != yes; then
>> +      if test "$" = yes; then
> Also here.
[Zied] issue fixed.
>
>> +        AC_MSG_ERROR([libopencsd_c_api is missing or unusable])
>> +      else
>> +        AC_MSG_WARN([libopencsd_c_api is missing or unusable; CoreSight Tracing
>> will be unavailable.])
>> +      fi
>> +    else
>> +      LIBS="$LIBS $LIBOPENCSD_C_API"
>> +    fi
>> +  fi
>> +
>> +
>>     BFD_SYS_PROCFS_H
>>     if test "$ac_cv_header_sys_procfs_h" = yes; then
>>       BFD_HAVE_SYS_PROCFS_TYPE(gregset_t)
> Regards,
> Markus.
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
>
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/8] add btrace coresight related commands
       [not found]     ` <8a71a9a3-ad14-b716-6d86-ece063061b02@trande.de>
@ 2021-03-10 22:37       ` Zied Guermazi
  2021-03-16 10:16         ` Metzger, Markus T
  0 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-03-10 22:37 UTC (permalink / raw)
  To: Metzger, Markus T, gdb-patches


hi Markus,

thanks for your review. I have done needed changes for most of them. The 
changes will be published in the version 2 of the patchset.

The parameters needed for decoding the traces are more complex than the 
one for decoding PT traces. So an implementation for allowing the user a 
full flexibility in changing them will be very complex. Therefore, I did 
not provide a mean for changing them manually. I have added CV_ARM to 
the list of btrace_cpu_vendor to be able to show it. It can be removed 
if assessed as not needed.


please see inlined feedback

On 04.03.21 17:35, Metzger, Markus T wrote:
> Hello Zied,
>
>> This patch extends the commands needed for using branch tracing
>> with ARM CoreSight traces.
>> Those commands are:
>> set record btrace etm sink
>> set record btrace etm size
>> record btrace etm
> You'd want to describe them in gdb/doc/gdb.texinfo and announce the
> new commands in gdb/NEWS.
>
[Zied] set record btrace etm buffer-size : an error in the description.
both commands are documented in patch 8/8
>> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
>> index d9cc7a3b6d8..39ac9aafc28 100644
>> --- a/gdb/record-btrace.c
>> +++ b/gdb/record-btrace.c
>> @@ -525,6 +529,22 @@ record_btrace_print_pt_conf (const struct
>> btrace_config_pt *conf)
>>       }
>>   }
>>
>> +/* Print an ARM Processor Trace configuration.  */
>> +
>> +static void
>> +record_btrace_print_etm_conf (const struct btrace_config_etm *conf)
>> +{
>> +  const char *suffix;
>> +  unsigned int size;
> The surrounding code is old.  New code should declare variables when
> they are first used.
>
[Zied] done.
>> +    case BTRACE_FORMAT_ETM:
>> +      record_btrace_print_etm_conf (&conf->etm);
> You may want to use a const & parameter, instead.
>
>
[Zied] kept as is.
>> @@ -2936,6 +2960,27 @@ cmd_record_btrace_pt_start (const char *args, int
>> from_tty)
>>       }
>>   }
>>
>> +/* Start recording in arm CoreSight ETM Trace format.  */
>> +
>> +static void
>> +cmd_record_btrace_etm_start (const char *args, int from_tty)
>> +{
>> +  if (args != NULL && *args != 0)
> nullptr instead of NULL.
>
>
[Zied] changed.
>> @@ -2950,10 +2995,18 @@ cmd_record_btrace_start (const char *args, int
>> from_tty)
>>       {
>>         execute_command ("target record-btrace", from_tty);
>>       }
>> -  catch (const gdb_exception &exception)
>> +  catch (const gdb_exception &exception_pt)
>>       {
>>         record_btrace_conf.format = BTRACE_FORMAT_BTS;
>>
>> +      try
>> +        {
>> +          execute_command ("target record-btrace", from_tty);
>> +        }
>> +      catch (const gdb_exception &exception_bts)
>> +        {
>> +          record_btrace_conf.format = BTRACE_FORMAT_ETM;
>> +
> We could look at the architecture to avoid trying PT and BTS first on ARM.
> Not sure it matters in practice.
>
[Zied] I prefer letting it so, changing it will add dependencies to the 
target description etc.., for a  comparable processing.
>> @@ -3074,6 +,10 @@ cmd_show_record_btrace_cpu (const char *args, int
>> from_tty)
>>                                  record_btrace_cpu.model,
>>                                  record_btrace_cpu.stepping);
>>             return;
>> +        case CV_ARM:
> Please leave an empty line before the new case.
>
[Zied] done
>> +          printf_unfiltered ("btrace cpu is 'ARM'.\n");
> The idea behind 'set record btrace cpu' is to allow the user to overwrite
> the cpu identifier for enabling errata workarounds.  The main use-case is
> when libipt does not know the cpu so it cannot enable workarounds
> automatically.
>
>
[Zied] yes, I initially went into the direction of letting the user 
change all parameters needed for decoding etm traces, but considering 
the complexity and the fact that this will be error prone, I reverted 
back to a minimum support by just printing that this is an ARM core.
>> @@ -3165,6 +3235,22 @@ When set to \"none\", errata workarounds are
>> disabled."),
>>   		  "set record btrace cpu ", 1,
>>   		  &set_record_btrace_cmdlist);
>>
>> +  add_cmd ("etm", class_obscure, cmd_record_btrace_etm_start,
>> +	   _("\
>> +Start branch trace recording in arm CoreSight ETM Trace format.\n\n\
> Isn't ARM typically spelled with capital letters?
>
[Zied] changed.
>> +This format may not be available on all processors."),
>> +	   &record_btrace_cmdlist);
>> +  add_alias_cmd ("etm", "btrace etm", class_obscure, 1, &record_cmdlist);
> This alias wasn't mentioned in the list of new commands.
>
[Zied] See patch 8/8
>> +  add_basic_prefix_cmd ("btrace", class_support,
>> +			_("Set record options."), &set_record_btrace_cmdlist,
>> +			"set record btrace ", 0, &set_record_cmdlist);
>> +
>> +  add_show_prefix_cmd ("btrace", class_support,
>> +		       _("Show record options."), &show_record_btrace_cmdlist,
>> +		       "show record btrace ", 0, &show_record_cmdlist);
> There already are such prefix commands.
>
[Zied] removed.
>> @@ -3226,6 +3312,39 @@ to see the actual buffer size."), NULL,
>> +The actual buffer size may differ from the requested size.  Use \"info record\" \
>> +to see the actual buffer size."), NULL, show_record_etm_buffer_size_value,
>> +		  &set_record_btrace_etm_cmdlist,
>> +		  &show_record_btrace_etm_cmdlist);
> Please add an empty line here.
[Zied] done.
>
>> +  add_setshow_string_cmd ("sink", no_class,
>> +                          &record_btrace_conf.etm.sink,
>> +                          _("Set the record/replay etm sink device."),
>> +                          _("Show the record/replay etm sink device."),
>> +                          _("\
>> +sink device is the device that intercepts etm traces and collects or routes \
> Please start with a capital letter.  Would etm be spelled ETM in the description?
[Zied] changed.
>> +them out of SoC.\n\
> Is there a 'the' missing in front of SoC?
[Zied] added.
>> +list of available sinks on linux targets are enumerated in the directory \
>> +\"/sys/bus/event_source/devices/cs_etm/sinks/\".\n\
>> +value \"default\" reverts it to default sink"),
> Is 'revert' the right term, here?
[Zied] changed to 'reset'
>> diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
>> index 26d26ec957f..7f3cabfde77 100644
>> --- a/gdbsupport/btrace-common.h
>> +++ b/gdbsupport/btrace-common.h
>> @@ -77,7 +80,10 @@ enum btrace_cpu_vendor
>>     CV_INTEL,
>>
>>     /* AMD.  */
>> -  CV_AMD
>> +  CV_AMD,
>> +
>> +  /* ARM. */
>> +  CV_ARM
> Does ARM also use model/family/stepping to identify their CPUs?
>
> If not, please also extend struct btrace_cpu to make it a union
> tagged with the vendor field.
>
[Zied] I am just using this to stub the show commands for ARM.
>> @@ -119,6 +125,18 @@ struct btrace_config_pt
>>     unsigned int size;
>>   };
>>
>> +/* An ARM CoreSight ETM Trace configuration.  */
>> +
>> +struct btrace_config_etm
>> +{
>> +  /* The size of the branch trace buffer in bytes.
>> +
>> +     This is unsigned int and not size_t since it is registered as
>> +     control variable for "set record btrace etm buffer-size".  */
>> +  unsigned int size;
>> +  char *sink;
> Please leave an empty line and add a comment for 'sink'.
[Zied] done
> Regards,
> Markus.
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0,www.intel.de  <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
>



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-03-04 16:35   ` Metzger, Markus T
@ 2021-03-11  0:12     ` Zied Guermazi
  2021-03-16 10:16       ` Metzger, Markus T
  0 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-03-11  0:12 UTC (permalink / raw)
  To: gdb-patches, Metzger, Markus T

hi Markus,

thanks for reviewing the patch. Review comments are handled And the 
outcome will be published in the version 2 of the patch set.

I reworked the patch for C coding style. To my knowledge there is not 
coding styles issues left.

For the point concerning the use of a vector of registers in btrace_insn:

a vector of registers is added to the btrace_insn structure. This adds 
an overhead of 3 pointers when the vector is empty. It will be the 
overhead when not used (intel pt). I think this should be acceptable.

on ARMv7 this is need for all instructions, to allow step and next to 
set the breakpoints properly in the code.

on ARMv8, this is currently not used.

This implementation paves the way to handling ETM traces with data, so 
that gdb can have access in addition, to the registers altered during an 
instruction. This is very useful in execution record and replay since we 
can then reconstruct (some of) the variables.


Kind Regards

Zied Guermazi


On 04.03.21 17:35, Metzger, Markus T wrote:
> Hello Zied,
>
>> This patch extend branch tracing by adding the functions nedded
>> to start and stop tracing, as well decoding them. This patch is not
> Start/stop was already added by 2/8.
[Zied]  changed to "This patch extend branch tracing by adding the 
functions needed
to collect etm parameters for decoding ETM traces and decoding them."
>
>
>> providing an implementation of the mechanisms on the target.
> What does 'mechanism' refer to?
[Zied] see above
>
>> diff --git a/gdb/btrace.c b/gdb/btrace.c
>> index c697f37f46c..dcb89964b81 100644
>> --- a/gdb/btrace.c
>> +++ b/gdb/btrace.c
>> @@ -227,6 +227,23 @@ ftrace_function_switched (const struct btrace_function
>> *bfun,
>>     return 0;
>>   }
>>
>> +#if defined (HAVE_LIBOPENCSD_C_API)
>> +
>> +/* set a record_btrace_reg_entry.  */
> Capital first letter.
[Zied] done
>> +
>> +static void
>> +btrace_reg_set (struct record_btrace_reg_entry *reg,
>> +                const struct regcache *regcache, int regnum, const gdb_byte *value)
>> +{
>> +  struct gdbarch *gdbarch = regcache->arch ();
>> +
>> +  reg->num = regnum;
>> +  reg->len = register_size (gdbarch, regnum);
>> +  memcpy(reg->buffer, value, reg->len);
>> +}
>> +
>> +#endif //defined (HAVE_LIBOPENCSD_C_API)
> I think there should be a space after //.
[Zied] done
>
>> @@ -257,6 +274,7 @@ ftrace_new_function (struct btrace_thread_info *btinfo,
>>       }
>>
>>     btinfo->functions.emplace_back (mfun, fun, number, insn_offset, level);
>> +  ftrace_debug (&btinfo->functions.back (), "new function");
>>     return &btinfo->functions.back ();
> Please leave empty lines.  How about a local variable to hold the pointer now
> that it is used in two places?
[Zied] empty line added. The pointer changed in between (new element 
inserted via emplace_back ), so keep it as it is.
>   
>> @@ -671,6 +689,32 @@ ftrace_update_insns (struct btrace_function *bfun, const
>> btrace_insn &insn)
>>       ftrace_debug (bfun, "update insn");
>>   }
>>
>> +#if defined (HAVE_LIBOPENCSD_C_API)
>> +  /* remove last instruction from BFUN's list.
> Capital first letter.  You may use empty lines in comments, too, to structure
> them.
[Zied] Done.
>> +     This function is not generic and is granted to work properly
>> +     only if the same removed instruction will be added later.  */
>> +
>> +static void
>> +ftrace_remove_last_insn (struct btrace_thread_info *btinfo)
>> +{
>> +  struct btrace_function  *bfun;
> Please declare below when it is initialized.
[Zied] done.
>
>> +
>> +  /* If we didn't have a function, we return.  */
>> +  if (btinfo->functions.empty ())
>> +    return;
> Please use empty lines to structure the code.
[Zied] done.
>
>> +  /* If we had a gap before, we return.  */
>> +  bfun = &btinfo->functions.back ();
>> +  if (bfun->errcode != 0)
>> +    return;
>> +  if (!bfun->insn.empty ())
>> +    bfun->insn.pop_back ();
>> +  else
>> +    {
>> +      /* a valid function must have at least one insn  */
>> +      error (_("Attempt to remove last instruction from an empty function"));
> Should this be internal_error?
[Zied] changed to internal_error
>
>
>> @@ -1502,6 +1546,533 @@ btrace_compute_ftrace_pt (struct thread_info *tp,
>>
>>   #endif /* defined (HAVE_LIBIPT)  */
>>
>> +#if defined (HAVE_LIBOPENCSD_C_API)
>> +
>> +struct cs_etm_decoder
> Please add a comment describing the structure.
[Zied] done
>
>> +#define ARM_PS_REGNUM  25               /* Contains processor status */
> This is already defined in arch/arm.h.  Please include that header instead
> of defining it here, again.
[Zied] done
>> +
>> +/* update btrace in the case of an instruction range  */
>> +
>> +static void
>> +cs_etm_update_btrace_with_inst_range (const void *context,
>> +                                     const ocsd_generic_trace_elem *elem)
> The indentation seems off.  You might want to run some GNU style
> checker or install one as pre-commit hook.
[Zied] Done.
>
>
>> +  struct cs_etm_decoder *etm_decoder;
>> +  struct thread_info *tp;
>> +  struct btrace_thread_info *btinfo;
>> +  struct btrace_function *bfun;
>> +  struct btrace_insn insn;
>> +  CORE_ADDR pc;
>> +  int size;
>> +  struct gdbarch *gdbarch;
>> +  unsigned int cpsr;
>> +  struct record_btrace_reg_entry reg;
> Please declare at first use.
[Zied] done
>> +
>> +  if (elem->elem_type == OCSD_GEN_TRC_ELEM_INSTR_RANGE)
> I looked for an else but didn't find one.  It may be better to turn this into
>
>      if (elem->elem_type != OCSD_GEN_TRC_ELEM_INSTR_RANGE)
>        return;
>
>> +    {
>> +      etm_decoder = (struct cs_etm_decoder *)context;
>> +      if (!etm_decoder->t_info )
> GNU style requires explicit comparison against nullptr.  Also, there's
> an additional space before ')'.
[Zied] done
>
>> +        return;
> Please add an empty line here to structure the code.
>
[Zied] done
>> +      tp = etm_decoder->t_info;
>> +      btinfo = &tp->btrace;
>> +      gdbarch = target_gdbarch ();
>> +
>> +      pc = elem->st_addr;
>> +      for (int i = 0; i< elem->num_instr_range; i++)
>> +        {
>> +          insn.pc = pc;
>> +          try
>> +            {
>> +              size = gdb_insn_length (gdbarch, pc);
>> +            }
>> +          catch (const gdb_exception_error &err)
>> +            {
>> +              error (_("Failed to get the size of the instruction."));
>> +            }
>> +          bfun = ftrace_update_function (btinfo, pc );
> Additional space before ')'.
[Zied] done
>
>> +          insn.iclass=BTRACE_INSN_OTHER;
>> +          insn.size = size;
>> +          if (etm_decoder->arch_version == ARCH_V7)
>> +            {
>> +              switch(elem->isa)
>> +              {
> Indentation seems off.  Indent two more spaces.
>
> Indentation uses 8-wide tabs and spaces.
[Zied] done.
>
>> +                case ocsd_isa_arm:
>> +                  cpsr = 0;
>> +                  break;
> Please add an empty line between cases.
[Zied] done.
>
>> +                case ocsd_isa_thumb2:
>> +                  cpsr = 0x20;
>> +                  break;
>> +                case ocsd_isa_tee:
>> +                  cpsr = 0x1000020;
>> +                  break;
>> +                case ocsd_isa_jazelle:
>> +                  cpsr = 0x1000000;
>> +                  break;
>> +                default:
>> +                  cpsr = 0;
>> +              }
> It might make sense to turn this if into a small helper function.
[Zied] it can be done, I am keeping it as is since there is no reuse.
>
>> +              btrace_reg_set (&reg, get_thread_regcache(tp),
> Space before '('.
[Zied] done.
>
>> +                              ARM_PS_REGNUM, (gdb_byte *)&cpsr);
>> +              insn.registers.push_back (reg);
>> +            }
>> +          if (i == elem->num_instr_range -1)
>> +            {
>> +              switch (elem->last_i_type)
>> +              {
>> +                case OCSD_INSTR_BR:
>> +                case OCSD_INSTR_BR_INDIRECT:
>> +                  switch (elem->last_i_subtype )
>> +                  {
>> +                    case OCSD_S_INSTR_V8_RET:
>> +                    case OCSD_S_INSTR_V8_ERET:
>> +                    case OCSD_S_INSTR_V7_IMPLIED_RET:
>> +                      insn.iclass=BTRACE_INSN_RETURN;
>> +                      break;
>> +                    case OCSD_S_INSTR_BR_LINK:
>> +                      insn.iclass=BTRACE_INSN_CALL;
>> +                      break;
>> +                    case OCSD_S_INSTR_NONE:
>> +                      insn.iclass=BTRACE_INSN_JUMP;
>> +                  }
>> +                  break;
>> +                    case OCSD_INSTR_ISB:
>> +                    case OCSD_INSTR_DSB_DMB:
>> +                    case OCSD_INSTR_WFI_WFE:
>> +                    case OCSD_INSTR_OTHER:
>> +                      insn.iclass=BTRACE_INSN_OTHER;
>> +                      break;
>> +                    default:
>> +                      break;
>> +              }
> This switch could be a small helper function, too.
[Zied] it can be done, I am keeping it as is since there is no reuse.
>
>> +            }
>> +          ftrace_update_insns (bfun, insn);
>> +          pc = pc + size;
>> +        }
>> +    }
>> +}
>> +#undef ARM_PS_REGNUM
>> +
>> +#define ARM_EXCEPTION_UNDEFINED_INSTRUCTION 9
> Should this go into arch/arm.h?
[Zied] hardware exceptions are not listed in this header file.
>
>> +          if (elem->exception_number ==
>> ARM_EXCEPTION_UNDEFINED_INSTRUCTION)
>> +            {
>> +              DEBUG ("handle breakpoints implementation in gdb for armv7");
>> +              ftrace_remove_last_insn(btinfo);
> Could we detect this before we added the instruction?
[Zied] Unfortunately not. On armv7 the processor attempts first to 
execute (and logs) the instruction, then it raises the exception.
>
>> +static void
>> +cs_etm_update_btrace_with_trace_on (const void *context,
>> +                                   const ocsd_generic_trace_elem *elem)
>> +{
>> +  struct cs_etm_decoder *etm_decoder;
>> +  struct thread_info *tp;
>> +  struct btrace_thread_info *btinfo;
>> +
>> +  etm_decoder = (struct cs_etm_decoder *)context;
>> +  if (!etm_decoder->t_info )
>> +    return;
>> +  tp = etm_decoder->t_info;
>> +  btinfo = &tp->btrace;
>> +
>> +  if (elem->elem_type==OCSD_GEN_TRC_ELEM_TRACE_ON)
> Should we rather assert this?  Also for similar functions above.
[Zied] done.
>> +static ocsd_datapath_resp_t
>> +cs_etm_trace_element_callback (const void *context,
>> +				const ocsd_trc_index_t indx,
>> +				const uint8_t trace_chan_id,
>> +				const ocsd_generic_trace_elem *elem)
>> +{
>> +  char str_buffer[128];
>> +  if(ocsd_gen_elem_str(elem, str_buffer,128) == OCSD_OK)
> Space between if and ( and between _str and (.
[Zied] done.
>> +    DEBUG("ETM trace_element: index= %d, channel= 0x%x, %s",
>> +          indx, trace_chan_id, str_buffer);
> Please add empty lines to structure the code.
[Zied] done.
>
>> +  ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
> This is not changed in the switch.  We could just return
> OCSD_RESP_CONT ...
[Zied] done.
>
>> +  switch (elem->elem_type) {
>> +    case OCSD_GEN_TRC_ELEM_TRACE_ON:
>> +      cs_etm_update_btrace_with_trace_on(context, elem);
>> +      break;
>> +    case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
>> +      cs_etm_update_btrace_with_inst_range(context, elem);
>> +      break;
>> +    case OCSD_GEN_TRC_ELEM_EXCEPTION:
>> +      cs_etm_update_btrace_with_exception(context, elem);
>> +      break;
>> +    case OCSD_GEN_TRC_ELEM_UNKNOWN:
>> +    case OCSD_GEN_TRC_ELEM_EO_TRACE:
>> +    case OCSD_GEN_TRC_ELEM_NO_SYNC:
>> +    case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
>> +    case OCSD_GEN_TRC_ELEM_TIMESTAMP:
>> +    case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
>> +    case OCSD_GEN_TRC_ELEM_ADDR_NACC:
>> +    case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
>> +    case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
>> +    case OCSD_GEN_TRC_ELEM_EVENT:
>> +    case OCSD_GEN_TRC_ELEM_SWTRACE:
>> +    case OCSD_GEN_TRC_ELEM_CUSTOM:
>> +    default:
>> +      break;
>> +  }
>> +  return resp;
> ... here.
>
>
>> +static bool
>> +cs_etm_create_decoder (struct cs_etm_trace_params *t_params,
>> +			struct cs_etm_decoder *decoder)
>> +{
>> +  const char *decoder_name;
>> +  ocsd_etmv3_cfg config_etmv3;
>> +  ocsd_etmv4_cfg trace_config_etmv4;
>> +  void *trace_config;
>> +  uint8_t csid;
>> +
>> +  switch (t_params->protocol) {
> The { goes onto the next line.
[Zied] done
>
>
>> +    default:
>> +      decoder->arch_version = ARCH_UNKNOWN;
>> +      return false;
> Wouldn't it make more sense to error () or return an error code?
> There are different things that can go wrong, it seems.
[Zied] yes, we can add some error code and add some logs according to 
the error code. Nevertheless, I prefer rather adding logs in the place 
where it can go wrong, and raise a go/no-go (it is not possible to 
recover from some errors or handle errors differently) .
>
>> +  if (dcdtree_handle == C_API_INVALID_TREE_HANDLE)
>> +    return NULL;
>> +  decoder=(struct cs_etm_decoder*)xmalloc (sizeof(struct cs_etm_decoder));
> How about new?
>
> There are spaces missing in several places in this line.
[Zied] spaces fixed
>> +  decoder->dcd_tree = dcdtree_handle;
>> +
>> +  for (i = 0; i < num_cpu; i++) {
>> +      ret = cs_etm_create_decoder(&(t_params->at(i)),
>> +                                  decoder);
> Is this overwriting the same decoder object?
[Zied] yes and No :). It updates the dcd_tree with a new node. It 
overwrites arch_version. This is safe, since there is no Linux kernel 
running on an ARM multi core MPU with cores belonging to different 
architectures.
>> +      if (ret == false)
>> +        {
>> +          ocsd_destroy_dcd_tree(decoder->dcd_tree);
>> +          free(decoder);
> Do we need to undo anything for the other cpus from 0 to i-1?
[Zied] no, decoder->dcd_tree holds the nodes of all previous cpus
> There's a cs_etm_free_decoder function defined below.  Should
> this be called to free the decoder?
[Zied] yes it can be called instead of this peace of code. this is not 
really needed.
>
>> +  result = (int) reqBytes;
>> +  try
>> +  {
>> +      errcode = target_read_code ((CORE_ADDR) address, byteBuffer, reqBytes);
>> +      if (errcode != 0)
>> +        result = 0;
>> +  }
>> +  catch (const gdb_exception_error &error)
>> +  {
>> +      result = 0;
>> +  }
>> +
>> +  return result;
> That construct was needed for the old TRY and CATCH macros.  We should meanwhile
> be OK to return from try and catch statements.
>
>
>> +static ocsd_err_t
>> +cs_etm_add_mem_access_callback (struct cs_etm_decoder *decoder,
>> +                               CORE_ADDR start, CORE_ADDR end,
>> +                               Fn_MemAcc_CB p_cb_func)
>> +{
>> +  ocsd_err_t error;
>> +  error = ocsd_dt_add_callback_mem_acc(decoder->dcd_tree,
>> +                                       (ocsd_vaddr_t) start, (ocsd_vaddr_t) end,
>> +                                       OCSD_MEM_SPACE_ANY, p_cb_func, decoder);
>> +  if (error != OCSD_OK)
>> +    decoder->mem_access = p_cb_func;
> Should this be
>
>      if (error == OCSD_OK)
[Zied] done.
>
>> +  return (error);
> The () should not be necessary.
[Zied] done
>
>> +  while (processed < len) {
>> +      if (OCSD_DATA_RESP_IS_WAIT(prev_return)) {
>> +          cur = ocsd_dt_process_data(decoder->dcd_tree,
>> +                                     OCSD_OP_FLUSH,
>> +                                     0,
>> +                                     0,
>> +                                     NULL,
>> +                                     NULL);
> Those arguments should all fit onto one line.
[Zied] compacted, well, a second line was needed.
>
>> +/* print all function in a btrace  */
>> +
>> +static void btrace_print_all (struct btrace_thread_info *btinfo)
> Break after function type.  Name goes onto next line.
[Zied] done
>> +{
>> +  std::vector<btrace_function> functions;
>> +
>> +  functions = btinfo->functions;
> Do we even need that local variable?
[Zied] removed
>   
>>     DEBUG ("enable thread %s (%s)", print_thread_id (tp),
>>            target_pid_to_str (tp->ptid).c_str ());
>> @@ -1791,6 +2370,9 @@ btrace_stitch_trace (struct btrace_data *btrace, struct
>> thread_info *tp)
>>       case BTRACE_FORMAT_PT:
>>         /* Delta reads are not supported.  */
>>         return -1;
>> +    case BTRACE_FORMAT_ETM:
> Please add an empty line before a new case.
[Zied] this was  a bad conflict handling  in an rebase, it is corrected 
in the next commit. I do not know how to handle it
>
>> @@ -3487,7 +4074,7 @@ first."),
>>   	   maint_btrace_clear_packet_history_cmd,
>>   	    _("Clears the branch tracing packet history.\n\
>>   Discards the raw branch tracing data but not the execution history data."),
>> -	   &maint_btrace_cmdlist);
>> +&maint_btrace_cmdlist);
> Unrelated change.
[Zied] fixed
>
>> diff --git a/gdb/btrace.h b/gdb/btrace.h
>> index 8f6ce32103d..5d734896632 100644
>> --- a/gdb/btrace.h
>> +++ b/gdb/btrace.h
>> @@ -63,6 +69,17 @@ enum btrace_insn_flag
>>   };
>>   DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags);
>>
>> +/* extend MAX_BTRACE_REGISTER_SIZE if targets with registers
>> +bigger than 64 bits are considered  */
>> +#define MAX_BTRACE_REGISTER_SIZE 8
>> +/* a register entry in btrace_insn*/
>> +struct record_btrace_reg_entry
>> +{
>> +  unsigned short num;
>> +  unsigned short len;
>> +  gdb_byte buffer[MAX_BTRACE_REGISTER_SIZE * sizeof (gdb_byte)];
>> +};
> Please add comments to all fields.
[Zied] done
>
>> @@ -74,6 +91,9 @@ struct btrace_insn
>>     /* The size of this instruction in bytes.  */
>>     gdb_byte size;
>>
>> +  /* a vector of registers */
>> +  std::vector<record_btrace_reg_entry> registers;
> This is very expensive.  We will have lots of btrace_insn objects.

[Zied] an empty vector takes 12 bytes on a 32bits processor and 24 bytes 
on a 64bits processor

> Do we need those registers on all ARM instructions?

[Zied] on Armv7 yes, for all instructions

             on Arm v7 and Armv8 it will be needed only if data tracing 
is enabled

> If yes, we need to see how we can make others that don't need them
> not pay the price.
> If no, we need to look into a better way of providing those registers;
> maybe inside the btrace_insn stream as special types of instructions.
>
>
>> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
>> index 39ac9aafc28..107abd7e653 100644
>> --- a/gdb/record-btrace.c
>> +++ b/gdb/record-btrace.c
>> @@ -3020,7 +3029,6 @@ cmd_record_btrace_start (const char *args, int from_tty)
>>       }
>>   }
>>
>> -
> Hmmm, I do not see two empty lines at that location.
[Zied] yes, it is. it was an error during a merge in a rebase. it is now 
hidden in the history and I do not find a way to fix it. when you squash 
the patches, the code will look fine.
>>   /* The "show record btrace replay-memory-access" command.  */
>>
>>   static void
>> @@ -3250,7 +3258,6 @@ This format may not be available on all processors."),
>>   		       _("Show record options."), &show_record_btrace_cmdlist,
>>   		       "show record btrace ", 0, &show_record_cmdlist);
>>
>> -
> Same here.
[Zied] yes, it is. it was an error during a merge in a rebase. it is now 
hidden in the history and I do not find a way to fix it. when you squash 
the patches, the code will look fine.
>>     add_cmd ("auto", class_support, cmd_set_record_btrace_cpu_auto, _("\
>>   Automatically determine the cpu to be used for trace decode."),
>>   	   &set_record_btrace_cpu_cmdlist);
>> diff --git a/gdbsupport/btrace-common.cc b/gdbsupport/btrace-common.cc
>> index 461f769ed51..8e31c8a65dd 100644
>> --- a/gdbsupport/btrace-common.cc
>> +++ b/gdbsupport/btrace-common.cc
>> @@ -62,7 +62,6 @@ btrace_format_short_string (enum btrace_format format)
>>
>>       case BTRACE_FORMAT_ETM:
>>         return "etm";
>> -
> Could this be leftovers from a previous patch in the series?
[Zied] yes, it is. it was an error during a merge in a rebase. it is now 
hidden in the history and I do not find a way to fix it. when you squash 
the patches, the code will look fine.
>>     }
>>
>>     internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
>> @@ -87,6 +86,12 @@ btrace_data::fini ()
>>       case BTRACE_FORMAT_PT:
>>         xfree (variant.pt.data);
>>         return;
>> +
>> +    case BTRACE_FORMAT_ETM:
>> +      /* Variant.etm.data can be null if no new traces are collected.  */
>> +      if (variant.etm.data!=NULL)
> Spaces around !=.
[Zied] done
>   
>> diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
>> index 7f3cabfde77..5bc6f8dbd0f 100644
>> --- a/gdbsupport/btrace-common.h
>> +++ b/gdbsupport/btrace-common.h
>> @@ -189,6 +188,108 @@ struct btrace_data_pt
>>     size_t size;
>>   };
>>
>> +/* Parameters needed for decoding ETMv3 traces.
>> +   See open source coresight trace decoder library (opencsd)
>> +   for further details.  */
>> +struct cs_etmv3_trace_params {
>> +  uint32_t reg_ctrl;
>> +  uint32_t reg_trc_id;
>> +  uint32_t reg_ccer;
>> +  uint32_t reg_idr;
>> +};
> Please describe all the fields in comments.
[Zied] done.
>> +/* The following enums are indexed starting with 1 to align with the
>> +   open source coresight trace decoder library (opencsd).  */
>> +enum {
>> +  CS_ETM_PROTO_ETMV3 = 1,
>> +  CS_ETM_PROTO_ETMV4i,
>> +  CS_ETM_PROTO_ETMV4d,
>> +  CS_ETM_PROTO_PTM,
> And all the enumeration constants.
[Zied] done
>
>> +/* The following enum must be aligned with the
>> +   open source coresight trace decoder library (opencsd).  */
> Could we get them from a header file?
[Zied] this was intentionally done so, since btrace-common.h is included 
in many files. This is to allow compiling gdb if opencsd library is not 
present.
>
>> +/* The following enum must be aligned with the
>> +   open source coresight trace decoder library (opencsd).  */
> And those, as well?
[Zied] See above
>
> I noticed a number of style issues in this patch.  I have not pointed out
> all of them.  Would it be possible to run a GNU style checker on this
> patch series and fix anything that it finds?
[Zied] revisited all patches and fixed spotted styles issues.
> We need to discuss how to handle register values inside the btrace_insn
> stream.  I'd suggest we close that before reviewing the rest of this patch
> series.

[Zied] a vector of registers is added to the btrace_insn structure. This 
adds an overhead of 3 pointers when the vector is empty. it will be the 
overhead when not used (intel pt). I think this should be acceptable.

This implementation paves the way to handling ETM traces with data, so 
that gdb can have access in addition, to the registers altered during an 
instruction. This is very useful in execution record and replay since we 
can then reconstruct (some of) the variables.

>
> Regards,
> Markus.
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0,www.intel.de  <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
>
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 2/8] add btrace coresight related commands
  2021-03-10 22:37       ` Zied Guermazi
@ 2021-03-16 10:16         ` Metzger, Markus T
  2021-03-19 15:21           ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Metzger, Markus T @ 2021-03-16 10:16 UTC (permalink / raw)
  To: Zied Guermazi, gdb-patches

Hello Zied,

> The parameters needed for decoding the traces are more complex than the one for decoding PT traces. So an implementation for allowing the user a full flexibility in changing them will be very complex. Therefore, I did not provide a mean for changing them manually. I have added CV_ARM to the list of btrace_cpu_vendor to be able to show it. It can be removed if assessed as not needed.

If we're not supporting any CPU identification for ARM, then adding
the vendor enum seems a bit pointless.


> This patch extends the commands needed for using branch tracing
> with ARM CoreSight traces.
> Those commands are:
> set record btrace etm sink
> set record btrace etm size
> record btrace etm
> You'd want to describe them in gdb/doc/gdb.texinfo and announce the
> new commands in gdb/NEWS.
> 
> [Zied] set record btrace etm buffer-size : an error in the description.
> both commands are documented in patch 8/8

I didn't get that far.  It makes sense to document things as they get
Introduced so we're not missing anything or documenting anything
wrongly as patches get modified.


> +          printf_unfiltered ("btrace cpu is 'ARM'.\n");
> The idea behind 'set record btrace cpu' is to allow the user to overwrite
> the cpu identifier for enabling errata workarounds.  The main use-case is
> when libipt does not know the cpu so it cannot enable workarounds
> automatically.
> 
> 
> [Zied] yes, I initially went into the direction of letting the user change all parameters needed for decoding etm traces, but considering the complexity and the fact that this will be error prone, I reverted back to a minimum support by just printing that this is an ARM core. 

We might just ignore it if that's not needed for ARM.  We would want to say
in the help text that this is not used for ARM.

 
> +This format may not be available on all processors."),
> +	   &record_btrace_cmdlist);
> +  add_alias_cmd ("etm", "btrace etm", class_obscure, 1, &record_cmdlist);
> This alias wasn't mentioned in the list of new commands.
> 
> [Zied] See patch 8/8

I was referring to the commit message.

 
> diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
> index 26d26ec957f..7f3cabfde77 100644
> --- a/gdbsupport/btrace-common.h
> +++ b/gdbsupport/btrace-common.h
> @@ -77,7 +80,10 @@ enum btrace_cpu_vendor
>    CV_INTEL,
> 
>    /* AMD.  */
> -  CV_AMD
> +  CV_AMD,
> +
> +  /* ARM. */
> +  CV_ARM
> Does ARM also use model/family/stepping to identify their CPUs?
> 
> If not, please also extend struct btrace_cpu to make it a union
> tagged with the vendor field.
> 
> [Zied] I am just using this to stub the show commands for ARM. 

The default is 'auto'.  Wouldn't that fix, here?

Regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-03-11  0:12     ` Zied Guermazi
@ 2021-03-16 10:16       ` Metzger, Markus T
  2021-03-19 15:29         ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Metzger, Markus T @ 2021-03-16 10:16 UTC (permalink / raw)
  To: Zied Guermazi, gdb-patches

Hello Zied,

> I reworked the patch for C coding style. To my knowledge there is not coding styles issues left.

Thanks a lot.  That should make it easier to review.

 
> For the point concerning the use of a vector of registers in btrace_insn:
> a vector of registers is added to the btrace_insn structure. This adds an overhead of 3 pointers when the vector is empty. It will be the overhead when not used (intel pt). I think this should be acceptable. 

That's doubling the current size; tripling it if we declared ICLASS 8b (as it
should be).  I don't think that's acceptable.


> on ARMv7 this is need for all instructions, to allow step and next to set the breakpoints properly in the code.

Is this to distinguish ARM and Thumb modes?  How would the information
be used?

> on ARMv8, this is currently not used.
> This implementation paves the way to handling ETM traces with data, so that gdb can have access in addition, to the registers altered during an instruction. This is very useful in execution record and replay since we can then reconstruct (some of) the variables.

I see how this can be very useful.  We should definitely support that, but
we need to find a better way of storing the information.


> +                case ocsd_isa_thumb2:
> +                  cpsr = 0x20;
> +                  break;
> +                case ocsd_isa_tee:
> +                  cpsr = 0x1000020;
> +                  break;
> +                case ocsd_isa_jazelle:
> +                  cpsr = 0x1000000;
> +                  break;
> +                default:
> +                  cpsr = 0;
> +              }
> It might make sense to turn this if into a small helper function.
> [Zied] it can be done, I am keeping it as is since there is no reuse.

It reduces the size of the function.  Even if there is no reuse it improves
readability.

 
> +                              ARM_PS_REGNUM, (gdb_byte *)&cpsr);
> +              insn.registers.push_back (reg);
> +            }
> +          if (i == elem->num_instr_range -1)
> +            {
> +              switch (elem->last_i_type)
> +              {
> +                case OCSD_INSTR_BR:
> +                case OCSD_INSTR_BR_INDIRECT:
> +                  switch (elem->last_i_subtype )
> +                  {
> +                    case OCSD_S_INSTR_V8_RET:
> +                    case OCSD_S_INSTR_V8_ERET:
> +                    case OCSD_S_INSTR_V7_IMPLIED_RET:
> +                      insn.iclass=BTRACE_INSN_RETURN;
> +                      break;
> +                    case OCSD_S_INSTR_BR_LINK:
> +                      insn.iclass=BTRACE_INSN_CALL;
> +                      break;
> +                    case OCSD_S_INSTR_NONE:
> +                      insn.iclass=BTRACE_INSN_JUMP;
> +                  }
> +                  break;
> +                    case OCSD_INSTR_ISB:
> +                    case OCSD_INSTR_DSB_DMB:
> +                    case OCSD_INSTR_WFI_WFE:
> +                    case OCSD_INSTR_OTHER:
> +                      insn.iclass=BTRACE_INSN_OTHER;
> +                      break;
> +                    default:
> +                      break;
> +              }
> This switch could be a small helper function, too.
> [Zied] it can be done, I am keeping it as is since there is no reuse. 

Same here.  All this text could be just one line.

 
> +            }
> +          ftrace_update_insns (bfun, insn);
> +          pc = pc + size;
> +        }
> +    }
> +}
> +#undef ARM_PS_REGNUM
> +
> +#define ARM_EXCEPTION_UNDEFINED_INSTRUCTION 9
> Should this go into arch/arm.h?
> [Zied] hardware exceptions are not listed in this header file.

If we need to enumerate them somewhere, I think it should be in this file.

 
> +          if (elem->exception_number ==
> ARM_EXCEPTION_UNDEFINED_INSTRUCTION)
> +            {
> +              DEBUG ("handle breakpoints implementation in gdb for armv7");
> +              ftrace_remove_last_insn(btinfo);
> Could we detect this before we added the instruction?
> [Zied] Unfortunately not. On armv7 the processor attempts first to execute (and logs) the instruction, then it raises the exception.

I meant before we added the instruction to the trace.

 
> +    default:
> +      decoder->arch_version = ARCH_UNKNOWN;
> +      return false;
> Wouldn't it make more sense to error () or return an error code?
> There are different things that can go wrong, it seems.
> [Zied] yes, we can add some error code and add some logs according to the error code. Nevertheless, I prefer rather adding logs in the place where it can go wrong, and raise a go/no-go (it is not possible to recover from some errors or handle errors differently) .

I'm fine with issuing warnings right where we detect non-fatal errors and with
error()ing out on fatal errors.

There's not point in a bool return type, though; void would do just fine.

 
> +  decoder->dcd_tree = dcdtree_handle;
> +
> +  for (i = 0; i < num_cpu; i++) {
> +      ret = cs_etm_create_decoder(&(t_params->at(i)),
> +                                  decoder);
> Is this overwriting the same decoder object?
> [Zied] yes and No :). It updates the dcd_tree with a new node. It overwrites arch_version. This is safe, since there is no Linux kernel running on an ARM multi core MPU with cores belonging to different architectures.

But there's nothing preventing that, either, as long as the kernel sticks to some
common base ISA.

It seems cleaner to not partially overwrite things.  And this doesn't seem to be
performance critical.


> +      if (ret == false)
> +        {
> +          ocsd_destroy_dcd_tree(decoder->dcd_tree);
> +          free(decoder);
> Do we need to undo anything for the other cpus from 0 to i-1?
> [Zied] no, decoder->dcd_tree holds the nodes of all previous cpus
> 
> 
> There's a cs_etm_free_decoder function defined below.  Should
> this be called to free the decoder?
> [Zied] yes it can be called instead of this peace of code. this is not really needed.

Let's do that.

  
>    DEBUG ("enable thread %s (%s)", print_thread_id (tp),
>           target_pid_to_str (tp->ptid).c_str ());
> @@ -1791,6 +2370,9 @@ btrace_stitch_trace (struct btrace_data *btrace, struct
> thread_info *tp)
>      case BTRACE_FORMAT_PT:
>        /* Delta reads are not supported.  */
>        return -1;
> +    case BTRACE_FORMAT_ETM:
> Please add an empty line before a new case.
> [Zied] this was  a bad conflict handling  in an rebase, it is corrected in the next commit. I do not know how to handle it

You'd simply fixup that commit.

 
> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
> index 39ac9aafc28..107abd7e653 100644
> --- a/gdb/record-btrace.c
> +++ b/gdb/record-btrace.c
> @@ -3020,7 +3029,6 @@ cmd_record_btrace_start (const char *args, int from_tty)
>      }
>  }
> 
> -
> Hmmm, I do not see two empty lines at that location.
> [Zied] yes, it is. it was an error during a merge in a rebase. it is now hidden in the history and I do not find a way to fix it. when you squash the patches, the code will look fine.

We're not going to squash the patches.  You could rebase and edit the parent commit
to not introduce those empty lines.  The change will propagate to this patch and the
hunk will be removed.

 
> +/* The following enum must be aligned with the
> +   open source coresight trace decoder library (opencsd).  */
> Could we get them from a header file?
> [Zied] this was intentionally done so, since btrace-common.h is included in many files. This is to allow compiling gdb if opencsd library is not present.

We could conditionally include the header and all code that references anything
declared in it.  Would that be feasible?

Regards,
Markus.

Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 2/8] add btrace coresight related commands
  2021-03-16 10:16         ` Metzger, Markus T
@ 2021-03-19 15:21           ` Zied Guermazi
  0 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-03-19 15:21 UTC (permalink / raw)
  To: Metzger, Markus T, gdb-patches

hi

here is the status of the rework of the patch set. Changes will be 
included in next version of the patch set.

Kind Regards

Zied Guermazi

On 16.03.21 11:16, Metzger, Markus T wrote:
> Hello Zied,
>
>> The parameters needed for decoding the traces are more complex than the one for decoding PT traces. So an implementation for allowing the user a full flexibility in changing them will be very complex. Therefore, I did not provide a mean for changing them manually. I have added CV_ARM to the list of btrace_cpu_vendor to be able to show it. It can be removed if assessed as not needed.
> If we're not supporting any CPU identification for ARM, then adding
> the vendor enum seems a bit pointless.
[Zied] Removed
>
>
>> This patch extends the commands needed for using branch tracing
>> with ARM CoreSight traces.
>> Those commands are:
>> set record btrace etm sink
>> set record btrace etm size
>> record btrace etm
>> You'd want to describe them in gdb/doc/gdb.texinfo and announce the
>> new commands in gdb/NEWS.
>>
>> [Zied] set record btrace etm buffer-size : an error in the description.
>> both commands are documented in patch 8/8
> I didn't get that far.  It makes sense to document things as they get
> Introduced so we're not missing anything or documenting anything
> wrongly as patches get modified.
>
>
>> +          printf_unfiltered ("btrace cpu is 'ARM'.\n");
>> The idea behind 'set record btrace cpu' is to allow the user to overwrite
>> the cpu identifier for enabling errata workarounds.  The main use-case is
>> when libipt does not know the cpu so it cannot enable workarounds
>> automatically.
>>
>>
>> [Zied] yes, I initially went into the direction of letting the user change all parameters needed for decoding etm traces, but considering the complexity and the fact that this will be error prone, I reverted back to a minimum support by just printing that this is an ARM core.
> We might just ignore it if that's not needed for ARM.  We would want to say
> in the help text that this is not used for ARM.
[Zied] removed
>
>   
>> +This format may not be available on all processors."),
>> +	   &record_btrace_cmdlist);
>> +  add_alias_cmd ("etm", "btrace etm", class_obscure, 1, &record_cmdlist);
>> This alias wasn't mentioned in the list of new commands.
>>
>> [Zied] See patch 8/8
> I was referring to the commit message.
>
>   
>> diff --git a/gdbsupport/btrace-common.h b/gdbsupport/btrace-common.h
>> index 26d26ec957f..7f3cabfde77 100644
>> --- a/gdbsupport/btrace-common.h
>> +++ b/gdbsupport/btrace-common.h
>> @@ -77,7 +80,10 @@ enum btrace_cpu_vendor
>>     CV_INTEL,
>>
>>     /* AMD.  */
>> -  CV_AMD
>> +  CV_AMD,
>> +
>> +  /* ARM. */
>> +  CV_ARM
>> Does ARM also use model/family/stepping to identify their CPUs?
>>
>> If not, please also extend struct btrace_cpu to make it a union
>> tagged with the vendor field.
>>
>> [Zied] I am just using this to stub the show commands for ARM.
> The default is 'auto'.  Wouldn't that fix, here?
[Zied] removed, 'auto' with a good documentation should be enough
>
> Regards,
> Markus.
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-03-16 10:16       ` Metzger, Markus T
@ 2021-03-19 15:29         ` Zied Guermazi
  2021-03-29 14:01           ` Metzger, Markus T
  0 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-03-19 15:29 UTC (permalink / raw)
  To: Metzger, Markus T, gdb-patches

hi

here is the status of the rework of the patchset. Changes will be 
published in the next version.

On 16.03.21 11:16, Metzger, Markus T wrote:
> Hello Zied,
>
>> I reworked the patch for C coding style. To my knowledge there is not coding styles issues left.
> Thanks a lot.  That should make it easier to review.
[Zied] sorry for the inconvenience and thanks for sharing the script to 
check patches for formatting issues.
>
>   
>> For the point concerning the use of a vector of registers in btrace_insn:
>> a vector of registers is added to the btrace_insn structure. This adds an overhead of 3 pointers when the vector is empty. It will be the overhead when not used (intel pt). I think this should be acceptable.
> That's doubling the current size; tripling it if we declared ICLASS 8b (as it
> should be).  I don't think that's acceptable.
>
>
>> on ARMv7 this is need for all instructions, to allow step and next to set the breakpoints properly in the code.
> Is this to distinguish ARM and Thumb modes?  How would the information
> be used?

[Zied] let me give you a better insight on this topic to find a better 
solution:

this information is needed for two purposes:

- when stepping in the code (next, step, finish), on ARMv7, and due to 
the limitations of debug block, the debugger (GDB) need to calculate the 
addresses of  the "landing" instructions. this is implemented in 
arm_get_next_pcs (arm-get-next-pcs.c) this class request the content of 
the register cpsr

- when setting a breakpoint, either directly by the user, or indirectly 
by stepping commands (next, nexti, step, stepi, finish), the debugger 
(GDB) requests the content of the register cpsr.

when in replay mode, forwards direction, we relay on the beneath stratum 
to calculate the "landing" addresses for stepping commands, and we relay 
also on the beneath stratum for setting breakpoints.

it is here about providing the content of this register at any 
instruction and this while stepping in the code as well as when 
navigating in the code (record goto command).

I have tried to use the debug info from elf files. I was limited by the 
fact that not all elf files contains a dwarf section (especially the 
libraries), and that the code can change the mode (arm <-> thumb for 
example) within the same section though the usage of veneer code.

a second constraint to keep in mind, is that once we finish decoding the 
traces, we lose the cpsr content information. so we have to capture it 
during decoding.

One possibility for "compressing" the cpsr content is to only store it 
at a change of its content or after a gap. And then take care of 
providing the right content when stepping and navigating in the traces.

One solution is to extend the btrace_function with a vector of 
btrace_registers i.e. a vector of (instruction number and vector of 
registers) and to extend btrace_thread_info with iterators for 
btrace_registers_history .  When the register is requested, we will have 
to get the instruction, iterate backwards until an entry is found in the 
btrace_registers of current or previous functions or a gap is found.

this solution trades run-time for memory, requires examination of 
previous instruction each time we decode a new instruction, and has a 
considerable level of complexity....

considering the complexity of this solution, my recommendation is to 
keep current implementation and schedule the above proposed approach as 
an optimization, or to drop support for armv7 until support for data 
tracing is added.


>
>> on ARMv8, this is currently not used.
>> This implementation paves the way to handling ETM traces with data, so that gdb can have access in addition, to the registers altered during an instruction. This is very useful in execution record and replay since we can then reconstruct (some of) the variables.
> I see how this can be very useful.  We should definitely support that, but
> we need to find a better way of storing the information.
>
>
>> +                case ocsd_isa_thumb2:
>> +                  cpsr = 0x20;
>> +                  break;
>> +                case ocsd_isa_tee:
>> +                  cpsr = 0x1000020;
>> +                  break;
>> +                case ocsd_isa_jazelle:
>> +                  cpsr = 0x1000000;
>> +                  break;
>> +                default:
>> +                  cpsr = 0;
>> +              }
>> It might make sense to turn this if into a small helper function.
>> [Zied] it can be done, I am keeping it as is since there is no reuse.
> It reduces the size of the function.  Even if there is no reuse it improves
> readability.
[Zied] done
>
>   
>> +                              ARM_PS_REGNUM, (gdb_byte *)&cpsr);
>> +              insn.registers.push_back (reg);
>> +            }
>> +          if (i == elem->num_instr_range -1)
>> +            {
>> +              switch (elem->last_i_type)
>> +              {
>> +                case OCSD_INSTR_BR:
>> +                case OCSD_INSTR_BR_INDIRECT:
>> +                  switch (elem->last_i_subtype )
>> +                  {
>> +                    case OCSD_S_INSTR_V8_RET:
>> +                    case OCSD_S_INSTR_V8_ERET:
>> +                    case OCSD_S_INSTR_V7_IMPLIED_RET:
>> +                      insn.iclass=BTRACE_INSN_RETURN;
>> +                      break;
>> +                    case OCSD_S_INSTR_BR_LINK:
>> +                      insn.iclass=BTRACE_INSN_CALL;
>> +                      break;
>> +                    case OCSD_S_INSTR_NONE:
>> +                      insn.iclass=BTRACE_INSN_JUMP;
>> +                  }
>> +                  break;
>> +                    case OCSD_INSTR_ISB:
>> +                    case OCSD_INSTR_DSB_DMB:
>> +                    case OCSD_INSTR_WFI_WFE:
>> +                    case OCSD_INSTR_OTHER:
>> +                      insn.iclass=BTRACE_INSN_OTHER;
>> +                      break;
>> +                    default:
>> +                      break;
>> +              }
>> This switch could be a small helper function, too.
>> [Zied] it can be done, I am keeping it as is since there is no reuse.
> Same here.  All this text could be just one line.
>
>   
[Zied] done
>> +            }
>> +          ftrace_update_insns (bfun, insn);
>> +          pc = pc + size;
>> +        }
>> +    }
>> +}
>> +#undef ARM_PS_REGNUM
>> +
>> +#define ARM_EXCEPTION_UNDEFINED_INSTRUCTION 9
>> Should this go into arch/arm.h?
>> [Zied] hardware exceptions are not listed in this header file.
> If we need to enumerate them somewhere, I think it should be in this file.
[Zied] this define is for the exception numbers as defined in the etm 
traces, and is different for the "normal" exception number. Let me check 
if  arch/arm.h is the right file for it and fix it.
>
>   
>> +          if (elem->exception_number ==
>> ARM_EXCEPTION_UNDEFINED_INSTRUCTION)
>> +            {
>> +              DEBUG ("handle breakpoints implementation in gdb for armv7");
>> +              ftrace_remove_last_insn(btinfo);
>> Could we detect this before we added the instruction?
>> [Zied] Unfortunately not. On armv7 the processor attempts first to execute (and logs) the instruction, then it raises the exception.
> I meant before we added the instruction to the trace.

[Zied] no, it is not possible without distording the code. removing 
previous inserted but not executed command is more appropriate. below is 
an illustration of the outcome of the decoder.

[btrace] ETM trace_element: index= 12, channel= 0x10, 
OCSD_GEN_TRC_ELEM_INSTR_RANGE(exec range=0x40050a:[0x40050c] num_i(1) 
last_sz(2) (ISA=T32) E --- ) <-- here the processor attempt to execute 
the instruction and traces it, the original instruction is patched with 
an undefined instruction opcode

btrace] ETM trace_element: index= 13, channel= 0x10, 
OCSD_GEN_TRC_ELEM_EXCEPTION(excep num (0x09) ) <-- here the exception is 
raised

btrace] ETM trace_element: index= 54, channel= 0x10, 
OCSD_GEN_TRC_ELEM_TRACE_ON( [begin or filter]) <-- restarting traces 
after coming back from kernel space
[btrace] ETM trace_element: index= 54, channel= 0x10, 
OCSD_GEN_TRC_ELEM_PE_CONTEXT((ISA=T32) N; 32-bit; ) <-- setting the 
context again

[btrace] ETM trace_element: index= 60, channel= 0x10, 
OCSD_GEN_TRC_ELEM_INSTR_RANGE(exec range=0x40050a:[0x40050c] num_i(1) 
last_sz(2) (ISA=T32) E --- ) <-- here the processor attempt to execute 
the instruction and succeed since the original opcode is written back to 
the location.

when the first instruction is decoded we do not know if it will fail and 
raise an exception or not so we add it. when the exception gets raised 
we remove it.

>
>   
>> +    default:
>> +      decoder->arch_version = ARCH_UNKNOWN;
>> +      return false;
>> Wouldn't it make more sense to error () or return an error code?
>> There are different things that can go wrong, it seems.
>> [Zied] yes, we can add some error code and add some logs according to the error code. Nevertheless, I prefer rather adding logs in the place where it can go wrong, and raise a go/no-go (it is not possible to recover from some errors or handle errors differently) .
> I'm fine with issuing warnings right where we detect non-fatal errors and with
> error()ing out on fatal errors.
>
> There's not point in a bool return type, though; void would do just fine.
>
>   
>> +  decoder->dcd_tree = dcdtree_handle;
>> +
>> +  for (i = 0; i < num_cpu; i++) {
>> +      ret = cs_etm_create_decoder(&(t_params->at(i)),
>> +                                  decoder);
>> Is this overwriting the same decoder object?
>> [Zied] yes and No :). It updates the dcd_tree with a new node. It overwrites arch_version. This is safe, since there is no Linux kernel running on an ARM multi core MPU with cores belonging to different architectures.
> But there's nothing preventing that, either, as long as the kernel sticks to some
> common base ISA.
>
> It seems cleaner to not partially overwrite things.  And this doesn't seem to be
> performance critical.
>
>
>> +      if (ret == false)
>> +        {
>> +          ocsd_destroy_dcd_tree(decoder->dcd_tree);
>> +          free(decoder);
>> Do we need to undo anything for the other cpus from 0 to i-1?
>> [Zied] no, decoder->dcd_tree holds the nodes of all previous cpus
>>
>>
>> There's a cs_etm_free_decoder function defined below.  Should
>> this be called to free the decoder?
>> [Zied] yes it can be called instead of this peace of code. this is not really needed.
> Let's do that.
>
>    
>>     DEBUG ("enable thread %s (%s)", print_thread_id (tp),
>>            target_pid_to_str (tp->ptid).c_str ());
>> @@ -1791,6 +2370,9 @@ btrace_stitch_trace (struct btrace_data *btrace, struct
>> thread_info *tp)
>>       case BTRACE_FORMAT_PT:
>>         /* Delta reads are not supported.  */
>>         return -1;
>> +    case BTRACE_FORMAT_ETM:
>> Please add an empty line before a new case.
>> [Zied] this was  a bad conflict handling  in an rebase, it is corrected in the next commit. I do not know how to handle it
> You'd simply fixup that commit.
[Zied] done
>
>   
>> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
>> index 39ac9aafc28..107abd7e653 100644
>> --- a/gdb/record-btrace.c
>> +++ b/gdb/record-btrace.c
>> @@ -3020,7 +3029,6 @@ cmd_record_btrace_start (const char *args, int from_tty)
>>       }
>>   }
>>
>> -
>> Hmmm, I do not see two empty lines at that location.
>> [Zied] yes, it is. it was an error during a merge in a rebase. it is now hidden in the history and I do not find a way to fix it. when you squash the patches, the code will look fine.
> We're not going to squash the patches.  You could rebase and edit the parent commit
> to not introduce those empty lines.  The change will propagate to this patch and the
> hunk will be removed.
>
>   
>> +/* The following enum must be aligned with the
>> +   open source coresight trace decoder library (opencsd).  */
>> Could we get them from a header file?
>> [Zied] this was intentionally done so, since btrace-common.h is included in many files. This is to allow compiling gdb if opencsd library is not present.
> We could conditionally include the header and all code that references anything
> declared in it.  Would that be feasible?
[Zied] done.
>
> Regards,
> Markus.
>
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-03-19 15:29         ` Zied Guermazi
@ 2021-03-29 14:01           ` Metzger, Markus T
  2021-03-30 15:11             ` Zied Guermazi
  0 siblings, 1 reply; 27+ messages in thread
From: Metzger, Markus T @ 2021-03-29 14:01 UTC (permalink / raw)
  To: Zied Guermazi; +Cc: Simon Marchi, gdb-patches

Hello Zied,

>> For the point concerning the use of a vector of registers in btrace_insn:
>> a vector of registers is added to the btrace_insn structure. This adds an overhead of 3 pointers when the vector is empty. It will be the overhead when not used (intel pt). I think this should be acceptable.
>>
>> That's doubling the current size; tripling it if we declared ICLASS 8b (as it
>> should be).  I don't think that's acceptable.
>
> on ARMv7 this is need for all instructions, to allow step and next to set the breakpoints properly in the code.
>
>> Is this to distinguish ARM and Thumb modes?  How would the information
>> be used?
> [Zied] let me give you a better insight on this topic to find a better solution:
> this information is needed for two purposes:

I believe this was discussed in https://sourceware.org/pipermail/gdb/2021-March/049293.html.

Is there anything left to discuss?

Regards,
Markus.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant
  2021-03-29 14:01           ` Metzger, Markus T
@ 2021-03-30 15:11             ` Zied Guermazi
  0 siblings, 0 replies; 27+ messages in thread
From: Zied Guermazi @ 2021-03-30 15:11 UTC (permalink / raw)
  To: Metzger, Markus T; +Cc: Simon Marchi, gdb-patches

Hello Markus

the code was amended according to the outcome of the discussion. it 
works fine. There is no blocking points anymore.

I am running the testsuite on i686, armv7 and armv8, to check any 
possible regression. it takes long time on ARMv7. I guess it will finish 
by the evening. I will send the patch suite after checking the result 
(if everything goes fine)

Kind Regards

Zied Guermazi

On 29.03.21 16:01, Metzger, Markus T wrote:
>
> Hello Zied,
>
> >> For the point concerning the use of a vector of registers in btrace_insn:
>
> >> a vector of registers is added to the btrace_insn structure. This adds 
> an overhead of 3 pointers when the vector is empty. It will be the 
> overhead when not used (intel pt). I think this should be acceptable.
>
> >> 
>
> >> That's doubling the current size; tripling it if we declared ICLASS 
> 8b (as it
>
> >> should be).  I don't think that's acceptable.
>
> > 
>
> > on ARMv7 this is need for all instructions, to allow step and next to 
> set the breakpoints properly in the code.
>
> > 
>
> >> Is this to distinguish ARM and Thumb modes?  How would the information
>
> >> be used?
>
> > [Zied] let me give you a better insight on this topic to find a better solution:
>
> > this information is needed for two purposes:
>
> I believe this was discussed in 
> https://sourceware.org/pipermail/gdb/2021-March/049293.html.
>
> Is there anything left to discuss?
>
> Regards,
>
> Markus.
>
> Intel Deutschland GmbH
> Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
> Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
> Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva
> Chairperson of the Supervisory Board: Nicole Lau
> Registered Office: Munich
> Commercial Register: Amtsgericht Muenchen HRB 186928
>
-- 

*Zied Guermazi*
founder

Trande UG
Leuschnerstraße 2
69469 Weinheim/Germany

Mobile: +491722645127
mailto:zied.guermazi@trande.de

*Trande UG*
Leuschnerstraße 2, D-69469 Weinheim; Telefon: +491722645127
Sitz der Gesellschaft: Weinheim- Registergericht: AG Mannheim HRB 736209 
- Geschäftsführung: Zied Guermazi

*Confidentiality Note*
This message is intended only for the use of the named recipient(s) and 
may contain confidential and/or privileged information. If you are not 
the intended recipient, please contact the sender and delete the 
message. Any unauthorized use of the information contained in this 
message is prohibited.



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH 8/8] document btrace support for arm targets using coresight etm traces
  2021-03-11  2:50 ` [PATCH 8/8] document btrace support for arm targets using coresight etm traces Zied Guermazi
@ 2021-03-11  6:23   ` Eli Zaretskii
  0 siblings, 0 replies; 27+ messages in thread
From: Eli Zaretskii @ 2021-03-11  6:23 UTC (permalink / raw)
  To: Zied Guermazi; +Cc: gdb-patches

> From: Zied Guermazi <zied.guermazi@trande.de>
> Date: Thu, 11 Mar 2021 03:50:39 +0100
> Cc: Zied Guermazi <zied.guermazi@trande.de>
> 
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 7f5a745d0c0..0c31af6ed0b 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS

This part is OK.

> +Use the value @kbd{default} to reset it to default sink.

Please use @code{default} or @samp{default}, not @kbd.

> +(@pxref{Qbtrace:bts}).

Please don't use the colon character in the names of anchors and in
the corresponding cross-references: those could cause trouble to some
Info readers, and are best avoided.  Please choose some other
character, like '_'.

The documentation part of this patch series is approved as soon as
those 2 nits are fixed.

Thanks.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH 8/8] document btrace support for arm targets using coresight etm traces
  2021-03-11  2:50 [PATCH v2 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
@ 2021-03-11  2:50 ` Zied Guermazi
  2021-03-11  6:23   ` Eli Zaretskii
  0 siblings, 1 reply; 27+ messages in thread
From: Zied Guermazi @ 2021-03-11  2:50 UTC (permalink / raw)
  To: gdb-patches; +Cc: Zied Guermazi

This patch documents the extensions done in GDB to enable using
ARM Coresight traces for btrace.

gdb/ChangeLog

	* gdb/NEWS: list new commands and remote packets for extending btrace
	to support using ARM CoreSight Traces.

gdb/doc/ChangeLog

	* gdb.texinfo (Process Record and Replay): Document extending 
	GDB btrace commands to support using ARM CoreSight traces.
	(General Query Packets) Document extending GDB remote protocol
	packets to support using ARM CoreSight traces for btrace.



---
 gdb/NEWS            |  30 ++++++++++++
 gdb/doc/ChangeLog   |   5 ++
 gdb/doc/gdb.texinfo | 115 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 7f5a745d0c0..0c31af6ed0b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -2,6 +2,7 @@
 	     (Organized release by release)
 
 *** Changes since GDB 10
+* Record btrace now  supports using ARM CoreSight ETM traces.
 
 * Building GDB now requires GMP (The GNU Multiple Precision Arithmetic
   Library).
@@ -35,6 +36,21 @@
 
 * New commands
 
+record btrace etm
+record etm
+  Start branch trace recording using ARM CoreSight trace format (ETM).
+
+set|show record btrace etm buffer-size
+  Set and show the size of the ring buffer used for branch tracing in
+  ETM format.
+  The obtained size may differ from the requested size.  Use "info
+  record" to see the obtained buffer size.
+
+set|show record btrace etm sink
+  Set and show the trace sink used for branch tracing in
+  ETM format.
+  Use "default" to reset it to default sink.
+
 set debug event-loop
 show debug event-loop
   Control the display of debug output about GDB's event loop.
@@ -98,6 +114,20 @@ maintenance info sections
 
 ARM Symbian			arm*-*-symbianelf*
 
+* New remote packets
+
+Qbtrace:etm
+  Enable ARM CoreSight ETM Trace-based branch tracing for the current
+  process.  The remote stub reports support for this packet to GDB's
+  qSupported query.
+
+Qbtrace-conf:etm:size
+  Set the requested ring buffer size for branch tracing in
+  ARM CoreSight ETM Trace format.
+
+Qbtrace-conf:etm:sink
+  Set the trace sink for branch tracing in ARM CoreSight ETM Trace format.
+
 *** Changes in GDB 10
 
 * There are new feature names for ARC targets: "org.gnu.gdb.arc.core"
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index add31a0cc39..b4b9faa20d5 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+2021-02-08  Zied Guermazi  <zied.guermazi@trande.de>
+
+	* gdb.texinfo: Document extending btrace to support
+	ARM CoreSight traces commands and packets
+
 2021-02-24  Andrew Burgess  <andrew.burgess@embecosm.com>
 
 	* gdb.texinfo (Files): Document new 'maint info target-sections'
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 80ccf74a049..fd528442503 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7371,15 +7371,19 @@ For architecture environments that support process record and replay,
 @kindex record btrace
 @kindex record btrace bts
 @kindex record btrace pt
+@kindex record btrace etm
 @kindex record bts
 @kindex record pt
+@kindex record etm
 @kindex rec
 @kindex rec full
 @kindex rec btrace
 @kindex rec btrace bts
 @kindex rec btrace pt
+@kindex rec btrace etm
 @kindex rec bts
 @kindex rec pt
+@kindex rec etm
 @item record @var{method}
 This command starts the process record and replay target.  The
 recording method can be specified as parameter.  Without a parameter
@@ -7393,7 +7397,7 @@ replay implementation.  This method allows replaying and reverse
 execution.
 
 @item btrace @var{format}
-Hardware-supported instruction recording, supported on Intel
+Hardware-supported instruction recording, supported on Intel and ARM
 processors.  This method does not record data.  Further, the data is
 collected in a ring buffer so old data will be overwritten when the
 buffer is full.  It allows limited reverse execution.  Variables and
@@ -7427,6 +7431,13 @@ Decoding the recorded execution trace, on the other hand, is more
 expensive than decoding @acronym{BTS} trace.  This is mostly due to the
 increased number of instructions to process.  You should increase the
 buffer-size with care.
+
+@item etm
+@cindex ARM CoreSight Trace
+Use the @dfn{ARM CoreSight Trace} recording format.  In this
+format, @acronym{ETM, Extended Trace Macrocell} stores the processor
+execution trace in a compressed form that is afterwards
+decoded by @value{GDBN}.
 @end table
 
 Not all recording formats may be available on all processors.
@@ -7574,6 +7585,12 @@ and to read-write memory.  Beware that the accessed memory corresponds
 to the live target and not necessarily to the current replay
 position.
 
+@item set record btrace etm sink @var{sink}
+Set ARM CoreSight ETM sink to collect traces.
+On @sc{gnu}/Linux systems, possible values for @var{sink} are the name of the
+files in the directory @file{/sys/bus/event_source/devices/cs_etm/sinks/}.
+Use the value @kbd{default} to reset it to default sink.
+
 @item set record btrace cpu @var{identifier}
 Set the processor to be used for enabling workarounds for processor
 errata when decoding the trace.
@@ -7637,6 +7654,9 @@ Recorded 84872 instructions in 3189 functions (0 gaps) for thread 1 (...).
 @item show record btrace replay-memory-access
 Show the current setting of @code{replay-memory-access}.
 
+@item show record btrace etm sink
+Show ARM CoreSight ETM sink.
+
 @item show record btrace cpu
 Show the processor to be used for enabling trace decode errata
 workarounds.
@@ -7688,6 +7708,29 @@ also need longer to process the branch trace data before it can be used.
 Show the current setting of the requested ring buffer size for branch
 tracing in Intel Processor Trace format.
 
+@kindex set record btrace etm
+@item set record btrace etm buffer-size @var{size}
+@itemx set record btrace etm buffer-size unlimited
+Set the requested ring buffer size for branch tracing in ARM
+CoreSight ETM Trace format.  Default is 16KB.
+
+If @var{size} is a positive number, then @value{GDBN} will try to
+allocate a buffer of at least @var{size} bytes for each new thread
+that uses the btrace recording method and the Intel Processor Trace
+format.  The actually obtained buffer size may differ from the
+requested @var{size}.  Use the @code{info record} command to see the
+actual buffer size for each thread.
+
+If @var{limit} is @code{unlimited} or zero, @value{GDBN} will try to
+allocate a buffer of 4MB.
+
+Bigger buffers mean longer traces.  On the other hand, @value{GDBN} will
+also need longer to process the branch trace data before it can be used.
+
+@item show record btrace etm buffer-size @var{size}
+Show the current setting of the requested ring buffer size for branch
+tracing in ARM CoreSight ETM Trace format.
+
 @kindex info record
 @item info record
 Show various statistics about the recording depending on the recording
@@ -7739,6 +7782,12 @@ For the @code{pt} recording format, it also shows:
 @item
 Size of the perf ring buffer.
 @end itemize
+
+For the @code{etm} recording format, it also shows:
+@itemize @bullet
+@item
+Size of the perf ring buffer.
+@end itemize
 @end table
 
 @kindex record delete
@@ -41659,6 +41708,21 @@ These are the currently defined stub features and their properties:
 @tab @samp{-}
 @tab No
 
+@item @samp{Qbtrace:etm}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
+@item @samp{Qbtrace-conf:etm:size}
+@tab Yes
+@tab @samp{-}
+@tab Yes
+
+
+@item @samp{Qbtrace-conf:etm:sink}
+@tab Yes
+@tab @samp{-}
+@tab Yes
 @end multitable
 
 These are the currently defined stub features, in more detail:
@@ -41835,9 +41899,11 @@ The remote stub understands the @samp{Qbtrace:off} packet.
 
 @item Qbtrace:bts
 The remote stub understands the @samp{Qbtrace:bts} packet.
+(@pxref{Qbtrace:bts}).
 
 @item Qbtrace:pt
 The remote stub understands the @samp{Qbtrace:pt} packet.
+(@pxref{Qbtrace:pt}).
 
 @item Qbtrace-conf:bts:size
 The remote stub understands the @samp{Qbtrace-conf:bts:size} packet.
@@ -41873,6 +41939,16 @@ The remote stub understands the @samp{QThreadEvents} packet.
 @item no-resumed
 The remote stub reports the @samp{N} stop reply.
 
+@item Qbtrace:etm
+The remote stub understands the @samp{Qbtrace:etm} packet.
+(@pxref{Qbtrace:etm}).
+
+@item Qbtrace-conf:etm:size
+The remote stub understands the @samp{Qbtrace-conf:etm:size} packet.
+
+@item Qbtrace-conf:etm:sink
+The remote stub understands the @samp{Qbtrace-conf:etm:sink} packet.
+
 @end table
 
 @item qSymbol::
@@ -42279,6 +42355,7 @@ A badly formed request or an error was encountered.
 @end table
 
 @item Qbtrace:bts
+@anchor{Qbtrace:bts}
 Enable branch tracing for the current thread using Branch Trace Store.
 
 Reply:
@@ -42290,6 +42367,7 @@ A badly formed request or an error was encountered.
 @end table
 
 @item Qbtrace:pt
+@anchor{Qbtrace:pt}
 Enable branch tracing for the current thread using Intel Processor Trace.
 
 Reply:
@@ -42335,6 +42413,41 @@ The ring buffer size has been set.
 A badly formed request or an error was encountered.
 @end table
 
+@item Qbtrace:etm
+@anchor{Qbtrace:etm}
+Enable branch tracing for the current thread using ARM CoreSight ETM Trace.
+
+Reply:
+@table @samp
+@item OK
+Branch tracing has been enabled.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace-conf:etm:size=@var{value}
+Set the requested ring buffer size for new threads that use the
+btrace recording method in etm format.
+
+Reply:
+@table @samp
+@item OK
+The ring buffer size has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
+
+@item Qbtrace-conf:etm:sink=@var{value}
+Set the requested trace sink for new threads that use the
+btrace recording method in etm format.
+
+Reply:
+@table @samp
+@item OK
+The ring buffer size has been set.
+@item E.errtext
+A badly formed request or an error was encountered.
+@end table
 @end table
 
 @node Architecture-Specific Protocol Details
-- 
2.25.1


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2021-03-30 15:11 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-26  2:45 [PATCH 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
2021-02-26  2:45 ` [PATCH 1/8] configure gdb build system for supporting btrace on arm processors Zied Guermazi
2021-03-04 16:35   ` Metzger, Markus T
2021-03-10 22:09     ` Zied Guermazi
2021-02-26  2:45 ` [PATCH 2/8] add btrace coresight related commands Zied Guermazi
2021-03-04 16:35   ` Metzger, Markus T
     [not found]     ` <8a71a9a3-ad14-b716-6d86-ece063061b02@trande.de>
2021-03-10 22:37       ` Zied Guermazi
2021-03-16 10:16         ` Metzger, Markus T
2021-03-19 15:21           ` Zied Guermazi
2021-02-26  2:45 ` [PATCH 3/8] start/stop btrace with coresight etm and parse etm buffer. nat independant Zied Guermazi
2021-03-04 16:35   ` Metzger, Markus T
2021-03-11  0:12     ` Zied Guermazi
2021-03-16 10:16       ` Metzger, Markus T
2021-03-19 15:29         ` Zied Guermazi
2021-03-29 14:01           ` Metzger, Markus T
2021-03-30 15:11             ` Zied Guermazi
2021-02-26  2:45 ` [PATCH 4/8] start/stop btrace with coresight etm and collect etm buffer on linux os Zied Guermazi
2021-02-26  2:45 ` [PATCH 5/8] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY Zied Guermazi
2021-02-26  7:12   ` Aktemur, Tankut Baris
2021-03-10 20:39     ` Zied Guermazi
2021-02-26  2:46 ` [PATCH 6/8] add support for coresight btrace via remote protocol Zied Guermazi
2021-02-26  2:46 ` [PATCH 7/8] adapt btrace testcases for arm target Zied Guermazi
2021-02-26  2:46 ` [PATCH 8/8] document btrace support for arm targets using coresight etm traces Zied Guermazi
2021-02-26  7:36   ` Eli Zaretskii
2021-03-10 20:36     ` Zied Guermazi
2021-03-11  2:50 [PATCH v2 0/8] extend branch tracing to use ARM CoreSight traces Zied Guermazi
2021-03-11  2:50 ` [PATCH 8/8] document btrace support for arm targets using coresight etm traces Zied Guermazi
2021-03-11  6:23   ` Eli Zaretskii

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).