Skip to content

Commit cd33a03

Browse files
author
Yao Qi
committed
Catch exceptions thrown from gdbarch_skip_prologue
PR 21555 is caused by the exception during the prologue analysis when re-set a breakpoint. (gdb) bt #0 memory_error_message (err=TARGET_XFER_E_IO, gdbarch=0x153db50, memaddr=93824992233232) at ../../binutils-gdb/gdb/corefile.c:192 #1 0x00000000005718ed in memory_error (err=TARGET_XFER_E_IO, memaddr=memaddr@entry=93824992233232) at ../../binutils-gdb/gdb/corefile.c:220 #2 0x00000000005719d6 in read_memory_object (object=object@entry=TARGET_OBJECT_CODE_MEMORY, memaddr=93824992233232, memaddr@entry=1, myaddr=myaddr@entry=0x7fffffffd0a0 "P\333S\001", len=len@entry=1) at ../../binutils-gdb/gdb/corefile.c:259 #3 0x0000000000571c6e in read_code (len=1, myaddr=0x7fffffffd0a0 "P\333S\001", memaddr=<optimized out>) at ../../binutils-gdb/gdb/corefile.c:287 #4 read_code_unsigned_integer (memaddr=memaddr@entry=93824992233232, len=len@entry=1, byte_order=byte_order@entry=BFD_ENDIAN_LITTLE) at ../../binutils-gdb/gdb/corefile.c:362 #5 0x000000000041d4a0 in amd64_analyze_prologue (gdbarch=gdbarch@entry=0x153db50, pc=pc@entry=93824992233232, current_pc=current_pc@entry=18446744073709551615, cache=cache@entry=0x7fffffffd1e0) at ../../binutils-gdb/gdb/amd64-tdep.c:2310 #6 0x000000000041e404 in amd64_skip_prologue (gdbarch=0x153db50, start_pc=93824992233232) at ../../binutils-gdb/gdb/amd64-tdep.c:2459 #7 0x000000000067bfb0 in skip_prologue_sal (sal=sal@entry=0x7fffffffd4e0) at ../../binutils-gdb/gdb/symtab.c:3628 #8 0x000000000067c4d8 in find_function_start_sal (sym=sym@entry=0x1549960, funfirstline=1) at ../../binutils-gdb/gdb/symtab.c:3501 #9 0x000000000060999d in symbol_to_sal (result=result@entry=0x7fffffffd5f0, funfirstline=<optimized out>, sym=sym@entry=0x1549960) at ../../binutils-gdb/gdb/linespec.c:3860 .... #16 0x000000000054b733 in location_to_sals (b=b@entry=0x15792d0, location=0x157c230, search_pspace=search_pspace@entry=0x1148120, found=found@entry=0x7fffffffdc64) at ../../binutils-gdb/gdb/breakpoint.c:14211 #17 0x000000000054c1f5 in breakpoint_re_set_default (b=0x15792d0) at ../../binutils-gdb/gdb/breakpoint.c:14301 #18 0x00000000005412a9 in breakpoint_re_set_one (bint=bint@entry=0x15792d0) at ../../binutils-gdb/gdb/breakpoint.c:14412 This problem can be fixed by - either each prologue analyzer doesn't throw exception, - or catch the exception thrown from gdbarch_skip_prologue, I choose the latter because the former needs to fix *every* prologue analyzer to not throw exception. This error can be reproduced by changing reread.exp. The test reread.exp has already test that breakpoint can be reset correctly after the executable is re-read. This patch extends this test by compiling test c file with and without -fPIE. (gdb) run ^M The program being debugged has been started already.^M Start it from the beginning? (y or n) y^M x86_64/gdb/testsuite/outputs/gdb.base/reread/reread' has changed; re-reading symbols. Error in re-setting breakpoint 1: Cannot access memory at address 0x555555554790^M Error in re-setting breakpoint 2: Cannot access memory at address 0x555555554790^M Starting program: /scratch/yao/gdb/build-git/x86_64/gdb/testsuite/outputs/gdb.base/reread/reread ^M This is foo^M [Inferior 1 (process 27720) exited normally]^M (gdb) FAIL: gdb.base/reread.exp: opts= "-fPIE" "ldflags=-pie" : run to foo() second time (the program exited) This patch doesn't re-indent the code, to keep the patch simple. gdb: 2017-07-25 Yao Qi <yao.qi@linaro.org> PR gdb/21555 * arch-utils.c (gdbarch_skip_prologue_noexcept): New function. * arch-utils.h (gdbarch_skip_prologue_noexcept): Declare. * infrun.c: Include arch-utils.h (handle_step_into_function): Call gdbarch_skip_prologue_noexcept. (handle_step_into_function_backward): Likewise. * symtab.c (skip_prologue_sal): Likewise. gdb/testsuite: 2017-07-25 Yao Qi <yao.qi@linaro.org> PR gdb/21555 * gdb.base/reread.exp: Wrap the whole test with two kinds of compilation flags, with -fPIE and without -fPIE.
1 parent 50e64da commit cd33a03

