From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8322 invoked by alias); 22 Jun 2009 07:45:12 -0000 Received: (qmail 8303 invoked by uid 22791); 22 Jun 2009 07:45:09 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL,BAYES_00,SARE_MSGID_LONG40,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail-pz0-f196.google.com (HELO mail-pz0-f196.google.com) (209.85.222.196) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 22 Jun 2009 07:45:03 +0000 Received: by pzk34 with SMTP id 34so3101454pzk.12 for ; Mon, 22 Jun 2009 00:45:00 -0700 (PDT) MIME-Version: 1.0 Received: by 10.142.221.11 with SMTP id t11mr1614877wfg.68.1245656700605; Mon, 22 Jun 2009 00:45:00 -0700 (PDT) In-Reply-To: <4A3EBDE9.9090002@vmware.com> References: <4A3EBDE9.9090002@vmware.com> Date: Mon, 22 Jun 2009 07:45:00 -0000 Message-ID: Subject: Re: [RFA] Reverse-step/next and shared libraries (with testsuite) From: Hui Zhu To: Michael Snyder Cc: gdb-patches@sourceware.org, marc.khouzam@ericsson.com Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes 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 X-SW-Source: 2009-06/txt/msg00561.txt.bz2 I try this patch in SLED 10. Everything is OK. Thanks, Hui On Mon, Jun 22, 2009 at 07:10, Michael Snyder wrote: > OK, this is a bit of a rewrite for the infrun code that > handles reverse stepping into/over shared library functions > and trampolines. =A0I believe we now correctly handle various > combinations of ... > =A0* reverse-step, reverse-next > =A0* trampolines, solib-dynsym-resolver > =A0* resolved and unresolved symbols > =A0* debuggable (user) and undebuggable (eg. libc) functions > > This also includes the first testsuite test case for reverse > debugging. =A0If this one's accepted, I've got more queued up. > > Hui, this patch will replace your patch > http://sourceware.org/ml/gdb-patches/2009-03/msg00005.html, > so I'll appreciate your review. > > Marc, this patch should fix all of your solib step/next bugs. > > No regressions on linux-i686. > > > 2009-06-21 =A0Michael Snyder =A0 > > =A0 =A0 =A0 =A0* infrun.c (handle_inferior_event): Improve handling of > =A0 =A0 =A0 =A0reverse-stepping into and over shared library functions. > > 2009-06-21 =A0Michael Snyder =A0 > > =A0 =A0 =A0 =A0* gdb.base/solib-reverse.exp: New file. > =A0 =A0 =A0 =A0* gdb.base/solib-reverse.c: New file. > > Index: infrun.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: /cvs/src/src/gdb/infrun.c,v > retrieving revision 1.392 > diff -u -p -r1.392 infrun.c > --- infrun.c =A0 =A018 Jun 2009 23:55:57 -0000 =A0 =A0 =A01.392 > +++ infrun.c =A0 =A021 Jun 2009 22:50:22 -0000 > @@ -3639,7 +3639,7 @@ infrun: not switching back to stepped th > =A0 if (stop_pc >=3D ecs->event_thread->step_range_start > =A0 =A0 =A0 && stop_pc < ecs->event_thread->step_range_end > =A0 =A0 =A0 && (execution_direction !=3D EXEC_REVERSE > - =A0 =A0 =A0 =A0 || frame_id_eq (get_frame_id (get_current_frame ()), > + =A0 =A0 =A0 =A0 || frame_id_eq (get_frame_id (frame), > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ecs->event_thread->ste= p_frame_id))) > =A0 =A0 { > =A0 =A0 =A0 if (debug_infrun) > @@ -3667,10 +3667,19 @@ infrun: not switching back to stepped th > =A0 /* We stepped out of the stepping range. =A0*/ > > =A0 /* If we are stepping at the source level and entered the runtime > - =A0 =A0 loader dynamic symbol resolution code, we keep on single steppi= ng > - =A0 =A0 until we exit the run time loader code and reach the callee's > - =A0 =A0 address. =A0*/ > - =A0if (ecs->event_thread->step_over_calls =3D=3D STEP_OVER_UNDEBUGGABLE > + =A0 =A0 loader dynamic symbol resolution code... > + > + =A0 =A0 EXEC_FORWARD: we keep on single stepping until we exit the run > + =A0 =A0 time loader code and reach the callee's address. > + > + =A0 =A0 EXEC_REVERSE: we've already executed the callee (backward), and > + =A0 =A0 the runtime loader code is handled just like any other > + =A0 =A0 undebuggable function call. =A0Now we need only keep stepping > + =A0 =A0 backward through the trampoline code, and that's handled further > + =A0 =A0 down, so there is nothing for us to do here. =A0*/ > + > + =A0if (execution_direction !=3D EXEC_REVERSE > + =A0 =A0 =A0&& ecs->event_thread->step_over_calls =3D=3D STEP_OVER_UNDEB= UGGABLE > =A0 =A0 =A0 && in_solib_dynsym_resolve_code (stop_pc)) > =A0 =A0 { > =A0 =A0 =A0 CORE_ADDR pc_after_resolver =3D > @@ -3740,12 +3749,29 @@ infrun: not switching back to stepped th > =A0 =A0 =A0 =A0 =A0/* Also, maybe we just did a "nexti" inside a prolog, = so we > =A0 =A0 =A0 =A0 =A0 =A0 thought it was a subroutine call but it was not. = =A0Stop as > =A0 =A0 =A0 =A0 =A0 =A0 well. =A0FENN */ > + =A0 =A0 =A0 =A0 /* And this works the same backward as frontward. =A0MV= S */ > =A0 =A0 =A0 =A0 =A0ecs->event_thread->stop_step =3D 1; > =A0 =A0 =A0 =A0 =A0print_stop_reason (END_STEPPING_RANGE, 0); > =A0 =A0 =A0 =A0 =A0stop_stepping (ecs); > =A0 =A0 =A0 =A0 =A0return; > =A0 =A0 =A0 =A0} > > + =A0 =A0 =A0/* Reverse stepping through solib trampolines. =A0*/ > + > + =A0 =A0 =A0if (execution_direction =3D=3D EXEC_REVERSE > + =A0 =A0 =A0 =A0 && (gdbarch_skip_trampoline_code (gdbarch, frame, stop_= pc) > + =A0 =A0 =A0 =A0 =A0 =A0 || (ecs->stop_func_start =3D=3D 0 > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && in_solib_dynsym_resolve_code (stop_p= c)))) > + =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 /* Any solib trampoline code can be handled in reverse > + =A0 =A0 =A0 =A0 =A0 =A0by simply continuing to single-step. =A0We have = already > + =A0 =A0 =A0 =A0 =A0 =A0executed the solib function (backwards), and a f= ew > + =A0 =A0 =A0 =A0 =A0 =A0steps will take us back through the trampoline t= o the > + =A0 =A0 =A0 =A0 =A0 =A0caller. =A0*/ > + =A0 =A0 =A0 =A0 keep_going (ecs); > + =A0 =A0 =A0 =A0 return; > + =A0 =A0 =A0 } > + > =A0 =A0 =A0 if (ecs->event_thread->step_over_calls =3D=3D STEP_OVER_ALL) > =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0 =A0/* We're doing a "next". > @@ -3763,35 +3789,10 @@ infrun: not switching back to stepped th > =A0 =A0 =A0 =A0 =A0 =A0{ > =A0 =A0 =A0 =A0 =A0 =A0 =A0struct symtab_and_line sr_sal; > > - =A0 =A0 =A0 =A0 =A0 =A0 if (ecs->stop_func_start =3D=3D 0 > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && in_solib_dynsym_resolve_code (stop_p= c)) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Stepped into runtime loader dynamic = symbol > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0resolution code. =A0Since we're = in reverse, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0we have already backed up throug= h the runtime > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0loader and the dynamic function.= =A0This is just > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0the trampoline (jump table). > - > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Just keep stepping, we'll soon b= e home. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 keep_going (ecs); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > - =A0 =A0 =A0 =A0 =A0 =A0 if (gdbarch_skip_trampoline_code(current_gdbarc= h, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0get_current_frame (), > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0stop_pc)) > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We are in a function call trampoline. > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Keep stepping backward to get to= the caller. =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ecs->event_thread->stepping_over_breakp= oint =3D 1; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > - =A0 =A0 =A0 =A0 =A0 =A0 else > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Normal function call return (static = or dynamic). =A0*/ > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 init_sal (&sr_sal); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sr_sal.pc =3D ecs->stop_func_start; > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 insert_step_resume_breakpoint_at_sal (s= r_sal, > null_frame_id); > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 =A0 /* Normal function call return (static or dynam= ic). =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 init_sal (&sr_sal); > + =A0 =A0 =A0 =A0 =A0 =A0 sr_sal.pc =3D ecs->stop_func_start; > + =A0 =A0 =A0 =A0 =A0 =A0 insert_step_resume_breakpoint_at_sal (sr_sal, n= ull_frame_id); > =A0 =A0 =A0 =A0 =A0 =A0} > =A0 =A0 =A0 =A0 =A0else > =A0 =A0 =A0 =A0 =A0 =A0insert_step_resume_breakpoint_at_caller (frame); > Index: testsuite/gdb.base/solib-reverse.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: testsuite/gdb.base/solib-reverse.c > diff -N testsuite/gdb.base/solib-reverse.c > --- /dev/null =A0 1 Jan 1970 00:00:00 -0000 > +++ testsuite/gdb.base/solib-reverse.c =A021 Jun 2009 22:54:01 -0000 > @@ -0,0 +1,26 @@ > +/* Test reverse debugging of shared libraries. =A0*/ > + > +#include > + > +/* Shared library function */ > +extern int shr2(int); > + > +int main () > +{ > + =A0char* cptr =3D "String 1"; > + =A0int b[2] =3D {5,8}; > + > + =A0b[0] =3D shr2(12); =A0 =A0 =A0 =A0 =A0 =A0 /* begin part two */ > + =A0b[1] =3D shr2(17); =A0 =A0 =A0 =A0 =A0 =A0 /* middle part two */ > + > + =A0b[0] =3D 6; =A0 b[1] =3D 9; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* generi= c statement, end part two > */ > + =A0printf ("message 1\n"); =A0 =A0 =A0/* printf one */ > + =A0printf ("message 2\n"); =A0 =A0 =A0/* printf two */ > + =A0printf ("message 3\n"); =A0 =A0 =A0/* printf three */ > + =A0sleep (0); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* sleep one */ > + =A0sleep (0); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* sleep two */ > + =A0sleep (0); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* sleep three */ > + > + =A0return 0; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* end part one */ > +} > + > Index: testsuite/gdb.base/solib-reverse.exp > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: testsuite/gdb.base/solib-reverse.exp > diff -N testsuite/gdb.base/solib-reverse.exp > --- /dev/null =A0 1 Jan 1970 00:00:00 -0000 > +++ testsuite/gdb.base/solib-reverse.exp =A0 =A0 =A0 =A021 Jun 2009 22:54= :01 -0000 > @@ -0,0 +1,127 @@ > +# Copyright 2009 > +# Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =A0See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. =A0If not, see . > + > +# This file was written by Michael Snyder (msnyder@vmware.com). > + > +# > +# Test reverse debugging with shared libraries. > +# > + > +if ![target_info exists gdb,can_reverse] { > + =A0 =A0return > +} > + > +set testfile "solib-reverse" > +set srcfile =A0${testfile}.c > +set libfile =A0"shr2" > +set libsrc =A0 ${libfile}.c > +set library =A0${objdir}/${subdir}/${libfile}.sl > +set binfile =A0${objdir}/${subdir}/${testfile} > + > +if [get_compiler_info ${binfile}] { > + =A0 =A0return -1 > +} > + > +if { [gdb_compile_shlib ${srcdir}/${subdir}/${libsrc} ${library} "debug"] > !=3D "" } { > + =A0 =A0untested "Could not compile shared library." > + =A0 =A0return -1 > +} > + > +set exec_opts [list debug shlib=3D${library}] > + > +if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable > $exec_opts] !=3D "" } { > + =A0 =A0untested "Could not compile $binfile." > + =A0 =A0return -1 > +} > + > +# Start with a fresh gdb. > + > +gdb_exit > +gdb_start > +gdb_reinitialize_dir $srcdir/$subdir > +gdb_load ${binfile} > + > + > +runto main > + > +if [target_info exists gdb,use_precord] { > + =A0 =A0# Activate process record/replay > + =A0 =A0gdb_test "record" "" "Turn on process record" > + =A0 =A0# FIXME: command ought to acknowledge, so we can test if it succ= eeded. > +} > + > +# > +# Test reverse-step over undebuggable solib functions. > +# > + > +# Run forward past some solib function calls. > + > +set end_part_one [gdb_get_line_number " end part one" "$srcfile"] > +set end_part_two [gdb_get_line_number " end part two" "$srcfile"] > +gdb_test "until $end_part_one" " end part one.*" "run until end part one" > + > +gdb_test "reverse-step" " sleep three .*" "reverse-step third sleep" > +gdb_test "reverse-step" " sleep two .*" =A0 "reverse-step second sleep" > +gdb_test "reverse-step" " sleep one .*" =A0 \ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "reverse-step first sleep, dynsym r= esolve" > + > +gdb_test "reverse-step" " printf three .*" "reverse-step third printf" > +gdb_test "reverse-step" " printf two .*" =A0 "reverse-step second printf" > +gdb_test "reverse-step" " printf one .*" =A0 \ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "reverse-step first printf, dynsym = resolve" > +gdb_test "reverse-step" " generic statement.*" "reverse-step generic" > + > + > +# > +# Test reverse-next over undebuggable solib functions. > +# > + > +# Run forward again... > + > +gdb_test "until $end_part_one" " end part one.*" "forward to end part on= e" > + > +gdb_test "reverse-next" " sleep three .*" "reverse-next third sleep" > +gdb_test "reverse-next" " sleep two .*" =A0 "reverse-next second sleep" > +gdb_test "reverse-next" " sleep one .*" =A0 \ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "reverse-next first sleep, dynsym r= esolve" > + > +gdb_test "reverse-next" " printf three .*" "reverse-next third printf" > +gdb_test "reverse-next" " printf two .*" =A0 "reverse-next second printf" > +gdb_test "reverse-next" " printf one .*" =A0 \ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "reverse-next first printf, dynsym = resolve" > +gdb_test "reverse-next" " generic statement.*" "reverse-next generic" > + > + > +# > +# Test reverse-step into debuggable solib function > +# > + > +gdb_test "reverse-step" "${libsrc}.*" "reverse-step into solib function > one" > +gdb_test "reverse-step" "return 2.x.*" "reverse-step within solib functi= on > one" > +gdb_test "reverse-step" " middle part two.*" "reverse-step back to main > one" > + > +gdb_test "reverse-step" "${libsrc}.*" "reverse-step into solib function > two" > +gdb_test "reverse-step" "return 2.x.*" "reverse-step within solib functi= on > two" > +gdb_test "reverse-step" " begin part two.*" "reverse-step back to main t= wo" > + > +# > +# Test reverse-next over debuggable solib function > +# > + > +gdb_test "until $end_part_two" " end part two.*" "run until end part two" > + > +gdb_test "reverse-next" " middle part two.*" "reverse-next over solib > function one" > +gdb_test "reverse-next" " begin part two.*" "reverse-next over solib > function two" > >