b/gdb/testsuite/gdb.arch/amd64-jit-reader.c
new file mode 100644
@@ -0,0 +1,117 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "jit-reader.h"
+
+GDB_DECLARE_GPL_COMPATIBLE_READER
+
+extern struct gdb_reader_funcs *gdb_init_reader (void);
+
+static enum gdb_status debug_info_provider (struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ void *memory, long memory_sz);
+static enum gdb_status frame_unwinder (struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb);
+static struct gdb_frame_id frame_id_provider(struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb);
+static void destructor (struct gdb_reader_funcs *self);
+
+#define DATA_COOKIE 0xdeaffead
+static int jit_data = DATA_COOKIE;
+
+static struct gdb_reader_funcs jit_reader_funcs =
+{
+ 1, /* version */
+ (void *)&jit_data,
+ debug_info_provider,
+ frame_unwinder,
+ frame_id_provider,
+ destructor
+};
+
+struct gdb_reader_funcs *
+gdb_init_reader (void)
+{
+ fprintf (stderr, "Test JIT reader loaded.\n");
+ return &jit_reader_funcs;
+}
+
+enum gdb_status
+debug_info_provider (struct gdb_reader_funcs *self,
+ struct gdb_symbol_callbacks *cb,
+ void *memory, long memory_sz)
+{
+ if (*(int *)(self->priv_data) != DATA_COOKIE)
+ return GDB_FAIL;
+ fprintf (stderr, "Debug info provider called for %p..%p.\n",
+ memory, (void *)(memory_sz + (char *)memory));
+ return GDB_SUCCESS;
+}
+
+void
+destructor (struct gdb_reader_funcs *self)
+{
+ fprintf (stderr, "Test JIT reader unloaded.\n");
+ return;
+}
+
+static GDB_CORE_ADDR
+_get_frame_register (struct gdb_unwind_callbacks *cb, int reg_no)
+{
+ struct gdb_reg_value *reg = cb->reg_get (cb, reg_no);
+ GDB_CORE_ADDR reg_value = *(GDB_CORE_ADDR *)reg->value;
+ reg->free (reg);
+ return reg_value;
+}
+
+static void
+_set_frame_register (struct gdb_unwind_callbacks *cb, int reg_no,
+ GDB_CORE_ADDR value)
+{
+ struct gdb_reg_value *reg = cb->reg_get (cb, reg_no);
+ *(GDB_CORE_ADDR *)(reg->value) = value;
+ reg->defined = 1;
+ (cb->reg_set)(cb, reg_no, reg);
+}
+
+#define REG_BP 6
+#define REG_PC 16
+#define REG_SP 7
+enum gdb_status
+frame_unwinder (struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb)
+{
+ GDB_CORE_ADDR bp = _get_frame_register (cb, REG_BP);
+ GDB_CORE_ADDR pc = _get_frame_register (cb, REG_PC);
+ GDB_CORE_ADDR sp = _get_frame_register (cb, REG_SP);
+ GDB_CORE_ADDR word;
+ cb->target_read(bp, &word, 8);
+ if (word != bp)
+ return GDB_FAIL;
+
+ /* We are at the frame that xxx-jit-unwind program altered for us.
+ We have:
+ BP-8 +--------------+
+ | Previous BP |
+ BP +--------------+
+ | BP (wrong!) |
+ BP+8 +--------------+
+ | Previous PC |
+ +--------------+
+ Save outer frame's BP, PC and SP. */
+ cb->target_read (bp - 8, &word, 8);
+ _set_frame_register (cb, REG_BP, word);
+ cb->target_read (bp + 8, &word, 8);
+ _set_frame_register (cb, REG_PC, word);
+ _set_frame_register (cb, REG_SP, bp + 16);
+ return GDB_SUCCESS;
+}
+
+struct gdb_frame_id frame_id_provider (struct gdb_reader_funcs *self,
+ struct gdb_unwind_callbacks *cb)
+{
+ struct gdb_frame_id frame_id =
+ { _get_frame_register (cb, REG_PC),
+ _get_frame_register (cb, REG_SP) };
+ fprintf (stderr, "frame_id_provider called.\n");
+ return frame_id;
+}
b/gdb/testsuite/gdb.arch/amd64-jit-reader.exp
new file mode 100644
@@ -0,0 +1,60 @@
+if {[skip_shlib_tests]} {
+ untested "Shared libraries are not supported"
+ return -1
+}
+
+if {[get_compiler_info]} {
+ return -1
+}
+
+if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+ verbose "Skipping amd64 JIT reader tests."
+ return
+}
+
+set testfile "amd64-jit-unwind"
+set srcfile ${testfile}.c
+set binfile [standard_output_file ${testfile}]
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}"
executable [list debug]] != "" } {
+ untested "could not compile test program"
+ return -1
+}
+
+set jit_reader "amd64-jit-reader"
+set jit_reader_source "${srcdir}/${subdir}/${jit_reader}.c"
+set jit_reader_binfile [standard_output_file ${jit_reader}.so]
+
+if { [gdb_compile_shlib ${jit_reader_source} ${jit_reader_binfile}
{additional_flags="-I.."}] != "" } {
+ untested "Cannot compile amd-jit-reader"
+ return -1
+}
+
+# Check that GDB is unable to show the backtrace for jit-unwind without
+# JIT reader.
+clean_restart $testfile
+if { ![runto_main] } {
+ fail "Can't run to main"
+ return
+}
+gdb_breakpoint [gdb_get_line_number "break backtrace-broken" ]
+gdb_continue_to_breakpoint "break backtrace-broken"
+gdb_test "where" "Backtrace stopped: frame did not save the .*"
+gdb_test "continue" "Continuing\..*$inferior_exited_re.*"
+
+# Check that GDB shows backtrace with JIT reader present
+# and that JIT reader can be unloaded.
+clean_restart $testfile
+if { ![runto_main] } {
+ fail "Can't run to main"
+ return
+}
+gdb_test "jit-reader-load ${jit_reader_binfile}" "Test JIT reader loaded."
+gdb_breakpoint [gdb_get_line_number "break backtrace-broken" ]
+gdb_continue_to_breakpoint "break backtrace-broken"
+gdb_test_sequence "where" "Bad backtrace" {
+ "\[\r\n\]+#0 .* break_unwind_chain \\(\\) at "
+ "\[\r\n\]+#1 .* break_unwind_chain_1 \\(\\) at "
+ "\[\r\n\]+#2 .* main \\(.*\\) at"
+}
+gdb_test "continue" "Continuing\..*$inferior_exited_re.*"
+gdb_test "jit-reader-unload" "Test JIT reader unloaded."
b/gdb/testsuite/gdb.arch/amd64-jit-unwind.c
new file mode 100644
@@ -0,0 +1,43 @@
+/* This test program is part of GDB, the GNU debugger.
+
+ Copyright 2011-2014 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 program is used to verify that a JIT handler can unwind custom
+ stack frames. */
+
+#include <stdint.h>
+#include <stdio.h>
+static void break_unwind_chain()
+{
+ /* Save outer frame address, then corrupt the frame chain by setting
+ the outer frame address in it to self. */
+ void *outer_fp = *(void **)__builtin_frame_address(0);
+ *(void **)__builtin_frame_address(0) = __builtin_frame_address(0);
+ /* Now restore it so that we can return. The test sets the
+ breakpoint just before this happens, and GDB will not be able to
+ show the backtrace without JIT reader. */
+ *(void **)__builtin_frame_address(0) = outer_fp; /* break backtrace-broken */
+}
+
+static void break_unwind_chain_1()
+{
+ break_unwind_chain();
+}
+
+int main(int argc, char *argv[])
+{
+ break_unwind_chain_1();
+}