File tree

5 files changed

+154
-108
lines changed

5 files changed

+154
-108
lines changed

gdb/arch-utils.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,24 @@ default_guess_tracepoint_registers (struct gdbarch *gdbarch,
964964
regcache_raw_supply (regcache, pc_regno, regs);
965965
}
966966

967+
/* See arch-utils.h. */
968+
969+
CORE_ADDR
970+
gdbarch_skip_prologue_noexcept (gdbarch *gdbarch, CORE_ADDR pc) noexcept
971+
{
972+
CORE_ADDR new_pc = pc;
973+
974+
TRY
975+
{
976+
new_pc = gdbarch_skip_prologue (gdbarch, pc);
977+
}
978+
CATCH (ex, RETURN_MASK_ALL)
979+
{}
980+
END_CATCH
981+
982+
return new_pc;
983+
}
984+
967985
/* -Wmissing-prototypes */
968986
extern initialize_file_ftype _initialize_gdbarch_utils;
969987

gdb/arch-utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,10 @@ extern void default_guess_tracepoint_registers (struct gdbarch *gdbarch,
267267
struct regcache *regcache,
268268
CORE_ADDR addr);
269269

270+
/* Wrapper to gdbarch_skip_prologue, but doesn't throw exception. Catch
271+
exception thrown from gdbarch_skip_prologue, and return PC. */
272+
273+
extern CORE_ADDR gdbarch_skip_prologue_noexcept (gdbarch *gdbarch,
274+
CORE_ADDR pc) noexcept;
275+
270276
#endif

gdb/infrun.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "event-loop.h"
6565
#include "thread-fsm.h"
6666
#include "common/enum-flags.h"
67+
#include "arch-utils.h"
6768

6869
/* Prototypes for local functions */
6970

