* Status of 'blacklist' patch? @ 2011-10-06 12:12 Diego Novillo 2011-10-06 14:08 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Diego Novillo @ 2011-10-06 12:12 UTC (permalink / raw) To: Justin Lebar, Tom Tromey, Lawrence Crowl, gdb-patches Justin, Tom recently pointed me to your 'blacklist' patch for gdb. I think this could be very useful for GCC (http://gcc.gnu.org/ml/gcc-patches/2011-10/msg00324.html). What is the status of this patch? Any chance this will be included in gdb at some point? Thanks. Diego. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 12:12 Status of 'blacklist' patch? Diego Novillo @ 2011-10-06 14:08 ` Justin Lebar 2011-10-06 15:51 ` Stan Shebs ` (2 more replies) 0 siblings, 3 replies; 44+ messages in thread From: Justin Lebar @ 2011-10-06 14:08 UTC (permalink / raw) To: Diego Novillo; +Cc: Tom Tromey, Lawrence Crowl, gdb-patches I last pinged gdb-patches about the patch on May 16 and got no response. I imagine the patch has bitrotted by now. I'd be happy to bring it up to date if there were a reasonable chance it would get reviewed this time. Regards, -Justin On Thu, Oct 6, 2011 at 8:12 AM, Diego Novillo <dnovillo@google.com> wrote: > Justin, > > Tom recently pointed me to your 'blacklist' patch for gdb. I think > this could be very useful for GCC > (http://gcc.gnu.org/ml/gcc-patches/2011-10/msg00324.html). > > What is the status of this patch? Any chance this will be included in > gdb at some point? > > > Thanks. Diego. > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 14:08 ` Justin Lebar @ 2011-10-06 15:51 ` Stan Shebs 2011-10-06 20:16 ` Justin Lebar 2011-10-06 17:19 ` Diego Novillo 2011-10-06 17:33 ` Tom Tromey 2 siblings, 1 reply; 44+ messages in thread From: Stan Shebs @ 2011-10-06 15:51 UTC (permalink / raw) To: gdb-patches On 10/6/11 7:07 AM, Justin Lebar wrote: > I last pinged gdb-patches about the patch on May 16 and got no response. > > I imagine the patch has bitrotted by now. I'd be happy to bring it up > to date if there were a reasonable chance it would get reviewed this > time. > (It took a bit of digging to find the last version of the patch - I probably missed it because the patch was attached as a binary, including the changelog entry.) Anyway, I really like the concept, and "skip" seems like a good general term for the functionality. I skimmed the April version, and noticed a few things to fix up. The file headers say things like "Header for GDB line completion.", which I'm guessing is cut-n-paste from another file. :-) Also it's now 2011, not 2010. There's a lot of change of terminology from "default breakpoint" to "displayed codepoint". I know we've debated better substitutes for "breakpoint", but this patch is maybe not the best place to introduce one. (Or I'm confused about what "codepoint" means, I didn't see a definition.) I didn't see a patch for the GDB manual, so I'm not sure of the intended functionality details. If you update the patch and resubmit, I promise I'll give it a prompt review. Stan stan@codesourcery.com ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 15:51 ` Stan Shebs @ 2011-10-06 20:16 ` Justin Lebar 2011-10-10 12:34 ` Stan Shebs 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-06 20:16 UTC (permalink / raw) To: Stan Shebs, Tom Tromey, Diego Novillo; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 2401 bytes --] > If you update the patch and resubmit, I promise I'll give it a prompt > review. Deal. I've attached an updated patch, and it looks like gmail got the mime type right this time. :) > There's a lot of change of terminology from "default breakpoint" to > "displayed codepoint". I know we've debated better substitutes for > "breakpoint", but this patch is maybe not the best place to introduce one. How about "last displayed symtab and line"? That seems to be something which is meaningful. On Thu, Oct 6, 2011 at 1:33 PM, Tom Tromey <tromey@redhat.com> wrote: > Just for future reference, I encourage everybody to ping a lot -- send a > ping once a week. In my experience, it feels like I'm being obnoxious > when I write the note, but it is a good way to get attention, and I > promise you nobody will be offended by it. Thanks; that's good to know. Different communities handle this sort of thing differently. Regards, -Justin On Thu, Oct 6, 2011 at 11:51 AM, Stan Shebs <stanshebs@earthlink.net> wrote: > On 10/6/11 7:07 AM, Justin Lebar wrote: >> >> I last pinged gdb-patches about the patch on May 16 and got no response. >> >> I imagine the patch has bitrotted by now. I'd be happy to bring it up >> to date if there were a reasonable chance it would get reviewed this >> time. >> > > (It took a bit of digging to find the last version of the patch - I probably > missed it because the patch was attached as a binary, including the > changelog entry.) > > Anyway, I really like the concept, and "skip" seems like a good general term > for the functionality. > > I skimmed the April version, and noticed a few things to fix up. > > The file headers say things like "Header for GDB line completion.", which > I'm guessing is cut-n-paste from another file. :-) Also it's now 2011, not > 2010. > > There's a lot of change of terminology from "default breakpoint" to > "displayed codepoint". I know we've debated better substitutes for > "breakpoint", but this patch is maybe not the best place to introduce one. > (Or I'm confused about what "codepoint" means, I didn't see a definition.) > > I didn't see a patch for the GDB manual, so I'm not sure of the intended > functionality details. > > If you update the patch and resubmit, I promise I'll give it a prompt > review. > > Stan > stan@codesourcery.com > > > [-- Attachment #2: skip.diff --] [-- Type: text/x-patch, Size: 52231 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..22130b9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,40 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New + * breakpoint.h (set_default_breakpoint): removed + * breakpoint.c: Removed default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (set_default_breakpoint): Removed + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Removed uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Added cmd_list_element *skiplist. + * cli/cli-cmds.c: Added skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fixed comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Added check that we don't step + into a function whose pc is marked for skip. + * stack.c: Added last_codepoint_valid, last_codepoint_pspace, + last_codepoint_addr, last_codepoint_symtab, last_codepoint_line + variables. + (set_last_displayed_codepoint): New static function. + (print_frame_info): Switched call to set_default_breakpoint to call to + set_last_displayed_codepoint. + (clear_last_displayed_symtab_and_line, + last_displayed_symtab_and_line_is_valid, get_last_displayed_pspace, + get_last_displayed_addr, get_last_displayed_symtab, + get_last_displayed_line, get_last_displayed_symtab_and_line): New + public functions. + * stack.h (clear_last_displayed_symtab_and_line, + last_displayed_symtab_and_line_is_valid, get_last_displayed_pspace, + get_last_displayed_addr, get_last_displayed_symtab, + get_last_displayed_line, get_last_displayed_symtab_and_line): Added + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. @@ -4733,6 +4770,7 @@ (symbol_file_add): Pass NULL to the new parameter parent. * symfile.h (symbol_file_add_from_bfd): New parameter parent. +<<<<<<< HEAD 2011-04-17 Jan Kratochvil <jan.kratochvil@redhat.com> * elfread.c (elf_symtab_read): Do not ignore .L symbols if they are diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..3d3e12b 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_symtab_and_line_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_symtab_and_line (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_symtab_and_line_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_symtab_and_line_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_symtab_and_line (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_symtab_and_line_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..d7e3799 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..bd854ca 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,104 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skip + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip over a file or function when stepping. + +For example, suppose you are stepping through the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! What can you do? + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +Another solution is to execute @code{skip boring}. This instructs @value{GDBN} +never to step into @code{boring}. Now when you execute @code{step} at line +103, you'll step over @code{boring} and directly into @code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. (@pxref{Specify Location}) + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip +Print a table of all functions and files marked for skipping. This table +contains the following information for each function or file: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +@samp{function} or @samp{file} +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info break} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @var{n} +Delete the skip with identifier @var{n}. + +@kindex skip enable +@item skip enable @var{n} +Enable the skip with identifier @var{n}. + +@kindex skip disable +@item skip disable @var{n} +Disable the skip with identifier @var{n}. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..edb51ff --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,574 @@ +/* Skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" + +struct skiplist_entry +{ + int number; + + /* null if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); +//static void try_resolve_pending_entry (struct skiplist_entry *e); +static struct gdbarch *get_sal_arch (struct symtab_and_line *sal); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_symtab_and_line_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line *sal = &sals.sals[0]; + CORE_ADDR pc = sal->pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int entry_num = -1; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + if (arg != 0) + { + entry_num = parse_and_eval_long (arg); + } + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (entry_num == -1 || e->number == entry_num) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (entry_num == -1) + ui_out_message (current_uiout, 0, _("Not ignoring any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entry numbered %d.\n"), entry_num); + + return; + } + + if (opts.addressprint) + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 5, num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (entry_num != -1 && entry_num != e->number) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int entry_num = parse_and_eval_long (arg); + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + e->enabled = 1; + return; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int entry_num = parse_and_eval_long (arg); + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + e->enabled = 0; + return; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *b_prev; + int entry_num = parse_and_eval_long (arg); + + /* We don't need to use a SAFE macro here since we return as soon as we + remove an element from the list. */ + b_prev = 0; + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + return; + } + else + { + b_prev = e; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + struct symtab_and_line sal; + char *filename; + struct skiplist_entry *e; + + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + + ALL_SKIPLIST_ENTRIES (e) + { + int pc_match = e->pc != 0 && pc == e->pc; + int filename_match = e->filename != 0 && filename != 0 && + strcmp (filename, e->filename) == 0; + if (e->enabled && !e->pending && (pc_match || filename_match)) + return 1; + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set () +{ + struct skiplist_entry *e; + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 && + sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line *sal = &sals.sals[0]; + CORE_ADDR pc = sal->pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (find_pc_partial_function (pc, &e->function_name, + &func_start, 0)) + { + e->pending = 0; + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +/* Helper function to get a gdbarch from a symtab_and_line. */ +static struct gdbarch* +get_sal_arch (struct symtab_and_line *sal) +{ + if (sal->section) + return get_objfile_arch (sal->section->objfile); + if (sal->symtab) + return get_objfile_arch (sal->symtab->objfile); + return get_current_arch (); +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable a skip entry.\n\ +skip enable [NUMBER]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable a skip entry.\n\ +skip disable [NUMBER]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete a skip entry.\n\ +skip delete [NUMBER]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Status of all skips, or of skip NUMBER.\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..c611555 --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..6f3693a 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_codepoint (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last codepoint we displayed to the user. This is + where we insert a breakpoint or a skiplist entry by default. */ +static int last_codepoint_valid = 0; +static struct program_space *last_codepoint_pspace = 0; +static CORE_ADDR last_codepoint_addr = 0; +static struct symtab *last_codepoint_symtab = 0; +static int last_codepoint_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_codepoint (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_codepoint (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,88 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last codepoint we displayed, which we use e.g. as the place to + put a breakpoint when the `break' command is invoked with no arguments. */ +static void +set_last_displayed_codepoint (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_codepoint_valid = valid; + last_codepoint_pspace = pspace; + last_codepoint_addr = addr; + last_codepoint_symtab = symtab; + last_codepoint_line = line; +} + +void +clear_last_displayed_symtab_and_line () +{ + last_codepoint_valid = 0; + last_codepoint_pspace = 0; + last_codepoint_addr = 0; + last_codepoint_symtab = 0; + last_codepoint_line = 0; +} + +int +last_displayed_symtab_and_line_is_valid () +{ + return last_codepoint_valid; +} + +struct program_space* +get_last_displayed_pspace () +{ + if (last_codepoint_valid) + return last_codepoint_pspace; + return 0; +} + +CORE_ADDR +get_last_displayed_addr () +{ + if (last_codepoint_valid) + return last_codepoint_addr; + return 0; +} + +struct symtab* +get_last_displayed_symtab () +{ + if (last_codepoint_valid) + return last_codepoint_symtab; + return 0; +} + +int +get_last_displayed_line () +{ + if (last_codepoint_valid) + return last_codepoint_line; + return 0; +} + +void +get_last_displayed_symtab_and_line (struct symtab_and_line *sal) +{ + if (last_codepoint_valid) + { + sal->pspace = last_codepoint_pspace; + sal->pc = last_codepoint_addr; + sal->symtab = last_codepoint_symtab; + sal->line = last_codepoint_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..320332b 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_symtab_and_line (); +int last_displayed_symtab_and_line_is_valid (); +struct program_space* get_last_displayed_pspace (); +CORE_ADDR get_last_displayed_addr (); +struct symtab* get_last_displayed_symtab (); +int get_last_displayed_line (); +void get_last_displayed_symtab_and_line (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..6967805 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_symtab_and_line (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..4f8838d --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,129 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${objdir}/${subdir}/${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +gdb_load ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ +"File ${srcfile_lib} will be skipped when stepping." \ +"ignoring file in solib" \ +"No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*"\ +"y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ +"info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ +"info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +gdb_load ${binfile_main} + +gdb_test "skip function multiply" \ +"Function multiply will be skipped when stepping, pending shared library load." \ +"ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*"\ +"y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..ba1e87b --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,135 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not ignoring any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entry numbered 999." +gdb_test "skip disable 999" "No skiplist entry numbered 999." +gdb_test "skip delete 999" "No skiplist entry numbered 999." +gdb_test "skip enable" "Argument required \\(expression to compute\\)." +gdb_test "skip disable" "Argument required \\(expression to compute\\)." +gdb_test "skip delete" "Argument required \\(expression to compute\\)." +gdb_test "skip enable a" "No symbol \"a\" in current context." +gdb_test "skip disable a" "No symbol \"a\" in current context." +gdb_test "skip delete a" "No symbol \"a\" in current context." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entry numbered 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# +if ![runto_main] { fail "skip tests suppressed" } +send_gdb "step\n" +gdb_test "bt" "#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +send_gdb "skip delete 1\n" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +send_gdb "skip disable 3\n" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +send_gdb "step\n"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +send_gdb "skip enable 3\n" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 20:16 ` Justin Lebar @ 2011-10-10 12:34 ` Stan Shebs 2011-10-11 21:34 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Stan Shebs @ 2011-10-10 12:34 UTC (permalink / raw) To: gdb-patches On 10/6/11 4:15 PM, Justin Lebar wrote: > There's a lot of change of terminology from "default breakpoint" to > "displayed codepoint". I know we've debated better substitutes for > "breakpoint", but this patch is maybe not the best place to introduce one. > How about "last displayed symtab and line"? That seems to be > something which is meaningful. Or even "last displayed sal" :-) + * stack.h (clear_last_displayed_symtab_and_line, + last_displayed_symtab_and_line_is_valid, get_last_displayed_pspace, + get_last_displayed_addr, get_last_displayed_symtab, + get_last_displayed_line, get_last_displayed_symtab_and_line): Added + This is why we like periods at the end of each ChangeLog bit - this looks like it got cut off... plus it's good to say as "Declare." as reminder that it's not a code bit that was added. @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ I'm not going to be persnickety about this one, but we really want random comment fixups to be separate patches - took me a moment to decide if this was somehow relevant to the masses of code. +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! What can you do? I would lose the rhetorical question, it's not really adding much. + +@kindex skip delete +@item skip delete @var{n} +Delete the skip with identifier @var{n}. No mass-delete by omitting the argument?? + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; I'm not clear on why we need gdbarch, since CORE_ADDR should always be long enough? + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (entry_num == -1 || e->number == entry_num) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } Ah, for address printing. My inclination is to say to drop this admirable goal and make a separate patch that attempts to be smart for address printing in breakpoint and skip lists in general. It seems like a nice design might look at actual values in the list and only use wide space if all addresses are large, sort of like how html table layout works. + ui_out_message (current_uiout, 0, _("Not ignoring any files or functions.\n")); "Not skipping" In general, it's looking pretty good! As people have commented previously, regexp would be nice to have, but with this much code, I think it's better to get a first version in, accumulate a little practical experience before deciding about which additional features to add. (Between Moz and GCC, there are going to be lots of users I think. :-) ) Also, in thumbing back through old discussion, I notice that the last state was that you had submitted paperwork for copyright assignment, but not received anything, and I don't remember getting any email adding you to the "has assignments" list. Did you ever get the confirmation from the FSF? Stan stan@codesourcery.com ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-10 12:34 ` Stan Shebs @ 2011-10-11 21:34 ` Justin Lebar 2011-10-11 23:54 ` Doug Evans 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-11 21:34 UTC (permalink / raw) To: Stan Shebs; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 2431 bytes --] Thanks a lot for the review, Stan. On Mon, Oct 10, 2011 at 8:34 AM, Stan Shebs <stanshebs@earthlink.net> wrote: > On 10/6/11 4:15 PM, Justin Lebar wrote: > + * stack.h (clear_last_displayed_symtab_and_line, > + last_displayed_symtab_and_line_is_valid, get_last_displayed_pspace, > + get_last_displayed_addr, get_last_displayed_symtab, > + get_last_displayed_line, get_last_displayed_symtab_and_line): Added > + > > This is why we like periods at the end of each ChangeLog bit - this looks > like > it got cut off... plus it's good to say as "Declare." as reminder that it's > not a code bit that was added. This ChangeLog process seems really archaic to me. git log --stat gives me much of this information already, and git blame gives me the rest. Keeping the ChangeLog in sync with my patch takes a significant amount of work! But anyway, I've fixed it up. > +@kindex skip delete > +@item skip delete @var{n} > +Delete the skip with identifier @var{n}. > > > No mass-delete by omitting the argument?? I've added mass- enable, disable, and delete. > + /* Architecture we used to create the skiplist entry. May be null > + if the entry is pending a shared library load. */ > + struct gdbarch *gdbarch; > > > I'm not clear on why we need gdbarch, since CORE_ADDR should always be long > enough? > > Ah, for address printing. My inclination is to say to drop this admirable > goal and make a separate patch that attempts to be smart for address > printing in breakpoint and skip lists in general. It seems like a nice > design might look at actual values in the list and only use wide space if > all addresses are large, sort of like how html table layout works. What I have is, insofar as I can tell, exactly what we currently do for breakpoints. I can fake the length, but what about the call to ui_out_field_core_addr? > Also, in thumbing back through old discussion, I notice that the last state > was that you had submitted paperwork for copyright assignment, but not > received anything, and I don't remember getting any email adding you to the > "has assignments" list. Did you ever get the confirmation from the FSF? Yes, this is (finally) taken care of. The attached patch addresses everything except this issue with gdbarch. I didn't rebase, so you should be able to use interdiff to view the changes. -Justin [-- Attachment #2: skip-v2.diff --] [-- Type: text/x-patch, Size: 53450 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..e079155 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. @@ -4733,6 +4769,7 @@ (symbol_file_add): Pass NULL to the new parameter parent. * symfile.h (symbol_file_add_from_bfd): New parameter parent. +<<<<<<< HEAD 2011-04-17 Jan Kratochvil <jan.kratochvil@redhat.com> * elfread.c (elf_symtab_read): Do not ignore .L symbols if they are diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..d66d42b 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..d7e3799 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..a7a7e9c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,109 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skip + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip over a file or function when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @code{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. (@pxref{Specify Location}) + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{n}@r{]} +Print details about the skip with identifier @var{n}. If @var{n} is not +specified, print a table with details about all functions and files marked for +skipping. @code{info skip} prints the following information: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +@samp{function} or @samp{file} +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info break} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{n}@r{]} +Delete the skip with identifier @var{n}. If @var{n} is not specified, delete +all skips. + +@kindex skip enable +@item skip enable @r{[}@var{n}@r{]} +Enable the skip with identifier @var{n}. If @var{n} is not specified, enable +all skips. + +@kindex skip disable +@item skip disable @r{[}@var{n}@r{]} +Disable the skip with identifier @var{n}. If @var{n} is not specified, disable +all skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..40098bf --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,609 @@ +/* Skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" + +struct skiplist_entry +{ + int number; + + /* null if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); +//static void try_resolve_pending_entry (struct skiplist_entry *e); +static struct gdbarch *get_sal_arch (struct symtab_and_line *sal); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line *sal = &sals.sals[0]; + CORE_ADDR pc = sal->pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int entry_num = -1; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + if (arg != 0) + { + entry_num = parse_and_eval_long (arg); + } + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (entry_num == -1 || e->number == entry_num) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (entry_num == -1) + ui_out_message (current_uiout, 0, _("Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entry numbered %d.\n"), entry_num); + + return; + } + + if (opts.addressprint) + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 5, num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (entry_num != -1 && entry_num != e->number) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int entry_num; + if (arg == 0) + { + ALL_SKIPLIST_ENTRIES (e) + e->enabled = 1; + return; + } + + entry_num = parse_and_eval_long (arg); + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + e->enabled = 1; + return; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int entry_num; + if (arg == 0) + { + ALL_SKIPLIST_ENTRIES (e) + e->enabled = 0; + return; + } + + entry_num = parse_and_eval_long (arg); + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + e->enabled = 0; + return; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int entry_num; + + if (arg == 0) + { + ALL_SKIPLIST_ENTRIES_SAFE(e, temp) + { + xfree (e->function_name); + xfree (e->filename); + xfree (e); + } + skiplist_entry_chain = 0; + return; + } + + /* We don't need to use a SAFE macro here since we return as soon as we + remove an element from the list. */ + entry_num = parse_and_eval_long (arg); + b_prev = 0; + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + return; + } + else + { + b_prev = e; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + struct symtab_and_line sal; + char *filename; + struct skiplist_entry *e; + + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + + ALL_SKIPLIST_ENTRIES (e) + { + int pc_match = e->pc != 0 && pc == e->pc; + int filename_match = e->filename != 0 && filename != 0 && + strcmp (filename, e->filename) == 0; + if (e->enabled && !e->pending && (pc_match || filename_match)) + return 1; + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set () +{ + struct skiplist_entry *e; + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 && + sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line *sal = &sals.sals[0]; + CORE_ADDR pc = sal->pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup(func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +/* Helper function to get a gdbarch from a symtab_and_line. */ +static struct gdbarch* +get_sal_arch (struct symtab_and_line *sal) +{ + if (sal->section) + return get_objfile_arch (sal->section->objfile); + if (sal->symtab) + return get_objfile_arch (sal->symtab->objfile); + return get_current_arch (); +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable a skip entry.\n\ +skip enable [NUMBER]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable a skip entry.\n\ +skip disable [NUMBER]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete a skip entry.\n\ +skip delete [NUMBER]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Status of all skips, or of skip NUMBER.\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..c611555 --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..eedfd1b 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,88 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last codepoint we displayed, which we use e.g. as the place to + put a breakpoint when the `break' command is invoked with no arguments. */ +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +void +clear_last_displayed_sal () +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +int +last_displayed_sal_is_valid () +{ + return last_displayed_sal_valid; +} + +struct program_space* +get_last_displayed_pspace () +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +CORE_ADDR +get_last_displayed_addr () +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +struct symtab* +get_last_displayed_symtab () +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +int +get_last_displayed_line () +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..6200f52 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (); +int last_displayed_sal_is_valid (); +struct program_space* get_last_displayed_pspace (); +CORE_ADDR get_last_displayed_addr (); +struct symtab* get_last_displayed_symtab (); +int get_last_displayed_line (); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..1c4d0c9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..4f8838d --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,129 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${objdir}/${subdir}/${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +gdb_load ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ +"File ${srcfile_lib} will be skipped when stepping." \ +"ignoring file in solib" \ +"No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*"\ +"y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ +"info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ +"info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +gdb_load ${binfile_main} + +gdb_test "skip function multiply" \ +"Function multiply will be skipped when stepping, pending shared library load." \ +"ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*"\ +"y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..fecc197 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,151 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entry numbered 999." +gdb_test "skip disable 999" "No skiplist entry numbered 999." +gdb_test "skip delete 999" "No skiplist entry numbered 999." +gdb_test "skip enable a" "No symbol \"a\" in current context." +gdb_test "skip disable a" "No symbol \"a\" in current context." +gdb_test "skip delete a" "No symbol \"a\" in current context." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entry numbered 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# +if ![runto_main] { fail "skip tests suppressed" } +send_gdb "step\n" +gdb_test "bt" "#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +send_gdb "skip delete 1\n" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +send_gdb "skip disable 3\n" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +send_gdb "step\n"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +send_gdb "skip enable 3\n" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +send_gdb "skip disable\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after disabling all" + +send_gdb "skip enable\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after enabling all" + +send_gdb "skip delete\n" +gdb_test "info skip" "Not skipping any files or functions\." \ +"info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-11 21:34 ` Justin Lebar @ 2011-10-11 23:54 ` Doug Evans 2011-10-16 19:22 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Doug Evans @ 2011-10-11 23:54 UTC (permalink / raw) To: Justin Lebar; +Cc: Stan Shebs, gdb-patches On Tue, Oct 11, 2011 at 2:34 PM, Justin Lebar <justin.lebar@gmail.com> wrote: > The attached patch addresses everything except this issue with > gdbarch. I didn't rebase, so you should be able to use interdiff to > view the changes. Nit: This requires a NEWS entry to mention the new commands. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-11 23:54 ` Doug Evans @ 2011-10-16 19:22 ` Justin Lebar 2011-10-20 19:46 ` Tom Tromey 2011-10-20 20:40 ` Eli Zaretskii 0 siblings, 2 replies; 44+ messages in thread From: Justin Lebar @ 2011-10-16 19:22 UTC (permalink / raw) To: Doug Evans; +Cc: Stan Shebs, gdb-patches [-- Attachment #1: Type: text/plain, Size: 431 bytes --] Added a NEWS entry in this patch. -Justin On Tue, Oct 11, 2011 at 7:54 PM, Doug Evans <dje@google.com> wrote: > On Tue, Oct 11, 2011 at 2:34 PM, Justin Lebar <justin.lebar@gmail.com> wrote: >> The attached patch addresses everything except this issue with >> gdbarch. I didn't rebase, so you should be able to use interdiff to >> view the changes. > > Nit: This requires a NEWS entry to mention the new commands. > [-- Attachment #2: skip-3.diff --] [-- Type: text/x-patch, Size: 53650 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..4368e1b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/NEWS b/gdb/NEWS index 4d434c5..5e8d689 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB now allows you to skip over uninteresting functions and files when + stepping with the "skip function" and "skip file" commands. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..d66d42b 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..d7e3799 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..a7a7e9c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,109 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skip + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip over a file or function when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @code{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. (@pxref{Specify Location}) + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{n}@r{]} +Print details about the skip with identifier @var{n}. If @var{n} is not +specified, print a table with details about all functions and files marked for +skipping. @code{info skip} prints the following information: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +@samp{function} or @samp{file} +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info break} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{n}@r{]} +Delete the skip with identifier @var{n}. If @var{n} is not specified, delete +all skips. + +@kindex skip enable +@item skip enable @r{[}@var{n}@r{]} +Enable the skip with identifier @var{n}. If @var{n} is not specified, enable +all skips. + +@kindex skip disable +@item skip disable @r{[}@var{n}@r{]} +Disable the skip with identifier @var{n}. If @var{n} is not specified, disable +all skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..40098bf --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,609 @@ +/* Skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" + +struct skiplist_entry +{ + int number; + + /* null if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); +//static void try_resolve_pending_entry (struct skiplist_entry *e); +static struct gdbarch *get_sal_arch (struct symtab_and_line *sal); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line *sal = &sals.sals[0]; + CORE_ADDR pc = sal->pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int entry_num = -1; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + if (arg != 0) + { + entry_num = parse_and_eval_long (arg); + } + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (entry_num == -1 || e->number == entry_num) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (entry_num == -1) + ui_out_message (current_uiout, 0, _("Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entry numbered %d.\n"), entry_num); + + return; + } + + if (opts.addressprint) + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 5, num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (entry_num != -1 && entry_num != e->number) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int entry_num; + if (arg == 0) + { + ALL_SKIPLIST_ENTRIES (e) + e->enabled = 1; + return; + } + + entry_num = parse_and_eval_long (arg); + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + e->enabled = 1; + return; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int entry_num; + if (arg == 0) + { + ALL_SKIPLIST_ENTRIES (e) + e->enabled = 0; + return; + } + + entry_num = parse_and_eval_long (arg); + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + e->enabled = 0; + return; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int entry_num; + + if (arg == 0) + { + ALL_SKIPLIST_ENTRIES_SAFE(e, temp) + { + xfree (e->function_name); + xfree (e->filename); + xfree (e); + } + skiplist_entry_chain = 0; + return; + } + + /* We don't need to use a SAFE macro here since we return as soon as we + remove an element from the list. */ + entry_num = parse_and_eval_long (arg); + b_prev = 0; + ALL_SKIPLIST_ENTRIES (e) + if (e->number == entry_num) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + return; + } + else + { + b_prev = e; + } + + error (_("No skiplist entry numbered %d."), entry_num); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + struct symtab_and_line sal; + char *filename; + struct skiplist_entry *e; + + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + + ALL_SKIPLIST_ENTRIES (e) + { + int pc_match = e->pc != 0 && pc == e->pc; + int filename_match = e->filename != 0 && filename != 0 && + strcmp (filename, e->filename) == 0; + if (e->enabled && !e->pending && (pc_match || filename_match)) + return 1; + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set () +{ + struct skiplist_entry *e; + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 && + sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line *sal = &sals.sals[0]; + CORE_ADDR pc = sal->pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup(func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +/* Helper function to get a gdbarch from a symtab_and_line. */ +static struct gdbarch* +get_sal_arch (struct symtab_and_line *sal) +{ + if (sal->section) + return get_objfile_arch (sal->section->objfile); + if (sal->symtab) + return get_objfile_arch (sal->symtab->objfile); + return get_current_arch (); +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable a skip entry.\n\ +skip enable [NUMBER]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable a skip entry.\n\ +skip disable [NUMBER]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete a skip entry.\n\ +skip delete [NUMBER]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Status of all skips, or of skip NUMBER.\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..c611555 --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..eedfd1b 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,88 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last codepoint we displayed, which we use e.g. as the place to + put a breakpoint when the `break' command is invoked with no arguments. */ +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +void +clear_last_displayed_sal () +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +int +last_displayed_sal_is_valid () +{ + return last_displayed_sal_valid; +} + +struct program_space* +get_last_displayed_pspace () +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +CORE_ADDR +get_last_displayed_addr () +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +struct symtab* +get_last_displayed_symtab () +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +int +get_last_displayed_line () +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..6200f52 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (); +int last_displayed_sal_is_valid (); +struct program_space* get_last_displayed_pspace (); +CORE_ADDR get_last_displayed_addr (); +struct symtab* get_last_displayed_symtab (); +int get_last_displayed_line (); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..1c4d0c9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..4f8838d --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,129 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${objdir}/${subdir}/${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +gdb_load ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ +"File ${srcfile_lib} will be skipped when stepping." \ +"ignoring file in solib" \ +"No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*"\ +"y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ +"info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ +"info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +gdb_load ${binfile_main} + +gdb_test "skip function multiply" \ +"Function multiply will be skipped when stepping, pending shared library load." \ +"ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*"\ +"y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..fecc197 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,151 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entry numbered 999." +gdb_test "skip disable 999" "No skiplist entry numbered 999." +gdb_test "skip delete 999" "No skiplist entry numbered 999." +gdb_test "skip enable a" "No symbol \"a\" in current context." +gdb_test "skip disable a" "No symbol \"a\" in current context." +gdb_test "skip delete a" "No symbol \"a\" in current context." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entry numbered 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# +if ![runto_main] { fail "skip tests suppressed" } +send_gdb "step\n" +gdb_test "bt" "#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +send_gdb "skip delete 1\n" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +send_gdb "skip disable 3\n" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +send_gdb "step\n"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +send_gdb "skip enable 3\n" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +send_gdb "skip disable\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after disabling all" + +send_gdb "skip enable\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after enabling all" + +send_gdb "skip delete\n" +gdb_test "info skip" "Not skipping any files or functions\." \ +"info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-16 19:22 ` Justin Lebar @ 2011-10-20 19:46 ` Tom Tromey 2011-10-25 20:07 ` Justin Lebar 2011-10-20 20:40 ` Eli Zaretskii 1 sibling, 1 reply; 44+ messages in thread From: Tom Tromey @ 2011-10-20 19:46 UTC (permalink / raw) To: Justin Lebar; +Cc: Doug Evans, Stan Shebs, gdb-patches >>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: Justin> Added a NEWS entry in this patch. Thanks. I think this still needs a doc review. Some review below. I think this patch is pretty close to being ready; and I am eager for it to go in. Justin> + /* null if this isn't a skiplist entry for an entire file. "NULL" Justin> + The skiplist entry owns this pointer. */ In our style, sentences have 2 spaces after the period. Justin> +//static void try_resolve_pending_entry (struct skiplist_entry *e); We can't use "//" comments in gdb, but I think there's really no reason for a new file to have commented-out code. Justin> + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) Space before the open paren. Justin> + if (arg != 0) Justin> + { Justin> + entry_num = parse_and_eval_long (arg); Justin> + } This will parse and evaluate an expression. I think something like what "info break" does would be more in keeping with other places in gdb -- that is, use get_number_or_range, then iterate. Justin> + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, "blklst-entry"); I think this line is too long. Maybe a few others in this function, too. Justin> +static void Justin> +skip_enable_command (char *arg, int from_tty) Justin> +{ Justin> + struct skiplist_entry *e; Justin> + int entry_num; Justin> + if (arg == 0) Newline after the declaration block, here and elsewhere. Justin> + entry_num = parse_and_eval_long (arg); This command and others should use get_number_or_range. Justin> + ALL_SKIPLIST_ENTRIES_SAFE(e, temp) Space before open paren. Justin> + ALL_SKIPLIST_ENTRIES (e) Justin> + { Justin> + int pc_match = e->pc != 0 && pc == e->pc; Justin> + int filename_match = e->filename != 0 && filename != 0 && You have to parenthesize the RHS according to GNU standards, and put the "&&" at the start of the second line. Justin> + strcmp (filename, e->filename) == 0; Justin> + if (e->enabled && !e->pending && (pc_match || filename_match)) Justin> + return 1; I think you could check enabled and pending earlier and avoid the strcmp unless truly needed. Also I think it would be worthwhile to lazily compute the SAL in this function, to avoid computing it at all when there are no (or no enabled) skip entries. Justin> +void Justin> +skip_re_set () Should be '(void)' Justin> + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) Space before paren. Justin> + if (decode_exception.reason >= 0 && "&&" on next line. Justin> + e->function_name = xstrdup(func_name); Space before paren. Justin> +/* Helper function to get a gdbarch from a symtab_and_line. */ Justin> +static struct gdbarch* Justin> +get_sal_arch (struct symtab_and_line *sal) Justin> +{ Justin> + if (sal->section) Justin> + return get_objfile_arch (sal->section->objfile); Justin> + if (sal->symtab) Justin> + return get_objfile_arch (sal->symtab->objfile); Justin> + return get_current_arch (); Justin> +} I think it is better to make this public in breakpoint.c. Really, we should probably have a "sal.h" and "sal.c" and treat it like a real data structure. Not your job though. Justin> + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ Justin> +Ignore a function while stepping.\n\ Justin> +skip [FUNCTION NAME]\n\ I'd like this line to start with "Usage: " (and likewise in the other help text). Justin> +void skip_re_set (); Should be '(void)'. Justin> +struct program_space* Justin> +get_last_displayed_pspace () Space before "*". "(void)", here and elsewhere. Most of the functions around this need introductory comments. Justin> +void clear_last_displayed_sal (); Justin> +int last_displayed_sal_is_valid (); Justin> +struct program_space* get_last_displayed_pspace (); Justin> +CORE_ADDR get_last_displayed_addr (); Justin> +struct symtab* get_last_displayed_symtab (); Justin> +int get_last_displayed_line (); "(void)" for all of these. Tom ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-20 19:46 ` Tom Tromey @ 2011-10-25 20:07 ` Justin Lebar 2011-10-25 20:41 ` Pedro Alves 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-25 20:07 UTC (permalink / raw) To: Tom Tromey; +Cc: Doug Evans, Stan Shebs, gdb-patches > Justin> + if (arg != 0) > Justin> + { > Justin> + entry_num = parse_and_eval_long (arg); > Justin> + } > > This will parse and evaluate an expression. I think something like what > "info break" does would be more in keeping with other places in gdb -- > that is, use get_number_or_range, then iterate. breakpoint_1 calls parse_and_eval_long: if (allflag && parse_and_eval_long (args) != b->number) continue; if (!allflag && !number_is_in_list (args, b->number)) continue; Do we want to copy the breakpoint code here, or not? On Thu, Oct 20, 2011 at 3:33 PM, Tom Tromey <tromey@redhat.com> wrote: >>>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: > > Justin> Added a NEWS entry in this patch. > > Thanks. > > I think this still needs a doc review. > > Some review below. I think this patch is pretty close to being ready; > and I am eager for it to go in. > > Justin> + /* null if this isn't a skiplist entry for an entire file. > > "NULL" > > Justin> + The skiplist entry owns this pointer. */ > > In our style, sentences have 2 spaces after the period. > > Justin> +//static void try_resolve_pending_entry (struct skiplist_entry *e); > > We can't use "//" comments in gdb, but I think there's really no reason > for a new file to have commented-out code. > > Justin> + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) > > Space before the open paren. > > Justin> + if (arg != 0) > Justin> + { > Justin> + entry_num = parse_and_eval_long (arg); > Justin> + } > > This will parse and evaluate an expression. I think something like what > "info break" does would be more in keeping with other places in gdb -- > that is, use get_number_or_range, then iterate. > > Justin> + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, "blklst-entry"); > > I think this line is too long. > Maybe a few others in this function, too. > > Justin> +static void > Justin> +skip_enable_command (char *arg, int from_tty) > Justin> +{ > Justin> + struct skiplist_entry *e; > Justin> + int entry_num; > Justin> + if (arg == 0) > > Newline after the declaration block, here and elsewhere. > > Justin> + entry_num = parse_and_eval_long (arg); > > This command and others should use get_number_or_range. > > Justin> + ALL_SKIPLIST_ENTRIES_SAFE(e, temp) > > Space before open paren. > > Justin> + ALL_SKIPLIST_ENTRIES (e) > Justin> + { > Justin> + int pc_match = e->pc != 0 && pc == e->pc; > Justin> + int filename_match = e->filename != 0 && filename != 0 && > > You have to parenthesize the RHS according to GNU standards, and put the > "&&" at the start of the second line. > > Justin> + strcmp (filename, e->filename) == 0; > Justin> + if (e->enabled && !e->pending && (pc_match || filename_match)) > Justin> + return 1; > > I think you could check enabled and pending earlier and avoid the strcmp > unless truly needed. > > Also I think it would be worthwhile to lazily compute the SAL in this > function, to avoid computing it at all when there are no (or no enabled) > skip entries. > > Justin> +void > Justin> +skip_re_set () > > Should be '(void)' > > Justin> + TRY_CATCH(decode_exception, NOT_FOUND_ERROR) > > Space before paren. > > Justin> + if (decode_exception.reason >= 0 && > > "&&" on next line. > > Justin> + e->function_name = xstrdup(func_name); > > Space before paren. > > Justin> +/* Helper function to get a gdbarch from a symtab_and_line. */ > Justin> +static struct gdbarch* > Justin> +get_sal_arch (struct symtab_and_line *sal) > Justin> +{ > Justin> + if (sal->section) > Justin> + return get_objfile_arch (sal->section->objfile); > Justin> + if (sal->symtab) > Justin> + return get_objfile_arch (sal->symtab->objfile); > Justin> + return get_current_arch (); > Justin> +} > > I think it is better to make this public in breakpoint.c. > > Really, we should probably have a "sal.h" and "sal.c" and treat it like > a real data structure. Not your job though. > > Justin> + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ > Justin> +Ignore a function while stepping.\n\ > Justin> +skip [FUNCTION NAME]\n\ > > I'd like this line to start with "Usage: " (and likewise in the other > help text). > > Justin> +void skip_re_set (); > > Should be '(void)'. > > Justin> +struct program_space* > Justin> +get_last_displayed_pspace () > > Space before "*". > "(void)", here and elsewhere. > > Most of the functions around this need introductory comments. > > Justin> +void clear_last_displayed_sal (); > Justin> +int last_displayed_sal_is_valid (); > Justin> +struct program_space* get_last_displayed_pspace (); > Justin> +CORE_ADDR get_last_displayed_addr (); > Justin> +struct symtab* get_last_displayed_symtab (); > Justin> +int get_last_displayed_line (); > > "(void)" for all of these. > > Tom > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 20:07 ` Justin Lebar @ 2011-10-25 20:41 ` Pedro Alves 2011-10-25 21:25 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Pedro Alves @ 2011-10-25 20:41 UTC (permalink / raw) To: gdb-patches; +Cc: Justin Lebar, Tom Tromey, Doug Evans, Stan Shebs On Tuesday 25 October 2011 20:51:31, Justin Lebar wrote: > > Justin> + if (arg != 0) > > Justin> + { > > Justin> + entry_num = parse_and_eval_long (arg); > > Justin> + } > > > > This will parse and evaluate an expression. I think something like what > > "info break" does would be more in keeping with other places in gdb -- > > that is, use get_number_or_range, then iterate. > > breakpoint_1 calls parse_and_eval_long: > > if (allflag && parse_and_eval_long (args) != b->number) > continue; > if (!allflag && !number_is_in_list (args, b->number)) > continue; > > Do we want to copy the breakpoint code here, or not? Yes. :-) ALLFLAG being true means breakpoint_1 is being called to implement the "maint info breakpoints" command, which needs to handle negative breakpoint numbers, which are not visible to the regular "info breakpoints" command. That uses parse_and_eval_long because ranges can't handle negative numbers. When ALLFLAG is false, that code is implementing the "info breakpoints" command, and that you'll notice the number_is_in_list call, which is a wrapper around get_number_or_range. If you make your code use number_is_in_list, you'll get e.g., "info skip 1-10 12 30" support for free. -- Pedro Alves ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 20:41 ` Pedro Alves @ 2011-10-25 21:25 ` Justin Lebar 0 siblings, 0 replies; 44+ messages in thread From: Justin Lebar @ 2011-10-25 21:25 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Tom Tromey, Doug Evans, Stan Shebs Ah, I missed that "!". Thanks! On Tue, Oct 25, 2011 at 4:36 PM, Pedro Alves <pedro@codesourcery.com> wrote: > On Tuesday 25 October 2011 20:51:31, Justin Lebar wrote: >> > Justin> + if (arg != 0) >> > Justin> + { >> > Justin> + entry_num = parse_and_eval_long (arg); >> > Justin> + } >> > >> > This will parse and evaluate an expression. I think something like what >> > "info break" does would be more in keeping with other places in gdb -- >> > that is, use get_number_or_range, then iterate. >> >> breakpoint_1 calls parse_and_eval_long: >> >> if (allflag && parse_and_eval_long (args) != b->number) >> continue; >> if (!allflag && !number_is_in_list (args, b->number)) >> continue; >> >> Do we want to copy the breakpoint code here, or not? > > Yes. :-) ALLFLAG being true means breakpoint_1 is being called > to implement the "maint info breakpoints" command, which needs to > handle negative breakpoint numbers, which are not visible to the > regular "info breakpoints" command. That uses parse_and_eval_long > because ranges can't handle negative numbers. When ALLFLAG is false, > that code is implementing the "info breakpoints" command, and that > you'll notice the number_is_in_list call, which is a wrapper around > get_number_or_range. If you make your code use number_is_in_list, > you'll get e.g., "info skip 1-10 12 30" support for free. > > -- > Pedro Alves > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-16 19:22 ` Justin Lebar 2011-10-20 19:46 ` Tom Tromey @ 2011-10-20 20:40 ` Eli Zaretskii 2011-10-25 16:47 ` Justin Lebar 1 sibling, 1 reply; 44+ messages in thread From: Eli Zaretskii @ 2011-10-20 20:40 UTC (permalink / raw) To: Justin Lebar; +Cc: dje, stanshebs, gdb-patches > From: Justin Lebar <justin.lebar@gmail.com> > Date: Sun, 16 Oct 2011 12:40:39 -0400 > Cc: Stan Shebs <stanshebs@earthlink.net>, gdb-patches@sourceware.org > > Added a NEWS entry in this patch. Thanks. > +* GDB now allows you to skip over uninteresting functions and files when ^^^^^^^^^ I think either "step over" or just "skip". > +@node Skipping Over Functions and Files > +@subsection Skipping Over Functions and Files > +@cindex skip This @cindex entry would be better if it just said what the subsection name says: @cindex skipping over functions and files > +The program you are debugging may contain some functions which are > +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to > +skip over a file or function when stepping. Again, I think this is better: ... to skip a function or all functions in a file ... > +A more flexible solution is to execute @code{skip boring}. This instructs ^^^^^^^^^^^^^^^^^^ @kbd{skip boring}, since this is something the user types on the keyboard. > +You can also instruct @value{GDBN} to skip all functions in a file, with, for > +example, @code{skip file boring.c}. What happens if I have a function called "file" in the same program? IOW, to what degree is "file" a reserved keyword here? > +@table @code > +@kindex skip > +@kindex skip function No need for two @kindex entries here, the second one is enough. > +stepping. (@pxref{Specify Location}) Just @xref, and no parentheses, like so: @xref{Specify Location}. > +@item Type > +@samp{function} or @samp{file} The text below the @item line should be at least one complete sentence. > +being skipped. If you've set a function skip on a function which has not yet > +been loaded, this field will contain @samp{<PENDING>}. Once a shared library > +which has the function is loaded, @code{info break} will show the function's ^^^^^^^^^^ I guess you meant "info skip", right? Okay with those changes. Thanks. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-20 20:40 ` Eli Zaretskii @ 2011-10-25 16:47 ` Justin Lebar 2011-10-25 16:53 ` Eli Zaretskii 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-25 16:47 UTC (permalink / raw) To: Eli Zaretskii; +Cc: dje, stanshebs, gdb-patches > What happens if I have a function called "file" in the same program? > IOW, to what degree is "file" a reserved keyword here? Even if you have a function named "file", |skip file| will skip the current file. But |skip function file| would skip the function called "file". >> +@item Type >> +@samp{function} or @samp{file} > > The text below the @item line should be at least one complete > sentence. FWIW, I think @samp{function} or @samp{file} beats This field contains either @samp{function} or @samp{file}, indicating whether the skip is on one function or all the functions in a file. > @item Identifier > A number identifying this skip. This is not a complete sentence. Should it be changed as well? -Justin On Thu, Oct 20, 2011 at 4:17 PM, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Justin Lebar <justin.lebar@gmail.com> >> Date: Sun, 16 Oct 2011 12:40:39 -0400 >> Cc: Stan Shebs <stanshebs@earthlink.net>, gdb-patches@sourceware.org >> >> Added a NEWS entry in this patch. > > Thanks. > >> +* GDB now allows you to skip over uninteresting functions and files when > ^^^^^^^^^ > I think either "step over" or just "skip". > >> +@node Skipping Over Functions and Files >> +@subsection Skipping Over Functions and Files >> +@cindex skip > > This @cindex entry would be better if it just said what the subsection > name says: > > @cindex skipping over functions and files > >> +The program you are debugging may contain some functions which are >> +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to >> +skip over a file or function when stepping. > > Again, I think this is better: > > ... to skip a function or all functions in a file ... > >> +A more flexible solution is to execute @code{skip boring}. This instructs > ^^^^^^^^^^^^^^^^^^ > @kbd{skip boring}, since this is something the user types on the > keyboard. > >> +You can also instruct @value{GDBN} to skip all functions in a file, with, for >> +example, @code{skip file boring.c}. > > What happens if I have a function called "file" in the same program? > IOW, to what degree is "file" a reserved keyword here? > >> +@table @code >> +@kindex skip >> +@kindex skip function > > No need for two @kindex entries here, the second one is enough. > >> +stepping. (@pxref{Specify Location}) > > Just @xref, and no parentheses, like so: > > @xref{Specify Location}. > >> +@item Type >> +@samp{function} or @samp{file} > > The text below the @item line should be at least one complete > sentence. > >> +being skipped. If you've set a function skip on a function which has not yet >> +been loaded, this field will contain @samp{<PENDING>}. Once a shared library >> +which has the function is loaded, @code{info break} will show the function's > ^^^^^^^^^^ > I guess you meant "info skip", right? > > Okay with those changes. > > Thanks. > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 16:47 ` Justin Lebar @ 2011-10-25 16:53 ` Eli Zaretskii 2011-10-25 19:52 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Eli Zaretskii @ 2011-10-25 16:53 UTC (permalink / raw) To: Justin Lebar; +Cc: dje, stanshebs, gdb-patches > From: Justin Lebar <justin.lebar@gmail.com> > Date: Tue, 25 Oct 2011 12:08:09 -0400 > Cc: dje@google.com, stanshebs@earthlink.net, gdb-patches@sourceware.org > > > What happens if I have a function called "file" in the same program? > > IOW, to what degree is "file" a reserved keyword here? > > Even if you have a function named "file", |skip file| will skip the > current file. But |skip function file| would skip the function called > "file". I suggest to say this explicitly as a note. E.g., like this: (If you have a function called @code{file} that you want to skip, use @kbd{skip function file} to specify it.) > >> +@item Type > >> +@samp{function} or @samp{file} > > > > The text below the @item line should be at least one complete > > sentence. > > FWIW, I think > > @samp{function} or @samp{file} > > beats > > This field contains either @samp{function} or @samp{file}, > indicating whether > the skip is on one function or all the functions in a file. I didn't suggest the latter; you did ;-) I will settle for The type of this skip, either @samp{function} or @samp{file}. > > @item Identifier > > A number identifying this skip. > > This is not a complete sentence. Should it be changed as well? No need, it is complete enough for me. Thanks. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 16:53 ` Eli Zaretskii @ 2011-10-25 19:52 ` Justin Lebar 2011-10-25 20:13 ` Eli Zaretskii 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-25 19:52 UTC (permalink / raw) To: Eli Zaretskii; +Cc: dje, stanshebs, gdb-patches > (If you have a function called @code{file} that you want to skip, use > @kbd{skip function file} to specify it.) I have no stake in the matter, but is this really such a common issue that it belongs in the manual? -Justin On Tue, Oct 25, 2011 at 12:47 PM, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Justin Lebar <justin.lebar@gmail.com> >> Date: Tue, 25 Oct 2011 12:08:09 -0400 >> Cc: dje@google.com, stanshebs@earthlink.net, gdb-patches@sourceware.org >> >> > What happens if I have a function called "file" in the same program? >> > IOW, to what degree is "file" a reserved keyword here? >> >> Even if you have a function named "file", |skip file| will skip the >> current file. But |skip function file| would skip the function called >> "file". > > I suggest to say this explicitly as a note. E.g., like this: > > (If you have a function called @code{file} that you want to skip, use > @kbd{skip function file} to specify it.) > >> >> +@item Type >> >> +@samp{function} or @samp{file} >> > >> > The text below the @item line should be at least one complete >> > sentence. >> >> FWIW, I think >> >> @samp{function} or @samp{file} >> >> beats >> >> This field contains either @samp{function} or @samp{file}, >> indicating whether >> the skip is on one function or all the functions in a file. > > I didn't suggest the latter; you did ;-) > > I will settle for > > The type of this skip, either @samp{function} or @samp{file}. > >> > @item Identifier >> > A number identifying this skip. >> >> This is not a complete sentence. Should it be changed as well? > > No need, it is complete enough for me. > > Thanks. > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 19:52 ` Justin Lebar @ 2011-10-25 20:13 ` Eli Zaretskii 2011-10-25 20:30 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Eli Zaretskii @ 2011-10-25 20:13 UTC (permalink / raw) To: Justin Lebar; +Cc: dje, stanshebs, gdb-patches > From: Justin Lebar <justin.lebar@gmail.com> > Date: Tue, 25 Oct 2011 15:49:51 -0400 > Cc: dje@google.com, stanshebs@earthlink.net, gdb-patches@sourceware.org > > > (If you have a function called @code{file} that you want to skip, use > > @kbd{skip function file} to specify it.) > > I have no stake in the matter, but is this really such a common issue > that it belongs in the manual? Put yourself in the shoes of someone who, however rare this can be, stumbles on it. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 20:13 ` Eli Zaretskii @ 2011-10-25 20:30 ` Justin Lebar 2011-10-26 1:06 ` Stan Shebs 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-25 20:30 UTC (permalink / raw) To: Eli Zaretskii; +Cc: dje, stanshebs, gdb-patches On Tue, Oct 25, 2011 at 4:07 PM, Eli Zaretskii <eliz@gnu.org> wrote: >> From: Justin Lebar <justin.lebar@gmail.com> >> Date: Tue, 25 Oct 2011 15:49:51 -0400 >> Cc: dje@google.com, stanshebs@earthlink.net, gdb-patches@sourceware.org >> >> > (If you have a function called @code{file} that you want to skip, use >> > @kbd{skip function file} to specify it.) >> >> I have no stake in the matter, but is this really such a common issue >> that it belongs in the manual? > > Put yourself in the shoes of someone who, however rare this can be, > stumbles on it. In the unlikely case that I actually opened the manual (not because it's no good, but because most people I know who use GDB aren't aware of the manual -- it's not well-linked on the web), I think the fact that there are |skip file| and |skip function| commands would clear things up pretty quickly. There's a cost to a comment like this; it's not useful to most readers, but they have to parse it anyway. (What the heck does "skip function file" mean?) But again, I don't really have a stake in this either way. I just want to get my patch in. :) ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-25 20:30 ` Justin Lebar @ 2011-10-26 1:06 ` Stan Shebs 2011-10-26 3:45 ` Justin Lebar 2011-10-26 13:28 ` Eli Zaretskii 0 siblings, 2 replies; 44+ messages in thread From: Stan Shebs @ 2011-10-26 1:06 UTC (permalink / raw) To: gdb-patches On 10/25/2011 01:16 PM, Justin Lebar wrote: > In the unlikely case that I actually opened the manual (not because > it's no good, but because most people I know who use GDB aren't aware > of the manual -- it's not well-linked on the web), I think the fact > that there are |skip file| and |skip function| commands would clear > things up pretty quickly. > > There's a cost to a comment like this; it's not useful to most > readers, but they have to parse it anyway. (What the heck does "skip > function file" mean?) Another purpose for having niggling details in the manual is that in the absence of a formal specification, the manual is our promise to users of what they should expect to work, and how it will work. So users find themselves referring to the manual when they try something that seems obvious, and are surprised that it doesn't work as expected. > But again, I don't really have a stake in this either way. I just > want to get my patch in. :) I'd like to see a new rollup with all the feedback incorporated, I've lost track of the state... :-) Stan ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 1:06 ` Stan Shebs @ 2011-10-26 3:45 ` Justin Lebar 2011-10-26 5:37 ` Stan Shebs 2011-10-26 13:28 ` Eli Zaretskii 1 sibling, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-26 3:45 UTC (permalink / raw) To: Stan Shebs, Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 2953 bytes --] Rollup patch is attached, incorporating all feedback so far (I think!). As usual, you should be able to use interdiff to view the changes. Let me know if that doesn't work and I can make git spit it out. Unfortunately the tests are randomly failing on me. I'm not sure what's going on, but it looks like we're not always waiting long enough after runto_main, somehow. The relevant expect code (in gdb.base/skip.exp) is: if ![runto_main] { fail "skip tests suppressed" } send_gdb "step\n" # XXX This gdb_test sometimes fails, due to an apparent race. gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" Here's a diff of gdb.log in a successful run (-) and an unsuccessful run (+). @@ -112,20 +112,20 @@ Start it from the beginning? (y or n) y Starting program: /home/jlebar/code/gdb/debug/gdb/testsuite/gdb.base/skip Breakpoint 2, main () at ../../../src/gdb/testsuite/gdb.base/skip.c:7 7 return baz(foo(), bar()); (gdb) step bt 8 } -(gdb) bt +(gdb) FAIL: gdb.base/skip.exp: step after all ignored +bt #0 main () at ../../../src/gdb/testsuite/gdb.base/skip.c:8 -(gdb) PASS: gdb.base/skip.exp: step after all ignored -skip delete 1 +(gdb) skip delete 1 (gdb) info skip Num Type Enb Address What 2 function y 0x00000000004004e4 main at ../../../src/gdb/testsuite/gdb.base/skip.c:5 3 file y ../../../src/gdb/testsuite/gdb.base/skip1.c 4 function y 0x000000000040052b baz at ../../../src/gdb/testsuite/gdb.base/skip1.c:6 (gdb) PASS: gdb.base/skip.exp: info skip delete breakpoints Delete all breakpoints? (y or n) y @@ -226,17 +226,16 @@ Any ideas what's going on here? -Justin On Tue, Oct 25, 2011 at 8:26 PM, Stan Shebs <stan_shebs@mentor.com> wrote: > On 10/25/2011 01:16 PM, Justin Lebar wrote: >> >> In the unlikely case that I actually opened the manual (not because >> it's no good, but because most people I know who use GDB aren't aware >> of the manual -- it's not well-linked on the web), I think the fact >> that there are |skip file| and |skip function| commands would clear >> things up pretty quickly. >> >> There's a cost to a comment like this; it's not useful to most >> readers, but they have to parse it anyway. (What the heck does "skip >> function file" mean?) > > Another purpose for having niggling details in the manual is that in the > absence of a formal specification, the manual is our promise to users of > what they should expect to work, and how it will work. So users find > themselves referring to the manual when they try something that seems > obvious, and are surprised that it doesn't work as expected. > >> But again, I don't really have a stake in this either way. I just >> want to get my patch in. :) > > I'd like to see a new rollup with all the feedback incorporated, I've lost > track of the state... :-) > > Stan > > [-- Attachment #2: skip-4.diff --] [-- Type: text/x-patch, Size: 56453 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..0f10225 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + (get_sal_arch): Declare. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (get_sal_arch): Make public. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/NEWS b/gdb/NEWS index 4d434c5..8225cf8 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB now allows you to skip uninteresting functions and files when + stepping with the "skip function" and "skip file" commands. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..b41fb79 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -5764,7 +5739,7 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) } /* Attempt to determine architecture of location identified by SAL. */ -static struct gdbarch * +struct gdbarch * get_sal_arch (struct symtab_and_line sal) { if (sal.section) @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..f171035 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); @@ -1359,4 +1356,8 @@ extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint * extern int user_breakpoint_p (struct breakpoint *); +/* Attempt to determine architecture of location identified by SAL. */ +extern struct gdbarch * +get_sal_arch (struct symtab_and_line sal); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..382dfd4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,111 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skipping over functions and files + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip a function or all functions in a file when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @kbd{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. @xref{Specify Location} + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +(If you have a function called @code{file} that you want to skip, use +@kbd{skip function file}.) + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{range}@r{]} +Print details about the specified skip(s). If @var{range} is not specified, +print a table with details about all functions and files marked for skipping. +@code{info skip} prints the following information about each skip: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +The type of this skip, either @samp{function} or @samp{file}. +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info skip} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{range}@r{]} +Delete the specified skip(s). If @var{range} is not specified, delete all +skips. + +@kindex skip enable +@item skip enable @r{[}@var{range}@r{]} +Enable the specified skip(s). If @var{range} is not specified, enable all +skips. + +@kindex skip disable +@item skip disable @r{[}@var{range}@r{]} +Disable the specified skip(s). If @var{range} is not specified, disable all +skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..d2f064f --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,598 @@ +/* Skipping uninteresting files and functions while stepping. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" +#include "breakpoint.h" /* for get_sal_arch() */ + +struct skiplist_entry +{ + int number; + + /* NULL if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH (decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (arg == 0) + ui_out_message (current_uiout, 0, _("\ +Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entries found with number %s.\n"), arg); + + return; + } + + if (opts.addressprint) + tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 5, + num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, + num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (arg != 0 && !number_is_in_list(arg, e->number)) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, + "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", + e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + e->enabled = 1; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + e->enabled = 0; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int found = 0; + + b_prev = 0; + ALL_SKIPLIST_ENTRIES_SAFE (e, temp) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + found = 1; + } + else + { + b_prev = e; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + int searched_for_sal = 0; + struct symtab_and_line sal; + char *filename = NULL; + struct skiplist_entry *e; + + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + + ALL_SKIPLIST_ENTRIES (e) + { + if (!e->enabled || e->pending) + continue; + + /* Does the pc we're stepping into match e's stored pc? */ + if (e->pc != 0 && pc == e->pc) + return 1; + + if (e->filename != 0) + { + /* Get the filename corresponding to this pc, if we haven't + * yet. */ + if (!searched_for_sal) + { + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + searched_for_sal = 1; + } + if (filename != 0 && strcmp (filename, e->filename) == 0) + return 1; + } + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set (void) +{ + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH (decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 + && sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup (func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +Usage: skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable skip entries. You can specify numbers (e.g. \"skip enable 1 3\"), \ +ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\ +Usage: skip enable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable skip entries. You can specify numbers (e.g. \"skip disable 1 3\"), \ +ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\ +Usage: skip disable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete skip entries. You can specify numbers (e.g. \"skip delete 1 3\"), \ +ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\ +Usage: skip delete [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Display the status of skips. You can specify numbers (e.g. \"skip info 1 3\"), \ +ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll show all skips.\n\n\ +Usage: skip info [NUMBERS AND/OR RANGES]\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..143f7ed --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (void); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..cf25eb7 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,98 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last symtab and line we displayed, which we use e.g. + * as the place to put a breakpoint when the `break' command is + * invoked with no arguments. */ +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +/* Forget the last sal we displayed. */ +void +clear_last_displayed_sal (void) +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +/* Is our record of the last sal we displayed valid? If not, + * the get_last_displayed_* functions will return NULL or 0, as + * appropriate. */ +int +last_displayed_sal_is_valid (void) +{ + return last_displayed_sal_valid; +} + +/* Get the pspace of the last sal we displayed, if it's valid. */ +struct program_space * +get_last_displayed_pspace (void) +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +/* Get the address of the last sal we displayed, if it's valid. */ +CORE_ADDR +get_last_displayed_addr (void) +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +/* Get the symtab of the last sal we displayed, if it's valid. */ +struct symtab* +get_last_displayed_symtab (void) +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +/* Get the line of the last sal we displayed, if it's valid. */ +int +get_last_displayed_line (void) +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +/* Get the last sal we displayed, if it's valid. */ +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..312e8ff 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (void); +int last_displayed_sal_is_valid (void); +struct program_space* get_last_displayed_pspace (void); +CORE_ADDR get_last_displayed_addr (void); +struct symtab* get_last_displayed_symtab (void); +int get_last_displayed_line (void); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..1c4d0c9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..4f8838d --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,129 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${objdir}/${subdir}/${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +gdb_load ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ +"File ${srcfile_lib} will be skipped when stepping." \ +"ignoring file in solib" \ +"No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*"\ +"y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ +"info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ +"info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +gdb_load ${binfile_main} + +gdb_test "skip function multiply" \ +"Function multiply will be skipped when stepping, pending shared library load." \ +"ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*"\ +"y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..d26a3c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,180 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entries found with number 999." +gdb_test "skip disable 999" "No skiplist entries found with number 999." +gdb_test "skip delete 999" "No skiplist entries found with number 999." +gdb_test "skip enable a" "Args must be numbers or '\\$' variables." +gdb_test "skip disable a" "Args must be numbers or '\\$' variables." +gdb_test "skip delete a" "Args must be numbers or '\\$' variables." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entries found with number 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# + +# XXX This gdb_test sometimes fails, due to an apparent race. +if ![runto_main] { fail "skip tests suppressed" } +send_gdb "step\n" +gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +send_gdb "skip delete 1\n" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +send_gdb "skip disable 3\n" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +send_gdb "step\n"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +send_gdb "skip enable 3\n" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +send_gdb "step\n"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +send_gdb "skip disable\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after disabling all" + +send_gdb "skip enable\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after enabling all" + +send_gdb "skip disable 4 2-3\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after disabling 4 2-3" + +send_gdb "skip enable 2-3\n" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after enabling 2-3" + +gdb_test "info skip 2-3" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s*" \ +"info skip 2-3" + +send_gdb "skip delete 2 3\n" +gdb_test "info skip" \ +"4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after deleting 2 3" + +send_gdb "skip delete\n" +gdb_test "info skip" "Not skipping any files or functions\." \ +"info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 3:45 ` Justin Lebar @ 2011-10-26 5:37 ` Stan Shebs 2011-10-26 8:10 ` Joel Brobecker 0 siblings, 1 reply; 44+ messages in thread From: Stan Shebs @ 2011-10-26 5:37 UTC (permalink / raw) To: gdb-patches On 10/25/11 6:05 PM, Justin Lebar wrote: > Rollup patch is attached, incorporating all feedback so far (I > think!). As usual, you should be able to use interdiff to view the > changes. Let me know if that doesn't work and I can make git spit it > out. > > Unfortunately the tests are randomly failing on me. I'm not sure > what's going on, but it looks like we're not always waiting long > enough after runto_main, somehow. > > The relevant expect code (in gdb.base/skip.exp) is: > > if ![runto_main] { fail "skip tests suppressed" } > send_gdb "step\n" > # XXX This gdb_test sometimes fails, due to an apparent race. > gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" > You need a gdb_expect after the send_gdb, otherwise the output from the step leaks into the next gdb_test and things get confused in the way you're seeing. I would use gdb_test for the "step" also, it's much simpler; send_gdb is only needed for unusual testing situations, and this is not one of them. :-) Stan ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 5:37 ` Stan Shebs @ 2011-10-26 8:10 ` Joel Brobecker 0 siblings, 0 replies; 44+ messages in thread From: Joel Brobecker @ 2011-10-26 8:10 UTC (permalink / raw) To: Stan Shebs; +Cc: gdb-patches > You need a gdb_expect after the send_gdb, otherwise the output from > the step leaks into the next gdb_test and things get confused in the > way you're seeing. I would use gdb_test for the "step" also, it's > much simpler; send_gdb is only needed for unusual testing > situations, and this is not one of them. :-) Actually, I am going to say something a little stronger: you must NOT use send_gdb/gdb_expect unless you have a good reason to do so. I know that many old test still use them, but I guess we didn't know better at the time... -- Joel ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 1:06 ` Stan Shebs 2011-10-26 3:45 ` Justin Lebar @ 2011-10-26 13:28 ` Eli Zaretskii 2011-10-26 15:11 ` Justin Lebar 1 sibling, 1 reply; 44+ messages in thread From: Eli Zaretskii @ 2011-10-26 13:28 UTC (permalink / raw) To: Stan Shebs; +Cc: gdb-patches > Date: Tue, 25 Oct 2011 17:26:44 -0700 > From: Stan Shebs <stan_shebs@mentor.com> > > > There's a cost to a comment like this; it's not useful to most > > readers, but they have to parse it anyway. (What the heck does "skip > > function file" mean?) > > Another purpose for having niggling details in the manual is that in the > absence of a formal specification, the manual is our promise to users of > what they should expect to work, and how it will work. So users find > themselves referring to the manual when they try something that seems > obvious, and are surprised that it doesn't work as expected. I know _I_ always consult the manual (not only for GDB), because I never remember enough details, especially subtle and obscure ones. Anyway, if Justin is opposed to adding this comment, I can always do it myself later. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 13:28 ` Eli Zaretskii @ 2011-10-26 15:11 ` Justin Lebar 2011-10-28 18:18 ` Tom Tromey 2011-10-28 19:49 ` Tom Tromey 0 siblings, 2 replies; 44+ messages in thread From: Justin Lebar @ 2011-10-26 15:11 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Stan Shebs, gdb-patches [-- Attachment #1: Type: text/plain, Size: 1157 bytes --] Thanks for the testing advice; I ran the test many times on my machine, and it now works without error every time. New roll-up patch is attached. The only difference from v4 is in skip.exp. -Justin On Wed, Oct 26, 2011 at 4:09 AM, Eli Zaretskii <eliz@gnu.org> wrote: >> Date: Tue, 25 Oct 2011 17:26:44 -0700 >> From: Stan Shebs <stan_shebs@mentor.com> >> >> > There's a cost to a comment like this; it's not useful to most >> > readers, but they have to parse it anyway. (What the heck does "skip >> > function file" mean?) >> >> Another purpose for having niggling details in the manual is that in the >> absence of a formal specification, the manual is our promise to users of >> what they should expect to work, and how it will work. So users find >> themselves referring to the manual when they try something that seems >> obvious, and are surprised that it doesn't work as expected. > > I know _I_ always consult the manual (not only for GDB), because I > never remember enough details, especially subtle and obscure ones. > > Anyway, if Justin is opposed to adding this comment, I can always do > it myself later. > [-- Attachment #2: skip-5.diff --] [-- Type: text/x-patch, Size: 56362 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..0f10225 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + (get_sal_arch): Declare. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (get_sal_arch): Make public. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/NEWS b/gdb/NEWS index 4d434c5..8225cf8 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB now allows you to skip uninteresting functions and files when + stepping with the "skip function" and "skip file" commands. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..b41fb79 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -5764,7 +5739,7 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) } /* Attempt to determine architecture of location identified by SAL. */ -static struct gdbarch * +struct gdbarch * get_sal_arch (struct symtab_and_line sal) { if (sal.section) @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..f171035 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); @@ -1359,4 +1356,8 @@ extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint * extern int user_breakpoint_p (struct breakpoint *); +/* Attempt to determine architecture of location identified by SAL. */ +extern struct gdbarch * +get_sal_arch (struct symtab_and_line sal); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..382dfd4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,111 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skipping over functions and files + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip a function or all functions in a file when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @kbd{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. @xref{Specify Location} + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +(If you have a function called @code{file} that you want to skip, use +@kbd{skip function file}.) + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{range}@r{]} +Print details about the specified skip(s). If @var{range} is not specified, +print a table with details about all functions and files marked for skipping. +@code{info skip} prints the following information about each skip: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +The type of this skip, either @samp{function} or @samp{file}. +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info skip} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{range}@r{]} +Delete the specified skip(s). If @var{range} is not specified, delete all +skips. + +@kindex skip enable +@item skip enable @r{[}@var{range}@r{]} +Enable the specified skip(s). If @var{range} is not specified, enable all +skips. + +@kindex skip disable +@item skip disable @r{[}@var{range}@r{]} +Disable the specified skip(s). If @var{range} is not specified, disable all +skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..d2f064f --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,598 @@ +/* Skipping uninteresting files and functions while stepping. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" +#include "breakpoint.h" /* for get_sal_arch() */ + +struct skiplist_entry +{ + int number; + + /* NULL if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH (decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (arg == 0) + ui_out_message (current_uiout, 0, _("\ +Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entries found with number %s.\n"), arg); + + return; + } + + if (opts.addressprint) + tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 5, + num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, + num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (arg != 0 && !number_is_in_list(arg, e->number)) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, + "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", + e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + e->enabled = 1; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + e->enabled = 0; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int found = 0; + + b_prev = 0; + ALL_SKIPLIST_ENTRIES_SAFE (e, temp) + if (arg == 0 || number_is_in_list(arg, e->number)) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + found = 1; + } + else + { + b_prev = e; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + int searched_for_sal = 0; + struct symtab_and_line sal; + char *filename = NULL; + struct skiplist_entry *e; + + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + + ALL_SKIPLIST_ENTRIES (e) + { + if (!e->enabled || e->pending) + continue; + + /* Does the pc we're stepping into match e's stored pc? */ + if (e->pc != 0 && pc == e->pc) + return 1; + + if (e->filename != 0) + { + /* Get the filename corresponding to this pc, if we haven't + * yet. */ + if (!searched_for_sal) + { + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + searched_for_sal = 1; + } + if (filename != 0 && strcmp (filename, e->filename) == 0) + return 1; + } + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set (void) +{ + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH (decode_exception, NOT_FOUND_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 + && sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup (func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +Usage: skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable skip entries. You can specify numbers (e.g. \"skip enable 1 3\"), \ +ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\ +Usage: skip enable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable skip entries. You can specify numbers (e.g. \"skip disable 1 3\"), \ +ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\ +Usage: skip disable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete skip entries. You can specify numbers (e.g. \"skip delete 1 3\"), \ +ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\ +Usage: skip delete [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Display the status of skips. You can specify numbers (e.g. \"skip info 1 3\"), \ +ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll show all skips.\n\n\ +Usage: skip info [NUMBERS AND/OR RANGES]\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..143f7ed --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (void); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..cf25eb7 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,98 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last symtab and line we displayed, which we use e.g. + * as the place to put a breakpoint when the `break' command is + * invoked with no arguments. */ +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +/* Forget the last sal we displayed. */ +void +clear_last_displayed_sal (void) +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +/* Is our record of the last sal we displayed valid? If not, + * the get_last_displayed_* functions will return NULL or 0, as + * appropriate. */ +int +last_displayed_sal_is_valid (void) +{ + return last_displayed_sal_valid; +} + +/* Get the pspace of the last sal we displayed, if it's valid. */ +struct program_space * +get_last_displayed_pspace (void) +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +/* Get the address of the last sal we displayed, if it's valid. */ +CORE_ADDR +get_last_displayed_addr (void) +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +/* Get the symtab of the last sal we displayed, if it's valid. */ +struct symtab* +get_last_displayed_symtab (void) +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +/* Get the line of the last sal we displayed, if it's valid. */ +int +get_last_displayed_line (void) +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +/* Get the last sal we displayed, if it's valid. */ +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..312e8ff 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (void); +int last_displayed_sal_is_valid (void); +struct program_space* get_last_displayed_pspace (void); +CORE_ADDR get_last_displayed_addr (void); +struct symtab* get_last_displayed_symtab (void); +int get_last_displayed_line (void); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..1c4d0c9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..4f8838d --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,129 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${objdir}/${subdir}/${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +gdb_load ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ +"File ${srcfile_lib} will be skipped when stepping." \ +"ignoring file in solib" \ +"No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*"\ +"y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ +"info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ +"info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +gdb_load ${binfile_main} + +gdb_test "skip function multiply" \ +"Function multiply will be skipped when stepping, pending shared library load." \ +"ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*"\ +"y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..5a81cd4 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,179 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entries found with number 999." +gdb_test "skip disable 999" "No skiplist entries found with number 999." +gdb_test "skip delete 999" "No skiplist entries found with number 999." +gdb_test "skip enable a" "Args must be numbers or '\\$' variables." +gdb_test "skip disable a" "Args must be numbers or '\\$' variables." +gdb_test "skip delete a" "Args must be numbers or '\\$' variables." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entries found with number 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" +gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +gdb_test "skip delete 1" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +gdb_test "skip disable 3" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +gdb_test "step"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +gdb_test "skip enable 3" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +gdb_test "skip disable" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after disabling all" + +gdb_test "skip enable" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after enabling all" + +gdb_test "skip disable 4 2-3" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after disabling 4 2-3" + +gdb_test "skip enable 2-3" +gdb_test "info skip" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after enabling 2-3" + +gdb_test "info skip 2-3" \ +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s*" \ +"info skip 2-3" + +gdb_test "skip delete 2 3" +gdb_test "info skip" \ +"4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ +"info skip after deleting 2 3" + +gdb_test "skip delete" +gdb_test "info skip" "Not skipping any files or functions\." \ +"info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 15:11 ` Justin Lebar @ 2011-10-28 18:18 ` Tom Tromey 2011-10-28 19:48 ` Justin Lebar 2011-10-28 19:49 ` Tom Tromey 1 sibling, 1 reply; 44+ messages in thread From: Tom Tromey @ 2011-10-28 18:18 UTC (permalink / raw) To: Justin Lebar; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches >>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: Justin> Thanks for the testing advice; I ran the test many times on my Justin> machine, and it now works without error every time. Justin> New roll-up patch is attached. The only difference from v4 is Justin> in skip.exp. Thanks for persevering. Your test cases seem nicely comprehensive; thanks for making the extra effort. I think one more iteration; I would approve-it-with-changes but there is one non-cosmetic issue. It isn't too major. Justin> +/* Attempt to determine architecture of location identified by SAL. */ Justin> +extern struct gdbarch * Justin> +get_sal_arch (struct symtab_and_line sal); In a case like this, indent the continuation line a bit. Justin> + TRY_CATCH (decode_exception, NOT_FOUND_ERROR) The second argument to TRY_CATCH actually must be one of the RETURN_MASK_* constants. Here I suggest RETURN_MASK_ERROR. Justin> + if (decode_exception.reason < 0) Justin> + { Then here you can: if (decode_exception.reason < 0) { if (decode_exception.error != NOT_FOUND_ERROR) throw_exception (decode_exception); ... Justin> + ALL_SKIPLIST_ENTRIES (e) Justin> + if (arg == 0 || number_is_in_list(arg, e->number)) Space before the open paren. Justin> + if (arg != 0 && !number_is_in_list(arg, e->number)) Likewise. This appears in a few more places -- all uses of number_is_in_list. Justin> +/* Create a skiplist entry for the given pc corresponding to the given Justin> + function name and add it to the list. */ Justin> +static void Justin> +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, Blank line between intro comment and the start of the function. I think there are a few instances of this. Justin> +gdb_start Justin> +gdb_load ${binfile_main} Use clean_restart here instead. Justin> +gdb_test "skip file ${srcfile_lib}" \ Justin> +"File ${srcfile_lib} will be skipped when stepping." \ Justin> +"ignoring file in solib" \ Justin> +"No source file named ${srcfile_lib}.* Justin> +Ignore file pending future shared library load.*"\ Justin> +"y" Code like this is more readable if you indent the continuation lines. I realize this can't be done for every line here, and that is ok -- but the lines following a "\" should be indented. There should be a space before the last "\". Justin> +gdb_test "info skip" \ Justin> +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* Justin> +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ Justin> +"info skip with pending file" Indentation. Justin> +gdb_test "info skip" \ Justin> +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* Justin> +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ Justin> +"info skip with pending file" Indentation. There are a few more of these. Justin> +gdb_exit Justin> +gdb_start Justin> +gdb_load ${binfile_main} clean_restart Tom ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-28 18:18 ` Tom Tromey @ 2011-10-28 19:48 ` Justin Lebar 2011-10-28 19:53 ` Tom Tromey 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-28 19:48 UTC (permalink / raw) To: Tom Tromey; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches [-- Attachment #1: Type: text/plain, Size: 3662 bytes --] I'm sorry about all the formatting issues; it's hard to keep multiple styles in my head at once! I need a set of git hooks to pester me, I guess. > Blank line between intro comment and the start of the function. > I think there are a few instances of this. Only for function definitions, not declarations, right? I don't see blank lines in breakpoint.h, for example. -Justin On Fri, Oct 28, 2011 at 2:13 PM, Tom Tromey <tromey@redhat.com> wrote: >>>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: > > Justin> Thanks for the testing advice; I ran the test many times on my > Justin> machine, and it now works without error every time. > > Justin> New roll-up patch is attached. The only difference from v4 is > Justin> in skip.exp. > > Thanks for persevering. > > Your test cases seem nicely comprehensive; thanks for making the extra > effort. > > I think one more iteration; I would approve-it-with-changes but there is > one non-cosmetic issue. It isn't too major. > > Justin> +/* Attempt to determine architecture of location identified by SAL. */ > Justin> +extern struct gdbarch * > Justin> +get_sal_arch (struct symtab_and_line sal); > > In a case like this, indent the continuation line a bit. > > Justin> + TRY_CATCH (decode_exception, NOT_FOUND_ERROR) > > The second argument to TRY_CATCH actually must be one of the > RETURN_MASK_* constants. Here I suggest RETURN_MASK_ERROR. > > Justin> + if (decode_exception.reason < 0) > Justin> + { > > Then here you can: > > if (decode_exception.reason < 0) > { > if (decode_exception.error != NOT_FOUND_ERROR) > throw_exception (decode_exception); > ... > > Justin> + ALL_SKIPLIST_ENTRIES (e) > Justin> + if (arg == 0 || number_is_in_list(arg, e->number)) > > Space before the open paren. > > Justin> + if (arg != 0 && !number_is_in_list(arg, e->number)) > > Likewise. > > This appears in a few more places -- all uses of number_is_in_list. > > Justin> +/* Create a skiplist entry for the given pc corresponding to the given > Justin> + function name and add it to the list. */ > Justin> +static void > Justin> +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, > > Blank line between intro comment and the start of the function. > I think there are a few instances of this. > > Justin> +gdb_start > Justin> +gdb_load ${binfile_main} > > Use clean_restart here instead. > > Justin> +gdb_test "skip file ${srcfile_lib}" \ > Justin> +"File ${srcfile_lib} will be skipped when stepping." \ > Justin> +"ignoring file in solib" \ > Justin> +"No source file named ${srcfile_lib}.* > Justin> +Ignore file pending future shared library load.*"\ > Justin> +"y" > > Code like this is more readable if you indent the continuation lines. > I realize this can't be done for every line here, and that is ok -- but > the lines following a "\" should be indented. > There should be a space before the last "\". > > Justin> +gdb_test "info skip" \ > Justin> +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* > Justin> +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ > Justin> +"info skip with pending file" > > Indentation. > > Justin> +gdb_test "info skip" \ > Justin> +"Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* > Justin> +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ > Justin> +"info skip with pending file" > > Indentation. > > There are a few more of these. > > Justin> +gdb_exit > Justin> +gdb_start > Justin> +gdb_load ${binfile_main} > > clean_restart > > Tom > [-- Attachment #2: skip-6.diff --] [-- Type: text/x-patch, Size: 56573 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..0f10225 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + (get_sal_arch): Declare. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (get_sal_arch): Make public. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/NEWS b/gdb/NEWS index 4d434c5..8225cf8 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB now allows you to skip uninteresting functions and files when + stepping with the "skip function" and "skip file" commands. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..b41fb79 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -5764,7 +5739,7 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) } /* Attempt to determine architecture of location identified by SAL. */ -static struct gdbarch * +struct gdbarch * get_sal_arch (struct symtab_and_line sal) { if (sal.section) @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..d8a7601 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); @@ -1359,4 +1356,7 @@ extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint * extern int user_breakpoint_p (struct breakpoint *); +/* Attempt to determine architecture of location identified by SAL. */ +extern struct gdbarch *get_sal_arch (struct symtab_and_line sal); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..382dfd4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,111 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skipping over functions and files + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip a function or all functions in a file when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @kbd{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. @xref{Specify Location} + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +(If you have a function called @code{file} that you want to skip, use +@kbd{skip function file}.) + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{range}@r{]} +Print details about the specified skip(s). If @var{range} is not specified, +print a table with details about all functions and files marked for skipping. +@code{info skip} prints the following information about each skip: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +The type of this skip, either @samp{function} or @samp{file}. +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info skip} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{range}@r{]} +Delete the specified skip(s). If @var{range} is not specified, delete all +skips. + +@kindex skip enable +@item skip enable @r{[}@var{range}@r{]} +Enable the specified skip(s). If @var{range} is not specified, enable all +skips. + +@kindex skip disable +@item skip disable @r{[}@var{range}@r{]} +Disable the specified skip(s). If @var{range} is not specified, disable all +skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..67ccc64 --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,604 @@ +/* Skipping uninteresting files and functions while stepping. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" +#include "breakpoint.h" /* for get_sal_arch () */ + +struct skiplist_entry +{ + int number; + + /* NULL if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + if (decode_exception.error != NOT_FOUND_ERROR) + throw_exception (decode_exception); + + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (arg == 0) + ui_out_message (current_uiout, 0, _("\ +Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entries found with number %s.\n"), arg); + + return; + } + + if (opts.addressprint) + tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 5, + num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, + num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (arg != 0 && !number_is_in_list (arg, e->number)) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, + "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", + e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 1; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 0; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int found = 0; + + b_prev = 0; + ALL_SKIPLIST_ENTRIES_SAFE (e, temp) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + found = 1; + } + else + { + b_prev = e; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ + +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ + +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ + +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + int searched_for_sal = 0; + struct symtab_and_line sal; + char *filename = NULL; + struct skiplist_entry *e; + + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + + ALL_SKIPLIST_ENTRIES (e) + { + if (!e->enabled || e->pending) + continue; + + /* Does the pc we're stepping into match e's stored pc? */ + if (e->pc != 0 && pc == e->pc) + return 1; + + if (e->filename != 0) + { + /* Get the filename corresponding to this pc, if we haven't + * yet. */ + if (!searched_for_sal) + { + sal = find_pc_line (pc, 0); + filename = sal.symtab->filename; + searched_for_sal = 1; + } + if (filename != 0 && strcmp (filename, e->filename) == 0) + return 1; + } + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set (void) +{ + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 + && sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup (func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +Usage: skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable skip entries. You can specify numbers (e.g. \"skip enable 1 3\"), \ +ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\ +Usage: skip enable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable skip entries. You can specify numbers (e.g. \"skip disable 1 3\"), \ +ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\ +Usage: skip disable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete skip entries. You can specify numbers (e.g. \"skip delete 1 3\"), \ +ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\ +Usage: skip delete [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Display the status of skips. You can specify numbers (e.g. \"skip info 1 3\"), \ +ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll show all skips.\n\n\ +Usage: skip info [NUMBERS AND/OR RANGES]\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..143f7ed --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (void); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..0ad2926 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,106 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last symtab and line we displayed, which we use e.g. + * as the place to put a breakpoint when the `break' command is + * invoked with no arguments. */ + +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +/* Forget the last sal we displayed. */ + +void +clear_last_displayed_sal (void) +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +/* Is our record of the last sal we displayed valid? If not, + * the get_last_displayed_* functions will return NULL or 0, as + * appropriate. */ + +int +last_displayed_sal_is_valid (void) +{ + return last_displayed_sal_valid; +} + +/* Get the pspace of the last sal we displayed, if it's valid. */ + +struct program_space * +get_last_displayed_pspace (void) +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +/* Get the address of the last sal we displayed, if it's valid. */ + +CORE_ADDR +get_last_displayed_addr (void) +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +/* Get the symtab of the last sal we displayed, if it's valid. */ + +struct symtab* +get_last_displayed_symtab (void) +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +/* Get the line of the last sal we displayed, if it's valid. */ + +int +get_last_displayed_line (void) +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +/* Get the last sal we displayed, if it's valid. */ + +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..312e8ff 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (void); +int last_displayed_sal_is_valid (void); +struct program_space* get_last_displayed_pspace (void); +CORE_ADDR get_last_displayed_addr (void); +struct symtab* get_last_displayed_symtab (void); +int get_last_displayed_line (void); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..1c4d0c9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..d6e25a4 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,130 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +clean_restart ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ + "File ${srcfile_lib} will be skipped when stepping." \ + "ignoring file in solib" \ + "No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*" \ + "y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ + "info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ + "info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +clean_restart ${binfile_main} + +gdb_test "skip function multiply" \ + "Function multiply will be skipped when stepping, pending shared library load." \ + "ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*" \ + "y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + "skip should no longer be pending." + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..7c699eb --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,179 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entries found with number 999." +gdb_test "skip disable 999" "No skiplist entries found with number 999." +gdb_test "skip delete 999" "No skiplist entries found with number 999." +gdb_test "skip enable a" "Args must be numbers or '\\$' variables." +gdb_test "skip disable a" "Args must be numbers or '\\$' variables." +gdb_test "skip delete a" "Args must be numbers or '\\$' variables." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entries found with number 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" +gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +gdb_test "skip delete 1" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +gdb_test "skip disable 3" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +gdb_test "step"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +gdb_test "skip enable 3" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +gdb_test "skip disable" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after disabling all" + +gdb_test "skip enable" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after enabling all" + +gdb_test "skip disable 4 2-3" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after disabling 4 2-3" + +gdb_test "skip enable 2-3" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after enabling 2-3" + +gdb_test "info skip 2-3" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s*" \ + "info skip 2-3" + +gdb_test "skip delete 2 3" +gdb_test "info skip" \ + "4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after deleting 2 3" + +gdb_test "skip delete" +gdb_test "info skip" "Not skipping any files or functions\." \ + "info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-28 19:48 ` Justin Lebar @ 2011-10-28 19:53 ` Tom Tromey 0 siblings, 0 replies; 44+ messages in thread From: Tom Tromey @ 2011-10-28 19:53 UTC (permalink / raw) To: Justin Lebar; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches >>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: Justin> I'm sorry about all the formatting issues; it's hard to keep multiple Justin> styles in my head at once! I need a set of git hooks to pester me, I Justin> guess. No worries, everybody struggles with this. I wish we could define our style as the output of some tool; then we wouldn't have to review for this at all. But AFAIK no tool comes close enough. >> Blank line between intro comment and the start of the function. >> I think there are a few instances of this. Justin> Only for function definitions, not declarations, right? I don't see Justin> blank lines in breakpoint.h, for example. I think so. Or at least I don't recall us agreeing on anything and the code is already not very consistent. Unfortunately I just noticed a different issue, so you'll need one more spin. See my other mail. Tom ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-26 15:11 ` Justin Lebar 2011-10-28 18:18 ` Tom Tromey @ 2011-10-28 19:49 ` Tom Tromey 2011-10-28 19:55 ` Justin Lebar 1 sibling, 1 reply; 44+ messages in thread From: Tom Tromey @ 2011-10-28 19:49 UTC (permalink / raw) To: Justin Lebar; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches >>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: One more note... Justin> +int Justin> +function_pc_is_marked_for_skip (CORE_ADDR pc) Justin> +{ Justin> + int searched_for_sal = 0; Justin> + struct symtab_and_line sal; Justin> + char *filename = NULL; Justin> + struct skiplist_entry *e; Justin> + Justin> + sal = find_pc_line (pc, 0); Justin> + filename = sal.symtab->filename; These last two lines should be removed. They defeat the lazy computation scheme. Justin> + sal = find_pc_line (pc, 0); Justin> + filename = sal.symtab->filename; I think sal.symtab can be NULL. Tom ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-28 19:49 ` Tom Tromey @ 2011-10-28 19:55 ` Justin Lebar 2011-10-28 20:37 ` Tom Tromey 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-28 19:55 UTC (permalink / raw) To: Tom Tromey; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches [-- Attachment #1: Type: text/plain, Size: 864 bytes --] > One more note... Oops; I should have noticed that. Fixed. -Justin On Fri, Oct 28, 2011 at 3:47 PM, Tom Tromey <tromey@redhat.com> wrote: >>>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: > > One more note... > > Justin> +int > Justin> +function_pc_is_marked_for_skip (CORE_ADDR pc) > Justin> +{ > Justin> + int searched_for_sal = 0; > Justin> + struct symtab_and_line sal; > Justin> + char *filename = NULL; > Justin> + struct skiplist_entry *e; > Justin> + > Justin> + sal = find_pc_line (pc, 0); > Justin> + filename = sal.symtab->filename; > > These last two lines should be removed. > They defeat the lazy computation scheme. > > Justin> + sal = find_pc_line (pc, 0); > Justin> + filename = sal.symtab->filename; > > I think sal.symtab can be NULL. > > Tom > [-- Attachment #2: skip-7.diff --] [-- Type: text/x-patch, Size: 56549 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a166d14..0f10225 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + (get_sal_arch): Declare. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (get_sal_arch): Make public. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-05 Tristan Gingold <gingold@adacore.com> * ada-tasks.c (read_atcb): Make ravenscar_task_name static. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 826d339..d6b004b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -719,7 +719,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -819,7 +819,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -907,7 +907,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/NEWS b/gdb/NEWS index 4d434c5..8225cf8 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB now allows you to skip uninteresting functions and files when + stepping with the "skip function" and "skip file" commands. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 08ff69b..b41fb79 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -5764,7 +5739,7 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) } /* Attempt to determine architecture of location identified by SAL. */ -static struct gdbarch * +struct gdbarch * get_sal_arch (struct symtab_and_line sal) { if (sal.section) @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5e5d1b9..d8a7601 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); @@ -1359,4 +1356,7 @@ extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint * extern int user_breakpoint_p (struct breakpoint *); +/* Attempt to determine architecture of location identified by SAL. */ +extern struct gdbarch *get_sal_arch (struct symtab_and_line sal); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index ccf6ea6..dab3a12 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -185,6 +185,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1329,6 +1331,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1394,7 +1397,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index dd0f7f6..382dfd4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,111 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skipping over functions and files + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip a function or all functions in a file when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @kbd{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. @xref{Specify Location} + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +(If you have a function called @code{file} that you want to skip, use +@kbd{skip function file}.) + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{range}@r{]} +Print details about the specified skip(s). If @var{range} is not specified, +print a table with details about all functions and files marked for skipping. +@code{info skip} prints the following information about each skip: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +The type of this skip, either @samp{function} or @samp{file}. +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info skip} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{range}@r{]} +Delete the specified skip(s). If @var{range} is not specified, delete all +skips. + +@kindex skip enable +@item skip enable @r{[}@var{range}@r{]} +Enable the specified skip(s). If @var{range} is not specified, enable all +skips. + +@kindex skip disable +@item skip disable @r{[}@var{range}@r{]} +Disable the specified skip(s). If @var{range} is not specified, disable all +skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index 225034c..e8be121 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4829,7 +4830,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4838,7 +4840,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..954f487 --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,602 @@ +/* Skipping uninteresting files and functions while stepping. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" +#include "breakpoint.h" /* for get_sal_arch () */ + +struct skiplist_entry +{ + int number; + + /* NULL if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + if (decode_exception.error != NOT_FOUND_ERROR) + throw_exception (decode_exception); + + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (arg == 0) + ui_out_message (current_uiout, 0, _("\ +Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entries found with number %s.\n"), arg); + + return; + } + + if (opts.addressprint) + tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 5, + num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, + num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (arg != 0 && !number_is_in_list (arg, e->number)) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, + "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", + e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 1; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 0; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int found = 0; + + b_prev = 0; + ALL_SKIPLIST_ENTRIES_SAFE (e, temp) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + found = 1; + } + else + { + b_prev = e; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ + +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ + +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ + +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + int searched_for_sal = 0; + struct symtab_and_line sal; + char *filename = NULL; + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (!e->enabled || e->pending) + continue; + + /* Does the pc we're stepping into match e's stored pc? */ + if (e->pc != 0 && pc == e->pc) + return 1; + + if (e->filename != 0) + { + /* Get the filename corresponding to this pc, if we haven't + * yet. */ + if (!searched_for_sal) + { + sal = find_pc_line (pc, 0); + if (sal.symtab != 0) + filename = sal.symtab->filename; + searched_for_sal = 1; + } + if (filename != 0 && strcmp (filename, e->filename) == 0) + return 1; + } + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set (void) +{ + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 + && sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup (func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +Usage: skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable skip entries. You can specify numbers (e.g. \"skip enable 1 3\"), \ +ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\ +Usage: skip enable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable skip entries. You can specify numbers (e.g. \"skip disable 1 3\"), \ +ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\ +Usage: skip disable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete skip entries. You can specify numbers (e.g. \"skip delete 1 3\"), \ +ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\ +Usage: skip delete [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Display the status of skips. You can specify numbers (e.g. \"skip info 1 3\"), \ +ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll show all skips.\n\n\ +Usage: skip info [NUMBERS AND/OR RANGES]\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..143f7ed --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (void); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 15666ee..0ad2926 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -73,6 +73,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,6 +86,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -599,9 +613,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -609,6 +623,106 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last symtab and line we displayed, which we use e.g. + * as the place to put a breakpoint when the `break' command is + * invoked with no arguments. */ + +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +/* Forget the last sal we displayed. */ + +void +clear_last_displayed_sal (void) +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +/* Is our record of the last sal we displayed valid? If not, + * the get_last_displayed_* functions will return NULL or 0, as + * appropriate. */ + +int +last_displayed_sal_is_valid (void) +{ + return last_displayed_sal_valid; +} + +/* Get the pspace of the last sal we displayed, if it's valid. */ + +struct program_space * +get_last_displayed_pspace (void) +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +/* Get the address of the last sal we displayed, if it's valid. */ + +CORE_ADDR +get_last_displayed_addr (void) +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +/* Get the symtab of the last sal we displayed, if it's valid. */ + +struct symtab* +get_last_displayed_symtab (void) +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +/* Get the line of the last sal we displayed, if it's valid. */ + +int +get_last_displayed_line (void) +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +/* Get the last sal we displayed, if it's valid. */ + +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..312e8ff 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (void); +int last_displayed_sal_is_valid (void); +struct program_space* get_last_displayed_pspace (void); +CORE_ADDR get_last_displayed_addr (void); +struct symtab* get_last_displayed_symtab (void); +int get_last_displayed_line (void); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index 1540cb7..1c4d0c9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2780,7 +2781,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f9efd1..7deea3e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-05 Pierre Muller <muller@ics.u-strasbg.fr> Add tests for passing of environment variables to inferior. diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..d6e25a4 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,130 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +clean_restart ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ + "File ${srcfile_lib} will be skipped when stepping." \ + "ignoring file in solib" \ + "No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*" \ + "y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ + "info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ + "info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +clean_restart ${binfile_main} + +gdb_test "skip function multiply" \ + "Function multiply will be skipped when stepping, pending shared library load." \ + "ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*" \ + "y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + "skip should no longer be pending." + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..7c699eb --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,179 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entries found with number 999." +gdb_test "skip disable 999" "No skiplist entries found with number 999." +gdb_test "skip delete 999" "No skiplist entries found with number 999." +gdb_test "skip enable a" "Args must be numbers or '\\$' variables." +gdb_test "skip disable a" "Args must be numbers or '\\$' variables." +gdb_test "skip delete a" "Args must be numbers or '\\$' variables." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entries found with number 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" +gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +gdb_test "skip delete 1" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +gdb_test "skip disable 3" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +gdb_test "step"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +gdb_test "skip enable 3" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +gdb_test "skip disable" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after disabling all" + +gdb_test "skip enable" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after enabling all" + +gdb_test "skip disable 4 2-3" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after disabling 4 2-3" + +gdb_test "skip enable 2-3" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after enabling 2-3" + +gdb_test "info skip 2-3" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s*" \ + "info skip 2-3" + +gdb_test "skip delete 2 3" +gdb_test "info skip" \ + "4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after deleting 2 3" + +gdb_test "skip delete" +gdb_test "info skip" "Not skipping any files or functions\." \ + "info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-28 19:55 ` Justin Lebar @ 2011-10-28 20:37 ` Tom Tromey 2011-10-31 15:52 ` Justin Lebar 0 siblings, 1 reply; 44+ messages in thread From: Tom Tromey @ 2011-10-28 20:37 UTC (permalink / raw) To: Justin Lebar; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches >>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: Justin> Oops; I should have noticed that. Fixed. Thanks, this version is ok. Tom ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-28 20:37 ` Tom Tromey @ 2011-10-31 15:52 ` Justin Lebar [not found] ` <4EAF2E0E.7080508@earthlink.net> 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-10-31 15:52 UTC (permalink / raw) To: Tom Tromey; +Cc: Eli Zaretskii, Stan Shebs, gdb-patches > Thanks, this version is ok. Is this final approval on the patch, or are we waiting on something else? If the former, how do I check in? -Justin On Fri, Oct 28, 2011 at 3:55 PM, Tom Tromey <tromey@redhat.com> wrote: >>>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: > > Justin> Oops; I should have noticed that. Fixed. > > Thanks, this version is ok. > > Tom > ^ permalink raw reply [flat|nested] 44+ messages in thread
[parent not found: <4EAF2E0E.7080508@earthlink.net>]
* Re: Status of 'blacklist' patch? [not found] ` <4EAF2E0E.7080508@earthlink.net> @ 2011-11-01 14:53 ` Justin Lebar 2011-11-02 22:43 ` Maciej W. Rozycki 0 siblings, 1 reply; 44+ messages in thread From: Justin Lebar @ 2011-11-01 14:53 UTC (permalink / raw) To: Stan Shebs; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 3319 bytes --] Checked in, with two spaces after periods in comments. Thank you for your patience! -Justin 2011-10-06 Justin Lebar <justin.lebar@gmail.com> * Makefile.in: (SFILES): Add skip.c. (HFILES_NO_SRCDIR): Add skip.h. (COMMON_OBS): Add skip.o. * skip.h, skip.c: New. * breakpoint.h (set_default_breakpoint): Remove. (get_sal_arch): Declare. * breakpoint.c: Remove default_breakpoint_valid, default_breakpoint_address, default_breakpoint_symtab, default_breakpoint_line, default_breakpoint_pspace variables. (get_sal_arch): Make public. (set_default_breakpoint): Remove. (parse_breakpoint_sals, create_breakpoint, clear_command, decode_line_spec_1): Remove uses of default_breakpoint variables; replaced with function calls into stack.c. * cli/cli-cmds.h: Add cmd_list_element *skiplist. * cli/cli-cmds.c: Add skiplist. (init_cmd_lists): Initialize skiplist. (init_cli_cmds): Fix comment (classes of commands appear in alphabetical order). * infrun.c (handle_inferior_event): Add check that we don't step into a function whose pc is marked for skip. * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, last_displayed_addr, last_displayed_symtab, last_displayed_line variables. (set_last_displayed_sal): New static function. (print_frame_info): Switch call to set_default_breakpoint to call to set_last_displayed_sal. (clear_last_displayed_sal, last_displayed_sal_is_valid, get_last_displayed_pspace, get_last_displayed_addr, get_last_displayed_symtab, get_last_displayed_line, get_last_displayed_sal): New public functions. * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, get_last_displayed_pspace, get_last_displayed_addr, get_last_displayed_symtab, get_last_displayed_line, get_last_displayed_sal): Declare. 2011-10-06 Justin Lebar <justin.lebar@gmail.com> Add tests for skip command. * testsuite/gdb.base/skip-solib-lib.c: New * testsuite/gdb.base/skip-solib-main.c: New * testsuite/gdb.base/skip-solib.exp: New * testsuite/gdb.base/skip.c: New * testsuite/gdb.base/skip.exp: New * testsuite/gdb.base/skip1.c: New * testsuite/gdb.base/Makefile.in: Adding new files. On Mon, Oct 31, 2011 at 7:23 PM, Stan Shebs <stanshebs@earthlink.net> wrote: > On 10/31/11 6:28 AM, Justin Lebar wrote: >>> >>> Thanks, this version is ok. >> >> Is this final approval on the patch, or are we waiting on something else? > > I was going to say it was ready to go in, but then I noticed these in > skip.c: > > + /* Default to the current function if no argument is given. */ > > > We like to have two spaces after the period. (Yes, it's borderline OCD, but > we avoid source churn and confusing diffs if we prescribe this level of > consistency.) > > There might be other things to fix, but at this point I think it's more > efficient to push the code in and start getting it some real-world exercise. > > >> If the former, how do I check in? > > Somebody else can commit it for you, but if you intend to be an ongoing > contributor, you need an account on sourceware.org (see > http://sourceware.org/ for instructions), and then set up a read-write > checkout, per http://sourceware.org/gdb/current/ , and check in from there. > > Stan > stan@codesourcery.com > > [-- Attachment #2: skip-8.diff --] [-- Type: text/x-patch, Size: 56521 bytes --] diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bdc9bf2..5f5fabc 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,41 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + * Makefile.in: (SFILES): Add skip.c. + (HFILES_NO_SRCDIR): Add skip.h. + (COMMON_OBS): Add skip.o. + * skip.h, skip.c: New. + * breakpoint.h (set_default_breakpoint): Remove. + (get_sal_arch): Declare. + * breakpoint.c: Remove default_breakpoint_valid, + default_breakpoint_address, default_breakpoint_symtab, + default_breakpoint_line, default_breakpoint_pspace variables. + (get_sal_arch): Make public. + (set_default_breakpoint): Remove. + (parse_breakpoint_sals, create_breakpoint, clear_command, + decode_line_spec_1): Remove uses of default_breakpoint variables; + replaced with function calls into stack.c. + * cli/cli-cmds.h: Add cmd_list_element *skiplist. + * cli/cli-cmds.c: Add skiplist. + (init_cmd_lists): Initialize skiplist. + (init_cli_cmds): Fix comment (classes of commands appear in + alphabetical order). + * infrun.c (handle_inferior_event): Add check that we don't step into + a function whose pc is marked for skip. + * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, + last_displayed_addr, last_displayed_symtab, last_displayed_line + variables. + (set_last_displayed_sal): New static function. + (print_frame_info): Switch call to set_default_breakpoint to call to + set_last_displayed_sal. + (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): New public functions. + * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, + get_last_displayed_pspace, get_last_displayed_addr, + get_last_displayed_symtab, get_last_displayed_line, + get_last_displayed_sal): Declare. + 2011-10-29 Yao Qi <yao@codesourcery.com> * infcmd.c (disconnect_command): Call disconnect_tracing. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 32d8ef3..7a7ff9f 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -727,7 +727,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ prologue-value.c psymtab.c \ regcache.c reggroups.c remote.c remote-fileio.c reverse.c \ sentinel-frame.c \ - serial.c ser-base.c ser-unix.c \ + serial.c ser-base.c ser-unix.c skip.c \ solib.c solib-target.c source.c \ stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \ symtab.c \ @@ -827,7 +827,7 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h \ +gnulib/stddef.in.h inline-frame.h skip.h \ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ common/linux-osdata.h @@ -915,7 +915,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o \ + jit.o progspace.o skip.o \ common-utils.o buffer.o ptid.o TSOBS = inflow.o diff --git a/gdb/NEWS b/gdb/NEWS index 973ed0b..9a27b64 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,9 @@ *** Changes since GDB 7.3.1 +* GDB now allows you to skip uninteresting functions and files when + stepping with the "skip function" and "skip file" commands. + * GDB has two new commands: "set remote hardware-watchpoint-length-limit" and "show remote hardware-watchpoint-length-limit". These allows to set or show the maximum length limit (in bytes) of a remote diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index ba1b08f..8c98bef 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -65,6 +65,8 @@ #include "parser-defs.h" #include "cli/cli-utils.h" #include "continuations.h" +#include "stack.h" +#include "skip.h" /* readline include files */ #include "readline/readline.h" @@ -572,19 +574,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - \f /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -5339,20 +5328,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } \f -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -5764,7 +5739,7 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) } /* Attempt to determine architecture of location identified by SAL. */ -static struct gdbarch * +struct gdbarch * get_sal_arch (struct symtab_and_line sal) { if (sal.section) @@ -7543,24 +7518,26 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ sals->sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; sals->sals[0] = sal; @@ -7574,19 +7551,22 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. + time while leaving the last displayed codepoint pointers + alone. ObjC: However, don't match an Objective-C method name which may have a '+' or '-' succeeded by a '[' */ struct symtab_and_line cursal = get_current_source_symtab_and_line (); - if (default_breakpoint_valid + if (last_displayed_sal_is_valid () && (!cursal.symtab || ((strchr ("+-", (*address)[0]) != NULL) && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + *sals = decode_line_1 (address, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical); else *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, canonical); @@ -9611,9 +9591,11 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, 1, + get_last_displayed_symtab (), + get_last_displayed_line (), + NULL); else sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); @@ -10135,10 +10117,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -11986,6 +11969,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } \f /* Reset the thread number of this breakpoint: @@ -12435,7 +12421,8 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines decode_line_spec_1 (char *string, int funfirstline) @@ -12444,10 +12431,10 @@ decode_line_spec_1 (char *string, int funfirstline) if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) + if (last_displayed_sal_is_valid ()) sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, + get_last_displayed_symtab (), + get_last_displayed_line (), NULL); else sals = decode_line_1 (&string, funfirstline, diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index c2116e2..fe381df 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -1033,9 +1033,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); @@ -1365,4 +1362,7 @@ extern int pc_at_non_inline_function (struct address_space *aspace, extern int user_breakpoint_p (struct breakpoint *); +/* Attempt to determine architecture of location identified by SAL. */ +extern struct gdbarch *get_sal_arch (struct symtab_and_line sal); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index 624d0de..94328c4 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -186,6 +186,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -1511,6 +1513,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1576,7 +1579,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ diff --git a/gdb/cli/cli-cmds.h b/gdb/cli/cli-cmds.h index e79dcf0..73ccdd2 100644 --- a/gdb/cli/cli-cmds.h +++ b/gdb/cli/cli-cmds.h @@ -106,6 +106,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c200b55..0f37e6e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -4854,6 +4854,111 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@subsection Skipping Over Functions and Files +@cindex skipping over functions and files + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip a function or all functions in a file when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @kbd{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. @xref{Specify Location} + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +(If you have a function called @code{file} that you want to skip, use +@kbd{skip function file}.) + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{range}@r{]} +Print details about the specified skip(s). If @var{range} is not specified, +print a table with details about all functions and files marked for skipping. +@code{info skip} prints the following information about each skip: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +The type of this skip, either @samp{function} or @samp{file}. +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{<PENDING>}. Once a shared library +which has the function is loaded, @code{info skip} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{range}@r{]} +Delete the specified skip(s). If @var{range} is not specified, delete all +skips. + +@kindex skip enable +@item skip enable @r{[}@var{range}@r{]} +Enable the specified skip(s). If @var{range} is not specified, enable all +skips. + +@kindex skip disable +@item skip disable @r{[}@var{range}@r{]} +Disable the specified skip(s). If @var{range} is not specified, disable all +skips. + +@end table + @node Signals @section Signals @cindex signals diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index c02ce69..606b812 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -124,6 +124,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Chain containing all defined "save" subcommands. */ extern struct cmd_list_element *save_cmdlist; diff --git a/gdb/infrun.c b/gdb/infrun.c index e0c59a1..7ec0788 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -56,6 +56,7 @@ #include "tracepoint.h" #include "continuations.h" #include "interps.h" +#include "skip.h" /* Prototypes for local functions */ @@ -4917,7 +4918,8 @@ process_event_stop_test: } /* If we have line number information for the function we are - thinking of stepping into, step into it. + thinking of stepping into and the function isn't on the skip + list, step into it. If there are several symtabs at that PC (e.g. with include files), just want to know whether *any* of them have line @@ -4926,7 +4928,8 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - if (tmp_sal.line != 0) + if (tmp_sal.line != 0 && + !function_pc_is_marked_for_skip (ecs->stop_func_start)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); diff --git a/gdb/skip.c b/gdb/skip.c new file mode 100644 index 0000000..4bda3c4 --- /dev/null +++ b/gdb/skip.c @@ -0,0 +1,602 @@ +/* Skipping uninteresting files and functions while stepping. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" +#include "breakpoint.h" /* for get_sal_arch () */ + +struct skiplist_entry +{ + int number; + + /* NULL if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&arg, 1, 0, 0, 0); + } + + if (decode_exception.reason < 0) + { + if (decode_exception.error != NOT_FOUND_ERROR) + throw_exception (decode_exception); + + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (arg == 0) + ui_out_message (current_uiout, 0, _("\ +Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entries found with number %s.\n"), arg); + + return; + } + + if (opts.addressprint) + tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 5, + num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, + num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (arg != 0 && !number_is_in_list (arg, e->number)) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, + "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", + e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 1; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 0; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int found = 0; + + b_prev = 0; + ALL_SKIPLIST_ENTRIES_SAFE (e, temp) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + found = 1; + } + else + { + b_prev = e; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ + +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ + +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ + +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + int searched_for_sal = 0; + struct symtab_and_line sal; + char *filename = NULL; + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (!e->enabled || e->pending) + continue; + + /* Does the pc we're stepping into match e's stored pc? */ + if (e->pc != 0 && pc == e->pc) + return 1; + + if (e->filename != 0) + { + /* Get the filename corresponding to this pc, if we haven't + * yet. */ + if (!searched_for_sal) + { + sal = find_pc_line (pc, 0); + if (sal.symtab != 0) + filename = sal.symtab->filename; + searched_for_sal = 1; + } + if (filename != 0 && strcmp (filename, e->filename) == 0) + return 1; + } + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set (void) +{ + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals; + volatile struct gdb_exception decode_exception; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&func_name, 1, 0, 0, 0); + } + + if (decode_exception.reason >= 0 + && sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup (func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +Usage: skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable skip entries. You can specify numbers (e.g. \"skip enable 1 3\"), \ +ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\ +Usage: skip enable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable skip entries. You can specify numbers (e.g. \"skip disable 1 3\"), \ +ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\ +Usage: skip disable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete skip entries. You can specify numbers (e.g. \"skip delete 1 3\"), \ +ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\ +Usage: skip delete [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Display the status of skips. You can specify numbers (e.g. \"skip info 1 3\"), \ +ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll show all skips.\n\n\ +Usage: skip info [NUMBERS AND/OR RANGES]\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/gdb/skip.h b/gdb/skip.h new file mode 100644 index 0000000..14aa4f3 --- /dev/null +++ b/gdb/skip.h @@ -0,0 +1,28 @@ +/* Header for skipping over uninteresting files and functions when debugging. + + Copyright (C) 2011 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); + +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (void); + +#endif /* !defined (SKIP_H) */ diff --git a/gdb/stack.c b/gdb/stack.c index 003725a..9136daa 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -96,6 +96,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -103,6 +109,14 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; + +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; \f /* Return 1 if we should display the address in addition to the location, @@ -872,9 +886,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -882,6 +896,106 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last symtab and line we displayed, which we use e.g. + * as the place to put a breakpoint when the `break' command is + * invoked with no arguments. */ + +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +/* Forget the last sal we displayed. */ + +void +clear_last_displayed_sal (void) +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +/* Is our record of the last sal we displayed valid? If not, + * the get_last_displayed_* functions will return NULL or 0, as + * appropriate. */ + +int +last_displayed_sal_is_valid (void) +{ + return last_displayed_sal_valid; +} + +/* Get the pspace of the last sal we displayed, if it's valid. */ + +struct program_space * +get_last_displayed_pspace (void) +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +/* Get the address of the last sal we displayed, if it's valid. */ + +CORE_ADDR +get_last_displayed_addr (void) +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +/* Get the symtab of the last sal we displayed, if it's valid. */ + +struct symtab* +get_last_displayed_symtab (void) +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +/* Get the line of the last sal we displayed, if it's valid. */ + +int +get_last_displayed_line (void) +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +/* Get the last sal we displayed, if it's valid. */ + +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ diff --git a/gdb/stack.h b/gdb/stack.h index 3cce623..312e8ff 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -38,4 +38,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (void); +int last_displayed_sal_is_valid (void); +struct program_space* get_last_displayed_pspace (void); +CORE_ADDR get_last_displayed_addr (void); +struct symtab* get_last_displayed_symtab (void); +int get_last_displayed_line (void); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/gdb/symfile.c b/gdb/symfile.c index dfce380..a4eaad9 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -56,6 +56,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include <sys/types.h> #include <fcntl.h> @@ -2839,7 +2840,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ceecad1..e5d8114 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-10-06 Justin Lebar <justin.lebar@gmail.com> + + Add tests for skip command. + * testsuite/gdb.base/skip-solib-lib.c: New + * testsuite/gdb.base/skip-solib-main.c: New + * testsuite/gdb.base/skip-solib.exp: New + * testsuite/gdb.base/skip.c: New + * testsuite/gdb.base/skip.exp: New + * testsuite/gdb.base/skip1.c: New + * testsuite/gdb.base/Makefile.in: Adding new files. + 2011-10-31 Yao Qi <yao@codesourcery.com> Pedro Alves <pedro@codesourcery.com> diff --git a/gdb/testsuite/gdb.base/Makefile.in b/gdb/testsuite/gdb.base/Makefile.in index 72f1ba4..7ceb121 100644 --- a/gdb/testsuite/gdb.base/Makefile.in +++ b/gdb/testsuite/gdb.base/Makefile.in @@ -30,8 +30,8 @@ EXECUTABLES = a2-run advance all-types annota1 annota1-watch_thread_num \ sepsymtab.debug sepsymtab.stripped setshow setvar shmain shreloc \ sigall sigaltstack sigbpt sigchld siginfo siginfo-addr \ siginfo-infcall siginfo-obj signals signull sigrepeat sigstep \ - sizeof solib solib-corrupted solib-display-main solib-nodir \ - solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ + sizeof skip skip-solib solib solib-corrupted solib-display-main + solib-nodir solib-overlap-main-0x40000000 solib-symbol-main solib-weak \ solib-weak-lib2 solib_sl so-impl-ld so-indr-cl \ stack-checking start step-break step-bt step-line step-resume-infcall \ step-test store structs-t* structs2 structs3 \ diff --git a/gdb/testsuite/gdb.base/skip-solib-lib.c b/gdb/testsuite/gdb.base/skip-solib-lib.c new file mode 100644 index 0000000..792cd01 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-lib.c @@ -0,0 +1,11 @@ +/* Simple shared library */ + +int square(int num) +{ + return multiply(num, num); +} + +int multiply(int a, int b) +{ + return a * b; +} diff --git a/gdb/testsuite/gdb.base/skip-solib-main.c b/gdb/testsuite/gdb.base/skip-solib-main.c new file mode 100644 index 0000000..746bb5f --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib-main.c @@ -0,0 +1,6 @@ +int square(int num); + +int main() +{ + return square(0); +} diff --git a/gdb/testsuite/gdb.base/skip-solib.exp b/gdb/testsuite/gdb.base/skip-solib.exp new file mode 100644 index 0000000..d6e25a4 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip-solib.exp @@ -0,0 +1,130 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +# +# Tests skipping shared libraries. +# + +# This only works on GNU/Linux. +if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { + continue +} + +set test "skip-solib" +set srcfile_main "${test}-main.c" +set binfile_main "${test}-test" +set srcfile_lib "${test}-lib.c" +set libname "lib${test}" +set binfile_lib ${objdir}/${subdir}/${libname}.so + +# +# Compile our program under test. The main program references a shared library +# libskip-solib.so, which contains two functions, square(), which is +# referenced by the main program, and multiply(), which is not referenced by +# the main program. +# + +if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-fPIC -Wl,-soname,${libname}.so]] != ""} { + return -1 +} + +if {[gdb_compile "${srcdir}/${subdir}/${srcfile_main}" "${binfile_main}.o" object debug] != ""} { + return -1 +} + +if {[gdb_compile "${binfile_main}.o" "${binfile_main}" executable \ + [list debug "additional_flags=-L${objdir}/${subdir} -l${test} \ + -Wl,-rpath=${objdir}/${subdir}"]] != ""} { + return -1 +} + +gdb_start +clean_restart ${binfile_main} + +# +# At this point, if we try to skip the file ${srcfile_lib} or the function +# multiply(), we should get a prompt asking us if we want to enable the +# skip entry pending a shared library load. +# + +gdb_test "skip file ${srcfile_lib}" \ + "File ${srcfile_lib} will be skipped when stepping." \ + "ignoring file in solib" \ + "No source file named ${srcfile_lib}.* +Ignore file pending future shared library load.*" \ + "y" + +# +# Does info skip list this entry as pending? +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+${srcfile_lib} \\(PENDING\\)\\s*" \ + "info skip with pending file" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# We shouldn't step into square(), since we skipped skip-solib-lib.c. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+main.*" "step after ignoring solib file." + +# +# Our entry should no longer be pending. Note that we unfortunately need to do +# at least one step before the entry will be unmarked as pending. +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+\\s+.*${srcfile_lib}\\s*" \ + "info skip with pending file" + +# +# Now restart gdb and testing ignoring of a function inside a solib. +# +gdb_exit +gdb_start +clean_restart ${binfile_main} + +gdb_test "skip function multiply" \ + "Function multiply will be skipped when stepping, pending shared library load." \ + "ignoring function in solib" \ +"No function found named multiply..* +Ignore function pending future shared library load.*" \ + "y" + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Our first step should take us into square. +# +gdb_test "step" "square.*" + +# +# Now our entry should no longer be pending. +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+function\\s+y\\s+0x\[0-9a-f\]+\\s+multiply at .*${srcfile_lib}:.*\\s*" \ + "skip should no longer be pending." + +# +# This step shouldn't go into multiply -- we should skip it and go on to the +# last line of square. +# +gdb_test "step" "" +gdb_test "bt" "#0\\s+square.*" diff --git a/gdb/testsuite/gdb.base/skip.c b/gdb/testsuite/gdb.base/skip.c new file mode 100644 index 0000000..565ba93 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.c @@ -0,0 +1,13 @@ +int foo(); +int bar(); +int baz(int, int); + +int main() +{ + return baz(foo(), bar()); +} + +int foo() +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp new file mode 100644 index 0000000..7c699eb --- /dev/null +++ b/gdb/testsuite/gdb.base/skip.exp @@ -0,0 +1,179 @@ +# Copyright 2011 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. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# This file was written by Justin Lebar. (justin.lebar@gmail.com) + +if { [prepare_for_testing skip.exp "skip" \ + {skip.c skip1.c } \ + {debug nowarnings}] } { + return -1 +} + +set srcfile skip.c +set srcfile1 skip1.c + +# +# Right after we start gdb, there's no default file or function to skip. +# +gdb_test "skip file" "No default file now." +gdb_test "skip function" "No default function now." +gdb_test "skip" "No default function now." + +if ![runto_main] { fail "skip tests suppressed" } + +# +# Test |info skip| with an empty skiplist. +# +gdb_test "info skip" "Not skipping any files or functions\." "info skip empty" + +# +# Create a skiplist entry for the current file and function. +# +gdb_test "skip file" "File .*$srcfile will be skipped when stepping\." +gdb_test "skip" "Function main at .* will be skipped when stepping\." + +# +# Create a skiplist entry for a specified file and function. +# +gdb_test "skip file skip1.c" "File .*$srcfile1 will be skipped when stepping\." +gdb_test "skip function baz" "Function baz at .* will be skipped when stepping\." + +# +# Test bad skiplist entry modification commands +# +gdb_test "skip enable 999" "No skiplist entries found with number 999." +gdb_test "skip disable 999" "No skiplist entries found with number 999." +gdb_test "skip delete 999" "No skiplist entries found with number 999." +gdb_test "skip enable a" "Args must be numbers or '\\$' variables." +gdb_test "skip disable a" "Args must be numbers or '\\$' variables." +gdb_test "skip delete a" "Args must be numbers or '\\$' variables." + +# +# Ask for info on a skiplist entry which doesn't exist. +# +gdb_test "info skip 999" "No skiplist entries found with number 999." + +# +# Does |info skip| look right? +# +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +1\\s+file\\s+y\\s+.*$srcfile\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +# +# Right now, we have an outstanding skiplist entry on both source +# files, so when we step into the first line in main(), we should step +# right over it and go to the second line of main(). +# + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" +gdb_test "bt" "\\s*\\#0\\s+main.*" "step after all ignored" + +# +# Now remove skip.c from the skiplist. Our first step should take us +# into foo(), and our second step should take us to the next line in +# main(). +# +gdb_test "skip delete 1" +# Check that entry 1 is missing from |info skip| +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +# +# Now disable the skiplist entry for skip1.c. We should now +# step into foo(), then into bar(), but not into baz(). +# +gdb_test "skip disable 3" +# Is entry 3 disabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+n.*" \ + "info skip shows entry as disabled" + +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "bar \\(\\) at.*" "step after disabling 3 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "foo \\(\\) at.*" "step after disabling 3 (2)" +gdb_test "step"; # Return from bar() +gdb_test "step" "main \\(\\) at.*" "step after disabling 3 (3)" + +# +# Enable skiplist entry 3 and make sure we step over it like before. +# +gdb_test "skip enable 3" +# Is entry 3 enabled in |info skip|? +gdb_test "info skip 3" ".*\\n3\\s+file\\s+y.*" \ + "info skip shows entry as enabled" +if ![runto_main] { fail "skip tests suppressed" } +gdb_test "step" "foo \\(\\) at.*" "step after deleting 1 (1)" +gdb_test "step"; # Return from foo() +gdb_test "step" "main \\(\\) at.*" "step after deleting 1 (2)" + +gdb_test "skip disable" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after disabling all" + +gdb_test "skip enable" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+y\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after enabling all" + +gdb_test "skip disable 4 2-3" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+n\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+n\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after disabling 4 2-3" + +gdb_test "skip enable 2-3" +gdb_test "info skip" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s* +4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after enabling 2-3" + +gdb_test "info skip 2-3" \ + "Num\\s+Type\\s+Enb\\s+Address\\s+What\\s* +2\\s+function\\s+y\\s+0x\[0-9a-f\]+ main at .*$srcfile:\[0-9\]+\\s* +3\\s+file\\s+y\\s+.*$srcfile1\\s*" \ + "info skip 2-3" + +gdb_test "skip delete 2 3" +gdb_test "info skip" \ + "4\\s+function\\s+n\\s+0x\[0-9a-f\]+ baz at .*$srcfile1:\[0-9\]+\\s*" \ + "info skip after deleting 2 3" + +gdb_test "skip delete" +gdb_test "info skip" "Not skipping any files or functions\." \ + "info skip after deleting all" diff --git a/gdb/testsuite/gdb.base/skip1.c b/gdb/testsuite/gdb.base/skip1.c new file mode 100644 index 0000000..2dab5c3 --- /dev/null +++ b/gdb/testsuite/gdb.base/skip1.c @@ -0,0 +1,9 @@ +int bar() +{ + return 1; +} + +int baz(int a, int b) +{ + return a + b; +} ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-01 14:53 ` Justin Lebar @ 2011-11-02 22:43 ` Maciej W. Rozycki 2011-11-02 23:52 ` Stan Shebs 2011-11-03 3:54 ` Eli Zaretskii 0 siblings, 2 replies; 44+ messages in thread From: Maciej W. Rozycki @ 2011-11-02 22:43 UTC (permalink / raw) To: Justin Lebar; +Cc: Stan Shebs, gdb-patches On Tue, 1 Nov 2011, Justin Lebar wrote: > Checked in, with two spaces after periods in comments. > > Thank you for your patience! > > -Justin > > 2011-10-06 Justin Lebar <justin.lebar@gmail.com> > > * Makefile.in: (SFILES): Add skip.c. > (HFILES_NO_SRCDIR): Add skip.h. > (COMMON_OBS): Add skip.o. > * skip.h, skip.c: New. > * breakpoint.h (set_default_breakpoint): Remove. > (get_sal_arch): Declare. > * breakpoint.c: Remove default_breakpoint_valid, > default_breakpoint_address, default_breakpoint_symtab, > default_breakpoint_line, default_breakpoint_pspace variables. > (get_sal_arch): Make public. > (set_default_breakpoint): Remove. > (parse_breakpoint_sals, create_breakpoint, clear_command, > decode_line_spec_1): Remove uses of default_breakpoint variables; > replaced with function calls into stack.c. > * cli/cli-cmds.h: Add cmd_list_element *skiplist. > * cli/cli-cmds.c: Add skiplist. > (init_cmd_lists): Initialize skiplist. > (init_cli_cmds): Fix comment (classes of commands appear in > alphabetical order). > * infrun.c (handle_inferior_event): Add check that we don't step into > a function whose pc is marked for skip. > * stack.c: Declare last_displayed_sal_valid, last_displayed_pspace, > last_displayed_addr, last_displayed_symtab, last_displayed_line > variables. > (set_last_displayed_sal): New static function. > (print_frame_info): Switch call to set_default_breakpoint to call to > set_last_displayed_sal. > (clear_last_displayed_sal, last_displayed_sal_is_valid, > get_last_displayed_pspace, get_last_displayed_addr, > get_last_displayed_symtab, get_last_displayed_line, > get_last_displayed_sal): New public functions. > * stack.h (clear_last_displayed_sal, last_displayed_sal_is_valid, > get_last_displayed_pspace, get_last_displayed_addr, > get_last_displayed_symtab, get_last_displayed_line, > get_last_displayed_sal): Declare. > > 2011-10-06 Justin Lebar <justin.lebar@gmail.com> > > Add tests for skip command. > * testsuite/gdb.base/skip-solib-lib.c: New > * testsuite/gdb.base/skip-solib-main.c: New > * testsuite/gdb.base/skip-solib.exp: New > * testsuite/gdb.base/skip.c: New > * testsuite/gdb.base/skip.exp: New > * testsuite/gdb.base/skip1.c: New > * testsuite/gdb.base/Makefile.in: Adding new files. This change broke the build of gdb.info: makeinfo --css-ref=../cs.css --split-size=5000000 --split-size=5000000 --split-size=5000000 -DHAVE_MAKEINFO_CLICK -I .../gdb/doc/../../readline/doc -I .../gdb/doc/../mi -I .../gdb/doc \ -o gdb.info .../gdb/doc/gdb.texinfo .../gdb/doc/gdb.texinfo:4899: warning: `.' or `,' must follow @xref, not `I'. .../gdb/doc/gdb.texinfo:4857: `Skipping Over Functions and Files' has no Up field(perhaps incorrect sectioning?). .../gdb/doc/gdb.texinfo:4857: warning: unreferenced node `Skipping Over Functionsand Files'. makeinfo: Removing output file `gdb.info' due to errors; use --force to preserve. make[5]: *** [gdb.info] Error 1 Also a ChangeLog entry is missing for changes to gdb.texinfo -- please fix that up. OK to apply the fix for the build errors below? 2011-11-02 Maciej W. Rozycki <macro@codesourcery.com> gdb/doc/ * gdb.texinfo (Skipping Over Functions and Files): Remove node designation. Fix "Specify Location" cross-reference. Maciej gdb-info-fix.diff Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo =================================================================== --- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo 2011-11-02 21:25:50.000000000 +0000 +++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo 2011-11-02 22:22:53.495572496 +0000 @@ -4854,7 +4854,6 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table -@node Skipping Over Functions and Files @subsection Skipping Over Functions and Files @cindex skipping over functions and files @@ -4896,7 +4895,7 @@ example, @code{skip file boring.c}. @itemx skip function @r{[}@var{linespec}@r{]} After running this command, the function named by @var{linespec} or the function containing the line named by @var{linespec} will be skipped over when -stepping. @xref{Specify Location} +stepping. @xref{Specify Location}. If you do not specify @var{linespec}, the function you're currently debugging will be skipped. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-02 22:43 ` Maciej W. Rozycki @ 2011-11-02 23:52 ` Stan Shebs 2011-11-03 0:20 ` Maciej W. Rozycki 2011-11-03 3:54 ` Eli Zaretskii 1 sibling, 1 reply; 44+ messages in thread From: Stan Shebs @ 2011-11-02 23:52 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Justin Lebar, gdb-patches On 11/2/11 3:42 PM, Maciej W. Rozycki wrote: > This change broke the build of gdb.info: > > makeinfo --css-ref=../cs.css --split-size=5000000 --split-size=5000000 --split-size=5000000 -DHAVE_MAKEINFO_CLICK -I .../gdb/doc/../../readline/doc -I .../gdb/doc/../mi -I .../gdb/doc \ > -o gdb.info .../gdb/doc/gdb.texinfo > .../gdb/doc/gdb.texinfo:4899: warning: `.' or `,' must follow @xref, not `I'. > .../gdb/doc/gdb.texinfo:4857: `Skipping Over Functions and Files' has no Up field(perhaps incorrect sectioning?). > .../gdb/doc/gdb.texinfo:4857: warning: unreferenced node `Skipping Over Functionsand Files'. > makeinfo: Removing output file `gdb.info' due to errors; use --force to preserve. > make[5]: *** [gdb.info] Error 1 > > Also a ChangeLog entry is missing for changes to gdb.texinfo -- please fix > that up. > > OK to apply the fix for the build errors below? Yes, this is good. (I just bumped into it myself...) Stan > > 2011-11-02 Maciej W. Rozycki<macro@codesourcery.com> > > gdb/doc/ > * gdb.texinfo (Skipping Over Functions and Files): Remove node > designation. Fix "Specify Location" cross-reference. > > Maciej > > gdb-info-fix.diff > Index: gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo > =================================================================== > --- gdb-fsf-trunk-quilt.orig/gdb/doc/gdb.texinfo 2011-11-02 21:25:50.000000000 +0000 > +++ gdb-fsf-trunk-quilt/gdb/doc/gdb.texinfo 2011-11-02 22:22:53.495572496 +0000 > @@ -4854,7 +4854,6 @@ proceed until the function returns. > An argument is a repeat count, as in @code{next}. > @end table > > -@node Skipping Over Functions and Files > @subsection Skipping Over Functions and Files > @cindex skipping over functions and files > > @@ -4896,7 +4895,7 @@ example, @code{skip file boring.c}. > @itemx skip function @r{[}@var{linespec}@r{]} > After running this command, the function named by @var{linespec} or the > function containing the line named by @var{linespec} will be skipped over when > -stepping. @xref{Specify Location} > +stepping. @xref{Specify Location}. > > If you do not specify @var{linespec}, the function you're currently debugging > will be skipped. > ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-02 23:52 ` Stan Shebs @ 2011-11-03 0:20 ` Maciej W. Rozycki 0 siblings, 0 replies; 44+ messages in thread From: Maciej W. Rozycki @ 2011-11-03 0:20 UTC (permalink / raw) To: Stan Shebs; +Cc: Justin Lebar, gdb-patches On Wed, 2 Nov 2011, Stan Shebs wrote: > Yes, this is good. (I just bumped into it myself...) Applied, thanks. Maciej ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-02 22:43 ` Maciej W. Rozycki 2011-11-02 23:52 ` Stan Shebs @ 2011-11-03 3:54 ` Eli Zaretskii 2011-11-03 14:32 ` Tom Tromey 1 sibling, 1 reply; 44+ messages in thread From: Eli Zaretskii @ 2011-11-03 3:54 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: justin.lebar, stanshebs, gdb-patches > Date: Wed, 2 Nov 2011 22:42:35 +0000 > From: "Maciej W. Rozycki" <macro@codesourcery.com> > CC: Stan Shebs <stanshebs@earthlink.net>, <gdb-patches@sourceware.org> > > OK to apply the fix for the build errors below? No, please don't remove the @node line. Instead, add to the parent node a @menu that mentions this node, or add the node to an existing menu, if the parent node already has a menu. > -stepping. @xref{Specify Location} > +stepping. @xref{Specify Location}. This part is fine, thanks. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-03 3:54 ` Eli Zaretskii @ 2011-11-03 14:32 ` Tom Tromey 2011-11-03 16:54 ` Eli Zaretskii 2011-11-03 18:04 ` Maciej W. Rozycki 0 siblings, 2 replies; 44+ messages in thread From: Tom Tromey @ 2011-11-03 14:32 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Maciej W. Rozycki, justin.lebar, stanshebs, gdb-patches >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes: Eli> No, please don't remove the @node line. Instead, add to the parent Eli> node a @menu that mentions this node, or add the node to an existing Eli> menu, if the parent node already has a menu. Here is what I am committing to fix the problem. Tested by building with makeinfo 4.13. Tom 2011-11-03 Tom Tromey <tromey@redhat.com> * gdb.texinfo (Stopping): Add menu entry. (Continuing and Stepping): Restore @node. Use @section, not @subsection. Index: gdb.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v retrieving revision 1.887 diff -u -r1.887 gdb.texinfo --- gdb.texinfo 3 Nov 2011 00:16:45 -0000 1.887 +++ gdb.texinfo 3 Nov 2011 14:31:48 -0000 @@ -3216,6 +3216,8 @@ @menu * Breakpoints:: Breakpoints, watchpoints, and catchpoints * Continuing and Stepping:: Resuming execution +* Skipping Over Functions and Files:: + Skipping over functions and files * Signals:: Signals * Thread Stops:: Stopping and starting multi-thread programs @end menu @@ -4854,7 +4856,8 @@ An argument is a repeat count, as in @code{next}. @end table -@subsection Skipping Over Functions and Files +@node Skipping Over Functions and Files +@section Skipping Over Functions and Files @cindex skipping over functions and files The program you are debugging may contain some functions which are ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-03 14:32 ` Tom Tromey @ 2011-11-03 16:54 ` Eli Zaretskii 2011-11-03 18:04 ` Maciej W. Rozycki 1 sibling, 0 replies; 44+ messages in thread From: Eli Zaretskii @ 2011-11-03 16:54 UTC (permalink / raw) To: Tom Tromey; +Cc: macro, justin.lebar, stanshebs, gdb-patches > From: Tom Tromey <tromey@redhat.com> > Cc: "Maciej W. Rozycki" <macro@codesourcery.com>, justin.lebar@gmail.com, > stanshebs@earthlink.net, gdb-patches@sourceware.org > Date: Thu, 03 Nov 2011 08:32:21 -0600 > > >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes: > > Eli> No, please don't remove the @node line. Instead, add to the parent > Eli> node a @menu that mentions this node, or add the node to an existing > Eli> menu, if the parent node already has a menu. > > Here is what I am committing to fix the problem. > > Tested by building with makeinfo 4.13. Thank you. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-03 14:32 ` Tom Tromey 2011-11-03 16:54 ` Eli Zaretskii @ 2011-11-03 18:04 ` Maciej W. Rozycki 2011-11-03 18:25 ` Eli Zaretskii 1 sibling, 1 reply; 44+ messages in thread From: Maciej W. Rozycki @ 2011-11-03 18:04 UTC (permalink / raw) To: Tom Tromey; +Cc: Eli Zaretskii, justin.lebar, stanshebs, gdb-patches Hi Tom, > >>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes: > > Eli> No, please don't remove the @node line. Instead, add to the parent > Eli> node a @menu that mentions this node, or add the node to an existing > Eli> menu, if the parent node already has a menu. > > Here is what I am committing to fix the problem. > > Tested by building with makeinfo 4.13. > > Tom > > 2011-11-03 Tom Tromey <tromey@redhat.com> > > * gdb.texinfo (Stopping): Add menu entry. > (Continuing and Stepping): Restore @node. Use @section, not > @subsection. s/(Continuing and Stepping)/(Skipping Over Functions and Files)/ in the entry above, I presume. You managed to get at it before I did, thanks for fixing the breakage I caused. What about the other places where @subsection is used without @node -- are they legitimate? I followed their precedent here. Just making sure we all know what's going on here. Maciej ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-03 18:04 ` Maciej W. Rozycki @ 2011-11-03 18:25 ` Eli Zaretskii 2011-11-03 19:01 ` Stan Shebs 0 siblings, 1 reply; 44+ messages in thread From: Eli Zaretskii @ 2011-11-03 18:25 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: tromey, justin.lebar, stanshebs, gdb-patches > Date: Thu, 3 Nov 2011 18:04:08 +0000 > From: "Maciej W. Rozycki" <macro@codesourcery.com> > CC: Eli Zaretskii <eliz@gnu.org>, <justin.lebar@gmail.com>, > <stanshebs@earthlink.net>, <gdb-patches@sourceware.org> > > What about the other places where @subsection is used without @node -- > are they legitimate? They are legitimate, but having sections and subsections without a @node makes finding them harder, since there's no commands in Info to find a section by name, only by its node name. So I'd like to avoid introducing more of them. > I followed their precedent here. Well, bad precedent ;-) Most of them originated long ago. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-11-03 18:25 ` Eli Zaretskii @ 2011-11-03 19:01 ` Stan Shebs 0 siblings, 0 replies; 44+ messages in thread From: Stan Shebs @ 2011-11-03 19:01 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Maciej W. Rozycki, tromey, justin.lebar, gdb-patches On 11/3/11 11:25 AM, Eli Zaretskii wrote: >> Date: Thu, 3 Nov 2011 18:04:08 +0000 >> From: "Maciej W. Rozycki"<macro@codesourcery.com> >> CC: Eli Zaretskii<eliz@gnu.org>,<justin.lebar@gmail.com>, >> <stanshebs@earthlink.net>,<gdb-patches@sourceware.org> >> >> What about the other places where @subsection is used without @node -- >> are they legitimate? > They are legitimate, but having sections and subsections without a > @node makes finding them harder, since there's no commands in Info to > find a section by name, only by its node name. So I'd like to avoid > introducing more of them. > That's a good deal my fault - at one point I had it stuck in my head that makeinfo could auto-generate nodes from section headings, but in reviewing the texinfo doc, it looks like I must have confused that with auto-generation of next/prev/up links (or else it was an option that came and went long ago). Stan stan@codesourcery.com ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 14:08 ` Justin Lebar 2011-10-06 15:51 ` Stan Shebs @ 2011-10-06 17:19 ` Diego Novillo 2011-10-06 17:33 ` Tom Tromey 2 siblings, 0 replies; 44+ messages in thread From: Diego Novillo @ 2011-10-06 17:19 UTC (permalink / raw) To: Justin Lebar; +Cc: Tom Tromey, Lawrence Crowl, gdb-patches On Thu, Oct 6, 2011 at 10:07, Justin Lebar <justin.lebar@gmail.com> wrote: > I last pinged gdb-patches about the patch on May 16 and got no response. > > I imagine the patch has bitrotted by now. I'd be happy to bring it up > to date if there were a reasonable chance it would get reviewed this > time. Thanks. I would very much like to see it in GDB but I have no real way of making it happen other than to generate user demand for it. Over on GCC, we are discussing converting some macros into one-liner inline functions and we want to avoid the mess this would cause for 'step' in the presence of things like foo(f(g()), h()). One additional request that came up in the thread I pointed you to (http://gcc.gnu.org/ml/gcc-patches/2011-10/msg00324.html) is Jakub's request to blacklist DW_AT_artificial functions by default. I think that's a good idea. Thanks. Diego. ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 14:08 ` Justin Lebar 2011-10-06 15:51 ` Stan Shebs 2011-10-06 17:19 ` Diego Novillo @ 2011-10-06 17:33 ` Tom Tromey 2011-10-06 17:37 ` Diego Novillo 2 siblings, 1 reply; 44+ messages in thread From: Tom Tromey @ 2011-10-06 17:33 UTC (permalink / raw) To: Justin Lebar; +Cc: Diego Novillo, Lawrence Crowl, gdb-patches >>>>> "Justin" == Justin Lebar <justin.lebar@gmail.com> writes: Justin> I last pinged gdb-patches about the patch on May 16 and got no response. I must have missed it :-( Just for future reference, I encourage everybody to ping a lot -- send a ping once a week. In my experience, it feels like I'm being obnoxious when I write the note, but it is a good way to get attention, and I promise you nobody will be offended by it. Justin> I imagine the patch has bitrotted by now. I'd be happy to bring it up Justin> to date if there were a reasonable chance it would get reviewed this Justin> time. I definitely want it to go in. Tom ^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: Status of 'blacklist' patch? 2011-10-06 17:33 ` Tom Tromey @ 2011-10-06 17:37 ` Diego Novillo 0 siblings, 0 replies; 44+ messages in thread From: Diego Novillo @ 2011-10-06 17:37 UTC (permalink / raw) To: Tom Tromey; +Cc: Justin Lebar, Lawrence Crowl, gdb-patches On 11-10-06 13:33 , Tom Tromey wrote: > I definitely want it to go in. Yay! Thanks. Diego. ^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2011-11-03 19:01 UTC | newest]
Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-06 12:12 Status of 'blacklist' patch? Diego Novillo
2011-10-06 14:08 ` Justin Lebar
2011-10-06 15:51 ` Stan Shebs
2011-10-06 20:16 ` Justin Lebar
2011-10-10 12:34 ` Stan Shebs
2011-10-11 21:34 ` Justin Lebar
2011-10-11 23:54 ` Doug Evans
2011-10-16 19:22 ` Justin Lebar
2011-10-20 19:46 ` Tom Tromey
2011-10-25 20:07 ` Justin Lebar
2011-10-25 20:41 ` Pedro Alves
2011-10-25 21:25 ` Justin Lebar
2011-10-20 20:40 ` Eli Zaretskii
2011-10-25 16:47 ` Justin Lebar
2011-10-25 16:53 ` Eli Zaretskii
2011-10-25 19:52 ` Justin Lebar
2011-10-25 20:13 ` Eli Zaretskii
2011-10-25 20:30 ` Justin Lebar
2011-10-26 1:06 ` Stan Shebs
2011-10-26 3:45 ` Justin Lebar
2011-10-26 5:37 ` Stan Shebs
2011-10-26 8:10 ` Joel Brobecker
2011-10-26 13:28 ` Eli Zaretskii
2011-10-26 15:11 ` Justin Lebar
2011-10-28 18:18 ` Tom Tromey
2011-10-28 19:48 ` Justin Lebar
2011-10-28 19:53 ` Tom Tromey
2011-10-28 19:49 ` Tom Tromey
2011-10-28 19:55 ` Justin Lebar
2011-10-28 20:37 ` Tom Tromey
2011-10-31 15:52 ` Justin Lebar
[not found] ` <4EAF2E0E.7080508@earthlink.net>
2011-11-01 14:53 ` Justin Lebar
2011-11-02 22:43 ` Maciej W. Rozycki
2011-11-02 23:52 ` Stan Shebs
2011-11-03 0:20 ` Maciej W. Rozycki
2011-11-03 3:54 ` Eli Zaretskii
2011-11-03 14:32 ` Tom Tromey
2011-11-03 16:54 ` Eli Zaretskii
2011-11-03 18:04 ` Maciej W. Rozycki
2011-11-03 18:25 ` Eli Zaretskii
2011-11-03 19:01 ` Stan Shebs
2011-10-06 17:19 ` Diego Novillo
2011-10-06 17:33 ` Tom Tromey
2011-10-06 17:37 ` Diego Novillo
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox