Fix PR11094: JIT breakpoint is not properly recreated on reruns
authorPedro Alves <palves@redhat.com>
Thu, 6 Oct 2016 11:53:52 +0000 (12:53 +0100)
committerPedro Alves <palves@redhat.com>
Thu, 6 Oct 2016 11:53:52 +0000 (12:53 +0100)
commit4a556533cf0256613c412b9627fa8b8edfa7674a
treeec814e1184cf95e51c5051b7f8f0af0dc7a5e7a0
parent5a122fbc307f35093b8fe038a8e6caa51b4d0dae
Fix PR11094: JIT breakpoint is not properly recreated on reruns

Even though this was supposedly in the gdb 7.2 timeframe, the testcase
in PR11094 crashes current GDB with a segfault:

  Program received signal SIGSEGV, Segmentation fault.
  0x00000000005ee894 in event_location_to_string (location=0x0) at
  src/gdb/location.c:412
  412       if (EL_STRING (location) == NULL)
  (top-gdb) bt
  #0  0x00000000005ee894 in event_location_to_string (location=0x0) at
  src/gdb/location.c:412
  #1  0x000000000057411a in print_breakpoint_location (b=0x18288e0, loc=0x0) at
  src/gdb/breakpoint.c:6201
  #2  0x000000000057483f in print_one_breakpoint_location (b=0x18288e0,
  loc=0x182cf10, loc_number=0, last_loc=0x7fffffffd258, allflag=1)
      at src/gdb/breakpoint.c:6473
  #3  0x00000000005751e1 in print_one_breakpoint (b=0x18288e0,
  last_loc=0x7fffffffd258, allflag=1) at
  src/gdb/breakpoint.c:6707
  #4  0x000000000057589c in breakpoint_1 (args=0x0, allflag=1, filter=0x0) at
  src/gdb/breakpoint.c:6947
  #5  0x0000000000575aa8 in maintenance_info_breakpoints (args=0x0, from_tty=0)
  at src/gdb/breakpoint.c:7026
  [...]

This is GDB trying to print the location spec of the JIT event
breakpoint, but that's an internal breakpoint without one.

If I add a NULL check, then we see that the JIT breakpoint is now
pending (because its location has shlib_disabled set):

  (gdb) maint info breakpoints
  Num     Type           Disp Enb Address            What
  [...]
  -8      jit events     keep y   <PENDING>           inf 1
  [...]

But that's incorrect.  GDB should have managed to recreate the JIT
breakpoint's location for the second run.  So the problem is
elsewhere.

The problem is that if the JIT loads at the same address on the second
run, we never recreate the JIT breakpoint, because we hit this early
return:

  static int
  jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
  struct jit_program_space_data *ps_data)
  {
    [...]
    if (ps_data->cached_code_address == addr)
      return 0;

    [...]
      delete_breakpoint (ps_data->jit_breakpoint);
    [...]
    ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr);

Fix this by deleting the breakpoint and discarding the cached code
address when the objfile where the previous JIT breakpoint was found
is deleted/unloaded in the first place.

The test that was originally added for PR11094 doesn't trip on this
because:

  #1 - It doesn't test the case of the JIT descriptor's address _not_
       changing between reruns.

  #2 - And then it doesn't do "maint info breakpoints", or really
       anything with the JIT at all.

  #3 - and even then, to trigger the problem the JIT descriptor needs
       to be in a separate library, while the current test puts it in
       the main program.

The patch extends the test to cover all combinations of these
scenarios.

gdb/ChangeLog:
2016-10-06  Pedro Alves  <palves@redhat.com>

* jit.c (free_objfile_data): Delete the JIT breakpoint and clear
the cached code address.

gdb/testsuite/ChangeLog:
2016-10-06  Pedro Alves  <palves@redhat.com>

* gdb.base/jit-simple-dl.c: New file.
* gdb.base/jit-simple-jit.c: New file, factored out from ...
* gdb.base/jit-simple.c: ... this.
* gdb.base/jit-simple.exp (jit_run): Delete.
(build_jit): New proc.
(jit_test_reread): Recompile either the main program or the shared
library, depending on what is being tested.  Skip changing address
if caller wants to.  Compare before/after addresses.  If testing
standalone, explicitly load the binary.  Test "maint info
breakpoints".
(top level): Add "standalone vs shared lib" and "change address"
vs "same address" axes.
gdb/ChangeLog
gdb/jit.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/jit-simple-dl.c [new file with mode: 0644]
gdb/testsuite/gdb.base/jit-simple-jit.c [new file with mode: 0644]
gdb/testsuite/gdb.base/jit-simple.c
gdb/testsuite/gdb.base/jit-simple.exp
This page took 0.031891 seconds and 4 git commands to generate.