@@ -7314,8 +7315,8 @@ handle_step_into_function (struct gdbarch *gdbarch,
73147315

73157316
cust = find_pc_compunit_symtab (stop_pc);
73167317
if (cust != NULL && compunit_language (cust) != language_asm)
7317-
ecs->stop_func_start = gdbarch_skip_prologue (gdbarch,
7318-
ecs->stop_func_start);
7318+
ecs->stop_func_start
7319+
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
73197320

73207321
stop_func_sal = find_pc_line (ecs->stop_func_start, 0);
73217322
/* Use the step_resume_break to step until the end of the prologue,
@@ -7393,8 +7394,8 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
73937394

73947395
cust = find_pc_compunit_symtab (stop_pc);
73957396
if (cust != NULL && compunit_language (cust) != language_asm)
7396-
ecs->stop_func_start = gdbarch_skip_prologue (gdbarch,
7397-
ecs->stop_func_start);
7397+
ecs->stop_func_start
7398+
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
73987399

73997400
stop_func_sal = find_pc_line (stop_pc, 0);
74007401

gdb/symtab.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161

6262
#include "parser-defs.h"
6363
#include "completer.h"
64+
#include "arch-utils.h"
6465

6566
/* Forward declarations for local functions. */
6667

@@ -3626,7 +3627,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
36263627
if (gdbarch_skip_entrypoint_p (gdbarch))
36273628
pc = gdbarch_skip_entrypoint (gdbarch, pc);
36283629
if (skip)
3629-
pc = gdbarch_skip_prologue (gdbarch, pc);
3630+
pc = gdbarch_skip_prologue_noexcept (gdbarch, pc);
36303631

36313632
/* For overlays, map pc back into its mapped VMA range. */
36323633
pc = overlay_mapped_address (pc, section);

gdb/testsuite/gdb.base/reread.exp

Lines changed: 123 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -15,111 +15,131 @@
1515

1616
set prototypes 1
1717

18-
# build the first test case
18+
# Build programs in PIE mode, to reproduce PR 21555.
19+
foreach_with_prefix opts {
20+
{ "" "" }
21+
{ "-fPIE" "ldflags=-pie" } } {
1922

20-
set testfile1 "reread1"
21-
set srcfile1 ${testfile1}.c
22-
# Cygwin needs $EXEEXT.
23-
set binfile1 [standard_output_file ${testfile1}$EXEEXT]
24-
25-
if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executable {debug nowarnings}] != "" } {
26-
untested "failed to compile first testcase"
27-
return -1
28-
}
29-
30-
# build the second test case
31-
32-
set testfile2 "reread2"
33-
set srcfile2 ${testfile2}.c
34-
set binfile2 [standard_output_file ${testfile2}$EXEEXT]
35-
36-
if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug nowarnings}] != ""
37-
&& [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug nowarnings additional_flags=-DNO_SECTIONS}] != ""} {
38-
untested "failed to compile second testcase"
39-
return -1
40-
}
41-
42-
# Start with a fresh gdb.
43-
44-
set testfile "reread"
45-
set binfile [standard_output_file ${testfile}$EXEEXT]
46-
47-
gdb_start
48-
gdb_reinitialize_dir $srcdir/$subdir
49-
50-
# Load the first executable.
51-
52-
gdb_rename_execfile ${binfile1} ${binfile}
53-
gdb_load ${binfile}
54-
55-
# Set a breakpoint at foo
56-
57-
gdb_test "break foo" \
58-
"Breakpoint.*at.* file .*$srcfile1, line 14.*" \
59-
"breakpoint foo in first file"
60-
61-
62-
# Run, should see "Breakpoint 1, foo () at hello1.c:14"
63-
64-
gdb_run_cmd
65-
gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" "run to foo()"
66-
67-
# Restore first executable to its original name, and move
68-
# second executable into its place. Ensure that the new
69-
# executable is at least a second newer than the old.
70-
71-
gdb_rename_execfile ${binfile} ${binfile1}
72-
gdb_rename_execfile ${binfile2} ${binfile}
73-
gdb_test "shell sleep 1" ".*" ""
74-
gdb_touch_execfile ${binfile}
75-
76-
# Run a second time; GDB should detect that the executable has changed
77-
# and reset the breakpoints correctly.
78-
# Should see "Breakpoint 1, foo () at reread2.c:9"
79-
80-
set test "run to foo() second time"
81-
if [is_remote target] {
82-
unsupported $test
83-
} else {
84-
gdb_run_cmd
85-
gdb_test "" "Breakpoint.* foo .* at .*:9.*" $test
86-
}
87-
88-
89-
### Second pass: verify that GDB checks the executable file's
90-
### timestamp when the program is *restarted*, not just when it exits.
91-
92-
if [is_remote target] {
93-
unsupported "second pass: GDB should check for changes before running"
94-
} else {
95-
96-
# Put the older executable back in place.
97-
gdb_rename_execfile ${binfile} ${binfile2}
98-
gdb_rename_execfile ${binfile1} ${binfile}
99-
100-
# Restart GDB entirely.
101-
clean_restart ${binfile}
102-
103-
# Set a breakpoint on foo and run to it.
104-
gdb_test "break foo" \
105-
"Breakpoint.*at.* file .*$srcfile1, line 14.*" \
106-
"second pass: breakpoint foo in first file"
107-
gdb_run_cmd
108-
gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" "second pass: run to foo()"
109-
110-
# This time, let the program run to completion. If GDB checks the
111-
# executable file's timestamp now, it won't notice any change.
112-
gdb_continue_to_end "second pass"
113-
114-
# Now move the newer executable into place, and re-run. GDB
115-
# should still notice that the executable file has changed,
116-
# and still re-set the breakpoint appropriately.
117-
gdb_rename_execfile ${binfile} ${binfile1}
118-
gdb_rename_execfile ${binfile2} ${binfile}
119-
gdb_run_cmd
120-
gdb_test "" "Breakpoint.* foo .* at .*:9.*" "second pass: run to foo() second time"
121-
}
23+
# build the first test case
12224

