Skip to content
This repository was archived by the owner on Aug 17, 2022. It is now read-only.

Commit 4a55653

Browse files
committed
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 <[email protected]> * jit.c (free_objfile_data): Delete the JIT breakpoint and clear the cached code address. gdb/testsuite/ChangeLog: 2016-10-06 Pedro Alves <[email protected]> * 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.
1 parent 5a122fb commit 4a55653

File tree

7 files changed

+226
-43
lines changed

7 files changed

+226
-43
lines changed

gdb/ChangeLog

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2016-10-06 Pedro Alves <[email protected]>
2+
3+
* jit.c (free_objfile_data): Delete the JIT breakpoint and clear
4+
the cached code address.
5+
16
2016-10-06 Doug Evans <[email protected]>
27

38
* features/aarch64-core.xml (cpsr_flags): Elide "type" and specify

gdb/jit.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -1482,7 +1482,11 @@ free_objfile_data (struct objfile *objfile, void *data)
14821482
= ((struct jit_program_space_data *)
14831483
program_space_data (objfile->pspace, jit_program_space_data));
14841484
if (ps_data != NULL && ps_data->objfile == objfile)
1485-
ps_data->objfile = NULL;
1485+
{
1486+
ps_data->objfile = NULL;
1487+
delete_breakpoint (ps_data->jit_breakpoint);
1488+
ps_data->cached_code_address = 0;
1489+
}
14861490
}
14871491

14881492
xfree (data);

gdb/testsuite/ChangeLog

+15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
2016-10-06 Pedro Alves <[email protected]>
2+
3+
* gdb.base/jit-simple-dl.c: New file.
4+
* gdb.base/jit-simple-jit.c: New file, factored out from ...
5+
* gdb.base/jit-simple.c: ... this.
6+
* gdb.base/jit-simple.exp (jit_run): Delete.
7+
(build_jit): New proc.
8+
(jit_test_reread): Recompile either the main program or the shared
9+
library, depending on what is being tested. Skip changing address
10+
if caller wants to. Compare before/after addresses. If testing
11+
standalone, explicitly load the binary. Test "maint info
12+
breakpoints".
13+
(top level): Add "standalone vs shared lib" and "change address"
14+
vs "same address" axes.
15+
116
2016-10-06 Pedro Alves <[email protected]>
217

318
* gdb.base/jit-simple.exp (top level) Delete get_compiler_info
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* This testcase is part of GDB, the GNU debugger.
2+
3+
Copyright 2016 Free Software Foundation, Inc.
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
17+
18+
/* A stub program that links with a simple library that uses the JIT
19+
API. */
20+
21+
int
22+
main (void)
23+
{
24+
return 0;
25+
}
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* This testcase is part of GDB, the GNU debugger.
2+
3+
Copyright 2012-2016 Free Software Foundation, Inc.
4+
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
17+
18+
/* Simple library using the JIT API. */
19+
20+
#include <stdint.h>
21+
22+
struct jit_code_entry
23+
{
24+
struct jit_code_entry *next_entry;
25+
struct jit_code_entry *prev_entry;
26+
const char *symfile_addr;
27+
uint64_t symfile_size;
28+
};
29+
30+
struct jit_descriptor
31+
{
32+
uint32_t version;
33+
/* This type should be jit_actions_t, but we use uint32_t
34+
to be explicit about the bitwidth. */
35+
uint32_t action_flag;
36+
struct jit_code_entry *relevant_entry;
37+
struct jit_code_entry *first_entry;
38+
};
39+
40+
#ifdef SPACER
41+
/* This exists to change the address of __jit_debug_descriptor. */
42+
int spacer = 4;
43+
#endif
44+
45+
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
46+
47+
void
48+
__jit_debug_register_code (void)
49+
{
50+
}

gdb/testsuite/gdb.base/jit-simple.c

+16-27
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,26 @@
1-
/* Simple program using the JIT API. */
1+
/* This testcase is part of GDB, the GNU debugger.
22
3-
#include <stdint.h>
3+
Copyright 2016 Free Software Foundation, Inc.
44
5-
struct jit_code_entry
6-
{
7-
struct jit_code_entry *next_entry;
8-
struct jit_code_entry *prev_entry;
9-
const char *symfile_addr;
10-
uint64_t symfile_size;
11-
};
5+
This program is free software; you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation; either version 3 of the License, or
8+
(at your option) any later version.
129
13-
struct jit_descriptor
14-
{
15-
uint32_t version;
16-
/* This type should be jit_actions_t, but we use uint32_t
17-
to be explicit about the bitwidth. */
18-
uint32_t action_flag;
19-
struct jit_code_entry *relevant_entry;
20-
struct jit_code_entry *first_entry;
21-
};
10+
This program is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
2214
23-
#ifdef SPACER
24-
/* This exists to change the address of __jit_debug_descriptor. */
25-
int spacer = 4;
26-
#endif
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
2717

28-
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
18+
/* Simple standalone program using the JIT API. */
2919

30-
void __jit_debug_register_code()
31-
{
32-
}
20+
#include "jit-simple-jit.c"
3321

34-
int main()
22+
int
23+
main (void)
3524
{
3625
return 0;
3726
}

gdb/testsuite/gdb.base/jit-simple.exp

+110-15
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,99 @@
1313
# You should have received a copy of the GNU General Public License
1414
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1515

