+2016-07-01  Pedro Alves  <palves@redhat.com>
+           Tom Tromey  <tom@tromey.com>
+
+       * jit.c (jit_reader_load_command): Call reinit_frame_cache and
+       jit_inferior_created_hook.
+       (jit_reader_unload_command): Call reinit_frame_cache and
+       jit_inferior_exit_hook.
+       * jit.c (struct jit_unwind_private) <registers>: Delete field.
+       <regcache>: New field.
+       (jit_unwind_reg_set_impl): Set the register's value in the
+       regcache.  Free the passed-in gdb_reg_value.
+       (jit_dealloc_cache): Adjust to free the regcache.
+       (jit_frame_sniffer): Allocate a regcache instead of an array of
+       gdb_reg_value pointers.
+       (jit_frame_this_id): Adjust.
+       (jit_frame_prev_register): Read raw registers off of the regcache
+       instead of from the gdb_reg_value pointer array.  Use
+       gdbarch_pseudo_register_read_value to read pseudo registers.
+       * regcache.c (regcache_raw_set_cached_value): New function,
+       factored out from ...
+       (regcache_raw_write): ... here.
+       * regcache.h (regcache_raw_set_cached_value): Declare.
+
 2016-07-01  Pedro Alves  <palves@redhat.com>
            Antoine Tremblay  <antoine.tremblay@ericsson.com>
 
 
 static const struct program_space_data *jit_program_space_data = NULL;
 
 static void jit_inferior_init (struct gdbarch *gdbarch);
+static void jit_inferior_exit_hook (struct inferior *inf);
 
 /* An unwinder is registered for every gdbarch.  This key is used to
    remember if the unwinder has been registered for a particular
   prev_cleanup = make_cleanup (xfree, so_name);
 
   loaded_jit_reader = jit_reader_load (so_name);
+  reinit_frame_cache ();
+  jit_inferior_created_hook ();
   do_cleanups (prev_cleanup);
 }
 
   if (!loaded_jit_reader)
     error (_("No JIT reader loaded."));
 
+  reinit_frame_cache ();
+  jit_inferior_exit_hook (current_inferior ());
   loaded_jit_reader->functions->destroy (loaded_jit_reader->functions);
 
   gdb_dlclose (loaded_jit_reader->handle);
 {
   /* Cached register values.  See jit_frame_sniffer to see how this
      works.  */
-  struct gdb_reg_value **registers;
+  struct regcache *regcache;
 
   /* The frame being unwound.  */
   struct frame_info *this_frame;
         fprintf_unfiltered (gdb_stdlog,
                             _("Could not recognize DWARF regnum %d"),
                             dwarf_regnum);
+      value->free (value);
       return;
     }
 
-  gdb_assert (priv->registers);
-  priv->registers[gdb_reg] = value;
+  regcache_raw_set_cached_value (priv->regcache, gdb_reg, value->value);
+  value->free (value);
 }
 
 static void
   struct gdbarch *frame_arch;
   int i;
 
-  gdb_assert (priv_data->registers);
+  gdb_assert (priv_data->regcache != NULL);
   frame_arch = get_frame_arch (priv_data->this_frame);
 
-  for (i = 0; i < gdbarch_num_regs (frame_arch); i++)
-    if (priv_data->registers[i] && priv_data->registers[i]->free)
-      priv_data->registers[i]->free (priv_data->registers[i]);
-
-  xfree (priv_data->registers);
+  regcache_xfree (priv_data->regcache);
   xfree (priv_data);
 }
 
   struct jit_unwind_private *priv_data;
   struct gdb_unwind_callbacks callbacks;
   struct gdb_reader_funcs *funcs;
+  struct address_space *aspace;
+  struct gdbarch *gdbarch;
 
   callbacks.reg_get = jit_unwind_reg_get_impl;
   callbacks.reg_set = jit_unwind_reg_set_impl;
 
   gdb_assert (!*cache);
 
+  aspace = get_frame_address_space (this_frame);
+  gdbarch = get_frame_arch (this_frame);
+
   *cache = XCNEW (struct jit_unwind_private);
   priv_data = (struct jit_unwind_private *) *cache;
-  priv_data->registers =
-    XCNEWVEC (struct gdb_reg_value *,        
-             gdbarch_num_regs (get_frame_arch (this_frame)));
+  priv_data->regcache = regcache_xmalloc (gdbarch, aspace);
   priv_data->this_frame = this_frame;
 
   callbacks.priv_data = priv_data;
   struct gdb_reader_funcs *funcs;
   struct gdb_unwind_callbacks callbacks;
 
