Blob Blame History Raw
http://sourceware.org/ml/gdb-patches/2016-03/msg00013.html
Subject: [PATCH 1/2] Fix PR gdb/19676: Disable displaced stepping if /proc not mounted

On GNU/Linux archs that support displaced stepping, if /proc is not
mounted, GDB gets stuck not able to step past breakpoints:

 (gdb) c
 Continuing.
 dl_main (phdr=<optimized out>, phnum=<optimized out>, user_entry=<optimized out>, auxv=<optimized out>) at rtld.c:2163
 2163      LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
 Cannot find AT_ENTRY auxiliary vector entry.
 (gdb) c
 Continuing.
 dl_main (phdr=<optimized out>, phnum=<optimized out>, user_entry=<optimized out>, auxv=<optimized out>) at rtld.c:2163
 2163      LIBC_PROBE (init_complete, 2, LM_ID_BASE, r);
 Cannot find AT_ENTRY auxiliary vector entry.
 (gdb)

That's because GDB can't figure out where the scratch pad is.

This is a regression introduced by the earlier changes to make the
Linux native target always work in non-stop mode.

This commit makes GDB detect the case and fallback to stepping over
breakpoints in-line.

gdb/ChangeLog:
2016-03-01  Pedro Alves  <pedro@cascais.lan>

	PR gdb/19676
	* infrun.c (displaced_step_prepare): Also disable displaced
	stepping on NOT_SUPPORTED_ERROR.
	* linux-tdep.c (linux_displaced_step_location): If reading auxv
	fails, throw NOT_SUPPORTED_ERROR instead of generic error.
---
 gdb/infrun.c     | 3 ++-
 gdb/linux-tdep.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/gdb/infrun.c b/gdb/infrun.c
