This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/3] Add a test case for the jit-reader interface.


---
 gdb/testsuite/ChangeLog               |    8 ++
 gdb/testsuite/gdb.base/jit-reader.exp |   72 +++++++++++++++++
 gdb/testsuite/gdb.base/jithost.c      |   67 ++++++++++++++++
 gdb/testsuite/gdb.base/jithost.h      |    9 +++
 gdb/testsuite/gdb.base/jitreader.c    |  136 +++++++++++++++++++++++++++++++++
 5 files changed, 292 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/jit-reader.exp
 create mode 100644 gdb/testsuite/gdb.base/jithost.c
 create mode 100644 gdb/testsuite/gdb.base/jithost.h
 create mode 100644 gdb/testsuite/gdb.base/jitreader.c

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 4eb19bd..02f909e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2012-10-08  Sanjoy Das <sanjoy@playingwithpointers.com>
+
+	* gdb.base/jit-reader.exp: New file. Test case for the jit-reader
+	interface.
+	* gdb.base/jithost.c: Do.
+	* gdb.base/jithost.h: Do.
+	* gdb.base/jitreader.c : Do.
+
 2012-10-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	Fix crash during stepping on ppc32.
diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp
new file mode 100644
index 0000000..737d091
--- /dev/null
+++ b/gdb/testsuite/gdb.base/jit-reader.exp
@@ -0,0 +1,72 @@
+# Copyright 2011-2012 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/>.
+
+standard_testfile jithost.c
+
+if ![istarget x86_64-*-linux-gnu*] then {
+    untested jit-reader.exp
+    return -1;
+}
+
+if {[skip_shlib_tests]} {
+    untested jit-reader.exp
+    return -1
+}
+
+if {[get_compiler_info]} {
+    warning "Could not get compiler info"
+    untested jit-reader.exp
+    return 1
+}
+
+set jit_host_src ${srcfile}
+set jit_host_bin ${binfile}
+
+set include_dir ${objdir}/../../
+
+if  { [gdb_compile "${srcdir}/${subdir}/${jit_host_src}" "${jit_host_bin}" \
+       executable  [list debug incdir=${include_dir}]] != "" } {
+    untested jit-reader.exp
+    return -1
+}
+
+set jit_reader jitreader
+set jit_reader_src ${jit_reader}.c
+set jit_reader_bin [standard_output_file ${jit_reader}.so]
+
+if { [gdb_compile_shlib "${srcdir}/${subdir}/${jit_reader_src}" "${jit_reader_bin}" \
+	  [list debug incdir=${include_dir}]] != "" } {
+    untested jit-reader.exp
+    return -1
+}
+
+proc jit_reader_test {} {
+    global jit_host_bin
+    global jit_reader_bin
+    global verbose
+
+    clean_restart $jit_host_bin
+
+    if {$verbose > 0} {
+	gdb_run_cmd "set debug jit 1"
+    }
+
+    gdb_test_no_output "jit-reader-load ${jit_reader_bin}"
+    gdb_run_cmd "run"
+
+    gdb_test "bt" "jit_function_00.*"
+}
+
+jit_reader_test
diff --git a/gdb/testsuite/gdb.base/jithost.c b/gdb/testsuite/gdb.base/jithost.c
new file mode 100644
index 0000000..967245c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/jithost.c
@@ -0,0 +1,67 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include "gdb/jit-reader.h"
+#include "jithost.h"
+
+typedef enum
+{
+  JIT_NOACTION = 0,
+  JIT_REGISTER_FN,
+  JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry
+{
+  struct jit_code_entry *next_entry;
+  struct jit_code_entry *prev_entry;
+  void *symfile_addr;
+  uint64_t symfile_size;
+};
+
+struct jit_descriptor
+{
+  uint32_t version;
+  uint32_t action_flag;
+  struct jit_code_entry *relevant_entry;
+  struct jit_code_entry *first_entry;
+};
+
+void __attribute__((noinline)) __jit_debug_register_code () { }
+
+struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
+struct jit_code_entry only_entry;
+
+typedef void (jit_function_t)();
+
+int main(int argc, char **argv)
+{
+  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; // Generate a SIGTRAP
+  code[1] = 0xc3; // RET
+
+  struct jithost_abi *symfile = malloc(sizeof(struct jithost_abi));
+  symfile->begin = code;
+  symfile->end = code + 2;
+
+  only_entry.symfile_addr = symfile;
+  only_entry.symfile_size = sizeof(struct jithost_abi);
+
+  __jit_debug_descriptor.first_entry =
+    __jit_debug_descriptor.relevant_entry = &only_entry;
+  __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
+  __jit_debug_descriptor.version = 1;
+  __jit_debug_register_code();
+
+  function();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/jithost.h b/gdb/testsuite/gdb.base/jithost.h
new file mode 100644
index 0000000..37cf042
--- /dev/null
+++ b/gdb/testsuite/gdb.base/jithost.h
@@ -0,0 +1,9 @@
+#ifndef JITHOST_H
+#define JITHOST_H
+
+struct jithost_abi {
+  const char *begin;
+  const char *end;
+};
+
+#endif /* JITHOST_H */
diff --git a/gdb/testsuite/gdb.base/jitreader.c b/gdb/testsuite/gdb.base/jitreader.c
new file mode 100644
index 0000000..2438b0d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/jitreader.c
@@ -0,0 +1,136 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gdb/jit-reader.h"
+#include "jithost.h"
+
+GDB_DECLARE_GPL_COMPATIBLE_READER;
+
+enum RegisterMapping {
+    AMD64_RA = 16,
+    AMD64_RSP = 7,
+};
+
+struct reader_state {
+  uintptr_t code_begin;
+  uintptr_t code_end;
+};
+
+static enum gdb_status
+read_debug_info (struct gdb_reader_funcs* self,
+                 struct gdb_symbol_callbacks* cbs,
+                 void* memory, long memory_sz)
+{
+  struct jithost_abi *symfile = memory;
+  struct gdb_object* object = cbs->object_open (cbs);
+  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;
+
+  cbs->block_open (cbs, symtab, NULL, begin, end, "jit_function_00");
+
+  cbs->symtab_close (cbs, symtab);
+  cbs->object_close (cbs, object);
+  return GDB_SUCCESS;
+}
+
+static void
+free_reg_value(struct gdb_reg_value *value)
+{
+  free (value);
+}
+
+static void
+write_register (struct gdb_unwind_callbacks *callbacks, int dw_reg,
+                uintptr_t value)
+{
+  const int size = sizeof (uintptr_t);
+  struct gdb_reg_value *reg_val =
+    malloc (sizeof(struct gdb_reg_value) + size - 1);
+  reg_val->defined = 1;
+  reg_val->free = free_reg_value;
+
+  memcpy (reg_val->value, &value, size);
+  callbacks->reg_set (callbacks, dw_reg, reg_val);
+}
+
+static int
+read_register (struct gdb_unwind_callbacks *callbacks, int dw_reg, uintptr_t *value)
+{
+  const int size = sizeof (uintptr_t);
+  struct gdb_reg_value *reg_val = callbacks->reg_get (callbacks, dw_reg);
+  if (reg_val->size != size || !reg_val->defined)
+    {
+      reg_val->free (reg_val);
+      return 0;
+    }
+  memcpy (value, reg_val->value, size);
+  reg_val->free (reg_val);
+  return 1;
+}
+
+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;
+  struct reader_state *state = (struct reader_state *) self->priv_data;
+
+  if (!read_register (cbs, AMD64_RA, &this_ip))
+    return GDB_FAIL;
+
+  if (this_ip >= state->code_end || this_ip < state->code_begin)
+    return GDB_FAIL;
+
+  printf("Unwinding %p\n", (void *) this_ip);
+
+  if (!read_register (cbs, AMD64_RSP, &this_sp))
+    return GDB_FAIL;
+
+  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);
+  return GDB_SUCCESS;
+}
+
+struct gdb_frame_id
+get_frame_id (struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs)
+{
+  struct reader_state *state = (struct reader_state *) self->priv_data;
+  struct gdb_frame_id frame_id;
+
+  uintptr_t sp;
+  read_register (cbs, AMD64_RSP, &sp);
+
+  frame_id.code_address = (GDB_CORE_ADDR) state->code_begin;
+  frame_id.stack_address = (GDB_CORE_ADDR) sp;
+
+  return frame_id;
+}
+
+void
+destroy_reader(struct gdb_reader_funcs* self)
+{
+  free (self->priv_data);
+  free (self);
+}
+
+extern struct gdb_reader_funcs* gdb_init_reader(void) {
+  struct reader_state *state = malloc (sizeof (struct reader_state));
+  struct gdb_reader_funcs *reader_funcs =
+    malloc (sizeof (struct gdb_reader_funcs));
+
+  reader_funcs->reader_version = GDB_READER_INTERFACE_VERSION;
+  reader_funcs->priv_data = state;
+  reader_funcs->read = read_debug_info;
+  reader_funcs->unwind = unwind_frame;
+  reader_funcs->get_frame_id = get_frame_id;
+  reader_funcs->destroy = destroy_reader;
+
+  return reader_funcs;
+}
-- 
1.7.10.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]