PR gdb/13987:
authorTom Tromey <tromey@redhat.com>
Thu, 31 Jan 2013 19:52:03 +0000 (19:52 +0000)
committerTom Tromey <tromey@redhat.com>
Thu, 31 Jan 2013 19:52:03 +0000 (19:52 +0000)
* jit.c (struct jit_inferior_data) <cached_code_address,
jit_breakpoint>: New fields.
(jit_breakpoint_re_set_internal): Fix logging.  Only create
breakpoint if cached address has changed.
(jit_update_inferior_cache, jit_breakpoint_deleted): New
functions.
(_initialize_jit): Register breakpoint deleted observer.
gdb/testsuite
* gdb.base/jit.exp (compile_jit_test): New proc.
Add PIE tests.

gdb/ChangeLog
gdb/jit.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/jit.exp

index 5482a52..cbcbf16 100644 (file)
@@ -1,3 +1,14 @@
+2013-01-31  Tom Tromey  <tromey@redhat.com>
+
+       PR gdb/13987:
+       * jit.c (struct jit_inferior_data) <cached_code_address,
+       jit_breakpoint>: New fields.
+       (jit_breakpoint_re_set_internal): Fix logging.  Only create
+       breakpoint if cached address has changed.
+       (jit_update_inferior_cache, jit_breakpoint_deleted): New
+       functions.
+       (_initialize_jit): Register breakpoint deleted observer.
+
 2013-01-31  Aleksandar Ristovski  <aristovski@qnx.com>
 
        * infrun.c (handle_syscall_event): Remove unused gdbarch.
index 62fe97b..a2a9b9e 100644 (file)
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -243,9 +243,24 @@ struct jit_inferior_data
      symbols.  */
 
   struct objfile *objfile;
+
+  /* If this inferior has __jit_debug_register_code, this is the
+     cached address from the minimal symbol.  This is used to detect
+     relocations requiring the breakpoint to be re-created.  */
+
+  CORE_ADDR cached_code_address;
+
+  /* This is the JIT event breakpoint, or NULL if it has not been
+     set.  */
+
+  struct breakpoint *jit_breakpoint;
 };
 
-/* Per-objfile structure recording the addresses in the inferior.  */
+/* Per-objfile structure recording the addresses in the inferior.
+   This object serves two purposes: for ordinary objfiles, it may
+   cache some symbols related to the JIT interface; and for
+   JIT-created objfiles, it holds some information about the
+   jit_code_entry.  */
 
 struct jit_objfile_data
 {
@@ -255,7 +270,8 @@ struct jit_objfile_data
   /* Symbol for __jit_debug_descriptor.  */
   struct minimal_symbol *descriptor;
 
-  /* Address of struct jit_code_entry in this objfile.  */
+  /* Address of struct jit_code_entry in this objfile.  This is only
+     non-zero for objfiles that represent code created by the JIT.  */
   CORE_ADDR addr;
 };
 
@@ -968,6 +984,44 @@ jit_find_objf_with_entry_addr (CORE_ADDR entry_addr)
   return NULL;
 }
 
+/* A callback for iterate_over_inferiors that updates the inferior's
+   JIT breakpoint information, if necessary.  */
+
+static int
+jit_update_inferior_cache (struct inferior *inf, void *data)
+{
+  struct bp_location *loc = data;
+
+  if (inf->pspace == loc->pspace)
+    {
+      struct jit_inferior_data *inf_data;
+
+      inf_data = inferior_data (inf, jit_inferior_data);
+      if (inf_data != NULL && inf_data->jit_breakpoint == loc->owner)
+       {
+         inf_data->cached_code_address = 0;
+         inf_data->jit_breakpoint = NULL;
+       }
+    }
+
+  return 0;
+}
+
+/* This is called when a breakpoint is deleted.  It updates the
+   inferior's cache, if needed.  */
+
+static void
+jit_breakpoint_deleted (struct breakpoint *b)
+{
+  struct bp_location *iter;
+
+  if (b->type != bp_jit_event)
+    return;
+
+  for (iter = b->loc; iter != NULL; iter = iter->next)
+    iterate_over_inferiors (jit_update_inferior_cache, iter);
+}
+
 /* (Re-)Initialize the jit breakpoint if necessary.
    Return 0 on success.  */
 
@@ -978,36 +1032,47 @@ jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
   struct minimal_symbol *reg_symbol, *desc_symbol;
   struct objfile *objf;
   struct jit_objfile_data *objf_data;
+  CORE_ADDR addr;
 
-  if (inf_data->objfile != NULL)
-    return 0;
-
-  /* Lookup the registration symbol.  If it is missing, then we assume
-     we are not attached to a JIT.  */
-  reg_symbol = lookup_minimal_symbol_and_objfile (jit_break_name, &objf);
-  if (reg_symbol == NULL || SYMBOL_VALUE_ADDRESS (reg_symbol) == 0)
-    return 1;
+  if (inf_data->objfile == NULL)
+    {
+      /* Lookup the registration symbol.  If it is missing, then we
+        assume we are not attached to a JIT.  */
+      reg_symbol = lookup_minimal_symbol_and_objfile (jit_break_name, &objf);
+      if (reg_symbol == NULL || SYMBOL_VALUE_ADDRESS (reg_symbol) == 0)
+       return 1;
 
-  desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, objf);
-  if (desc_symbol == NULL || SYMBOL_VALUE_ADDRESS (desc_symbol) == 0)
-    return 1;
+      desc_symbol = lookup_minimal_symbol (jit_descriptor_name, NULL, objf);
+      if (desc_symbol == NULL || SYMBOL_VALUE_ADDRESS (desc_symbol) == 0)
+       return 1;
 