25+
set testfile1 "reread1"
26+
set srcfile1 ${testfile1}.c
27+
# Cygwin needs $EXEEXT.
28+
set binfile1 [standard_output_file ${testfile1}$EXEEXT]
29+
30+
set testfile1_opt [list debug nowarnings \
31+
additional_flags=[lindex $opts 0] \
32+
[lindex $opts 1] ]
33+
if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" \
34+
executable ${testfile1_opt}] != "" } {
35+
untested "failed to compile first testcase"
36+
return -1
37+
}
38+
39+
# build the second test case
40+
41+
set testfile2 "reread2"
42+
set srcfile2 ${testfile2}.c
43+
set binfile2 [standard_output_file ${testfile2}$EXEEXT]
44+
45+
set testfile2_opt1 [list debug nowarnings \
46+
additional_flags=[lindex $opts 0] \
47+
[lindex $opts 1]]
48+
set testfile2_op2 [list debug nowarnings \
49+
"additional_flags=-DNO_SECTIONS [lindex $opts 0]" \
50+
[lindex $opts 1]]
51+
if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" \
52+
executable ${testfile2_opt1}] != ""
53+
&& [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" \
54+
executable ${testfile2_opt2}] != ""} {
55+
untested "failed to compile second testcase"
56+
return -1
57+
}
58+
59+
# Start with a fresh gdb.
60+
61+
set testfile "reread"
62+
set binfile [standard_output_file ${testfile}$EXEEXT]
63+
64+
gdb_start
65+
gdb_reinitialize_dir $srcdir/$subdir
66+
67+
# Load the first executable.
68+
69+
gdb_rename_execfile ${binfile1} ${binfile}
70+
gdb_load ${binfile}
71+
72+
# Set a breakpoint at foo
73+
74+
gdb_test "break foo" \
75+
"Breakpoint.*at.* file .*$srcfile1, line 14.*" \
76+
"breakpoint foo in first file"
77+
78+
79+
# Run, should see "Breakpoint 1, foo () at hello1.c:14"
80+
81+
gdb_run_cmd
82+
gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" "run to foo()"
83+
84+
# Restore first executable to its original name, and move
85+
# second executable into its place. Ensure that the new
86+
# executable is at least a second newer than the old.
87+
88+
gdb_rename_execfile ${binfile} ${binfile1}
89+
gdb_rename_execfile ${binfile2} ${binfile}
90+
gdb_test "shell sleep 1" ".*" ""
91+
gdb_touch_execfile ${binfile}
92+
93+
# Run a second time; GDB should detect that the executable has changed
94+
# and reset the breakpoints correctly.
95+
# Should see "Breakpoint 1, foo () at reread2.c:9"
96+
97+
set test "run to foo() second time"
98+
if [is_remote target] {
99+
unsupported $test
100+
} else {
101+
gdb_run_cmd
102+
gdb_test "" "Breakpoint.* foo .* at .*:9.*" $test
103+
}
104+
105+
106+
### Second pass: verify that GDB checks the executable file's
107+
### timestamp when the program is *restarted*, not just when it exits.
108+
109+
if [is_remote target] {
110+
unsupported "second pass: GDB should check for changes before running"
111+
} else {
112+
113+
# Put the older executable back in place.
114+
gdb_rename_execfile ${binfile} ${binfile2}
115+
gdb_rename_execfile ${binfile1} ${binfile}
116+
117+
# Restart GDB entirely.
118+
clean_restart ${binfile}
119+
120+
# Set a breakpoint on foo and run to it.
121+
gdb_test "break foo" \
122+
"Breakpoint.*at.* file .*$srcfile1, line 14.*" \
123+
"second pass: breakpoint foo in first file"
124+
gdb_run_cmd
125+
gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" \
126+
"second pass: run to foo()"
127+
128+
# This time, let the program run to completion. If GDB checks the
129+
# executable file's timestamp now, it won't notice any change.
130+
gdb_continue_to_end "second pass"
131+
132+
# Now move the newer executable into place, and re-run. GDB
133+
# should still notice that the executable file has changed,
134+
# and still re-set the breakpoint appropriately.
135+
gdb_rename_execfile ${binfile} ${binfile1}
136+
gdb_rename_execfile ${binfile2} ${binfile}
137+
gdb_run_cmd
138+
gdb_test "" "Breakpoint.* foo .* at .*:9.*" \
139+
"second pass: run to foo() second time"
140+
}
141+
142+
}
123143
# End of tests.
124144

125145
return 0

0 commit comments

Comments
 (0)