aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@redhat.com>2013-01-31 19:52:03 +0000
committerTom Tromey <tromey@redhat.com>2013-01-31 19:52:03 +0000
commitf25c01353c492b47dc6f230257822ed54d554c95 (patch)
tree5120c960969c654229bc8f684fadf15f68510b4a
parent974a734be3dfcbc121c40b227fcd12cf03874ecc (diff)
downloadgdb-f25c01353c492b47dc6f230257822ed54d554c95.zip
gdb-f25c01353c492b47dc6f230257822ed54d554c95.tar.gz
gdb-f25c01353c492b47dc6f230257822ed54d554c95.tar.bz2
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. gdb/testsuite * gdb.base/jit.exp (compile_jit_test): New proc. Add PIE tests.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/jit.c107
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.base/jit.exp60
4 files changed, 144 insertions, 39 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5482a52..cbcbf16 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/jit.c b/gdb/jit.c
index 62fe97b..a2a9b9e 100644
--- 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 =
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6366a13..99236cb 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/gdb.base/jit.exp b/gdb/testsuite/gdb.base/jit.exp
index b904b78..35840be 100644
--- a/gdb/testsuite/gdb.base/jit.exp
+++ b/gdb/testsuite/gdb.base/jit.exp
@@ -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"
+}