-  objf_data = get_jit_objfile_data (objf);
-  objf_data->register_code = reg_symbol;
-  objf_data->descriptor = desc_symbol;
+      objf_data = get_jit_objfile_data (objf);
+      objf_data->register_code = reg_symbol;
+      objf_data->descriptor = desc_symbol;
 
-  inf_data->objfile = objf;
+      inf_data->objfile = objf;
+    }
+  else
+    objf_data = get_jit_objfile_data (inf_data->objfile);
 
-  jit_inferior_init (gdbarch);
+  addr = SYMBOL_VALUE_ADDRESS (objf_data->register_code);
 
   if (jit_debug)
     fprintf_unfiltered (gdb_stdlog,
                        "jit_breakpoint_re_set_internal, "
                        "breakpoint_addr = %s\n",
-                       paddress (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol)));
+                       paddress (gdbarch, addr));
+
+  if (inf_data->cached_code_address == addr)
+    return 1;
+
+  /* Delete the old breakpoint.  */
+  if (inf_data->jit_breakpoint != NULL)
+    delete_breakpoint (inf_data->jit_breakpoint);
 
   /* Put a breakpoint in the registration symbol.  */
-  create_jit_event_breakpoint (gdbarch, SYMBOL_VALUE_ADDRESS (reg_symbol));
+  inf_data->cached_code_address = addr;
+  inf_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr);
 
   return 0;
 }
@@ -1419,6 +1484,8 @@ _initialize_jit (void)
                             &setdebuglist, &showdebuglist);
 
   observer_attach_inferior_exit (jit_inferior_exit_hook);
+  observer_attach_breakpoint_deleted (jit_breakpoint_deleted);
+
   jit_objfile_data =
     register_objfile_data_with_cleanup (NULL, free_objfile_data);
   jit_inferior_data =
index 6366a13..99236cb 100644 (file)
@@ -1,5 +1,10 @@
 2013-01-31  Tom Tromey  <tromey@redhat.com>
 
+       * gdb.base/jit.exp (compile_jit_test): New proc.
+       Add PIE tests.
+
+2013-01-31  Tom Tromey  <tromey@redhat.com>
+
        * gdb.dwarf2/method-ptr.cc: New file.
        * gdb.dwarf2/method-ptr.exp: New file.
 
index b904b78..35840be 100644 (file)
@@ -28,28 +28,38 @@ if {[get_compiler_info]} {
 # test running programs
 #
 
-set testfile jit-main
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}
-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
-    untested jit.exp
-    return -1
-}
+proc compile_jit_test {testname 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]
+    if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
+             executable [concat debug $options]] != "" } {
+       untested $testname
+       return -1
+    }
 
-set solib_testfile "jit-solib"
-set solib_srcfile "${srcdir}/${subdir}/${solib_testfile}.c"
-set solib_binfile "${objdir}/${subdir}/${solib_testfile}.so"
-set solib_binfile_test_msg "SHLIBDIR/${solib_testfile}.so"
+    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"
+
+    # Note: compiling without debug info: the library goes through
+    # symbol renaming by munging on its symbol table, and that
+    # wouldn't work for .debug sections.  Also, output for "info
+    # function" changes when debug info is present.
+    if { [gdb_compile_shlib ${solib_srcfile} ${solib_binfile} {-fPIC}] != "" } {
+       untested $testname
+       return -1
+    }
 
-# Note: compiling without debug info: the library goes through symbol
-# renaming by munging on its symbol table, and that wouldn't work for .debug
-# sections.  Also, output for "info function" changes when debug info is resent.
-if { [gdb_compile_shlib ${solib_srcfile} ${solib_binfile} {-fPIC}] != "" } {
-    untested jit.exp
-    return -1
-}
+    set solib_binfile_target [gdb_download ${solib_binfile}]
 
-set solib_binfile_target [gdb_download ${solib_binfile}]
+    return 0
+}
 
 proc one_jit_test {count match_str} { with_test_prefix "one_jit_test-$count" {
     global verbose testfile solib_binfile_target solib_binfile_test_msg
@@ -93,5 +103,17 @@ proc one_jit_test {count match_str} { with_test_prefix "one_jit_test-$count" {
        "All functions matching regular expression \"jit_function\":"
 }}
 
+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"
+
+with_test_prefix PIE {
+    if {[compile_jit_test "jit.exp PIE tests" \
+            {additional_flags=-fPIE ldflags=-pie}] < 0} {
+       return
+    }
+
+    one_jit_test 1 "${hex}  jit_function_0000"
+}