From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8227 invoked by alias); 10 Jan 2012 16:06:42 -0000 Received: (qmail 8216 invoked by uid 22791); 10 Jan 2012 16:06:36 -0000 X-SWARE-Spam-Status: No, hits=-6.9 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,T_FILL_THIS_FORM_SHORT,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 10 Jan 2012 16:06:11 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q0AG6AFc010393 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 10 Jan 2012 11:06:10 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q0AG6AO3029021; Tue, 10 Jan 2012 11:06:10 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id q0AG68xD025002; Tue, 10 Jan 2012 11:06:09 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Subject: RFC: add relative file name handling for linespecs Date: Tue, 10 Jan 2012 16:32:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.92 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-01/txt/msg00295.txt.bz2 I'd appreciate comments on this patch. This patch changes gdb to allow relative file names to match a source file name if all the trailing components match. Previously this behavior was only allowed if the source file name did not have any directory separators. That is, now "break gcc/expr.c:1000" will work as many users expect. See the recent thread on gdb@. This needs at least a doc review. Built and regtested on x86-64 F15. Tom 2012-01-10 Tom Tromey * NEWS: Add item. * symtab.h (compare_filenames_for_search): Declare. * symtab.c (compare_filenames_for_search): New function. (iterate_over_some_symtabs): Use it. * symfile.h (struct quick_symbol_functions) : Change spec. * psymtab.c (partial_map_symtabs_matching_filename): Use compare_filenames_for_search. Update for new spec. * dwarf2read.c (dw2_map_symtabs_matching_filename): Use compare_filenames_for_search. Update for new spec. 2012-01-10 Tom Tromey * gdb.texinfo (Specify Location): Document relative file name handling. 2012-01-10 Tom Tromey * gdb.linespec/linespec.exp: Change some tests to use $decimal. Add test for relative directory. diff --git a/gdb/NEWS b/gdb/NEWS index a9a7859..10661c1 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -9,6 +9,11 @@ * The binary "gdbtui" can no longer be built or installed. Use "gdb -tui" instead. +* The filename part of a linespec will now match trailing components + of a source file name. For example, "break gcc/expr.c:1000" will + now set a breakpoint in build/gcc/expr.c, but not + build/libcpp/expr.c. + *** Changes in GDB 7.4 * GDB now handles ambiguous linespecs more consistently; the existing diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 2f4aa4f..1f3b2a1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6492,6 +6492,11 @@ linespec. @item @var{filename}:@var{linenum} Specifies the line @var{linenum} in the source file @var{filename}. +If @var{filename} is a relative file name, then it will match any +source file name with the same trailing components. For example, if +@var{filename} is @samp{gcc/expr.c}, then it will match source file +name of @file{/build/trunk/gcc/expr.c}, but not +@file{/build/trunk/libcpp/expr.c} or @file{/build/trunk/gcc/x-expr.c}. @item @var{function} Specifies the line that begins the body of the function @var{function}. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index d09b27a..861b8de 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -2402,8 +2402,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, { int i; const char *name_basename = lbasename (name); - int check_basename = name_basename == name; - struct dwarf2_per_cu_data *base_cu = NULL; + int name_len = strlen (name); + int is_abs = IS_ABSOLUTE_PATH (name); dw2_setup (objfile); @@ -2426,7 +2426,9 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, { const char *this_name = file_data->file_names[j]; - if (FILENAME_CMP (name, this_name) == 0) + if (FILENAME_CMP (name, this_name) == 0 + || (!is_abs && compare_filenames_for_search (this_name, + name, name_len))) { if (dw2_map_expand_apply (objfile, per_cu, name, full_path, real_path, @@ -2434,9 +2436,12 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, return 1; } - if (check_basename && ! base_cu - && FILENAME_CMP (lbasename (this_name), name) == 0) - base_cu = per_cu; + { + if (dw2_map_expand_apply (objfile, per_cu, + name, full_path, real_path, + callback, data)) + return 1; + } /* Before we invoke realpath, which can get expensive when many files are involved, do a quick comparison of the basenames. */ @@ -2450,7 +2455,10 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, file_data, j); if (this_real_name != NULL - && FILENAME_CMP (full_path, this_real_name) == 0) + && (FILENAME_CMP (full_path, this_real_name) == 0 + || (!is_abs + && compare_filenames_for_search (this_real_name, + name, name_len)))) { if (dw2_map_expand_apply (objfile, per_cu, name, full_path, real_path, @@ -2465,7 +2473,10 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, file_data, j); if (this_real_name != NULL - && FILENAME_CMP (real_path, this_real_name) == 0) + && (FILENAME_CMP (real_path, this_real_name) == 0 + || (!is_abs + && compare_filenames_for_search (this_real_name, + name, name_len)))) { if (dw2_map_expand_apply (objfile, per_cu, name, full_path, real_path, @@ -2476,14 +2487,6 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, } } - if (base_cu) - { - if (dw2_map_expand_apply (objfile, base_cu, - name, full_path, real_path, - callback, data)) - return 1; - } - return 0; } diff --git a/gdb/psymtab.c b/gdb/psymtab.c index 1f9457f..998bc05 100644 --- a/gdb/psymtab.c +++ b/gdb/psymtab.c @@ -164,10 +164,14 @@ partial_map_symtabs_matching_filename (struct objfile *objfile, { struct partial_symtab *pst; const char *name_basename = lbasename (name); + int name_len = strlen (name); + int is_abs = IS_ABSOLUTE_PATH (name); ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { - if (FILENAME_CMP (name, pst->filename) == 0) + if (FILENAME_CMP (name, pst->filename) == 0 + || (!is_abs && compare_filenames_for_search (pst->filename, + name, name_len))) { if (partial_map_expand_apply (objfile, name, full_path, real_path, pst, callback, data)) @@ -186,7 +190,9 @@ partial_map_symtabs_matching_filename (struct objfile *objfile, { psymtab_to_fullname (pst); if (pst->fullname != NULL - && FILENAME_CMP (full_path, pst->fullname) == 0) + && (FILENAME_CMP (full_path, pst->fullname) == 0 + || (!is_abs && compare_filenames_for_search (pst->fullname, + name, name_len)))) { if (partial_map_expand_apply (objfile, name, full_path, real_path, pst, callback, data)) @@ -203,7 +209,10 @@ partial_map_symtabs_matching_filename (struct objfile *objfile, rp = gdb_realpath (pst->fullname); make_cleanup (xfree, rp); } - if (rp != NULL && FILENAME_CMP (real_path, rp) == 0) + if (rp != NULL + && (FILENAME_CMP (real_path, rp) == 0 + || (!is_abs && compare_filenames_for_search (real_path, + name, name_len)))) { if (partial_map_expand_apply (objfile, name, full_path, real_path, pst, callback, data)) @@ -212,17 +221,6 @@ partial_map_symtabs_matching_filename (struct objfile *objfile, } } - /* Now, search for a matching tail (only if name doesn't have any dirs). */ - - if (name_basename == name) - ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) - { - if (FILENAME_CMP (lbasename (pst->filename), name) == 0) - if (partial_map_expand_apply (objfile, name, full_path, real_path, pst, - callback, data)) - return 1; - } - return 0; } diff --git a/gdb/symfile.h b/gdb/symfile.h index 6d39162..6b664cd 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -153,7 +153,7 @@ struct quick_symbol_functions /* Expand and iterate over each "partial" symbol table in OBJFILE where the source file is named NAME. - If there is no '/' in the name, a match after a '/' in the symbol + If NAME is not absolute, a match after a '/' in the symbol table's file name will also work. FULL_PATH is the absolute file name, and REAL_PATH is the same, run through gdb_realpath. diff --git a/gdb/symtab.c b/gdb/symtab.c index ab6a1aa..9471b81 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -145,6 +145,32 @@ multiple_symbols_select_mode (void) const struct block *block_found; +/* See whether FILENAME matches SEARCH_NAME using the rule that we + advertise to the user. SEARCH_LEN is the length of SEARCH_NAME. + We assume that SEARCH_NAME is a relative path. Returns true if + they match, false otherwise. */ + +int +compare_filenames_for_search (const char *filename, const char *search_name, + int search_len) +{ + int len = strlen (filename); + int offset; + + if (len < search_len) + return 0; + + /* The tail of FILENAME must match. */ + if (FILENAME_CMP (filename + len - search_len, search_name) != 0) + return 0; + + /* Either the names must completely match, or the character + preceding the trailing SEARCH_NAME segment of FILENAME must be a + directory separator. */ + return (len == search_len + || IS_DIR_SEPARATOR (filename[len - search_len - 1])); +} + /* Check for a symtab of a specific name by searching some symtabs. This is a helper function for callbacks of iterate_over_symtabs. @@ -169,15 +195,24 @@ iterate_over_some_symtabs (const char *name, struct symtab *s = NULL; struct cleanup *cleanup; const char* base_name = lbasename (name); + int name_len = strlen (name); + int is_abs = IS_ABSOLUTE_PATH (name); for (s = first; s != NULL && s != after_last; s = s->next) { + /* Exact match is always ok. */ if (FILENAME_CMP (name, s->filename) == 0) { if (callback (s, data)) return 1; } + if (!is_abs && compare_filenames_for_search (s->filename, name, name_len)) + { + if (callback (s, data)) + return 1; + } + /* Before we invoke realpath, which can get expensive when many files are involved, do a quick comparison of the basenames. */ if (! basenames_may_differ @@ -196,6 +231,13 @@ iterate_over_some_symtabs (const char *name, if (callback (s, data)) return 1; } + + if (fp != NULL && !is_abs && compare_filenames_for_search (fp, name, + name_len)) + { + if (callback (s, data)) + return 1; + } } if (real_path != NULL) @@ -212,24 +254,16 @@ iterate_over_some_symtabs (const char *name, if (callback (s, data)) return 1; } + + if (!is_abs && compare_filenames_for_search (rp, name, name_len)) + { + if (callback (s, data)) + return 1; + } } } } - /* Now, search for a matching tail (only if name doesn't have any dirs). */ - - if (lbasename (name) == name) - { - for (s = first; s != NULL && s != after_last; s = s->next) - { - if (FILENAME_CMP (lbasename (s->filename), name) == 0) - { - if (callback (s, data)) - return 1; - } - } - } - return 0; } diff --git a/gdb/symtab.h b/gdb/symtab.h index 7b96ab3..4836dd6 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1239,6 +1239,10 @@ struct objfile *lookup_objfile_from_block (const struct block *block); extern int basenames_may_differ; +int compare_filenames_for_search (const char *filename, + const char *search_name, + int search_len); + int iterate_over_some_symtabs (const char *name, const char *full_path, const char *real_path, diff --git a/gdb/testsuite/gdb.linespec/linespec.exp b/gdb/testsuite/gdb.linespec/linespec.exp index 4ac2fd8..02f796a 100644 --- a/gdb/testsuite/gdb.linespec/linespec.exp +++ b/gdb/testsuite/gdb.linespec/linespec.exp @@ -45,18 +45,19 @@ if {$l1 != $l2} { } gdb_test "break thefile.cc:$l1" \ - "Breakpoint 1 at $hex: thefile.cc:$l1. \[(\]2 locations\[)\]" \ + "Breakpoint $decimal at $hex: thefile.cc:$l1. \[(\]2 locations\[)\]" \ "multi-location break using file:line" -# We'd like this to work, but it currently does not. -# gdb_test "break one/thefile.cc:$l1" +gdb_test "break one/thefile.cc:$l1" \ + "Breakpoint $decimal at $hex: file .*thefile.cc, line $l1." \ + "single-location break using dir/file:line" gdb_test "break dupname" \ - "Breakpoint 2 at $hex: dupname. \[(\]2 locations\[)\]" \ + "Breakpoint $decimal at $hex: dupname. \[(\]2 locations\[)\]" \ "multi-location break using duplicate function name" gdb_test "break dupname:label" \ - "Breakpoint 3 at $hex: dupname:label. \[(\]2 locations\[)\]" \ + "Breakpoint $decimal at $hex: dupname:label. \[(\]2 locations\[)\]" \ "multi-location break using duplicate function name and label" gdb_test_no_output "set breakpoint pending off" \