16+
# Test re-running an inferior with a JIT descriptor, where the JIT
17+
# descriptor changes address between runs.
18+
# http://sourceware.org/bugzilla/show_bug.cgi?id=13431
19+
20+
# Test both the case of the JIT reader being included in the main
21+
# program directly, and the case of the JIT reader being split out to
22+
# a shared library.
23+
24+
# For completeness, also test when the JIT descriptor does not change
25+
# address between runs.
26+
1627
if {[skip_shlib_tests]} {
1728
untested jit-simple.exp
1829
return -1
1930
}
2031

2132
standard_testfile
2233

23-
if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
34+
set libname $testfile-jit
35+
set srcfile_lib $srcdir/$subdir/$libname.c
36+
set binfile_lib [standard_output_file $libname.so]
37+
38+
# Build a standalone JIT binary.
39+
40+
proc build_standalone_jit {{options ""}} {
41+
global testfile srcfile binfile
42+
43+
lappend options "debug"
44+
45+
if {[build_executable $testfile.exp $testfile $srcfile $options] == -1} {
46+
return -1
47+
}
48+
49+
return 0
50+
}
51+
52+
# Build the shared library JIT.
53+
54+
proc build_shared_jit {{options ""}} {
55+
global testfile
56+
global srcfile_lib binfile_lib
57+
58+
lappend options "debug additional_flags=-fPIC"
59+
if { [gdb_compile_shlib $srcfile_lib $binfile_lib $options] != "" } {
60+
return -1
61+
}
62+
63+
return 0
64+
}
65+
66+
if {[build_standalone_jit] == -1} {
67+
untested "could not compile $binfile"
68+
return
69+
}
70+
71+
if {[build_shared_jit] == -1} {
72+
untested "could not compile $binfile_lib"
73+
return
74+
}
75+
76+
# Built the program that loads the JIT library.
77+
set srcfile_dl $testfile-dl.c
78+
set binfile_dl $binfile-dl
79+
set options [list debug shlib=${binfile_lib}]
80+
if {[gdb_compile ${srcdir}/${subdir}/${srcfile_dl} $binfile_dl executable \
81+
[list debug shlib=$binfile_lib]] == -1 } {
2482
untested jit-simple.exp
2583
return -1
2684
}
2785

28-
# Test re-running an inferior with a JIT descriptor, where the JIT
29-
# descriptor changes address between runs.
30-
# http://sourceware.org/bugzilla/show_bug.cgi?id=13431
31-
proc jit_test_reread {} {
32-
global testfile binfile subdir srcfile srcdir
86+
# STANDALONE is true when the JIT reader is included directly in the
87+
# main program. False when the JIT reader is in a separate shared
88+
# library. If CHANGE_ADDR is true, force changing the JIT descriptor
89+
# changes address between runs.
90+
proc jit_test_reread {standalone change_addr} {
91+
global testfile binfile subdir srcfile srcdir binfile_lib binfile_dl
3392
global hex
3493

3594
with_test_prefix "initial run" {
36-
clean_restart $testfile
95+
if {$standalone} {
96+
clean_restart $binfile
97+
} else {
98+
clean_restart $binfile_dl
99+
}
37100

38101
runto_main
39102

40103
set addr_before [get_hexadecimal_valueof "&__jit_debug_descriptor" 0 \
41104
"get address of __jit_debug_descriptor"]
105+
106+
gdb_test "maint info breakpoints" \
107+
"jit events keep y $hex <__jit_debug_register_code>.*" \
108+
"maint info breakpoints shows jit breakpoint"
42109
}
43110

44111
with_test_prefix "second run" {
@@ -47,21 +114,49 @@ proc jit_test_reread {} {
47114
# second, gdb might not reload the executable automatically.
48115
sleep 1
49116

50-
gdb_rename_execfile $binfile ${binfile}x
51-
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DSPACER}] != "" } {
52-
fail "recompile"
53-
return
54-
} else {
55-
pass "recompile"
117+
if ${change_addr} {
118+
set options "additional_flags=-DSPACER"
119+
if {$standalone} {
120+
gdb_rename_execfile $binfile ${binfile}x
121+
set res [build_standalone_jit $options]
122+
} else {
123+
gdb_rename_execfile $binfile_lib ${binfile_lib}x
124+
set res [build_shared_jit $options]
125+
}
126+
if { $res == -1 } {
127+
fail "recompile"
128+
return
129+
} else {
130+
pass "recompile"
131+
}
56132
}
57133

58134
runto_main
59135

60136
set addr_after [get_hexadecimal_valueof "&__jit_debug_descriptor" 0 \
61137
"get address of __jit_debug_descriptor"]
138+
139+
# This used to crash in the JIT-in-shared-library case:
140+
# https://sourceware.org/bugzilla/show_bug.cgi?id=11094
141+
gdb_test "maint info breakpoints" \
142+
"jit events keep y $hex <__jit_debug_register_code>.*" \
143+
"maint info breakpoints shows jit breakpoint"
62144
}
63145

64-
gdb_assert {$addr_before != $addr_after} "address changed"
146+
if ${change_addr} {
147+
gdb_assert {$addr_before != $addr_after} "address changed"
148+
} else {
149+
gdb_assert {$addr_before == $addr_after} "address didn't change"
150+
}
65151
}
66152

67-
jit_test_reread
153+
foreach standalone {1 0} {
154+
with_test_prefix [expr ($standalone)?"standalone":"shared"] {
155+
with_test_prefix "change addr" {
156+
jit_test_reread $standalone 1
157+
}
158+
with_test_prefix "same addr" {
159+
jit_test_reread $standalone 0
160+
}
161+
}
162+
}

0 commit comments

Comments
 (0)