-  priv.registers = NULL;
+  priv.regcache = NULL;
   priv.this_frame = this_frame;
 
   /* We don't expect the frame_id function to set any registers, so we
 jit_frame_prev_register (struct frame_info *this_frame, void **cache, int reg)
 {
   struct jit_unwind_private *priv = (struct jit_unwind_private *) *cache;
-  struct gdb_reg_value *value;
+  struct gdbarch *gdbarch;
 
   if (priv == NULL)
     return frame_unwind_got_optimized (this_frame, reg);
 
-  gdb_assert (priv->registers);
-  value = priv->registers[reg];
-  if (value && value->defined)
-    return frame_unwind_got_bytes (this_frame, reg, value->value);
+  gdbarch = get_regcache_arch (priv->regcache);
+  if (reg < gdbarch_num_regs (gdbarch))
+    {
+      gdb_byte *buf = (gdb_byte *) alloca (register_size (gdbarch, reg));
+      enum register_status status;
+
+      status = regcache_raw_read (priv->regcache, reg, buf);
+      if (status == REG_VALID)
+       return frame_unwind_got_bytes (this_frame, reg, buf);
+      else
+       return frame_unwind_got_optimized (this_frame, reg);
+    }
   else
-    return frame_unwind_got_optimized (this_frame, reg);
+    return gdbarch_pseudo_register_read_value (gdbarch, priv->regcache, reg);
 }
 
 /* Relay everything back to the unwinder registered by the JIT debug
 
   regcache_cooked_write (regcache, regnum, buf);
 }
 
+/* See regcache.h.  */
+
+void
+regcache_raw_set_cached_value (struct regcache *regcache, int regnum,
+                              const gdb_byte *buf)
+{
+  memcpy (register_buffer (regcache, regnum), buf,
+         regcache->descr->sizeof_register[regnum]);
+  regcache->register_status[regnum] = REG_VALID;
+}
+
 void
 regcache_raw_write (struct regcache *regcache, int regnum,
                    const gdb_byte *buf)
   inferior_ptid = regcache->ptid;
 
   target_prepare_to_store (regcache);
-  memcpy (register_buffer (regcache, regnum), buf,
-         regcache->descr->sizeof_register[regnum]);
-  regcache->register_status[regnum] = REG_VALID;
+  regcache_raw_set_cached_value (regcache, regnum, buf);
 
   /* Register a cleanup function for invalidating the register after it is
      written, in case of a failure.  */
 
 extern void regcache_raw_write_unsigned (struct regcache *regcache,
                                         int regnum, ULONGEST val);
 
+/* Set a raw register's value in the regcache's buffer.  Unlike
+   regcache_raw_write, this is not write-through.  The intention is
+   allowing to change the buffer contents of a read-only regcache
+   allocated with regcache_xmalloc.  */
+
+extern void regcache_raw_set_cached_value
+  (struct regcache *regcache, int regnum, const gdb_byte *buf);
+
 /* Partial transfer of raw registers.  These perform read, modify,
    write style operations.  The read variant returns the status of the
    register.  */
 
+2016-07-01  Pedro Alves  <palves@redhat.com>
+
+       * gdb.base/jit-reader.exp (info_registers_current_frame): New
+       procedure.
+       (jit_reader_test): Test the jit reader's unwinder.
+       * gdb.base/jithost.c (jit_function_00_code): New global.
+       (main): Use memcpy to fill in the mmapped code, instead of poking
+       bytes manually here.
+       * gdb.base/jitreader.c (enum register_mapping) <AMD64_RBP>: New
+       value.
+       (read_debug_info): Save the function's range.
+       (read_sp): New function.
+       (unwind_frame): Use it.  Also unwind RBP.
+       (get_frame_id): Use read_sp.
+       (gdb_init_reader): Use calloc instead of malloc.
+       * lib/gdb.exp (get_hexadecimal_valueof): Add optional 'test'
+       parameter.  Use gdb_test_multiple.
+
 2016-07-01  Pedro Alves  <palves@redhat.com>
            Antoine Tremblay  <antoine.tremblay@ericsson.com>
 
 
     return -1
 }
 
