From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 100532 invoked by alias); 25 Jul 2017 10:38:30 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 99872 invoked by uid 89); 25 Jul 2017 10:38:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=re-run, Wrap, 9856 X-HELO: mail-it0-f47.google.com Received: from mail-it0-f47.google.com (HELO mail-it0-f47.google.com) (209.85.214.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 25 Jul 2017 10:38:26 +0000 Received: by mail-it0-f47.google.com with SMTP id v127so10183229itd.0 for ; Tue, 25 Jul 2017 03:38:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-transfer-encoding; bh=W8reshY20wp2Vv7FJsJMuVKYUnoC50zvN2Nf+Ob7bWs=; b=XOvPC6wQ2NL00ObxIDDp8SghOYYGGZtlaCq4BhjRttL3gOy1W6PFYGTjhK8AIHWLQW GC1rMUimTWLWMNnh0vfVYb2ZFUtxLh5f4WqYHAsHyTyU/l2BpQrzsGYKQFs175LnbyFI sis6f2IhsoCPq3G1fpAHwlq5jzvuaE0tQgqpIGgWx0knPO/G81JIQa5SfwAnOxnFVDrs P/ea7PKTiCCvq6+hZmEmEGPHk/fnR0LnKRSNEoHsLIRxL5VwZKNqHS4bsb9vcuaoaP+w I5mb4MIiokuwvCcVJse6faDbJEeINTxBSFD4M/dng3Cx0ElGKrYdfvSJGiFIhPWHhaIY v3hw== X-Gm-Message-State: AIVw113dJssVTgNHbjQPOxus+pDj5xt0p0yikRJlbHdfpygbQ5+NHbKR jHF8TAMzDZ7qq72S X-Received: by 10.36.118.194 with SMTP id z185mr9888403itb.66.1500979104844; Tue, 25 Jul 2017 03:38:24 -0700 (PDT) Received: from E107787-LIN (static.42.136.251.148.clients.your-server.de. [148.251.136.42]) by smtp.gmail.com with ESMTPSA id b83sm4770821iod.35.2017.07.25.03.38.23 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Tue, 25 Jul 2017 03:38:24 -0700 (PDT) From: Yao Qi To: Simon Marchi Cc: gdb-patches@sourceware.org Subject: Re: [PATCH 1/2] Catch exceptions thrown from gdbarch_skip_prologue References: <1500463680-1483-1-git-send-email-yao.qi@linaro.org> Date: Tue, 25 Jul 2017 10:38:00 -0000 In-Reply-To: (Simon Marchi's message of "Fri, 21 Jul 2017 23:57:17 +0200") Message-ID: <86wp6wpzs2.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2017-07/txt/msg00363.txt.bz2 Simon Marchi writes: >> This patch doesn't re-indent the code, to keep the patch simple. >> Regression tested on x86_64-linux (ubuntu xenial), and verified that >> it fixes some fails on Debian/stretch. > > I wouldn't mind if you indented the code in this patch. Many diff > viewers are good at highlighting what changed in a line, so it's > obvious when it's only whitespaces. Otherwise, here's always git > diff/show -w=20 > for those who like looking at raw diffs. > It was more about reading patch in email client. Anyway, I put these two into one patch. >> >> gdb: >> >> 2017-07-18 Yao Qi >> >> 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-18 Yao Qi >> >> PR gdb/21555 >> * gdb.base/reread.exp: Wrap the whole test with two kinds of >> compilation flags, with -fPIE and without -fPIE. >> --- >> gdb/arch-utils.c | 19 +++++++++++++++++++ >> gdb/arch-utils.h | 3 +++ >> gdb/infrun.c | 9 +++++---- >> gdb/symtab.c | 3 ++- >> gdb/testsuite/gdb.base/reread.exp | 12 +++++++++--- >> 5 files changed, 38 insertions(+), 8 deletions(-) >> >> diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c >> index 2ae3413..2f63b80 100644 >> --- a/gdb/arch-utils.c >> +++ b/gdb/arch-utils.c >> @@ -985,6 +985,25 @@ default_print_insn (bfd_vma memaddr, >> disassemble_info *info) >> return (*disassemble_fn) (memaddr, info); >> } >> >> +/* Wrapper to gdbarch_skip_prologue, but doesn't throw exception. >> Catch >> + exception thrown from gdbarch_skip_prologue, and return PC. */ > > Could you explain in the comment what is returned if an exception is > caught by the wrapper? I think I did :), "Catch exception throw from gdbarch_skip_prologue, and return PC.". > > The comment should probably go in the .h, with a "See arch-utils.h" > comment here. > OK, done. >> +CORE_ADDR >> +gdbarch_skip_prologue_noexcept (gdbarch *gdbarch, CORE_ADDR pc) >> noexcept >> +{ >> + CORE_ADDR new_pc =3D pc; >> + >> + TRY >> + { >> + new_pc =3D gdbarch_skip_prologue (gdbarch, new_pc); > > I know it does the same thing, but I think it would be clearer to pass > "pc" as a parameter to the function. > OK, fixed. >> >> -if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" >> executable {debug nowarnings}] !=3D "" >> - && [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" >> executable {debug nowarnings additional_flags=3D-DNO_SECTIONS}] !=3D ""}= { >> +if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" >> executable [list debug nowarnings additional_flags=3D[lindex $opts 0] >> [lindex $opts 1]]] !=3D "" >> + && [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" >> executable [list debug nowarnings "additional_flags=3D-DNO_SECTIONS >> [lindex $opts 0]" [lindex $opts 1]]] !=3D ""} { > > Could you split those really long lines? It would perhaps help to > define an intermediary variable for compilation opts. Fixed. Patch below is pushed in. --=20 Yao (=E9=BD=90=E5=B0=A7) =46rom 2df4f52a425c3e9b04afd7f40ce756cf79ed87b4 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Mon, 17 Jul 2017 15:36:41 +0100 Subject: [PATCH] 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=3DTARGET_XFER_E_IO, gdbarch=3D0x153db50, mem= addr=3D93824992233232) at ../../binutils-gdb/gdb/corefile.c:192 #1 0x00000000005718ed in memory_error (err=3DTARGET_XFER_E_IO, memaddr=3D= memaddr@entry=3D93824992233232) at ../../binutils-gdb/gdb/corefile.c:220 #2 0x00000000005719d6 in read_memory_object (object=3Dobject@entry=3DTARG= ET_OBJECT_CODE_MEMORY, memaddr=3D93824992233232, memaddr@entry=3D1, myaddr= =3Dmyaddr@entry=3D0x7fffffffd0a0 "P\333S\001", len=3Dlen@entry=3D1) at ../.= ./binutils-gdb/gdb/corefile.c:259 #3 0x0000000000571c6e in read_code (len=3D1, myaddr=3D0x7fffffffd0a0 "P\3= 33S\001", memaddr=3D) at ../../binutils-gdb/gdb/corefile.c:2= 87 #4 read_code_unsigned_integer (memaddr=3Dmemaddr@entry=3D93824992233232, = len=3Dlen@entry=3D1, byte_order=3Dbyte_order@entry=3DBFD_ENDIAN_LITTLE) = at ../../binutils-gdb/gdb/corefile.c:362 #5 0x000000000041d4a0 in amd64_analyze_prologue (gdbarch=3Dgdbarch@entry= =3D0x153db50, pc=3Dpc@entry=3D93824992233232, current_pc=3Dcurrent_pc@entry= =3D18446744073709551615, cache=3Dcache@entry=3D0x7fffffffd1e0) at ../../bin= utils-gdb/gdb/amd64-tdep.c:2310 #6 0x000000000041e404 in amd64_skip_prologue (gdbarch=3D0x153db50, start_= pc=3D93824992233232) at ../../binutils-gdb/gdb/amd64-tdep.c:2459 #7 0x000000000067bfb0 in skip_prologue_sal (sal=3Dsal@entry=3D0x7fffffffd= 4e0) at ../../binutils-gdb/gdb/symtab.c:3628 #8 0x000000000067c4d8 in find_function_start_sal (sym=3Dsym@entry=3D0x154= 9960, funfirstline=3D1) at ../../binutils-gdb/gdb/symtab.c:3501 #9 0x000000000060999d in symbol_to_sal (result=3Dresult@entry=3D0x7ffffff= fd5f0, funfirstline=3D, sym=3Dsym@entry=3D0x1549960) at ../.= ./binutils-gdb/gdb/linespec.c:3860 .... #16 0x000000000054b733 in location_to_sals (b=3Db@entry=3D0x15792d0, locat= ion=3D0x157c230, search_pspace=3Dsearch_pspace@entry=3D0x1148120, found=3Df= ound@entry=3D0x7fffffffdc64) at ../../binutils-gdb/gdb/breakpoint.c:14211 #17 0x000000000054c1f5 in breakpoint_re_set_default (b=3D0x15792d0) at ../= ../binutils-gdb/gdb/breakpoint.c:14301 #18 0x00000000005412a9 in breakpoint_re_set_one (bint=3Dbint@entry=3D0x157= 92d0) 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-readin= g symbols. Error in re-setting breakpoint 1: Cannot access memory at address 0x5555555= 54790^M Error in re-setting breakpoint 2: Cannot access memory at address 0x5555555= 54790^M Starting program: /scratch/yao/gdb/build-git/x86_64/gdb/testsuite/outputs/g= db.base/reread/reread ^M This is foo^M [Inferior 1 (process 27720) exited normally]^M (gdb) FAIL: gdb.base/reread.exp: opts=3D "-fPIE" "ldflags=3D-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 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 PR gdb/21555 * gdb.base/reread.exp: Wrap the whole test with two kinds of compilation flags, with -fPIE and without -fPIE. diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 2ae3413..0402eba 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -985,6 +985,24 @@ default_print_insn (bfd_vma memaddr, disassemble_info = *info) return (*disassemble_fn) (memaddr, info); } =20 +/* See arch-utils.h. */ + +CORE_ADDR +gdbarch_skip_prologue_noexcept (gdbarch *gdbarch, CORE_ADDR pc) noexcept +{ + CORE_ADDR new_pc =3D pc; + + TRY + { + new_pc =3D gdbarch_skip_prologue (gdbarch, pc); + } + CATCH (ex, RETURN_MASK_ALL) + {} + END_CATCH + + return new_pc; +} + /* -Wmissing-prototypes */ extern initialize_file_ftype _initialize_gdbarch_utils; =20 diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index 2aa9159..fa29086 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -268,4 +268,10 @@ extern void default_guess_tracepoint_registers (struct= gdbarch *gdbarch, =20 extern int default_print_insn (bfd_vma memaddr, disassemble_info *info); =20 +/* Wrapper to gdbarch_skip_prologue, but doesn't throw exception. Catch + exception thrown from gdbarch_skip_prologue, and return PC. */ + +extern CORE_ADDR gdbarch_skip_prologue_noexcept (gdbarch *gdbarch, + CORE_ADDR pc) noexcept; + #endif diff --git a/gdb/infrun.c b/gdb/infrun.c index a68da6a..37ff015 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -66,6 +66,7 @@ #include "common/enum-flags.h" #include "progspace-and-thread.h" #include "common/gdb_optional.h" +#include "arch-utils.h" =20 /* Prototypes for local functions */ =20 @@ -7317,8 +7318,8 @@ handle_step_into_function (struct gdbarch *gdbarch, =20 cust =3D find_pc_compunit_symtab (stop_pc); if (cust !=3D NULL && compunit_language (cust) !=3D language_asm) - ecs->stop_func_start =3D gdbarch_skip_prologue (gdbarch, - ecs->stop_func_start); + ecs->stop_func_start + =3D gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start); =20 stop_func_sal =3D find_pc_line (ecs->stop_func_start, 0); /* Use the step_resume_break to step until the end of the prologue, @@ -7396,8 +7397,8 @@ handle_step_into_function_backward (struct gdbarch *g= dbarch, =20 cust =3D find_pc_compunit_symtab (stop_pc); if (cust !=3D NULL && compunit_language (cust) !=3D language_asm) - ecs->stop_func_start =3D gdbarch_skip_prologue (gdbarch, - ecs->stop_func_start); + ecs->stop_func_start + =3D gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start); =20 stop_func_sal =3D find_pc_line (stop_pc, 0); =20 diff --git a/gdb/symtab.c b/gdb/symtab.c index d4e107a..ccf31cc 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -64,6 +64,7 @@ #include "progspace-and-thread.h" #include "common/gdb_optional.h" #include "filename-seen-cache.h" +#include "arch-utils.h" =20 /* Forward declarations for local functions. */ =20 @@ -3627,7 +3628,7 @@ skip_prologue_sal (struct symtab_and_line *sal) if (gdbarch_skip_entrypoint_p (gdbarch)) pc =3D gdbarch_skip_entrypoint (gdbarch, pc); if (skip) - pc =3D gdbarch_skip_prologue (gdbarch, pc); + pc =3D gdbarch_skip_prologue_noexcept (gdbarch, pc); =20 /* For overlays, map pc back into its mapped VMA range. */ pc =3D overlay_mapped_address (pc, section); diff --git a/gdb/testsuite/gdb.base/reread.exp b/gdb/testsuite/gdb.base/rer= ead.exp index cc0f577..4e611ce 100644 --- a/gdb/testsuite/gdb.base/reread.exp +++ b/gdb/testsuite/gdb.base/reread.exp @@ -15,111 +15,131 @@ =20 set prototypes 1 =20 -# build the first test case +# Build programs in PIE mode, to reproduce PR 21555. +foreach_with_prefix opts { + { "" "" } + { "-fPIE" "ldflags=3D-pie" } } { =20 -set testfile1 "reread1" -set srcfile1 ${testfile1}.c -# Cygwin needs $EXEEXT. -set binfile1 [standard_output_file ${testfile1}$EXEEXT] - -if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executa= ble {debug nowarnings}] !=3D "" } { - untested "failed to compile first testcase" - return -1 -} - -# build the second test case - -set testfile2 "reread2" -set srcfile2 ${testfile2}.c -set binfile2 [standard_output_file ${testfile2}$EXEEXT] - -if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executa= ble {debug nowarnings}] !=3D "" - && [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" exec= utable {debug nowarnings additional_flags=3D-DNO_SECTIONS}] !=3D ""} { - untested "failed to compile second testcase" - return -1 -} - -# Start with a fresh gdb. - -set testfile "reread" -set binfile [standard_output_file ${testfile}$EXEEXT] - -gdb_start -gdb_reinitialize_dir $srcdir/$subdir - -# Load the first executable. - -gdb_rename_execfile ${binfile1} ${binfile} -gdb_load ${binfile} - -# Set a breakpoint at foo - -gdb_test "break foo" \ - "Breakpoint.*at.* file .*$srcfile1, line 14.*" \ - "breakpoint foo in first file" - - -# Run, should see "Breakpoint 1, foo () at hello1.c:14" - -gdb_run_cmd -gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" "run to foo()" - -# Restore first executable to its original name, and move -# second executable into its place. Ensure that the new -# executable is at least a second newer than the old. - -gdb_rename_execfile ${binfile} ${binfile1} -gdb_rename_execfile ${binfile2} ${binfile} -gdb_test "shell sleep 1" ".*" "" -gdb_touch_execfile ${binfile} - -# Run a second time; GDB should detect that the executable has changed -# and reset the breakpoints correctly. -# Should see "Breakpoint 1, foo () at reread2.c:9" - -set test "run to foo() second time" -if [is_remote target] { - unsupported $test -} else { - gdb_run_cmd - gdb_test "" "Breakpoint.* foo .* at .*:9.*" $test -} - - -### Second pass: verify that GDB checks the executable file's -### timestamp when the program is *restarted*, not just when it exits. - -if [is_remote target] { - unsupported "second pass: GDB should check for changes before running" -} else { - - # Put the older executable back in place. - gdb_rename_execfile ${binfile} ${binfile2} - gdb_rename_execfile ${binfile1} ${binfile} - - # Restart GDB entirely. - clean_restart ${binfile} - - # Set a breakpoint on foo and run to it. - gdb_test "break foo" \ - "Breakpoint.*at.* file .*$srcfile1, line 14.*" \ - "second pass: breakpoint foo in first file" - gdb_run_cmd - gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" "second pass: ru= n to foo()" - - # This time, let the program run to completion. If GDB checks the - # executable file's timestamp now, it won't notice any change. - gdb_continue_to_end "second pass" -=20=20=20=20 - # Now move the newer executable into place, and re-run. GDB - # should still notice that the executable file has changed, - # and still re-set the breakpoint appropriately. - gdb_rename_execfile ${binfile} ${binfile1} - gdb_rename_execfile ${binfile2} ${binfile} - gdb_run_cmd - gdb_test "" "Breakpoint.* foo .* at .*:9.*" "second pass: run to foo()= second time" -} + # build the first test case =20 + set testfile1 "reread1" + set srcfile1 ${testfile1}.c + # Cygwin needs $EXEEXT. + set binfile1 [standard_output_file ${testfile1}$EXEEXT] + + set testfile1_opt [list debug nowarnings \ + additional_flags=3D[lindex $opts 0] \ + [lindex $opts 1] ] + if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" \ + executable ${testfile1_opt}] !=3D "" } { + untested "failed to compile first testcase" + return -1 + } + + # build the second test case + + set testfile2 "reread2" + set srcfile2 ${testfile2}.c + set binfile2 [standard_output_file ${testfile2}$EXEEXT] + + set testfile2_opt1 [list debug nowarnings \ + additional_flags=3D[lindex $opts 0] \ + [lindex $opts 1]] + set testfile2_op2 [list debug nowarnings \ + "additional_flags=3D-DNO_SECTIONS [lindex $opts 0]" \ + [lindex $opts 1]] + if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" \ + executable ${testfile2_opt1}] !=3D "" + && [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" \ + executable ${testfile2_opt2}] !=3D ""} { + untested "failed to compile second testcase" + return -1 + } + + # Start with a fresh gdb. + + set testfile "reread" + set binfile [standard_output_file ${testfile}$EXEEXT] + + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + # Load the first executable. + + gdb_rename_execfile ${binfile1} ${binfile} + gdb_load ${binfile} + + # Set a breakpoint at foo + + gdb_test "break foo" \ + "Breakpoint.*at.* file .*$srcfile1, line 14.*" \ + "breakpoint foo in first file" + + + # Run, should see "Breakpoint 1, foo () at hello1.c:14" + + gdb_run_cmd + gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" "run to foo()" + + # Restore first executable to its original name, and move + # second executable into its place. Ensure that the new + # executable is at least a second newer than the old. + + gdb_rename_execfile ${binfile} ${binfile1} + gdb_rename_execfile ${binfile2} ${binfile} + gdb_test "shell sleep 1" ".*" "" + gdb_touch_execfile ${binfile} + + # Run a second time; GDB should detect that the executable has changed + # and reset the breakpoints correctly. + # Should see "Breakpoint 1, foo () at reread2.c:9" + + set test "run to foo() second time" + if [is_remote target] { + unsupported $test + } else { + gdb_run_cmd + gdb_test "" "Breakpoint.* foo .* at .*:9.*" $test + } + + + ### Second pass: verify that GDB checks the executable file's + ### timestamp when the program is *restarted*, not just when it exits. + + if [is_remote target] { + unsupported "second pass: GDB should check for changes before running" + } else { + + # Put the older executable back in place. + gdb_rename_execfile ${binfile} ${binfile2} + gdb_rename_execfile ${binfile1} ${binfile} + + # Restart GDB entirely. + clean_restart ${binfile} + + # Set a breakpoint on foo and run to it. + gdb_test "break foo" \ + "Breakpoint.*at.* file .*$srcfile1, line 14.*" \ + "second pass: breakpoint foo in first file" + gdb_run_cmd + gdb_test "" "Breakpoint.* foo .* at .*$srcfile1:14.*" \ + "second pass: run to foo()" + + # This time, let the program run to completion. If GDB checks the + # executable file's timestamp now, it won't notice any change. + gdb_continue_to_end "second pass" + + # Now move the newer executable into place, and re-run. GDB + # should still notice that the executable file has changed, + # and still re-set the breakpoint appropriately. + gdb_rename_execfile ${binfile} ${binfile1} + gdb_rename_execfile ${binfile2} ${binfile} + gdb_run_cmd + gdb_test "" "Breakpoint.* foo .* at .*:9.*" \ + "second pass: run to foo() second time" + } + + } # End of tests. =20 return 0