gdb:
PR breakpoints/10738 * dwarf2read.c (use_deprecated_index_sections): New global. (struct partial_die_info): New member may_be_inlined. (read_partial_die): Set may_be_inlined where appropriate. (add_partial_subprogram): Add partial symbols for partial DIEs that may be inlined. (new_symbol_full): Add inlined subroutines to the current scope. (write_psymtabs_to_index): Bump version number. (dwarf2_read_index): Read only version 6 indices unless use_deprecated_index_sections is set. * linespec.c (symbol_and_data_callback): New structure. (iterate_inline_only): New function. (iterate_over_all_matching_symtabs): New argument "include_inline". If nonzero, also call the callback for symbols representing inlined subroutines. (lookup_prefix_sym): Pass extra argument to the above. (find_function_symbols): Likewise. (add_matching_symbols_to_info): Likewise. * NEWS: Mention that GDB can now set breakpoints on inlined functions. gdb/doc: PR breakpoints/10738 * gdb.texinfo (Inline Functions): Remove the now-unnecessary @item stating that GDB cannot set breakpoints on inlined functions. (Mode Options): Document --use-deprecated-index-sections. (Index Section Format): Document new index section version format. gdb/testsuite: PR breakpoints/10738 * gdb.opt/inline-break.exp: New file. * gdb.opt/inline-break.c: Likewise. * gdb.dwarf2/inline-break.exp: Likewise. * gdb.dwarf2/inline-break.S: Likewise. * gdb.base/annota1.exp: Cope with old .gdb_index warnings. * gdb.base/async-shell.exp: Likewise. * lib/mi-support.exp (library_loaded_re): Likewise.
This commit is contained in:
parent
ac56ee8f4c
commit
481860b396
@ -1,3 +1,27 @@
|
||||
2012-03-16 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
PR breakpoints/10738
|
||||
* dwarf2read.c (use_deprecated_index_sections): New global.
|
||||
(struct partial_die_info): New member may_be_inlined.
|
||||
(read_partial_die): Set may_be_inlined where appropriate.
|
||||
(add_partial_subprogram): Add partial symbols for partial
|
||||
DIEs that may be inlined.
|
||||
(new_symbol_full): Add inlined subroutines to the current
|
||||
scope.
|
||||
(write_psymtabs_to_index): Bump version number.
|
||||
(dwarf2_read_index): Read only version 6 indices unless
|
||||
use_deprecated_index_sections is set.
|
||||
* linespec.c (symbol_and_data_callback): New structure.
|
||||
(iterate_inline_only): New function.
|
||||
(iterate_over_all_matching_symtabs): New argument
|
||||
"include_inline". If nonzero, also call the callback for
|
||||
symbols representing inlined subroutines.
|
||||
(lookup_prefix_sym): Pass extra argument to the above.
|
||||
(find_function_symbols): Likewise.
|
||||
(add_matching_symbols_to_info): Likewise.
|
||||
* NEWS: Mention that GDB can now set breakpoints on inlined
|
||||
functions.
|
||||
|
||||
2012-03-16 Pierre Muller <muller@ics.u-strasbg.fr>
|
||||
|
||||
* p-typeprint.c (pascal_type_print_method_args):
|
||||
|
11
gdb/NEWS
11
gdb/NEWS
@ -62,6 +62,17 @@
|
||||
* The "info static-tracepoint-marker" command will now also work on
|
||||
native Linux targets with in-process agent.
|
||||
|
||||
* GDB can now set breakpoints on inlined functions.
|
||||
|
||||
* The .gdb_index section has been updated to include symbols for
|
||||
inlined functions. GDB will ignore older .gdb_index sections by
|
||||
default, which could cause symbol files to be loaded more slowly
|
||||
until their .gdb_index sections can be recreated. The new option
|
||||
--use-deprecated-index-sections will cause GDB to use any older
|
||||
.gdb_index sections it finds. This will restore performance, but
|
||||
the ability to set breakpoints on inlined functions will be lost
|
||||
in symbol files with older .gdb_index sections.
|
||||
|
||||
* New commands
|
||||
|
||||
** "catch load" and "catch unload" can be used to stop when a shared
|
||||
|
@ -1,3 +1,11 @@
|
||||
2012-03-16 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
PR breakpoints/10738
|
||||
* gdb.texinfo (Inline Functions): Remove the now-unnecessary @item
|
||||
stating that GDB cannot set breakpoints on inlined functions.
|
||||
(Mode Options): Document --use-deprecated-index-sections.
|
||||
(Index Section Format): Document new index section version format.
|
||||
|
||||
2012-03-15 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.texinfo (Debugging C Plus Plus): Document "info vtbl".
|
||||
|
@ -1221,6 +1221,13 @@ memory usage after it completes each command and returns to the prompt.
|
||||
This option causes @value{GDBN} to print its version number and
|
||||
no-warranty blurb, and exit.
|
||||
|
||||
@item -use-deprecated-index-sections
|
||||
@cindex @code{--use-deprecated-index-sections}
|
||||
This option causes @value{GDBN} to read and use deprecated
|
||||
@samp{.gdb_index} sections from symbol files. This can speed up
|
||||
startup, but may result in some functionality being lost.
|
||||
@xref{Index Section Format}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Startup
|
||||
@ -9889,14 +9896,6 @@ There are some ways that @value{GDBN} does not pretend that inlined
|
||||
function calls are the same as normal calls:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
You cannot set breakpoints on inlined functions. @value{GDBN}
|
||||
either reports that there is no symbol with that name, or else sets the
|
||||
breakpoint only on non-inlined copies of the function. This limitation
|
||||
will be removed in a future version of @value{GDBN}; until then,
|
||||
set a breakpoint by line number on the first line of the inlined
|
||||
function instead.
|
||||
|
||||
@item
|
||||
Setting breakpoints at the call site of an inlined function may not
|
||||
work, because the call site does not contain any code. @value{GDBN}
|
||||
@ -38956,8 +38955,11 @@ unless otherwise noted:
|
||||
|
||||
@enumerate
|
||||
@item
|
||||
The version number, currently 5. Versions 1, 2 and 3 are obsolete.
|
||||
Version 4 differs by its hashing function.
|
||||
The version number, currently 6. Versions 1, 2 and 3 are obsolete.
|
||||
Version 4 uses a different hashing function from versions 5 and 6.
|
||||
Version 6 includes symbols for inlined functions, whereas versions
|
||||
4 and 5 do not. @value{GDBN} will only read version 4 and 5 indices
|
||||
if the @code{--use-deprecated-index-sections} option is used.
|
||||
|
||||
@item
|
||||
The offset, from the start of the file, of the CU list.
|
||||
@ -39032,7 +39034,7 @@ index version:
|
||||
@item Version 4
|
||||
The formula is @code{r = r * 67 + c - 113}.
|
||||
|
||||
@item Version 5
|
||||
@item Versions 5 and 6
|
||||
The formula is @code{r = r * 67 + tolower (c) - 113}.
|
||||
@end table
|
||||
|
||||
|
@ -85,6 +85,9 @@ static int dwarf2_die_debug = 0;
|
||||
/* When non-zero, cross-check physname against demangler. */
|
||||
static int check_physname = 0;
|
||||
|
||||
/* When non-zero, do not reject deprecated .gdb_index sections. */
|
||||
int use_deprecated_index_sections = 0;
|
||||
|
||||
static int pagesize;
|
||||
|
||||
/* When set, the file that we're processing is known to have debugging
|
||||
@ -539,6 +542,7 @@ struct partial_die_info
|
||||
unsigned int has_type : 1;
|
||||
unsigned int has_specification : 1;
|
||||
unsigned int has_pc_info : 1;
|
||||
unsigned int may_be_inlined : 1;
|
||||
|
||||
/* Flag set if the SCOPE field of this structure has been
|
||||
computed. */
|
||||
@ -2118,13 +2122,41 @@ dwarf2_read_index (struct objfile *objfile)
|
||||
/* Versions earlier than 3 emitted every copy of a psymbol. This
|
||||
causes the index to behave very poorly for certain requests. Version 3
|
||||
contained incomplete addrmap. So, it seems better to just ignore such
|
||||
indices. Index version 4 uses a different hash function than index
|
||||
version 5 and later. */
|
||||
indices. */
|
||||
if (version < 4)
|
||||
return 0;
|
||||
/* Indices with higher version than the one supported by GDB may be no
|
||||
{
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
warning (_("Skipping obsolete .gdb_index section in %s."),
|
||||
objfile->name);
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Index version 4 uses a different hash function than index version
|
||||
5 and later.
|
||||
|
||||
Versions earlier than 6 did not emit psymbols for inlined
|
||||
functions. Using these files will cause GDB not to be able to
|
||||
set breakpoints on inlined functions by name, so we ignore these
|
||||
indices unless the --use-deprecated-index-sections command line
|
||||
option was supplied. */
|
||||
if (version < 6 && !use_deprecated_index_sections)
|
||||
{
|
||||
static int warning_printed = 0;
|
||||
if (!warning_printed)
|
||||
{
|
||||
warning (_("Skipping deprecated .gdb_index section in %s, pass "
|
||||
"--use-deprecated-index-sections to use them anyway"),
|
||||
objfile->name);
|
||||
warning_printed = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Indexes with higher version than the one supported by GDB may be no
|
||||
longer backward compatible. */
|
||||
if (version > 5)
|
||||
if (version > 6)
|
||||
return 0;
|
||||
|
||||
map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
|
||||
@ -4244,6 +4276,10 @@ add_partial_subprogram (struct partial_die_info *pdi,
|
||||
pdi->highpc - 1 + baseaddr,
|
||||
cu->per_cu->v.psymtab);
|
||||
}
|
||||
}
|
||||
|
||||
if (pdi->has_pc_info || (!pdi->is_external && pdi->may_be_inlined))
|
||||
{
|
||||
if (!pdi->is_declaration)
|
||||
/* Ignore subprogram DIEs that do not have a name, they are
|
||||
illegal. Do not emit a complaint at this point, we will
|
||||
@ -9874,6 +9910,11 @@ read_partial_die (struct partial_die_info *part_die,
|
||||
language_of_main = language_fortran;
|
||||
}
|
||||
break;
|
||||
case DW_AT_inline:
|
||||
if (DW_UNSND (&attr) == DW_INL_inlined
|
||||
|| DW_UNSND (&attr) == DW_INL_declared_inlined)
|
||||
part_die->may_be_inlined = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -11718,8 +11759,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
||||
finish_block. */
|
||||
SYMBOL_CLASS (sym) = LOC_BLOCK;
|
||||
SYMBOL_INLINED (sym) = 1;
|
||||
/* Do not add the symbol to any lists. It will be found via
|
||||
BLOCK_FUNCTION from the blockvector. */
|
||||
list_to_add = cu->list_in_scope;
|
||||
break;
|
||||
case DW_TAG_template_value_param:
|
||||
suppress_add = 1;
|
||||
@ -17027,7 +17067,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
||||
total_len = size_of_contents;
|
||||
|
||||
/* The version number. */
|
||||
val = MAYBE_SWAP (5);
|
||||
val = MAYBE_SWAP (6);
|
||||
obstack_grow (&contents, &val, sizeof (val));
|
||||
|
||||
/* The offset of the CU list from the start of the file. */
|
||||
|
@ -321,6 +321,33 @@ cplusplus_error (const char *name, const char *fmt, ...)
|
||||
throw_error (NOT_FOUND_ERROR, "%s", message);
|
||||
}
|
||||
|
||||
/* A callback function and the additional data to call it with. */
|
||||
|
||||
struct symbol_and_data_callback
|
||||
{
|
||||
/* The callback to use. */
|
||||
symbol_found_callback_ftype *callback;
|
||||
|
||||
/* Data to be passed to the callback. */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* A helper for iterate_over_all_matching_symtabs that is used to
|
||||
restrict calls to another callback to symbols representing inline
|
||||
symbols only. */
|
||||
|
||||
static int
|
||||
iterate_inline_only (struct symbol *sym, void *d)
|
||||
{
|
||||
if (SYMBOL_INLINED (sym))
|
||||
{
|
||||
struct symbol_and_data_callback *cad = d;
|
||||
|
||||
return cad->callback (sym, cad->data);
|
||||
}
|
||||
return 1; /* Continue iterating. */
|
||||
}
|
||||
|
||||
/* Some data for the expand_symtabs_matching callback. */
|
||||
|
||||
struct symbol_matcher_data
|
||||
@ -348,14 +375,16 @@ iterate_name_matcher (const char *name, void *d)
|
||||
/* A helper that walks over all matching symtabs in all objfiles and
|
||||
calls CALLBACK for each symbol matching NAME. If SEARCH_PSPACE is
|
||||
not NULL, then the search is restricted to just that program
|
||||
space. */
|
||||
space. If INCLUDE_INLINE is nonzero then symbols representing
|
||||
inlined instances of functions will be included in the result. */
|
||||
|
||||
static void
|
||||
iterate_over_all_matching_symtabs (const char *name,
|
||||
const domain_enum domain,
|
||||
symbol_found_callback_ftype *callback,
|
||||
void *data,
|
||||
struct program_space *search_pspace)
|
||||
struct program_space *search_pspace,
|
||||
int include_inline)
|
||||
{
|
||||
struct objfile *objfile;
|
||||
struct program_space *pspace;
|
||||
@ -394,6 +423,20 @@ iterate_over_all_matching_symtabs (const char *name,
|
||||
|
||||
block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
||||
LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
|
||||
|
||||
if (include_inline)
|
||||
{
|
||||
struct symbol_and_data_callback cad = { callback, data };
|
||||
int i;
|
||||
|
||||
for (i = FIRST_LOCAL_BLOCK;
|
||||
i < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (symtab)); i++)
|
||||
{
|
||||
block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), i);
|
||||
LA_ITERATE_OVER_SYMBOLS (block, name, domain,
|
||||
iterate_inline_only, &cad);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1885,10 +1928,10 @@ lookup_prefix_sym (char **argptr, char *p, VEC (symtab_p) *file_symtabs,
|
||||
{
|
||||
iterate_over_all_matching_symtabs (copy, STRUCT_DOMAIN,
|
||||
collect_one_symbol, &collector,
|
||||
NULL);
|
||||
NULL, 0);
|
||||
iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
|
||||
collect_one_symbol, &collector,
|
||||
NULL);
|
||||
NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2251,7 +2294,8 @@ find_function_symbols (char **argptr, char *p, int is_quote_enclosed,
|
||||
copy[p - *argptr] = 0;
|
||||
|
||||
iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
|
||||
collect_function_symbols, &result, NULL);
|
||||
collect_function_symbols, &result, NULL,
|
||||
0);
|
||||
|
||||
if (VEC_empty (symbolp, result))
|
||||
VEC_free (symbolp, result);
|
||||
@ -2952,7 +2996,7 @@ add_matching_symbols_to_info (const char *name,
|
||||
{
|
||||
iterate_over_all_matching_symtabs (name, VAR_DOMAIN,
|
||||
collect_symbols, info,
|
||||
pspace);
|
||||
pspace, 1);
|
||||
search_minsyms_for_name (info, name, pspace);
|
||||
}
|
||||
else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
|
||||
|
@ -450,6 +450,8 @@ captured_main (void *data)
|
||||
{"args", no_argument, &set_args, 1},
|
||||
{"l", required_argument, 0, 'l'},
|
||||
{"return-child-result", no_argument, &return_child_result, 1},
|
||||
{"use-deprecated-index-sections", no_argument,
|
||||
&use_deprecated_index_sections, 1},
|
||||
{0, no_argument, 0, 0}
|
||||
};
|
||||
|
||||
@ -1020,6 +1022,10 @@ Options:\n\n\
|
||||
--tui Use a terminal user interface.\n\
|
||||
"), stream);
|
||||
#endif
|
||||
fputs_unfiltered (_("\
|
||||
--use-deprecated-index-sections\n\
|
||||
Do not reject deprecated .gdb_index sections.\n\
|
||||
"), stream);
|
||||
fputs_unfiltered (_("\
|
||||
--version Print version information and then exit.\n\
|
||||
-w Use a window interface.\n\
|
||||
|
@ -617,6 +617,9 @@ extern void dwarf2_build_frame_info (struct objfile *);
|
||||
|
||||
void dwarf2_free_objfile (struct objfile *);
|
||||
|
||||
/* Whether to use deprecated .gdb_index sections. */
|
||||
extern int use_deprecated_index_sections;
|
||||
|
||||
/* From mdebugread.c */
|
||||
|
||||
/* Hack to force structures to exist before use in parameter list. */
|
||||
|
@ -1,3 +1,14 @@
|
||||
2012-03-16 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
PR breakpoints/10738
|
||||
* gdb.opt/inline-break.exp: New file.
|
||||
* gdb.opt/inline-break.c: Likewise.
|
||||
* gdb.dwarf2/inline-break.exp: Likewise.
|
||||
* gdb.dwarf2/inline-break.S: Likewise.
|
||||
* gdb.base/annota1.exp: Cope with old .gdb_index warnings.
|
||||
* gdb.base/async-shell.exp: Likewise.
|
||||
* lib/mi-support.exp (library_loaded_re): Likewise.
|
||||
|
||||
2012-03-15 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.cp/virtfunc2.exp: Update expected output.
|
||||
|
@ -133,7 +133,7 @@ gdb_test_multiple "info break" "breakpoint info" {
|
||||
#exp_internal 1
|
||||
set binexp [string_to_regexp $binfile]
|
||||
gdb_test_multiple "run" "run until main breakpoint" {
|
||||
-re "\r\n\032\032post-prompt\r\nStarting program: $binexp \(\(\r\n\r\n\032\032frames-invalid\)|\(\r\n\r\n\032\032breakpoints-invalid\)\)+\r\n\r\n\032\032starting\(\(\r\n\r\n\032\032frames-invalid\)|\(\r\n\r\n\032\032breakpoints-invalid\)\)*\r\n\r\n\032\032breakpoint 1\r\n\r\nBreakpoint 1, \r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nmain\r\n\032\032frame-args\r\n \\(\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*annota1.c\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n$main_line\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source.*$srcfile:$main_line:.*:beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped.*$gdb_prompt$" {
|
||||
-re "\r\n\032\032post-prompt\r\nStarting program: $binexp \(\r\nwarning: Skipping \[^\r\n\]+ .gdb_index section in \[^\r\n\]+\)?\(\(\r\n\r\n\032\032frames-invalid\)|\(\r\n\r\n\032\032breakpoints-invalid\)\)+\r\n\r\n\032\032starting\(\(\r\n\r\n\032\032frames-invalid\)|\(\r\n\r\n\032\032breakpoints-invalid\)\)*\r\n\r\n\032\032breakpoint 1\r\n\r\nBreakpoint 1, \r\n\032\032frame-begin 0 $hex\r\n\r\n\032\032frame-function-name\r\nmain\r\n\032\032frame-args\r\n \\(\\)\r\n\032\032frame-source-begin\r\n at \r\n\032\032frame-source-file\r\n.*annota1.c\r\n\032\032frame-source-file-end\r\n:\r\n\032\032frame-source-line\r\n$main_line\r\n\032\032frame-source-end\r\n\r\n\r\n\032\032source.*$srcfile:$main_line:.*:beg:$hex\r\n\r\n\032\032frame-end\r\n\r\n\032\032stopped.*$gdb_prompt$" {
|
||||
pass "run until main breakpoint"
|
||||
}
|
||||
}
|
||||
|
@ -29,9 +29,11 @@ if { [prepare_for_testing ${testfile}.exp ${testfile}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set gdbindex_warning_re "warning: Skipping \[^\r\n\]+ \\.gdb_index section \[^\r\n\]*"
|
||||
|
||||
gdb_test_no_output "set target-async on "
|
||||
gdb_test_no_output "set non-stop on"
|
||||
gdb_test "run &" "Starting program: \[^\r\n\]*"
|
||||
gdb_test "run &" "Starting program: \[^\r\n\]*(\r\n$gdbindex_warning_re)?"
|
||||
|
||||
# `sleep 5' here would workaround the bug, do not sleep here.
|
||||
# "shell" could eat waitpid event from the asynchronous inferior process.
|
||||
|
1663
gdb/testsuite/gdb.dwarf2/dw2-inline-break.S
Normal file
1663
gdb/testsuite/gdb.dwarf2/dw2-inline-break.S
Normal file
File diff suppressed because it is too large
Load Diff
124
gdb/testsuite/gdb.dwarf2/dw2-inline-break.exp
Normal file
124
gdb/testsuite/gdb.dwarf2/dw2-inline-break.exp
Normal file
@ -0,0 +1,124 @@
|
||||
# Copyright 2012 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/>.
|
||||
|
||||
# Note that the testcase gdb.opt/inline-break.exp largely mirrors
|
||||
# this testcase, and should be updated if this testcase is changed.
|
||||
|
||||
load_lib dwarf.exp
|
||||
|
||||
# This test can only be run on targets which support DWARF-2 and use gas.
|
||||
if ![dwarf2_support] {
|
||||
return 0
|
||||
}
|
||||
|
||||
# This test can only be run on x86_64 targets.
|
||||
if {![istarget "x86_64-*-*"] || ![is_lp64_target]} {
|
||||
return 0
|
||||
}
|
||||
|
||||
set basename "inline-break"
|
||||
set testfile "dw2-$basename"
|
||||
|
||||
if { [prepare_for_testing $testfile.exp $testfile $testfile.S {nodebug}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
#
|
||||
# func1 is a static inlined function that is called once.
|
||||
# The result should be a single-location breakpoint.
|
||||
#
|
||||
gdb_test "break func1" \
|
||||
"Breakpoint.*at.* file .*$basename\\.c, line.*"
|
||||
|
||||
#
|
||||
# func2 is a non-static inlined function that is called once.
|
||||
# The result should be a breakpoint with two locations: the
|
||||
# out-of-line function and the single inlined instance.
|
||||
#
|
||||
gdb_test "break func2" \
|
||||
"Breakpoint.*at.*func2.*\\(2 locations\\)"
|
||||
|
||||
#
|
||||
# func3b is a static inlined function that is called once from
|
||||
# within another static inlined function. The result should be
|
||||
# a single-location breakpoint.
|
||||
#
|
||||
gdb_test "break func3b" \
|
||||
"Breakpoint.*at.* file .*$basename\\.c, line.*"
|
||||
|
||||
#
|
||||
# func4b is a static inlined function that is called once from
|
||||
# within a non-static inlined function. The result should be
|
||||
# a breakpoint with two locations: the inlined instance within
|
||||
# the inlined call to func4a in main, and the inlined instance
|
||||
# within the out-of-line func4a.
|
||||
#
|
||||
gdb_test "break func4b" \
|
||||
"Breakpoint.*at.*func4b.*\\(2 locations\\)"
|
||||
|
||||
#
|
||||
# func5b is a non-static inlined function that is called once
|
||||
# from within a static inlined function. The result should be a
|
||||
# breakpoint with two locations: the out-of-line function and the
|
||||
# inlined instance within the inlined call to func5a in main.
|
||||
#
|
||||
gdb_test "break func5b" \
|
||||
"Breakpoint.*at.*func5b.*\\(2 locations\\)"
|
||||
#
|
||||
# func6b is a non-static inlined function that is called once from
|
||||
# within another non-static inlined function. The result should be
|
||||
# a breakpoint with three locations: the out-of-line function, the
|
||||
# inlined instance within the out-of-line func6a, and the inlined
|
||||
# instance within the inlined call to func6a in main,
|
||||
#
|
||||
gdb_test "break func6b" \
|
||||
"Breakpoint.*at.*func6b.*\\(3 locations\\)"
|
||||
|
||||
#
|
||||
# func7b is a static inlined function that is called twice: once from
|
||||
# func7a, and once from main. The result should be a breakpoint with
|
||||
# two locations: the inlined instance within the inlined instance of
|
||||
# func7a, and the inlined instance within main.
|
||||
#
|
||||
gdb_test "break func7b" \
|
||||
"Breakpoint.*at.*func7b.*\\(2 locations\\)"
|
||||
|
||||
#
|
||||
# func8b is a non-static inlined function that is called twice: once
|
||||
# func8a, and once from main. The result should be a breakpoint with
|
||||
# three locations: the out-of-line function, the inlined instance
|
||||
# within the inlined instance of func7a, and the inlined instance
|
||||
# within main.
|
||||
#
|
||||
gdb_test "break func8b" \
|
||||
"Breakpoint.*at.*func8b.*\\(3 locations\\)"
|
||||
|
||||
#
|
||||
# func1 is a static inlined function. The result should be that no
|
||||
# symbol is found to print.
|
||||
#
|
||||
gdb_test "print func1" \
|
||||
"No symbol \"func1\" in current context."
|
||||
|
||||
#
|
||||
# func2 is a non-static inlined function. The result should be that
|
||||
# one symbol is found to print, and that the printed symbol is called
|
||||
# "func2". Note that this does not cover the failure case that two
|
||||
# symbols were found, but that gdb chose the out-of-line copy to
|
||||
# print, but if this was failing the "print func1" test would likely
|
||||
# fail instead.
|
||||
#
|
||||
gdb_test "print func2" \
|
||||
"\\\$.* = {int \\(int\\)} .* <func2>"
|
159
gdb/testsuite/gdb.opt/inline-break.c
Normal file
159
gdb/testsuite/gdb.opt/inline-break.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 2012 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/>. */
|
||||
|
||||
/* The file ../gdb.dwarf2/inline-break.S was generated manually from
|
||||
this file, and should be regenerated if this file is modified. */
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define ATTR __attribute__((always_inline))
|
||||
#else
|
||||
# define ATTR
|
||||
#endif
|
||||
|
||||
/* A static inlined function that is called once. */
|
||||
|
||||
static inline ATTR int
|
||||
func1 (int x)
|
||||
{
|
||||
return x * 23;
|
||||
}
|
||||
|
||||
/* A non-static inlined function that is called once. */
|
||||
|
||||
inline ATTR int
|
||||
func2 (int x)
|
||||
{
|
||||
return x * 17;
|
||||
}
|
||||
|
||||
/* A static inlined function that calls another static inlined
|
||||
function. */
|
||||
|
||||
static inline ATTR int
|
||||
func3b (int x)
|
||||
{
|
||||
return x < 14 ? 1 : 2;
|
||||
}
|
||||
|
||||
static inline ATTR int
|
||||
func3a (int x)
|
||||
{
|
||||
return func3b (x * 23);
|
||||
}
|
||||
|
||||
/* A non-static inlined function that calls a static inlined
|
||||
function. */
|
||||
|
||||
static inline ATTR int
|
||||
func4b (int x)
|
||||
{
|
||||
return x < 13 ? 1 : 2;
|
||||
}
|
||||
|
||||
inline ATTR int
|
||||
func4a (int x)
|
||||
{
|
||||
return func4b (x * 17);
|
||||
}
|
||||
|
||||
/* A static inlined function that calls a non-static inlined
|
||||
function. */
|
||||
|
||||
inline ATTR int
|
||||
func5b (int x)
|
||||
{
|
||||
return x < 12 ? 1 : 2;
|
||||
}
|
||||
|
||||
static inline ATTR int
|
||||
func5a (int x)
|
||||
{
|
||||
return func5b (x * 23);
|
||||
}
|
||||
|
||||
/* A non-static inlined function that calls another non-static inlined
|
||||
function. */
|
||||
|
||||
inline ATTR int
|
||||
func6b (int x)
|
||||
{
|
||||
return x < 14 ? 3 : 2;
|
||||
}
|
||||
|
||||
inline ATTR int
|
||||
func6a (int x)
|
||||
{
|
||||
return func6b (x * 17);
|
||||
}
|
||||
|
||||
/* A static inlined function that is called more than once. */
|
||||
|
||||
static inline ATTR int
|
||||
func7b (int x)
|
||||
{
|
||||
return x < 23 ? 1 : 4;
|
||||
}
|
||||
|
||||
static inline ATTR int
|
||||
func7a (int x)
|
||||
{
|
||||
return func7b (x * 29);
|
||||
}
|
||||
|
||||
/* A non-static inlined function that is called more than once. */
|
||||
|
||||
inline ATTR int
|
||||
func8b (int x)
|
||||
{
|
||||
return x < 7 ? 11 : 9;
|
||||
}
|
||||
|
||||
static inline ATTR int
|
||||
func8a (int x)
|
||||
{
|
||||
return func8b (x * 31);
|
||||
}
|
||||
|
||||
/* Entry point. */
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
/* Declaring x as volatile here prevents GCC from combining calls.
|
||||
If GCC is allowed to combine calls then some of them end up with
|
||||
no instructions at all, so there is no specific address for GDB
|
||||
to set a breakpoint at. */
|
||||
volatile int x = argc;
|
||||
|
||||
x = func1 (x);
|
||||
|
||||
x = func2 (x);
|
||||
|
||||
x = func3a (x);
|
||||
|
||||
x = func4a (x);
|
||||
|
||||
x = func5a (x);
|
||||
|
||||
x = func6a (x);
|
||||
|
||||
x = func7a (x) + func7b (x);
|
||||
|
||||
x = func8a (x) + func8b (x);
|
||||
|
||||
return x;
|
||||
}
|
114
gdb/testsuite/gdb.opt/inline-break.exp
Normal file
114
gdb/testsuite/gdb.opt/inline-break.exp
Normal file
@ -0,0 +1,114 @@
|
||||
# Copyright 2012 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/>.
|
||||
|
||||
# Note that the testcase gdb.dwarf2/dw2-inline-break.exp largely
|
||||
# mirrors this testcase, and should be updated if this testcase is
|
||||
# changed.
|
||||
|
||||
set basename "inline-break"
|
||||
set testfile $basename
|
||||
|
||||
if { [prepare_for_testing $testfile.exp $testfile $testfile.c \
|
||||
{debug optimize=-O2 additional_flags=-Winline}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
#
|
||||
# func1 is a static inlined function that is called once.
|
||||
# The result should be a single-location breakpoint.
|
||||
#
|
||||
gdb_test "break func1" \
|
||||
"Breakpoint.*at.* file .*$basename\\.c, line.*"
|
||||
|
||||
#
|
||||
# func2 is a non-static inlined function that is called once.
|
||||
# The result should be a breakpoint with two locations: the
|
||||
# out-of-line function and the single inlined instance.
|
||||
#
|
||||
gdb_test "break func2" \
|
||||
"Breakpoint.*at.*func2.*\\(2 locations\\)"
|
||||
|
||||
#
|
||||
# func3b is a static inlined function that is called once from
|
||||
# within another static inlined function. The result should be
|
||||
# a single-location breakpoint.
|
||||
#
|
||||
gdb_test "break func3b" \
|
||||
"Breakpoint.*at.* file .*$basename\\.c, line.*"
|
||||
|
||||
#
|
||||
# func4b is a static inlined function that is called once from
|
||||
# within a non-static inlined function. The result should be
|
||||
# a breakpoint with two locations: the inlined instance within
|
||||
# the inlined call to func4a in main, and the inlined instance
|
||||
# within the out-of-line func4a.
|
||||
#
|
||||
gdb_test "break func4b" \
|
||||
"Breakpoint.*at.*func4b.*\\(2 locations\\)"
|
||||
|
||||
#
|
||||
# func5b is a non-static inlined function that is called once
|
||||
# from within a static inlined function. The result should be a
|
||||
# breakpoint with two locations: the out-of-line function and the
|
||||
# inlined instance within the inlined call to func5a in main.
|
||||
#
|
||||
gdb_test "break func5b" \
|
||||
"Breakpoint.*at.*func5b.*\\(2 locations\\)"
|
||||
#
|
||||
# func6b is a non-static inlined function that is called once from
|
||||
# within another non-static inlined function. The result should be
|
||||
# a breakpoint with three locations: the out-of-line function, the
|
||||
# inlined instance within the out-of-line func6a, and the inlined
|
||||
# instance within the inlined call to func6a in main,
|
||||
#
|
||||
gdb_test "break func6b" \
|
||||
"Breakpoint.*at.*func6b.*\\(3 locations\\)"
|
||||
|
||||
#
|
||||
# func7b is a static inlined function that is called twice: once from
|
||||
# func7a, and once from main. The result should be a breakpoint with
|
||||
# two locations: the inlined instance within the inlined instance of
|
||||
# func7a, and the inlined instance within main.
|
||||
#
|
||||
gdb_test "break func7b" \
|
||||
"Breakpoint.*at.*func7b.*\\(2 locations\\)"
|
||||
|
||||
#
|
||||
# func8b is a non-static inlined function that is called twice: once
|
||||
# func8a, and once from main. The result should be a breakpoint with
|
||||
# three locations: the out-of-line function, the inlined instance
|
||||
# within the inlined instance of func7a, and the inlined instance
|
||||
# within main.
|
||||
#
|
||||
gdb_test "break func8b" \
|
||||
"Breakpoint.*at.*func8b.*\\(3 locations\\)"
|
||||
|
||||
#
|
||||
# func1 is a static inlined function. The result should be that no
|
||||
# symbol is found to print.
|
||||
#
|
||||
gdb_test "print func1" \
|
||||
"No symbol \"func1\" in current context."
|
||||
|
||||
#
|
||||
# func2 is a non-static inlined function. The result should be that
|
||||
# one symbol is found to print, and that the printed symbol is called
|
||||
# "func2". Note that this does not cover the failure case that two
|
||||
# symbols were found, but that gdb chose the out-of-line copy to
|
||||
# print, but if this was failing the "print func1" test would likely
|
||||
# fail instead.
|
||||
#
|
||||
gdb_test "print func2" \
|
||||
"\\\$.* = {int \\(int\\)} .* <func2>"
|
@ -31,7 +31,8 @@ global mi_inferior_tty_name
|
||||
set MIFLAGS "-i=mi"
|
||||
|
||||
set thread_selected_re "=thread-selected,id=\"\[0-9\]+\"\r\n"
|
||||
set library_loaded_re "=library-loaded\[^\n\]+\"\r\n"
|
||||
set gdbindex_warning_re "&\"warning: Skipping \[^\r\n\]+ \.gdb_index section in \[^\"\]+\"\r\n"
|
||||
set library_loaded_re "=library-loaded\[^\n\]+\"\r\n(?:$gdbindex_warning_re)?"
|
||||
set breakpoint_re "=(?:breakpoint-created|breakpoint-deleted)\[^\n\]+\"\r\n"
|
||||
|
||||
#
|
||||
|
Loading…
x
Reference in New Issue
Block a user