+# Test "info registers" in the current frame, expecting RSP's value to
+# be SP.
+
+proc info_registers_current_frame {sp} {
+    global hex decimal
+
+    set any "\[^\r\n\]*"
+
+    gdb_test "info registers" \
+       [multi_line \
+            "rax            $hex       $decimal" \
+            "rbx            $hex       $decimal" \
+            "rcx            $hex       $decimal" \
+            "rdx            $hex       $decimal" \
+            "rsi            $hex       $decimal" \
+            "rdi            $hex       $decimal" \
+            "rbp            $hex       $hex" \
+            "rsp            $sp        $sp" \
+            "r8             $hex       $decimal" \
+            "r9             $hex       $decimal" \
+            "r10            $hex       $decimal" \
+            "r11            $hex       $decimal" \
+            "r12            $hex       $decimal" \
+            "r13            $hex       $decimal" \
+            "r14            $hex       $decimal" \
+            "r15            $hex       $decimal" \
+            "rip            $hex       $hex$any" \
+            "eflags         $hex       \\\[$any\\\]" \
+            "cs             $hex       $decimal" \
+            "ss             $hex       $decimal" \
+            "ds             $hex       $decimal" \
+            "es             $hex       $decimal" \
+            "fs             $hex       $decimal" \
+            "gs             $hex       $decimal" \
+           ]
+}
+
 proc jit_reader_test {} {
     global jit_host_bin
     global jit_reader_bin
     global verbose
+    global hex decimal
+
+    set any "\[^\r\n\]*"
 
     clean_restart $jit_host_bin
     gdb_load_shlib $jit_reader_bin
     gdb_run_cmd
     gdb_test "" "Program received signal SIGTRAP, .*" "expect SIGTRAP"
 
-    gdb_test "bt" "jit_function_00.*"
+    # Test the JIT reader unwinder.
+    with_test_prefix "with jit-reader" {
+
+       with_test_prefix "before mangling" {
+           gdb_test "bt" \
+               [multi_line \
+                    "#0 ${any} in jit_function_00 ${any}" \
+                    "#1 ${any} in main ${any}" \
+                   ] \
+               "bt works"
+
+           set sp_before_mangling \
+               [get_hexadecimal_valueof "\$sp" 0 "get sp"]
+
+           gdb_test "up" "#1  $any in main $any\r\n$any  function $any" \
+               "move up to caller"
+
+           set caller_sp \
+               [get_hexadecimal_valueof "\$sp" 0 "get caller sp"]
+       }
+
+       # Step over the instruction that mangles the stack pointer.
+       # While that confuses GDB's built-in unwinder, the JIT
+       # reader's unwinder understands the mangling and should thus
+       # be able to unwind at that location.
+       with_test_prefix "after mangling" {
+           gdb_test "si" "in jit_function_00 .*" "step over stack mangling"
+
+           set sp_after_mangling \
+               [get_hexadecimal_valueof "\$sp" 0 "get sp"]
+
+           gdb_assert {$sp_before_mangling != $sp_after_mangling} \
+               "sp is mangled"
+
+           # Check that the jit unwinder manages to backtrace through
+           # the mangled stack pointer.
+           gdb_test "bt" \
+               [multi_line \
+                    "#0 ${any} in jit_function_00 ${any}" \
+                    "#1 ${any} in main ${any}" \
+                   ] \
+               "bt works"
+
+           with_test_prefix "current frame" {
+               info_registers_current_frame $sp_after_mangling
+
+               gdb_test "info frame" \
+                   "Stack level 0, frame at $sp_before_mangling.*in jit_function_00.*"
+           }
+
+           with_test_prefix "caller frame" {
+               gdb_test "up" "#1  $any in main $any\r\n$any  function $any" \
+                   "up to caller"
+
+               # Since the JIT unwinder only provides RIP/RSP/RBP,
+               # all other registers should show as "<not saved>".
+               gdb_test "info registers" \
+                   [multi_line \
+                        "rax            <not saved>" \
+                        "rbx            <not saved>" \
+                        "rcx            <not saved>" \
+                        "rdx            <not saved>" \
+                        "rsi            <not saved>" \
+                        "rdi            <not saved>" \
+                        "rbp            $hex   $hex" \
+                        "rsp            $caller_sp     $caller_sp" \
+                        "r8             <not saved>" \
+                        "r9             <not saved>" \
+                        "r10            <not saved>" \
+                        "r11            <not saved>" \
+                        "r12            <not saved>" \
+                        "r13            <not saved>" \
+                        "r14            <not saved>" \
+                        "r15            <not saved>" \
+                        "rip            $hex   $hex $any" \
+                        "eflags         <not saved>" \
+                        "cs             <not saved>" \
+                        "ss             <not saved>" \
+                        "ds             <not saved>" \
+                        "es             <not saved>" \
+                        "fs             <not saved>" \
+                        "gs             <not saved>" \
+                       ]
+
+               # Make sure that "info frame" doesn't crash.
+               gdb_test "info frame" "Stack level 1, .*in main.*"
+
+               # ... and that neither does printing a pseudo
+               # register.
+               gdb_test "print /x \$ebp" " = $hex" "print pseudo register"
+
+               # There's no way for the JIT reader API to support
+               # modifyiable values.
+               gdb_test "print \$rbp = -1" \
+                   "Attempt to assign to an unmodifiable value\." \
+                   "cannot assign to register"
+           }
+       }
+    }
+
+    # Now unload the jit reader, and ensure that backtracing really
+    # doesn't work without it.
+    with_test_prefix "without jit-reader" {
+       gdb_test_no_output "jit-reader-unload ${jit_reader_bin}" \
+           "jit-reader-unload"
+
+       # Check that we're no longer using the JIT unwinder, and that
+       # the built-in unwinder cannot backtrace through the mangled
+       # stack pointer.
+       gdb_test "bt" \
+           [multi_line \
+                "Backtrace stopped: Cannot access memory at address $sp_after_mangling" \
+               ] \
+           "bt shows error"
+
+       gdb_test "info frame" "Cannot access memory at address.*" \
+           "info frame shows error"
+       info_registers_current_frame $sp_after_mangling
+       gdb_test "up" "Initial frame selected; you cannot go up\\." \
+           "cannot go up"
+    }
+
+    with_test_prefix "with jit-reader again" {
+       gdb_test_no_output "jit-reader-load ${jit_reader_bin}" "jit-reader-load"
+
+       # Check that the jit unwinder manages to backtrace through
+       # the mangled stack pointer.
+       gdb_test "bt" \
+           [multi_line \
+                "#0 ${any} in jit_function_00 ${any}" \
+                "#1 ${any} in main ${any}" \
+               ]
+    }
 }
 
 jit_reader_test
 
 
 typedef void (jit_function_t) ();
 