index 3e8c9e0..696105d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1894,7 +1894,8 @@ displaced_step_prepare (ptid_t ptid)
     {
       struct displaced_step_inferior_state *displaced_state;
 
-      if (ex.error != MEMORY_ERROR)
+      if (ex.error != MEMORY_ERROR
+	  && ex.error != NOT_SUPPORTED_ERROR)
 	throw_exception (ex);
 
       if (debug_infrun)
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 555c302..f197aa7 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -2426,7 +2426,8 @@ linux_displaced_step_location (struct gdbarch *gdbarch)
      location.  The auxiliary vector gets us the PowerPC-side entry
      point address instead.  */
   if (target_auxv_search (&current_target, AT_ENTRY, &addr) <= 0)
-    error (_("Cannot find AT_ENTRY auxiliary vector entry."));
+    throw_error (NOT_SUPPORTED_ERROR,
+		 _("Cannot find AT_ENTRY auxiliary vector entry."));
 
   /* Make certain that the address points at real code, and not a
      function descriptor.  */
-- 
2.5.0



http://sourceware.org/ml/gdb-patches/2016-03/msg00014.html
Subject: [PATCH 2/2] Fix PR gdb/19676: Internal error in linux-thread.db.c if /proc not mounted

If /proc is not mounted, GDB fails an assertion in find_new_threads_once:

 Continuing.
 /home/pedro/gdb/mygit/src/gdb/linux-thread-db.c:1249: internal-error: find_new_threads_once: Assertion `!target_has_execution' failed.
 A problem internal to GDB has been detected,
 further debugging may prove unreliable.
 Quit this debugging session? (y or n)

That was supposed to catch misuses of td_ta_thr_iter, which is unsafe
for live debugging.  However, if /proc is not mounted, we still
fallback to using it.

I didn't bother with a warning, because GDB already prints several
others related to failing to open /proc files.

gdb/ChangeLog:
2016-03-01  Pedro Alves  <pedro@cascais.lan>

	PR gdb/19676
	* linux-thread-db.c (try_thread_db_load_1): Leave
	info->td_ta_thr_iter_p NULL iff debugging a live process and we
	have /proc access.
	(find_new_threads_once): Assert that we have a non-NULL
	info->td_ta_thr_iter_p instead of checking whether the target has
	execution.
---
 gdb/linux-thread-db.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 1eb457d..ce60beb 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -564,7 +564,6 @@ try_thread_db_load_1 (struct thread_db_info *info)
 
   /* These are essential.  */
   CHK (TDB_VERBOSE_DLSYM (info, td_ta_map_lwp2thr));
-  CHK (TDB_VERBOSE_DLSYM (info, td_ta_thr_iter));
   CHK (TDB_VERBOSE_DLSYM (info, td_thr_validate));
   CHK (TDB_VERBOSE_DLSYM (info, td_thr_get_info));
 
@@ -572,10 +571,6 @@ try_thread_db_load_1 (struct thread_db_info *info)
   TDB_DLSYM (info, td_thr_tls_get_addr);
   TDB_DLSYM (info, td_thr_tlsbase);
 
-#undef TDB_VERBOSE_DLSYM
-#undef TDB_DLSYM
-#undef CHK
-
   /* It's best to avoid td_ta_thr_iter if possible.  That walks data
      structures in the inferior's address space that may be corrupted,
      or, if the target is running, may change while we walk them.  If
@@ -587,6 +582,15 @@ try_thread_db_load_1 (struct thread_db_info *info)
      currently on core targets, as it uses ptrace directly.  */
   if (target_has_execution
       && linux_proc_task_list_dir_exists (ptid_get_pid (inferior_ptid)))
+    info->td_ta_thr_iter_p = NULL;
+  else
+    CHK (TDB_VERBOSE_DLSYM (info, td_ta_thr_iter));
+
+#undef TDB_VERBOSE_DLSYM
+#undef TDB_DLSYM
+#undef CHK
+
+  if (info->td_ta_thr_iter_p == NULL)
     {
       struct lwp_info *lp;
       int pid = ptid_get_pid (inferior_ptid);
@@ -1246,7 +1250,7 @@ find_new_threads_once (struct thread_db_info *info, int iteration,
   data.new_threads = 0;
 
   /* See comment in thread_db_update_thread_list.  */
-  gdb_assert (!target_has_execution);
+  gdb_assert (info->td_ta_thr_iter_p != NULL);
 
   TRY
     {
-- 
2.5.0



http://sourceware.org/ml/gdb-patches/2016-03/msg00246.html
Subject: [patch] Suggest running gdbserver for a PID in container


--azLHFNyN32YCQGCU
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

currently
	gdb -p <pid from a container>
will print:
	warning: Target and debugger are in different PID namespaces; thread lists and other data are likely unreliable

BTW it is a bit lost in all the other messages.  Full screen output is in:
	https://sourceware.org/bugzilla/show_bug.cgi?id=19828

It correctly states the problem but it does not say how to solve it.

Is at least this little suggestion OK?

Originally I wanted to suggest also the Docker "-p 1234:1234" parameter but
I see the containers are more general topic than just Docker (even LxC etc.).

According to Gary future GDBs should be able to work even without gdbserver.
But currently gdbserver is still required.


Thanks,
Jan

--azLHFNyN32YCQGCU
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline; filename=1

gdb/ChangeLog
2016-03-15  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linux-thread-db.c (check_pid_namespace_match): Extend the message.

diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 1eb457d..21166bf 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -1020,7 +1020,8 @@ check_pid_namespace_match (void)
 	{
 	  warning (_ ("Target and debugger are in different PID "
 		      "namespaces; thread lists and other data are "
-		      "likely unreliable"));
+		      "likely unreliable.  "
+		      "Connect to gdbserver inside the container."));
 	}
     }
 }

--azLHFNyN32YCQGCU--



commit fef3cb9f3aa84018d10866f89228ae3f23e5ca7e
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Wed Apr 6 15:57:08 2016 +0200

    Print the "file" command suggestion in exec_file_locate_attach
    
    currently:
    	$ gdbserver-7.9 :1234 true &
    	$ gdb -q -ex 'target remote :1234' # that -q is not relevant here
    	Remote debugging using :1234
    	warning: Could not load vsyscall page because no executable was specified
    	try using the "file" command first.
    	0x00007ffff7ddcc80 in ?? ()
    	(gdb) b main
    	No symbol table is loaded.  Use the "file" command.
    	Make breakpoint pending on future shared library load? (y or [n]) _
    
    Provide more suggestive message to use the "file" command.
    
    gdb/ChangeLog
    2016-04-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
    	    Pedro Alves  <palves@redhat.com>
    
    	* exec.c (exec_file_locate_attach): Print warning for unsupported
    	target_pid_to_exec_file.
    	* symfile-mem.c (add_vsyscall_page): Remove the "file" command
    	message part.

### a/gdb/ChangeLog
### b/gdb/ChangeLog
## -1,3 +1,11 @@
+2016-04-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Pedro Alves  <palves@redhat.com>
+
+	* exec.c (exec_file_locate_attach): Print warning for unsupported
+	target_pid_to_exec_file.
+	* symfile-mem.c (add_vsyscall_page): Remove the "file" command
+	message part.
+
 2016-04-04  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* cli/cli-decode.c (help_cmd_list): Fix function doc and remove
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -151,7 +151,13 @@ exec_file_locate_attach (int pid, int from_tty)
   /* Try to determine a filename from the process itself.  */
   exec_file = target_pid_to_exec_file (pid);
   if (exec_file == NULL)
-    return;
+    {
+      warning (_("No executable has been specified and target does not "
+		 "support\n"
+		 "determining executable automatically.  "
+		 "Try using the \"file\" command."));
+      return;
+    }
 
   /* If gdb_sysroot is not empty and the discovered filename
      is absolute then prefix the filename with gdb_sysroot.  */
--- a/gdb/symfile-mem.c
+++ b/gdb/symfile-mem.c
@@ -214,8 +214,7 @@ add_vsyscall_page (struct target_ops *target, int from_tty)
 	  format should fix this.  */
 	{
 	  warning (_("Could not load vsyscall page "
-		     "because no executable was specified\n"
-		     "try using the \"file\" command first."));
+		     "because no executable was specified"));
 	  return;
 	}
       args.bfd = bfd;



commit 2ef34d11f61d79dcb152713aa059051d8cd3295d
Author: Markus Metzger <markus.t.metzger@intel.com>
Date:   Fri Feb 5 09:32:53 2016 +0100

    btrace: fix PR gdb/19829
    
    This is a backport of
    
    33b4777ca1b7 btrace, frame: fix crash in get_frame_type
    a038fa3e14a4 stack: check frame_unwind_caller_id
    2f3ef606b912 frame: add skip_tailcall_frames
    
    In skip_artificial_frames we repeatedly call get_prev_frame_always until we get
    a non-inline and non-tailcall frame assuming that there must be such a frame
    eventually.
    
    For record targets, however, we may have a frame chain that consists only of
    artificial frames.  This leads to a crash in get_frame_type when dereferencing a
    NULL frame pointer.
    
    Change skip_artificial_frames and skip_tailcall_frames to return NULL in such a
    case and modify each caller to cope with a NULL return.
    
    In frame_unwind_caller_pc and frame_unwind_caller_arch, we simply assert that
    the returned value is not NULL.  Their caller was supposed to check
    frame_unwind_caller_id before calling those functions.
    
    In other cases, we thrown an error.
    
    In infcmd further move the skip_tailcall_frames call to the forward-stepping
    case since we don't need a frame for reverse execution and we don't want to fail
    because of that.  Reverse-finish does make sense for a tailcall frame.
    
    gdb/
    	* frame.h (skip_tailcall_frames): New.
    	* infcmd.c (finish_command): Call skip_tailcall_frames.
    	* frame.c (skip_artificial_frames): Return NULL if only artificial frames
    	are found.  Update comment.
    	(frame_pop): Call skip_tailcall_frames.
    	(frame_unwind_caller_id): Handle NULL return.
    	(frame_unwind_caller_pc, frame_unwind_caller_arch): Assert that
    	skip_artificial_frames does not return NULL.
    	(frame_pop): Add an error if only tailcall frames are found.
    	* infcmd.c (finish_command): Move skip_tailcall_frames call into forward-
    	execution case.  Add an error if only tailcall frames are found.
    	* stack.c (frame_info): Check frame_unwind_caller_id.
    
    testsuite/
    	* gdb.btrace/tailcall-only.exp: New.
    	* gdb.btrace/tailcall-only.c: New.
    	* gdb.btrace/x86_64-tailcall-only.S: New.
    	* gdb.btrace/i686-tailcall-only.S: New.

### a/gdb/ChangeLog
### b/gdb/ChangeLog
## -1,3 +1,19 @@
+2016-03-17  Markus Metzger  <markus.t.metzger@intel.com>
+
+	PR gdb/19829
+	* frame.h (skip_tailcall_frames): New.
+	* infcmd.c (finish_command): Call skip_tailcall_frames.
+	* frame.c (skip_artificial_frames): Return NULL if only artificial
+	frames are found.  Update comment.
+	(frame_pop): Call skip_tailcall_frames.
+	(frame_unwind_caller_id): Handle NULL return.
+	(frame_unwind_caller_pc, frame_unwind_caller_arch): Assert that
+	skip_artificial_frames does not return NULL.
+	(frame_pop): Add an error if only tailcall frames are found.
+	* infcmd.c (finish_command): Move skip_tailcall_frames call into
+	forward-execution case.  Add an error if only tailcall frames are found.
+	* stack.c (frame_info): Check frame_unwind_caller_id.
+
 2016-03-15  Pedro Alves  <palves@redhat.com>
 
 	PR gdb/19676
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -420,7 +420,8 @@ fprint_frame (struct ui_file *file, struct frame_info *fi)
 
 /* Given FRAME, return the enclosing frame as found in real frames read-in from
    inferior memory.  Skip any previous frames which were made up by GDB.
-   Return the original frame if no immediate previous frames exist.  */
+   Return FRAME if FRAME is a non-artificial frame.
+   Return NULL if FRAME is the start of an artificial-only chain.  */
 
 static struct frame_info *
 skip_artificial_frames (struct frame_info *frame)
@@ -428,12 +429,34 @@ skip_artificial_frames (struct frame_info *frame)
   /* Note we use get_prev_frame_always, and not get_prev_frame.  The
      latter will truncate the frame chain, leading to this function
      unintentionally returning a null_frame_id (e.g., when the user
-     sets a backtrace limit).  This is safe, because as these frames
-     are made up by GDB, there must be a real frame in the chain
-     below.  */
+     sets a backtrace limit).
+
+     Note that for record targets we may get a frame chain that consists
+     of artificial frames only.  */
   while (get_frame_type (frame) == INLINE_FRAME
 	 || get_frame_type (frame) == TAILCALL_FRAME)
-    frame = get_prev_frame_always (frame);
+    {
+      frame = get_prev_frame_always (frame);
+      if (frame == NULL)
+	break;
+    }
+
+  return frame;
+}
+
+/* See frame.h.  */
+
+struct frame_info *
+skip_tailcall_frames (struct frame_info *frame)
+{
+  while (get_frame_type (frame) == TAILCALL_FRAME)
+    {
+      /* Note that for record targets we may get a frame chain that consists of
+	 tailcall frames only.  */
+      frame = get_prev_frame (frame);
+      if (frame == NULL)
+	break;
+    }
 
   return frame;
 }
@@ -496,6 +519,9 @@ frame_unwind_caller_id (struct frame_info *next_frame)
      requests the frame ID of "main()"s caller.  */
 
   next_frame = skip_artificial_frames (next_frame);
+  if (next_frame == NULL)
+    return null_frame_id;
+
   this_frame = get_prev_frame_always (next_frame);
   if (this_frame)
     return get_frame_id (skip_artificial_frames (this_frame));
@@ -869,7 +895,14 @@ frame_unwind_pc (struct frame_info *this_frame)
 CORE_ADDR
 frame_unwind_caller_pc (struct frame_info *this_frame)
 {
-  return frame_unwind_pc (skip_artificial_frames (this_frame));
+  this_frame = skip_artificial_frames (this_frame);
+
+  /* We must have a non-artificial frame.  The caller is supposed to check
+     the result of frame_unwind_caller_id (), which returns NULL_FRAME_ID
+     in this case.  */
+  gdb_assert (this_frame != NULL);
+
+  return frame_unwind_pc (this_frame);
 }
 
 int
@@ -972,8 +1005,10 @@ frame_pop (struct frame_info *this_frame)
 
   /* Ignore TAILCALL_FRAME type frames, they were executed already before
      entering THISFRAME.  */
-  while (get_frame_type (prev_frame) == TAILCALL_FRAME)
-    prev_frame = get_prev_frame (prev_frame);
+  prev_frame = skip_tailcall_frames (prev_frame);
+
+  if (prev_frame == NULL)
+    error (_("Cannot find the caller frame."));
 
   /* Make a copy of all the register values unwound from this frame.
      Save them in a scratch buffer so that there isn't a race between
@@ -2561,7 +2596,14 @@ frame_unwind_arch (struct frame_info *next_frame)
 struct gdbarch *
 frame_unwind_caller_arch (struct frame_info *next_frame)
 {
-  return frame_unwind_arch (skip_artificial_frames (next_frame));
+  next_frame = skip_artificial_frames (next_frame);
+
+  /* We must have a non-artificial frame.  The caller is supposed to check
+     the result of frame_unwind_caller_id (), which returns NULL_FRAME_ID
+     in this case.  */
+  gdb_assert (next_frame != NULL);
+
+  return frame_unwind_arch (next_frame);
 }
 
 /* Gets the language of FRAME.  */
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -820,5 +820,10 @@ extern int frame_unwinder_is (struct frame_info *fi,
 
 extern enum language get_frame_language (struct frame_info *frame);
 
+/* Return the first non-tailcall frame above FRAME or FRAME if it is not a
+   tailcall frame.  Return NULL if FRAME is the start of a tailcall-only
+   chain.  */
+
+extern struct frame_info *skip_tailcall_frames (struct frame_info *frame);
 
 #endif /* !defined (FRAME_H)  */
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2000,11 +2000,6 @@ finish_command (char *arg, int from_tty)
       return;
     }
 
-  /* Ignore TAILCALL_FRAME type frames, they were executed already before
-     entering THISFRAME.  */
-  while (get_frame_type (frame) == TAILCALL_FRAME)
-    frame = get_prev_frame (frame);
-
   /* Find the function we will return from.  */
 
   sm->function = find_pc_function (get_frame_pc (get_selected_frame (NULL)));
@@ -2031,7 +2026,16 @@ finish_command (char *arg, int from_tty)
   if (execution_direction == EXEC_REVERSE)
     finish_backward (sm);
   else
-    finish_forward (sm, frame);
+    {
+      /* Ignore TAILCALL_FRAME type frames, they were executed already before
+	 entering THISFRAME.  */
+      frame = skip_tailcall_frames (frame);
+
+      if (frame == NULL)
+	error (_("Cannot find the caller frame."));
+
+      finish_forward (sm, frame);
+    }
 }
 
 
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1509,27 +1509,32 @@ frame_info (char *addr_exp, int from_tty)
   wrap_here ("    ");
   printf_filtered ("saved %s = ", pc_regname);
 
-  TRY
-    {
-      caller_pc = frame_unwind_caller_pc (fi);
-      caller_pc_p = 1;
-    }
-  CATCH (ex, RETURN_MASK_ERROR)
+  if (!frame_id_p (frame_unwind_caller_id (fi)))
+    val_print_unavailable (gdb_stdout);
+  else
     {
-      switch (ex.error)
+      TRY
 	{
-	case NOT_AVAILABLE_ERROR:
-	  val_print_unavailable (gdb_stdout);
-	  break;
-	case OPTIMIZED_OUT_ERROR:
-	  val_print_not_saved (gdb_stdout);
-	  break;
-	default:
-	  fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
-	  break;
+	  caller_pc = frame_unwind_caller_pc (fi);
+	  caller_pc_p = 1;
 	}
+      CATCH (ex, RETURN_MASK_ERROR)
+	{
+	  switch (ex.error)
+	    {
+	    case NOT_AVAILABLE_ERROR:
+	      val_print_unavailable (gdb_stdout);
+	      break;
+	    case OPTIMIZED_OUT_ERROR:
+	      val_print_not_saved (gdb_stdout);
+	      break;
+	    default:
+	      fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message);
+	      break;
+	    }
+	}
+      END_CATCH
     }
-  END_CATCH
 
   if (caller_pc_p)
     fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout);
### a/gdb/testsuite/ChangeLog
### b/gdb/testsuite/ChangeLog
## -1,3 +1,11 @@
+2016-03-17  Markus Metzger  <markus.t.metzger@intel.com>
+
+	PR gdb/19829
+	* gdb.btrace/tailcall-only.exp: New.
+	* gdb.btrace/tailcall-only.c: New.
+	* gdb.btrace/x86_64-tailcall-only.S: New.
+	* gdb.btrace/i686-tailcall-only.S: New.
+
 2016-02-16  Don Breazeal  <donb@codesourcery.com>
 
 	PR remote/19496
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/i686-tailcall-only.S
@@ -0,0 +1,447 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2016 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 using:
+   gcc -m32 -march=i686 -S -O2 -dA -g tailcall-only.c -o i686-tailcall-only.S
+ */
+
+	.file	"tailcall-only.c"
+	.text
+.Ltext0:
+	.p2align 4,,15
+	.type	bar_1, @function
+bar_1:
+.LFB0:
+	.file 1 "tailcall-only.c"
+	# tailcall-only.c:22
+	.loc 1 22 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:24
+	.loc 1 24 0
+	movl	$42, %eax
+# SUCC: EXIT [100.0%]
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	bar_1, .-bar_1
+	.p2align 4,,15
+	.type	bar, @function
+bar:
+.LFB1:
+	# tailcall-only.c:28
+	.loc 1 28 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:29
+	.loc 1 29 0
+	jmp	bar_1
+# SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+.LVL0:
+	.cfi_endproc
+.LFE1:
+	.size	bar, .-bar
+	.p2align 4,,15
+	.type	foo_1, @function
+foo_1:
+.LFB2:
+	# tailcall-only.c:34
+	.loc 1 34 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:35
+	.loc 1 35 0
+	jmp	bar
+# SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+.LVL1:
+	.cfi_endproc
+.LFE2:
+	.size	foo_1, .-foo_1
+	.p2align 4,,15
+	.type	foo, @function
+foo:
+.LFB3:
+	# tailcall-only.c:40
+	.loc 1 40 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:41
+	.loc 1 41 0
+	jmp	foo_1
+# SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+.LVL2:
+	.cfi_endproc
+.LFE3:
+	.size	foo, .-foo
+	.section	.text.startup,"ax",@progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, @function
+main:
+.LFB4:
+	# tailcall-only.c:46
+	.loc 1 46 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:49
+	.loc 1 49 0
+	call	foo
+.LVL3:
+	# tailcall-only.c:50
+	.loc 1 50 0
+	addl	$1, %eax
+.LVL4:
+# SUCC: EXIT [100.0%]
+	# tailcall-only.c:53
+	.loc 1 53 0
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0xd5	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x4	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF1	# DW_AT_producer: "GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -m32 -march=i686 -g -O2"
+	.byte	0x1	# DW_AT_language
+	.long	.LASF2	# DW_AT_name: "tailcall-only.c"
+	.long	.LASF3	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.long	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x25) DW_TAG_subprogram)
+	.long	.LASF4	# DW_AT_name: "bar_1"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x15	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x3a	# DW_AT_type
+	.long	.LFB0	# DW_AT_low_pc
+	.long	.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
+	.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)
+	.ascii "bar\0"	# DW_AT_name
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x1b	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x3a	# DW_AT_type
+	.long	.LFB1	# DW_AT_low_pc
+	.long	.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
+	.long	0x64	# DW_AT_sibling
+	.uleb128 0x5	# (DIE (0x5a) DW_TAG_GNU_call_site)
+	.long	.LVL0	# DW_AT_low_pc
+			# DW_AT_GNU_tail_call
+	.long	0x25	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0x41
+	.uleb128 0x6	# (DIE (0x64) DW_TAG_subprogram)
+	.long	.LASF0	# DW_AT_name: "foo_1"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x21	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x3a	# DW_AT_type
+	.long	.LFB2	# DW_AT_low_pc
+	.long	.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
+	.long	0x87	# DW_AT_sibling
+	.uleb128 0x5	# (DIE (0x7d) DW_TAG_GNU_call_site)
+	.long	.LVL1	# DW_AT_low_pc
+			# DW_AT_GNU_tail_call
+	.long	0x41	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0x64
+	.uleb128 0x4	# (DIE (0x87) 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
+	.long	0x3a	# DW_AT_type
+	.long	.LFB3	# DW_AT_low_pc
+	.long	.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
+	.long	0xaa	# DW_AT_sibling
+	.uleb128 0x5	# (DIE (0xa0) DW_TAG_GNU_call_site)
+	.long	.LVL2	# DW_AT_low_pc
+			# DW_AT_GNU_tail_call
+	.long	0x64	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0x87
+	.uleb128 0x7	# (DIE (0xaa) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF5	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2d	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x3a	# DW_AT_type
+	.long	.LFB4	# DW_AT_low_pc
+	.long	.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
+	.uleb128 0x8	# (DIE (0xbf) DW_TAG_variable)
+	.long	.LASF6	# DW_AT_name: "answer"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2f	# DW_AT_decl_line
+	.long	0x3a	# DW_AT_type
+	.long	.LLST0	# DW_AT_location
+	.uleb128 0x9	# (DIE (0xce) DW_TAG_GNU_call_site)
+	.long	.LVL3	# DW_AT_low_pc
+	.long	0x87	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0xaa
+	.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	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
+	.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	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 0x5	# (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 0x6	# (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 0x7	# (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)
+	.byte	0
+	.byte	0
+	.uleb128 0x8	# (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 0x9	# (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
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.long	.LVL3	# Location list begin address (*.LLST0)
+	.long	.LVL4	# Location list end address (*.LLST0)
+	.value	0x3	# Location expression size
+	.byte	0x70	# DW_OP_breg0
+	.sleb128 1
+	.byte	0x9f	# DW_OP_stack_value
+	.long	.LVL4	# Location list begin address (*.LLST0)
+	.long	.LFE4	# Location list end address (*.LLST0)
+	.value	0x1	# Location expression size
+	.byte	0x50	# DW_OP_reg0
+	.long	0	# Location list terminator begin (*.LLST0)
+	.long	0	# Location list terminator end (*.LLST0)
+	.section	.debug_aranges,"",@progbits
+	.long	0x24	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x4	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 8 byte boundary
+	.value	0
+	.long	.Ltext0	# Address
+	.long	.Letext0-.Ltext0	# Length
+	.long	.LFB4	# Address
+	.long	.LFE4-.LFB4	# Length
+	.long	0
+	.long	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.long	.Ltext0	# Offset 0
+	.long	.Letext0
+	.long	.LFB4	# Offset 0x8
+	.long	.LFE4
+	.long	0
+	.long	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF4:
+	.string	"bar_1"
+.LASF2:
+	.string	"tailcall-only.c"
+.LASF1:
+	.string	"GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -m32 -march=i686 -g -O2"
+.LASF6:
+	.string	"answer"
+.LASF5:
+	.string	"main"
+.LASF3:
+	.string	""
+.LASF0:
+	.string	"foo_1"
+	.ident	"GCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-9)"
+	.section	.note.GNU-stack,"",@progbits
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/tailcall-only.c
@@ -0,0 +1,53 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2016 Free Software Foundation, Inc.
+
+   Contributed by Intel Corp. <markus.t.metzger@intel.com>
+
+   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/>.  */
+
+static __attribute__ ((noinline)) int
+bar_1 (void)
+{
+  return 42;
+}
+
+static __attribute__ ((noinline)) int
+bar (void)
+{
+  return bar_1 ();
+}
+
+static __attribute__ ((noinline)) int
+foo_1 (void)
+{
+  return bar ();
+}
+
+static __attribute__ ((noinline)) int
+foo (void)
+{
+  return foo_1 ();
+}
+
+int
+main (void)
+{
+  int answer;
+
+  answer = foo ();
+  answer += 1;
+
+  return answer;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/tailcall-only.exp
@@ -0,0 +1,97 @@
+# This testcase is part of GDB, the GNU debugger.
+#
+# Copyright 2016 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 is a variant of tailcall.exp where the entire trace contains only tail
+# calls.  This used to cause a crash in get_frame_type.
+#
+
+# check for btrace support
+if { [skip_btrace_tests] } { return -1 }
+
+# This test requires the compiler to generate a tail call.  To guarantee that
+# we always get one, we use an assembly source file.
+#
+# We use different assembly sources based on the target architecture.
+#
+# Luckily, they are similar enough that a single test script can handle
+# both.
+set opts {}
+if [info exists COMPILE] {
+    # make check RUNTESTFLAGS="gdb.btrace/tailcall-only.exp COMPILE=1"
+    standard_testfile tailcall-only.c
+    lappend opts debug optimize=-O2
+} elseif {[istarget "x86_64-*-*"]} {
+	standard_testfile x86_64-tailcall-only.S
+} elseif {[istarget "i?86-*-*"]} {
+	standard_testfile i686-tailcall-only.S
+} else {
+    verbose "Skipping ${testfile}."
+    return
+}
+
+if [prepare_for_testing tailcall-only.exp $testfile $srcfile $opts] {
+    return -1
+}
+if ![runto_main] {
+    return -1
+}
+
+# we want to see the full trace for this test
+gdb_test_no_output "set record function-call-history-size 0"
+
+# trace foo
+gdb_test "step" ".*" "prepare for recording"
+gdb_test_no_output "record btrace"
+gdb_test "stepi 4" ".*" "record branch trace"
+
+# for debugging
+gdb_test "info record" ".*"
+
+# show the branch trace with calls indented
+gdb_test "record function-call-history /c 1" [multi_line \
+  "1\tfoo" \
+  "2\t  foo_1" \
+  "3\t    bar" \
+  "4\t      bar_1"
+  ] "function-call-history"
+
+# We can step
+gdb_test "record goto begin" ".*foo.*"
+gdb_test "stepi" ".*foo_1.*" "step into foo_1"
+gdb_test "step" ".*bar.*" "step into bar"
+gdb_test "stepi" ".*bar_1.*" "step into bar_1"
+
+# We can neither finish nor return.
+gdb_test "finish" "Cannot find the caller frame.*"
+gdb_test_multiple "return" "return" {
+  -re "Make .* return now.*y or n. $" {
+    send_gdb "y\n"
+    exp_continue
+  }
+  -re "Cannot find the caller frame.*$gdb_prompt $" {
+    pass "return"
+  }
+}
+
+# But we can reverse-finish
+gdb_test "reverse-finish" ".*bar.*"
+gdb_test "reverse-step" ".*foo_1.*"
+
+# Info frame isn't useful but doesn't crash as it used to.
+gdb_test "up" ".*foo.*"
+gdb_test "info frame" ".*"
--- /dev/null
+++ b/gdb/testsuite/gdb.btrace/x86_64-tailcall-only.S
@@ -0,0 +1,446 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2016 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 using:
+   gcc -S -O2 -dA -g tailcall-only.c -o x86_64-tailcall-only.S  */
+
+	.file	"tailcall-only.c"
+	.text
+.Ltext0:
+	.p2align 4,,15
+	.type	bar_1, @function
+bar_1:
+.LFB0:
+	.file 1 "tailcall-only.c"
+	# tailcall-only.c:22
+	.loc 1 22 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:24
+	.loc 1 24 0
+	movl	$42, %eax
+# SUCC: EXIT [100.0%]
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	bar_1, .-bar_1
+	.p2align 4,,15
+	.type	bar, @function
+bar:
+.LFB1:
+	# tailcall-only.c:28
+	.loc 1 28 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:29
+	.loc 1 29 0
+	jmp	bar_1
+# SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+.LVL0:
+	.cfi_endproc
+.LFE1:
+	.size	bar, .-bar
+	.p2align 4,,15
+	.type	foo_1, @function
+foo_1:
+.LFB2:
+	# tailcall-only.c:34
+	.loc 1 34 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:35
+	.loc 1 35 0
+	jmp	bar
+# SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+.LVL1:
+	.cfi_endproc
+.LFE2:
+	.size	foo_1, .-foo_1
+	.p2align 4,,15
+	.type	foo, @function
+foo:
+.LFB3:
+	# tailcall-only.c:40
+	.loc 1 40 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:41
+	.loc 1 41 0
+	jmp	foo_1
+# SUCC: EXIT [100.0%]  (ABNORMAL,SIBCALL)
+.LVL2:
+	.cfi_endproc
+.LFE3:
+	.size	foo, .-foo
+	.section	.text.startup,"ax",@progbits
+	.p2align 4,,15
+	.globl	main
+	.type	main, @function
+main:
+.LFB4:
+	# tailcall-only.c:46
+	.loc 1 46 0
+	.cfi_startproc
+# BLOCK 2 freq:10000 seq:0
+# PRED: ENTRY [100.0%]  (FALLTHRU)
+	# tailcall-only.c:49
+	.loc 1 49 0
+	call	foo
+.LVL3:
+	# tailcall-only.c:50
+	.loc 1 50 0
+	addl	$1, %eax
+.LVL4:
+# SUCC: EXIT [100.0%]
+	# tailcall-only.c:53
+	.loc 1 53 0
+	ret
+	.cfi_endproc
+.LFE4:
+	.size	main, .-main
+	.text
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x111	# Length of Compilation Unit Info
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.long	.LASF1	# DW_AT_producer: "GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -mtune=generic -march=x86-64 -g -O2"
+	.byte	0x1	# DW_AT_language
+	.long	.LASF2	# DW_AT_name: "tailcall-only.c"
+	.long	.LASF3	# DW_AT_comp_dir: ""
+	.long	.Ldebug_ranges0+0	# DW_AT_ranges
+	.quad	0	# DW_AT_low_pc
+	.long	.Ldebug_line0	# DW_AT_stmt_list
+	.uleb128 0x2	# (DIE (0x29) DW_TAG_subprogram)
+	.long	.LASF4	# DW_AT_name: "bar_1"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x15	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x46	# DW_AT_type
+	.quad	.LFB0	# DW_AT_low_pc
+	.quad	.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
+	.uleb128 0x3	# (DIE (0x46) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.ascii "int\0"	# DW_AT_name
+	.uleb128 0x4	# (DIE (0x4d) 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
+	.long	0x46	# DW_AT_type
+	.quad	.LFB1	# DW_AT_low_pc
+	.quad	.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
+	.long	0x7c	# DW_AT_sibling
+	.uleb128 0x5	# (DIE (0x6e) DW_TAG_GNU_call_site)
+	.quad	.LVL0	# DW_AT_low_pc
+			# DW_AT_GNU_tail_call
+	.long	0x29	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0x4d
+	.uleb128 0x6	# (DIE (0x7c) DW_TAG_subprogram)
+	.long	.LASF0	# DW_AT_name: "foo_1"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x21	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x46	# DW_AT_type
+	.quad	.LFB2	# DW_AT_low_pc
+	.quad	.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
+	.long	0xab	# DW_AT_sibling
+	.uleb128 0x5	# (DIE (0x9d) DW_TAG_GNU_call_site)
+	.quad	.LVL1	# DW_AT_low_pc
+			# DW_AT_GNU_tail_call
+	.long	0x4d	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0x7c
+	.uleb128 0x4	# (DIE (0xab) 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
+	.long	0x46	# DW_AT_type
+	.quad	.LFB3	# DW_AT_low_pc
+	.quad	.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
+	.long	0xda	# DW_AT_sibling
+	.uleb128 0x5	# (DIE (0xcc) DW_TAG_GNU_call_site)
+	.quad	.LVL2	# DW_AT_low_pc
+			# DW_AT_GNU_tail_call
+	.long	0x7c	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0xab
+	.uleb128 0x7	# (DIE (0xda) DW_TAG_subprogram)
+			# DW_AT_external
+	.long	.LASF5	# DW_AT_name: "main"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2d	# DW_AT_decl_line
+			# DW_AT_prototyped
+	.long	0x46	# DW_AT_type
+	.quad	.LFB4	# DW_AT_low_pc
+	.quad	.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
+	.uleb128 0x8	# (DIE (0xf7) DW_TAG_variable)
+	.long	.LASF6	# DW_AT_name: "answer"
+	.byte	0x1	# DW_AT_decl_file (tailcall-only.c)
+	.byte	0x2f	# DW_AT_decl_line
+	.long	0x46	# DW_AT_type
+	.long	.LLST0	# DW_AT_location
+	.uleb128 0x9	# (DIE (0x106) DW_TAG_GNU_call_site)
+	.quad	.LVL3	# DW_AT_low_pc
+	.long	0xab	# DW_AT_abstract_origin
+	.byte	0	# end of children of DIE 0xda
+	.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	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 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
+	.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	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 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 0x5	# (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 0x6	# (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 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 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 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
+	.uleb128 0x8	# (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 0x9	# (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
+	.byte	0
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.quad	.LVL3	# Location list begin address (*.LLST0)
+	.quad	.LVL4	# Location list end address (*.LLST0)
+	.value	0x3	# Location expression size
+	.byte	0x70	# DW_OP_breg0
+	.sleb128 1
+	.byte	0x9f	# DW_OP_stack_value
+	.quad	.LVL4	# Location list begin address (*.LLST0)
+	.quad	.LFE4	# Location list end address (*.LLST0)
+	.value	0x1	# Location expression size
+	.byte	0x50	# DW_OP_reg0
+	.quad	0	# Location list terminator begin (*.LLST0)
+	.quad	0	# Location list terminator end (*.LLST0)
+	.section	.debug_aranges,"",@progbits
+	.long	0x3c	# Length of Address Ranges Info
+	.value	0x2	# DWARF Version
+	.long	.Ldebug_info0	# Offset of Compilation Unit Info
+	.byte	0x8	# Size of Address
+	.byte	0	# Size of Segment Descriptor
+	.value	0	# Pad to 16 byte boundary
+	.value	0
+	.quad	.Ltext0	# Address
+	.quad	.Letext0-.Ltext0	# Length
+	.quad	.LFB4	# Address
+	.quad	.LFE4-.LFB4	# Length
+	.quad	0
+	.quad	0
+	.section	.debug_ranges,"",@progbits
+.Ldebug_ranges0:
+	.quad	.Ltext0	# Offset 0
+	.quad	.Letext0
+	.quad	.LFB4	# Offset 0x10
+	.quad	.LFE4
+	.quad	0
+	.quad	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF4:
+	.string	"bar_1"
+.LASF2:
+	.string	"tailcall-only.c"
+.LASF1:
+	.string	"GNU C 4.8.3 20140911 (Red Hat 4.8.3-9) -mtune=generic -march=x86-64 -g -O2"
+.LASF6:
+	.string	"answer"
+.LASF5:
+	.string	"main"
+.LASF3:
+	.string	""
+.LASF0:
+	.string	"foo_1"
+	.ident	"GCC: (GNU) 4.8.3 20140911 (Red Hat 4.8.3-9)"
+	.section	.note.GNU-stack,"",@progbits



commit cd64cabb8c66a5565fc33bf66a07c08bc767e413
Author: Yichao Yu <yyc1992@gmail.com>
Date:   Thu Mar 31 19:28:47 2016 +0100

    Fix PR gdb/19858: GDB doesn't register the JIT libraries on attach
    
    Ref: https://sourceware.org/ml/gdb/2016-03/msg00023.html
    
    GDB currently fails to fetch the list of already-registered JIT
    modules on attach.
    
    Nothing is calling jit_inferior_init, which is what is responsible for
    walking the JIT object list at init time.
    
    Despite the misleading naming, jit_inferior_created_hook ->
    jit_inferior_init is only called when the inferior execs.
    
    This regressed with the fix for PR gdb/13431 (03bef283c2d3):
     https://sourceware.org/ml/gdb-patches/2012-02/msg00023.html which
    removed the inferior_created (jit_inferior_created_observer)
    observer.
    
    Adding an inferior_created observer back fixes the issue.
    
    In turn, this exposes a bug in jit_breakpoint_re_set_internal as well,
    which is returning the wrong result when we already have the
    breakpoint at the right address.
    
    gdb/ChangeLog:
    2016-03-31  Yichao Yu  <yyc1992@gmail.com>
    
    	PR gdb/19858
    	* jit.c (jit_breakpoint_re_set_internal): Return 0 if we already
    	got the breakpoint at the right address.
    	(jit_inferior_created): New function.
    	(_initialize_jit): Install jit_inferior_created as
    	inferior_created observer.
    
    Signed-off-by: Pedro Alves <palves@redhat.com>

### a/gdb/ChangeLog
### b/gdb/ChangeLog
## -1,3 +1,12 @@
+2016-03-31  Yichao Yu  <yyc1992@gmail.com>
+
+	PR gdb/19858
+	* jit.c (jit_breakpoint_re_set_internal): Return 0 if we already
+	got the breakpoint at the right address.
+	(jit_inferior_created): New function.
+	(_initialize_jit): Install jit_inferior_created as
+	inferior_created observer.
+
 2016-03-17  Markus Metzger  <markus.t.metzger@intel.com>
 
 	PR gdb/19829
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -1026,7 +1026,7 @@ jit_breakpoint_deleted (struct breakpoint *b)
 }
 
 /* (Re-)Initialize the jit breakpoint if necessary.
-   Return 0 on success.  */
+   Return 0 if the jit breakpoint has been successfully initialized.  */
 
 static int
 jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
@@ -1070,7 +1070,7 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
 			paddress (gdbarch, addr));
 
   if (ps_data->cached_code_address == addr)
-    return 1;
+    return 0;
 
   /* Delete the old breakpoint.  */
   if (ps_data->jit_breakpoint != NULL)
@@ -1367,6 +1367,14 @@ jit_inferior_init (struct gdbarch *gdbarch)
     }
 }
 
+/* inferior_created observer.  */
+
+static void
+jit_inferior_created (struct target_ops *ops, int from_tty)
+{
+  jit_inferior_created_hook ();
+}
+
 /* Exported routine to call when an inferior has been created.  */
 
 void
@@ -1496,6 +1504,7 @@ _initialize_jit (void)
 			     show_jit_debug,
 			     &setdebuglist, &showdebuglist);
 
+  observer_attach_inferior_created (jit_inferior_created);
   observer_attach_inferior_exit (jit_inferior_exit_hook);
   observer_attach_breakpoint_deleted (jit_breakpoint_deleted);
 



commit 89df5d6cce0e91c4b34c7a62ba4a68756a8ed4e7
Author: Pedro Alves <palves@redhat.com>
Date:   Thu Mar 31 19:28:47 2016 +0100

    Make gdb.base/jit.exp binaries unique
    
    This testcase compiles the same program and library differently
    multiple times using the same file names.  Make them unique, to make
    it easier to debug test problems.
    
    gdb/testsuite/ChangeLog:
    2016-03-31  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/19858
    	* gdb.base/jit.exp (compile_jit_test): Add intro comment.  Add
    	BINSUFFIX parameter, and handle it.
    	(top level): Adjust calls compile_jit_test.

### a/gdb/testsuite/ChangeLog
### b/gdb/testsuite/ChangeLog
## -1,3 +1,10 @@
+2016-03-31  Pedro Alves  <palves@redhat.com>
+
+	PR gdb/19858
+	* gdb.base/jit.exp (compile_jit_test): Add intro comment.  Add
+	BINSUFFIX parameter, and handle it.
+	(top level): Adjust calls compile_jit_test.
+
 2016-03-17  Markus Metzger  <markus.t.metzger@intel.com>
 
 	PR gdb/19829
--- a/gdb/testsuite/gdb.base/jit.exp
+++ b/gdb/testsuite/gdb.base/jit.exp
@@ -24,18 +24,19 @@ if {[get_compiler_info]} {
     return 1
 }
 
-#
-# test running programs
-#
+# Compile the testcase program and library.  BINSUFFIX is the suffix
+# to append to the program and library filenames, to make them unique
+# between invocations.  OPTIONS is passed to gdb_compile when
+# compiling the program.
 
-proc compile_jit_test {testname options} {
+proc compile_jit_test {testname binsuffix options} {
     global testfile srcfile binfile srcdir subdir
     global solib_testfile solib_srcfile solib_binfile solib_binfile_test_msg
     global solib_binfile_target
 
     set testfile jit-main
     set srcfile ${testfile}.c
-    set binfile [standard_output_file $testfile]
+    set binfile [standard_output_file $testfile$binsuffix]
     if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
 	      executable [concat debug $options]] != "" } {
 	untested $testname
@@ -44,8 +45,8 @@ proc compile_jit_test {testname options} {
 
     set solib_testfile "jit-solib"
     set solib_srcfile "${srcdir}/${subdir}/${solib_testfile}.c"
-    set solib_binfile [standard_output_file ${solib_testfile}.so]
-    set solib_binfile_test_msg "SHLIBDIR/${solib_testfile}.so"
+    set solib_binfile [standard_output_file ${solib_testfile}$binsuffix.so]
+    set solib_binfile_test_msg "SHLIBDIR/${solib_testfile}$binsuffix.so"
 
     # Note: compiling without debug info: the library goes through
     # symbol renaming by munging on its symbol table, and that
@@ -109,7 +110,7 @@ proc one_jit_test {count match_str} {
     }
 }
 
-if {[compile_jit_test jit.exp {}] < 0} {
+if {[compile_jit_test jit.exp "" {}] < 0} {
     return
 }
 one_jit_test 1 "${hex}  jit_function_0000"
@@ -117,7 +118,7 @@ one_jit_test 2 "${hex}  jit_function_0000\[\r\n\]+${hex}  jit_function_0001"
 
 with_test_prefix PIE {
     if {[compile_jit_test "jit.exp PIE tests" \
-	     {additional_flags=-fPIE ldflags=-pie}] < 0} {
+	     "-pie" {additional_flags=-fPIE ldflags=-pie}] < 0} {
 	return
     }
 



commit 85af34ee0211eedf8d30a5c44dfc59dddf8b512a
Author: Pedro Alves <palves@redhat.com>
Date:   Thu Mar 31 19:28:47 2016 +0100

    Add regression test for PR gdb/19858 (JIT code registration on attach)
    
    This test would fail without the previous gdb/jit.c fix:
    
      (gdb) attach 23031
      Attaching to program: .../build/gdb/testsuite/outputs/gdb.base/jit/jit-main, process 23031
      [...]
      207           WAIT_FOR_GDB; i = 0;  /* gdb break here 1 */
      (gdb) PASS: gdb.base/jit.exp: attach: one_jit_test-2: attach
      set var wait_for_gdb = 0
      (gdb) PASS: gdb.base/jit.exp: attach: one_jit_test-2: set var wait_for_gdb = 0
      info function ^jit_function
      All functions matching regular expression "^jit_function":
      (gdb) FAIL: gdb.base/jit.exp: attach: one_jit_test-2: info function ^jit_function
    
    gdb/testsuite/ChangeLog:
    2016-03-31  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/19858
    	* gdb.base/jit-main.c: Include unistd.h.
    	(ATTACH): Define to 0 if not already defined.
    	(wait_for_gdb, mypid): New globals.
    	(WAIT_FOR_GDB): New macro.
    	(MAIN): Set an alarm.  Store the process's pid.  Wait for GDB at
    	some breakpoint locations.
    	* gdb.base/jit.exp (clean_reattach, continue_to_test_location):
    	New procedures.
    	(one_jit_test): Add REATTACH parameter, and handle it.  Use
    	continue_to_test_location.
    	(top level): Test attach, and adjusts calls to one_jit_test.

### a/gdb/testsuite/ChangeLog
### b/gdb/testsuite/ChangeLog
## -1,6 +1,21 @@
 2016-03-31  Pedro Alves  <palves@redhat.com>
 
 	PR gdb/19858
+	* gdb.base/jit-main.c: Include unistd.h.
+	(ATTACH): Define to 0 if not already defined.
+	(wait_for_gdb, mypid): New globals.
+	(WAIT_FOR_GDB): New macro.
+	(MAIN): Set an alarm.  Store the process's pid.  Wait for GDB at
+	some breakpoint locations.
+	* gdb.base/jit.exp (clean_reattach, continue_to_test_location):
+	New procedures.
+	(one_jit_test): Add REATTACH parameter, and handle it.  Use
+	continue_to_test_location.
+	(top level): Test attach, and adjusts calls to one_jit_test.
+
+2016-03-31  Pedro Alves  <palves@redhat.com>
+
+	PR gdb/19858
 	* gdb.base/jit.exp (compile_jit_test): Add intro comment.  Add
 	BINSUFFIX parameter, and handle it.
 	(top level): Adjust calls compile_jit_test.
--- a/gdb/testsuite/gdb.base/jit-main.c
+++ b/gdb/testsuite/gdb.base/jit-main.c
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 /* ElfW is coming from linux. On other platforms it does not exist.
    Let us define it here. */
@@ -116,10 +117,22 @@ update_locations (const void *const addr, int idx)
     }
 }
 
+/* Defined by the .exp file if testing attach.  */
+#ifndef ATTACH
+#define ATTACH 0
+#endif
+
 #ifndef MAIN
 #define MAIN main
 #endif
 
+/* Used to spin waiting for GDB.  */
+volatile int wait_for_gdb = ATTACH;
+#define WAIT_FOR_GDB while (wait_for_gdb)
+
+/* The current process's PID.  GDB retrieves this.  */
+int mypid;
+
 int
 MAIN (int argc, char *argv[])
 {
@@ -127,6 +140,10 @@ MAIN (int argc, char *argv[])
   const char *libname = NULL;
   int count = 0;
 
+  alarm (300);
+
+  mypid = getpid ();
+
   count = count;  /* gdb break here 0  */
 
   if (argc < 2)
@@ -190,7 +207,7 @@ MAIN (int argc, char *argv[])
           __jit_debug_register_code ();
         }
 
-      i = 0;  /* gdb break here 1 */
+      WAIT_FOR_GDB; i = 0;  /* gdb break here 1 */
 
       /* Now unregister them all in reverse order.  */
       while (__jit_debug_descriptor.relevant_entry != NULL)
@@ -215,5 +232,5 @@ MAIN (int argc, char *argv[])
           free (entry);
         }
     }
-  return 0;  /* gdb break here 2  */
+  WAIT_FOR_GDB; return 0;  /* gdb break here 2  */
 }
--- a/gdb/testsuite/gdb.base/jit.exp
+++ b/gdb/testsuite/gdb.base/jit.exp
@@ -66,7 +66,49 @@ proc compile_jit_test {testname binsuffix options} {
     return 0
 }
 
-proc one_jit_test {count match_str} {
+# Detach, restart GDB, and re-attach to the program.
+
+proc clean_reattach {} {
+    global decimal gdb_prompt srcfile testfile
+
+    # Get PID of test program.
+    set testpid -1
+    set test "get inferior process ID"
+    gdb_test_multiple "p mypid" $test {
+	-re ".* = ($decimal).*$gdb_prompt $" {
+	    set testpid $expect_out(1,string)
+	    pass $test
+	}
+    }
+
+    gdb_test_no_output "set var wait_for_gdb = 1"
+    gdb_test "detach" "Detaching from .*"
+
+    clean_restart $testfile
+
+    set test "attach"
+    gdb_test_multiple "attach $testpid" "$test" {
+	-re "Attaching to program.*.*main.*at .*$srcfile:.*$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+
+    gdb_test_no_output "set var wait_for_gdb = 0"
+}
+
+# Continue to LOCATION in the program.  If REATTACH, detach and
+# re-attach to the program from scratch.
+proc continue_to_test_location {location reattach} {
+    gdb_breakpoint [gdb_get_line_number $location]
+    gdb_continue_to_breakpoint $location
+    if {$reattach} {
+	with_test_prefix "$location" {
+	    clean_reattach
+	}
+    }
+}
+
+proc one_jit_test {count match_str reattach} {
     with_test_prefix "one_jit_test-$count" {
 	global verbose testfile solib_binfile_target solib_binfile_test_msg
 
@@ -91,8 +133,7 @@ proc one_jit_test {count match_str} {
 	gdb_test_no_output "set var libname = \"$solib_binfile_target\"" "set var libname = \"$solib_binfile_test_msg\""
 	gdb_test_no_output "set var count = $count"
 
-	gdb_breakpoint [gdb_get_line_number "break here 1"]
-	gdb_continue_to_breakpoint "break here 1"
+	continue_to_test_location "break here 1" $reattach
 
 	gdb_test "info function ^jit_function" "$match_str"
 
@@ -102,8 +143,8 @@ proc one_jit_test {count match_str} {
 	    gdb_test "maintenance info break"
 	}
 
-	gdb_breakpoint [gdb_get_line_number "break here 2"]
-	gdb_continue_to_breakpoint "break here 2"
+	continue_to_test_location "break here 2" $reattach
+
 	# All jit librares must have been unregistered
 	gdb_test "info function jit_function" \
 	    "All functions matching regular expression \"jit_function\":"
@@ -113,8 +154,22 @@ proc one_jit_test {count match_str} {
 if {[compile_jit_test jit.exp "" {}] < 0} {
     return
 }
-one_jit_test 1 "${hex}  jit_function_0000"
-one_jit_test 2 "${hex}  jit_function_0000\[\r\n\]+${hex}  jit_function_0001"
+one_jit_test 1 "${hex}  jit_function_0000" 0
+one_jit_test 2 "${hex}  jit_function_0000\[\r\n\]+${hex}  jit_function_0001" 0
+
+# Test attaching to an inferior with some JIT libraries already
+# registered.  We reuse the normal test, and detach/reattach at
+# specific interesting points.
+if {[can_spawn_for_attach]} {
+    if {[compile_jit_test "jit.exp attach tests" \
+	     "-attach" {additional_flags=-DATTACH=1}] < 0} {
+	return
+    }
+
+    with_test_prefix attach {
+	one_jit_test 2 "${hex}  jit_function_0000\[\r\n\]+${hex}  jit_function_0001" 1
+    }
+}
 
 with_test_prefix PIE {
     if {[compile_jit_test "jit.exp PIE tests" \
@@ -122,5 +177,5 @@ with_test_prefix PIE {
 	return
     }
 
-    one_jit_test 1 "${hex}  jit_function_0000"
+    one_jit_test 1 "${hex}  jit_function_0000" 0
 }



commit 2d35e871274a48331c4d6c7b3e4fbee42b901f33
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Thu Apr 7 22:18:49 2016 +0200

    testsuite: Fix false FAILs with .bashrc GDBHISTFILE=...
    
    $ GDBHISTFILE=/tmp/gdbhistfile runtest gdb.base/gdbhistsize-history.exp gdb.base/gdbinit-history.exp
    Running ./gdb.base/gdbinit-history.exp ...
    FAIL: gdb.base/gdbinit-history.exp: home=gdbinit-history/unlimited gdbhistsize=1000: show commands
    FAIL: gdb.base/gdbinit-history.exp: home=gdbinit-history/unlimited gdbhistsize=foo: show commands
    Running ./gdb.base/gdbhistsize-history.exp ...
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=20: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize= 20 : show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=-5: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=not_an_integer: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=10zab: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=-5ab: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=99999999999999999999999999999999999: show commands
    FAIL: gdb.base/gdbhistsize-history.exp: histsize=50: show commands
    
    This happens for my setup due to my:
    	$ grep GDB ~/.bashrc
    	export GDBHISTFILE="$HOME/.gdb_history"
    
    gdb/testsuite/ChangeLog
    2016-04-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* gdb.base/gdbhistsize-history.exp: Save and unset GDBHISTFILE and
    	GDBHISTSIZE prior to the tests.
    	* gdb.base/gdbinit-history.exp: Likewise.

### a/gdb/testsuite/ChangeLog
### b/gdb/testsuite/ChangeLog
## -1,4 +1,10 @@
-2015-04-07  Pedro Alves  <palves@redhat.com>
+2016-04-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* gdb.base/gdbhistsize-history.exp: Save and unset GDBHISTFILE and
+	GDBHISTSIZE prior to the tests.
+	* gdb.base/gdbinit-history.exp: Likewise.
+
+2016-04-07  Pedro Alves  <palves@redhat.com>
 
 	* gdb.compile/compile.exp: Use gdb_compile with "shlib=" option
 	instead of build_executable.  Use gdb_load_shlibs.
--- a/gdb/testsuite/gdb.base/gdbhistsize-history.exp
+++ b/gdb/testsuite/gdb.base/gdbhistsize-history.exp
@@ -32,7 +32,13 @@ if { [is_remote host] } {
 proc test_histsize_history_setting { histsize size { env_var "GDBHISTSIZE" } } {
     global env
 
-    save_vars { env($env_var) } {
+    save_vars { env(GDBHISTFILE) env(GDBHISTSIZE) env($env_var) } {
+	# These environment variables take precedence over whatever
+	# history size is set in .gdbinit.  Make sure the former is not
+	# set.
+	unset -nocomplain env(GDBHISTFILE)
+	unset -nocomplain env(GDBHISTSIZE)
+
 	set env($env_var) $histsize
 
 	with_test_prefix "histsize=$histsize" {
--- a/gdb/testsuite/gdb.base/gdbinit-history.exp
+++ b/gdb/testsuite/gdb.base/gdbinit-history.exp
@@ -36,12 +36,13 @@ proc test_gdbinit_history_setting { home size { gdbhistsize_val "-" } } {
     global srcdir
     global subdir
 
-    save_vars { INTERNAL_GDBFLAGS env(GDBHISTSIZE) env(HOME) } {
+    save_vars { INTERNAL_GDBFLAGS env(GDBHISTFILE) env(GDBHISTSIZE) env(HOME) } {
 	set env(HOME) "$srcdir/$subdir/$home"
 
-	# The GDBHISTSIZE environment variable takes precedence over whatever
+	# These environment variables take precedence over whatever
 	# history size is set in .gdbinit.  Make sure the former is not
 	# set.
+	unset -nocomplain env(GDBHISTFILE)
 	unset -nocomplain env(GDBHISTSIZE)
 
 	if { $gdbhistsize_val != "-" } {
@@ -77,10 +78,11 @@ proc test_no_truncation_of_unlimited_history_file { } {
     global env
     global INTERNAL_GDBFLAGS
 
-    save_vars { INTERNAL_GDBFLAGS env(GDBHISTSIZE) } {
-	# The GDBHISTSIZE environment variable takes precedence over whatever
+    save_vars { INTERNAL_GDBFLAGS env(GDBHISTFILE) env(GDBHISTSIZE) } {
+	# These environment variables take precedence over whatever
 	# history size is set in .gdbinit.  Make sure the former is not
 	# set.
+	unset -nocomplain env(GDBHISTFILE)
 	unset -nocomplain env(GDBHISTSIZE)
 
 	set temp_gdbinit [standard_output_file "gdbinit-history.gdbinit"]



commit 065005336492337c92d06e87544646635a5b9566
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Fri Apr 8 15:38:53 2016 +0200

    testsuite: Fix for gcc-4.8: gdb.base/jit.exp gdb.base/jit-so.exp
    
    on CentOS-7.2 I get
    
    Running /home/jkratoch/redhat/gdb-test-reg/gdb/testsuite/gdb.base/jit.exp ...
    FAIL: gdb.base/jit.exp: one_jit_test-1: continue to breakpoint: break here 2 (the program exited)
    FAIL: gdb.base/jit.exp: one_jit_test-2: continue to breakpoint: break here 2 (the program exited)
    FAIL: gdb.base/jit.exp: attach: one_jit_test-2: continue to breakpoint: break here 2 (the program exited)
    FAIL: gdb.base/jit.exp: attach: one_jit_test-2: break here 2: set var wait_for_gdb = 1
    FAIL: gdb.base/jit.exp: attach: one_jit_test-2: break here 2: detach (the program is no longer running)
    FAIL: gdb.base/jit.exp: attach: one_jit_test-2: break here 2: attach
    FAIL: gdb.base/jit.exp: attach: one_jit_test-2: break here 2: set var wait_for_gdb = 0
    FAIL: gdb.base/jit.exp: PIE: one_jit_test-1: continue to breakpoint: break here 2 (the program exited)
    Running /home/jkratoch/redhat/gdb-test-reg/gdb/testsuite/gdb.base/jit-so.exp ...
    FAIL: gdb.base/jit-so.exp: one_jit_test-1: continue to breakpoint: break here 2 (the program exited)
    FAIL: gdb.base/jit-so.exp: one_jit_test-2: continue to breakpoint: break here 2 (the program exited)
    
    since:
    
    85af34ee0211eedf8d30a5c44dfc59dddf8b512a is the first bad commit
    commit 85af34ee0211eedf8d30a5c44dfc59dddf8b512a
    Author: Pedro Alves <palves@redhat.com>
    Date:   Thu Mar 31 19:28:47 2016 +0100
        Add regression test for PR gdb/19858 (JIT code registration on attach)
    
    The compiled code's .debug_line is wrong (for the simplistic approach of GDB
    to put a breakpoint on the first address belonging to that source line) and so
    GDB misses the breakpoint at the last line:
              WAIT_FOR_GDB; return 0;  /* gdb break here 2  */
    
    Most of the patch is just about reindentation, no changes there.
    
    gdb/testsuite/ChangeLog
    2016-04-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	Fix compatibility with gcc-4.8.5-4.el7.x86_64.
    	* gdb.base/jit-main.c: Use exit after usage.

### a/gdb/testsuite/ChangeLog
### b/gdb/testsuite/ChangeLog
## -1,3 +1,8 @@
+2016-04-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix compatibility with gcc-4.8.5-4.el7.x86_64.
+	* gdb.base/jit-main.c: Use exit after usage.
+
 2016-04-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	* gdb.base/gdbhistsize-history.exp: Save and unset GDBHISTFILE and
--- a/gdb/testsuite/gdb.base/jit-main.c
+++ b/gdb/testsuite/gdb.base/jit-main.c
@@ -138,7 +138,8 @@ MAIN (int argc, char *argv[])
 {
   /* These variables are here so they can easily be set from jit.exp.  */
   const char *libname = NULL;
-  int count = 0;
+  int count = 0, i, fd;
+  struct stat st;
 
   alarm (300);
 
@@ -147,90 +148,89 @@ MAIN (int argc, char *argv[])
   count = count;  /* gdb break here 0  */
 
   if (argc < 2)
-    usage (argv[0]);
-  else
     {
-      int i, fd;
-      struct stat st;
+      usage (argv[0]);
+      exit (1);
+    }
 
-      if (libname == NULL)
-        /* Only set if not already set from GDB.  */
-        libname = argv[1];
+  if (libname == NULL)
+    /* Only set if not already set from GDB.  */
+    libname = argv[1];
 
-      if (argc > 2 && count == 0)
-        /* Only set if not already set from GDB.  */
-        count = atoi (argv[2]);
+  if (argc > 2 && count == 0)
+    /* Only set if not already set from GDB.  */
+    count = atoi (argv[2]);
 
-      printf ("%s:%d: libname = %s, count = %d\n", __FILE__, __LINE__,
-              libname, count);
+  printf ("%s:%d: libname = %s, count = %d\n", __FILE__, __LINE__,
+	  libname, count);
 
-      if ((fd = open (libname, O_RDONLY)) == -1)
-        {
-          fprintf (stderr, "open (\"%s\", O_RDONLY): %s\n", libname,
-                   strerror (errno));
-          exit (1);
-        }
+  if ((fd = open (libname, O_RDONLY)) == -1)
+    {
+      fprintf (stderr, "open (\"%s\", O_RDONLY): %s\n", libname,
+	       strerror (errno));
+      exit (1);
+    }
 
-      if (fstat (fd, &st) != 0)
-        {
-          fprintf (stderr, "fstat (\"%d\"): %s\n", fd, strerror (errno));
-          exit (1);
-        }
+  if (fstat (fd, &st) != 0)
+    {
+      fprintf (stderr, "fstat (\"%d\"): %s\n", fd, strerror (errno));
+      exit (1);
+    }
 
-      for (i = 0; i < count; ++i)
-        {
-          const void *const addr = mmap (0, st.st_size, PROT_READ|PROT_WRITE,
-                                         MAP_PRIVATE, fd, 0);
-          struct jit_code_entry *const entry = calloc (1, sizeof (*entry));
-
-          if (addr == MAP_FAILED)
-            {
-              fprintf (stderr, "mmap: %s\n", strerror (errno));
-              exit (1);
-            }
-
-          update_locations (addr, i);
-
-          /* Link entry at the end of the list.  */
-          entry->symfile_addr = (const char *)addr;
-          entry->symfile_size = st.st_size;
-          entry->prev_entry = __jit_debug_descriptor.relevant_entry;
-          __jit_debug_descriptor.relevant_entry = entry;
-
-          if (entry->prev_entry != NULL)
-            entry->prev_entry->next_entry = entry;
-          else
-            __jit_debug_descriptor.first_entry = entry;
-
-          /* Notify GDB.  */
-          __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
-          __jit_debug_register_code ();
-        }
+  for (i = 0; i < count; ++i)
+    {
+      const void *const addr = mmap (0, st.st_size, PROT_READ|PROT_WRITE,
+				     MAP_PRIVATE, fd, 0);
+      struct jit_code_entry *const entry = calloc (1, sizeof (*entry));
+
+      if (addr == MAP_FAILED)
+	{
+	  fprintf (stderr, "mmap: %s\n", strerror (errno));
+	  exit (1);
+	}
+
+      update_locations (addr, i);
+
+      /* Link entry at the end of the list.  */
+      entry->symfile_addr = (const char *)addr;
+      entry->symfile_size = st.st_size;
+      entry->prev_entry = __jit_debug_descriptor.relevant_entry;
+      __jit_debug_descriptor.relevant_entry = entry;
+
+      if (entry->prev_entry != NULL)
+	entry->prev_entry->next_entry = entry;
+      else
+	__jit_debug_descriptor.first_entry = entry;
+
+      /* Notify GDB.  */
+      __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+      __jit_debug_register_code ();
+    }
 
-      WAIT_FOR_GDB; i = 0;  /* gdb break here 1 */
+  WAIT_FOR_GDB; i = 0;  /* gdb break here 1 */
 
-      /* Now unregister them all in reverse order.  */
-      while (__jit_debug_descriptor.relevant_entry != NULL)
-        {
-          struct jit_code_entry *const entry =
-            __jit_debug_descriptor.relevant_entry;
-          struct jit_code_entry *const prev_entry = entry->prev_entry;
-
-          if (prev_entry != NULL)
-            {
-              prev_entry->next_entry = NULL;
-              entry->prev_entry = NULL;
-            }
-          else
-            __jit_debug_descriptor.first_entry = NULL;
-
-          /* Notify GDB.  */
-          __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
-          __jit_debug_register_code ();
-
-          __jit_debug_descriptor.relevant_entry = prev_entry;
-          free (entry);
-        }
+  /* Now unregister them all in reverse order.  */
+  while (__jit_debug_descriptor.relevant_entry != NULL)
+    {
+      struct jit_code_entry *const entry =
+	__jit_debug_descriptor.relevant_entry;
+      struct jit_code_entry *const prev_entry = entry->prev_entry;
+
+      if (prev_entry != NULL)
+	{
+	  prev_entry->next_entry = NULL;
+	  entry->prev_entry = NULL;
+	}
+      else
+	__jit_debug_descriptor.first_entry = NULL;
+
+      /* Notify GDB.  */
+      __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
+      __jit_debug_register_code ();
+
+      __jit_debug_descriptor.relevant_entry = prev_entry;
+      free (entry);
     }
+
   WAIT_FOR_GDB; return 0;  /* gdb break here 2  */
 }