-int main (int argc, char **argv)
+/* The code of the jit_function_00 function that is copied into an
+   mmapped buffer in the inferior at run time.
+
+   The second instruction mangles the stack pointer, meaning that when
+   stopped at the third instruction, GDB needs assistance from the JIT
+   unwinder in order to be able to unwind successfully.  */
+const unsigned char jit_function_00_code[] = {
+  0xcc,                                /* int3 */
+  0x48, 0x83, 0xf4, 0xff,      /* xor $0xffffffffffffffff, %rsp */
+  0x48, 0x83, 0xf4, 0xff,      /* xor $0xffffffffffffffff, %rsp */
+  0xc3                         /* ret */
+};
+
+int
+main (int argc, char **argv)
 {
+  struct jithost_abi *symfile;
   char *code = mmap (NULL, getpagesize (), PROT_WRITE | PROT_EXEC,
                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   jit_function_t *function = (jit_function_t *) code;
 
-  code[0] = 0xcc; /* SIGTRAP  */
-  code[1] = 0xc3; /* RET  */
+  memcpy (code, jit_function_00_code, sizeof (jit_function_00_code));
 
-  struct jithost_abi *symfile = malloc (sizeof (struct jithost_abi));
+  symfile = malloc (sizeof (struct jithost_abi));
   symfile->begin = code;
-  symfile->end = code + 2;
+  symfile->end = code + sizeof (jit_function_00_code);
 
   only_entry.symfile_addr = symfile;
   only_entry.symfile_size = sizeof (struct jithost_abi);
 
 enum register_mapping
 {
   AMD64_RA = 16,
+  AMD64_RBP = 6,
   AMD64_RSP = 7,
 };
 
   struct gdb_symtab *symtab = cbs->symtab_open (cbs, object, "");
   GDB_CORE_ADDR begin = (GDB_CORE_ADDR) symfile->begin;
   GDB_CORE_ADDR end = (GDB_CORE_ADDR) symfile->end;
+  struct reader_state *state = (struct reader_state *) self->priv_data;
+
+  /* Record the function's range, for the unwinder.  */
+  state->code_begin = begin;
+  state->code_end = end;
 
   cbs->block_open (cbs, symtab, NULL, begin, end, "jit_function_00");
 
   return 1;
 }
 
+/* Read the stack pointer into *VALUE.  IP is the address the inferior
+   is currently stopped at.  Takes care of demangling the stack
+   pointer if necessary.  */
+
+static int
+read_sp (struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cbs,
+        uintptr_t ip, uintptr_t *value)
+{
+  struct reader_state *state = (struct reader_state *) self->priv_data;
+  uintptr_t sp;
+
+  if (!read_register (cbs, AMD64_RSP, &sp))
+    return GDB_FAIL;
+
+  /* If stopped at the instruction after the "xor $-1, %rsp", demangle
+     the stack pointer back.  */
+  if (ip == state->code_begin + 5)
+    sp ^= (uintptr_t) -1;
+
+  *value = sp;
+  return GDB_SUCCESS;
+}
+
 static enum gdb_status
 unwind_frame (struct gdb_reader_funcs *self, struct gdb_unwind_callbacks *cbs)
 {
   const int word_size = sizeof (uintptr_t);
-  uintptr_t this_sp, this_ip, prev_ip, prev_sp;
+  uintptr_t prev_sp, this_sp;
+  uintptr_t prev_ip, this_ip;
+  uintptr_t prev_bp, this_bp;
   struct reader_state *state = (struct reader_state *) self->priv_data;
 
   if (!read_register (cbs, AMD64_RA, &this_ip))
   if (this_ip >= state->code_end || this_ip < state->code_begin)
     return GDB_FAIL;
 
-  if (!read_register (cbs, AMD64_RSP, &this_sp))
+  /* Unwind RBP in order to make the unwinder that tries to unwind
+     from the just-unwound frame happy.  */
+  if (!read_register (cbs, AMD64_RBP, &this_bp))
     return GDB_FAIL;
+  /* RBP is unmodified.  */
+  prev_bp = this_bp;
 
-  if (cbs->target_read (this_sp, &prev_ip, word_size) == GDB_FAIL)
+  /* Fetch the demangled stack pointer.  */
+  if (!read_sp (self, cbs, this_ip, &this_sp))
     return GDB_FAIL;
 
+  /* The return address is saved on the stack.  */
+  if (cbs->target_read (this_sp, &prev_ip, word_size) == GDB_FAIL)
+    return GDB_FAIL;
   prev_sp = this_sp + word_size;
+
   write_register (cbs, AMD64_RA, prev_ip);
   write_register (cbs, AMD64_RSP, prev_sp);
+  write_register (cbs, AMD64_RBP, prev_bp);
   return GDB_SUCCESS;
 }
 
 {
   struct reader_state *state = (struct reader_state *) self->priv_data;
   struct gdb_frame_id frame_id;
-
+  uintptr_t ip;
   uintptr_t sp;
-  read_register (cbs, AMD64_RSP, &sp);
+
+  read_register (cbs, AMD64_RA, &ip);
+  read_sp (self, cbs, ip, &sp);
 
   frame_id.code_address = (GDB_CORE_ADDR) state->code_begin;
   frame_id.stack_address = (GDB_CORE_ADDR) sp;
 struct gdb_reader_funcs *
 gdb_init_reader (void)
 {
-  struct reader_state *state = malloc (sizeof (struct reader_state));
+  struct reader_state *state = calloc (1, sizeof (struct reader_state));
   struct gdb_reader_funcs *reader_funcs =
     malloc (sizeof (struct gdb_reader_funcs));
 
 
     return ${val}
 }
 
-proc get_hexadecimal_valueof { exp default } {
+# Retrieve the value of EXP in the inferior, as an hexadecimal value
+# (using "print /x").  DEFAULT is used as fallback if print fails.
+# TEST is the test message to use.  If can be ommitted, in which case
+# a test message is built from EXP.
+
+proc get_hexadecimal_valueof { exp default {test ""} } {
     global gdb_prompt
-    send_gdb "print /x ${exp}\n"
-    set test "get hexadecimal valueof \"${exp}\""
-    gdb_expect {
+
+    if {$test == ""} {
+       set test "get hexadecimal valueof \"${exp}\""
+    }
+
+    set val ${default}
+    gdb_test_multiple "print /x ${exp}" $test {
        -re "\\$\[0-9\]* = (0x\[0-9a-zA-Z\]+).*$gdb_prompt $" {
            set val $expect_out(1,string)
            pass "$test"
        }
-       timeout {
-           set val ${default}
-           fail "$test (timeout)"
-       }
     }
     return ${val}
 }