Bug 10738 - Cannot set breakpoint on inlined function
Summary: Cannot set breakpoint on inlined function
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: breakpoints (show other bugs)
Version: unknown
: P2 normal
Target Milestone: 7.5
Assignee: Gary Benson
URL:
Keywords:
Depends on: 12828
Blocks:
  Show dependency treegraph
 
Reported: 2009-10-06 11:39 UTC by Mark Wielaard
Modified: 2012-03-16 16:54 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2010-12-17 23:12:39


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Wielaard 2009-10-06 11:39:51 UTC
Tested against: GNU gdb (GDB) Fedora (6.8.91.20090930-2.fc12)

Take the following program:

struct foo
{
  const int i;
  const long j;
};

typedef struct foo fooer;

static int
bar (const int i, const long j)
{
  return i * j;
}

static int
func (int (*f) ())
{
  const fooer baz = { .i = 2, .j = 21 };
  return f(baz.i, baz.j);
}

int
main (int argc, char *argv[], char *envp[])
{
  return func (&bar) - 42;
}

Compiled with gcc -g -O2 -o const const.c

(gdb) break func
Function "func" not defined.
Make breakpoint pending on future shared library load? (y or [n]) 

While it is possible to break on the function by line:

(gdb) break const.c:18
Breakpoint 1 at 0x400490: file const.c, line 18.

func is marked as inlined in the dwarf debuginfo:

 <1><71>: Abbrev Number: 8 (DW_TAG_subprogram)
    <72>   DW_AT_name        : (indirect string, offset: 0x0): func     
    <76>   DW_AT_decl_file   : 1        
    <77>   DW_AT_decl_line   : 16       
    <78>   DW_AT_prototyped  : 1        
    <79>   DW_AT_type        : <0x53>   
    <7d>   DW_AT_inline      : 1        (inlined)
    <7e>   DW_AT_sibling     : <0xa8>   
[...]
 <2><147>: Abbrev Number: 18 (DW_TAG_inlined_subroutine)
    <148>   DW_AT_abstract_origin: <0x71>       
    <14c>   DW_AT_low_pc      : 0x400490        
    <154>   DW_AT_high_pc     : 0x4004a4        
    <15c>   DW_AT_call_file   : 1       
    <15d>   DW_AT_call_line   : 25
Comment 1 Xin Tong 2010-12-17 23:12:39 UTC
Tested against GNU gdb (GDB) 7.2. Able to produce the same error

Taking the same program from Mark


GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/tongxin1/gdb-7.2/gdb/test...done.
(gdb) b func
Function "func" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) b test.c:18
Breakpoint 1 at 0x400460: file test.c, line 18.
(gdb) list
10      bar (const int i, const long j)
11      {
12            return i * j;
13      }
14
15      static int
16      func (int (*f) ())
17      {
18            const fooer baz = { .i = 2, .j = 21 };
19              return f(baz.i, baz.j);
(gdb) r
Starting program: /home/tongxin1/gdb-7.2/gdb/test

Breakpoint 1, main (argc=1, argv=0x7fffffffe298, envp=0x7fffffffe2a8) at test.c:25
25            return func (&bar) - 42;
(gdb)


DWARF file 

 <2><fc>: Abbrev Number: 14 (DW_TAG_inlined_subroutine)
     DW_AT_abstract_origin: <7f>
     DW_AT_low_pc      : 0x400460
     DW_AT_high_pc     : 0x400472
     DW_AT_call_file   : 1
     DW_AT_call_line   : 25
Comment 2 Tom Tromey 2010-12-21 18:30:04 UTC
No reason for this to be in "WAIT".
Comment 3 Xin Tong 2010-12-23 02:05:23 UTC
This is my first time contributing to gdb. I am an developer from IBM Java Just-In-Time compiler team. I would like to give this defect a try. Is there help i can resort to if I am stuck ?
Comment 4 Tom Tromey 2010-12-23 02:17:42 UTC
(In reply to comment #3)
> This is my first time contributing to gdb. I am an developer from IBM Java
> Just-In-Time compiler team. I would like to give this defect a try. Is there
> help i can resort to if I am stuck ?

You can ask questions here, or on the gdb list, or on the gdb irc channel.
Comment 5 Xin Tong 2010-12-31 02:24:28 UTC
After spending sometime with gdb. i found that gdb uses two ways for the user (or much of the code in the debugger) to reference a symbol:

1. By its address (e.g. execution stops at some address which is inside a function in this file). The address will be noticed to be in the range of this psymtab, and the full symtab will be read in. find_pc_function, find_pc_line, and other find_pc_... functions handle this.

2. By its name (e.g. the user asks to print a variable, or set a breakpoint on a function). Global names and file-scope names will be found in the psymtab, which will cause the symtab to be pulled in. Local names will have to be qualified by a global name, or a file-scope name, in which case we will have already read in the symtab as we evaluated the qualifier. Or, a local symbol can be referenced when we are "in" a local scope, in which case the first case applies. lookup_symbol does most of the work here.

In this case, "func" is referenced by name. However, taking a look at the psymtab 


Partial symtab for source file test.c (object 0xa5e9d60)

  Read from object file /home/tongxin1/gdb-7.2/gdb/defect_10738/test (0xa5dd980)
  Relocate symbols by 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  Symbols cover text addresses 0x0-0x0
  Depends on 1 other partial symtabs.
    0 0xa5e9b20 test.c


Partial symtab for source file test.c (object 0xa5e9b20)

  Read from object file /home/tongxin1/gdb-7.2/gdb/defect_10738/test (0xa5dd980)
  Relocate symbols by 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  Symbols cover text addresses 0x400450-0x400473
  Depends on 0 other partial symtabs.
  Global partial symbols:
    `main', function, 0x400460
  Static partial symbols:
    `size_t', type, 0x0
    `long unsigned int', type, 0x0
    `unsigned char', type, 0x0
    `short unsigned int', type, 0x0
    `unsigned int', type, 0x0
    `signed char', type, 0x0
    `short int', type, 0x0
    `int', type, 0x0
    `long int', type, 0x0
    `__off_t', type, 0x0
    `__off64_t', type, 0x0
    `long unsigned int', type, 0x0
    `char', type, 0x0
    `_IO_lock_t', type, 0x0
    `_IO_FILE', struct domain, type, 0x0
    `_IO_marker', struct domain, type, 0x0
    `bar', function, 0x400450

"func" is not even included in the psymtab. I would like some pointers at this point. should I investigate why "func" is in dwarf2 but not in psymtab ? Any help would be greatly appreciated.


Xin
Comment 6 Tom Tromey 2011-01-03 20:53:34 UTC
(In reply to comment #5)

> "func" is not even included in the psymtab. I would like some pointers at this
> point. should I investigate why "func" is in dwarf2 but not in psymtab ? Any
> help would be greatly appreciated.

First, I'd like to note that what I am about to say may be wrong.
You will want to check it before making any decisions based on it.

Second, there are at least two cases to consider.  One case is the one
where all instances of a given function have been inlined.  Another
case is where the function has been inlined but also still exists as
an "out of line" function.

I think "break function" works ok if all instances have been inlined.

In the case where there is an out-of-line copy, I think it may be best
if "break function" noticed that "function" was inlined somewhere,
and then treat it as though "break file:line" were used instead.

You may want to trace through the "file:line" logic in this case to see
what happens.  That should tell you where to modify the gdb core to
make this happen.

You'll also need to change dwarf2read.c to read and respect DW_AT_inline.
Right now this is ignored.  In particular I think you need to check
for DW_INL_inlined, and use that to decide when to look for multiple
locations.

You may need to add a flag to function symbols to indicate when the special
inline processing should be done.
Comment 7 Xin Tong 2011-01-03 21:32:38 UTC
(In reply to comment #6)
> I think "break function" works ok if all instances have been inlined.
> 
> In the case where there is an out-of-line copy, I think it may be best
> if "break function" noticed that "function" was inlined somewhere,
> and then treat it as though "break file:line" were used instead.
> 
In this case, I do not think there is out-of-line copy for "func" . "func" is only used in one place and is inlined there. unless you mean "out-of-line"( not marked as inline) on the source code level. 

(In reply to comment #6)
> You'll also need to change dwarf2read.c to read and respect DW_AT_inline.
> Right now this is ignored.  In particular I think you need to check
> for DW_INL_inlined, and use that to decide when to look for multiple
> locations.
> 
> You may need to add a flag to function symbols to indicate when the special
> inline processing should be done.

I agree with you that further reading of dwarf section is needed and converting break function into break file:line might be the way to go.
Comment 8 Tom Tromey 2011-01-03 21:59:30 UTC
(In reply to comment #7)

> In this case, I do not think there is out-of-line copy for "func" . "func" is
> only used in one place and is inlined there. unless you mean "out-of-line"( not
> marked as inline) on the source code level. 

It may be gcc-version-dependent.
Or maybe I am misremembering the result of my experiment :-)
Comment 9 Sergio Durigan Junior 2011-04-04 19:01:11 UTC
(In reply to comment #3)
> This is my first time contributing to gdb. I am an developer from IBM Java
> Just-In-Time compiler team. I would like to give this defect a try. Is there
> help i can resort to if I am stuck ?

Hello Xin,

I would like to know if you're working on this feature.

Thank you very much!
Comment 10 Xin Tong 2011-04-04 19:04:59 UTC
I have been busy with my work in IBM recently and will have spare time in
May. you can either save the bug for me to work on in May or assign it to
someone else if there is someone who is willing to take it

Thank you

Xin


On Mon, Apr 4, 2011 at 3:01 PM, sergiodj at redhat dot com <
sourceware-bugzilla@sourceware.org> wrote:

> http://sourceware.org/bugzilla/show_bug.cgi?id=10738
>
> Sergio Durigan Junior <sergiodj at redhat dot com> changed:
>
>           What    |Removed                     |Added
>
> ----------------------------------------------------------------------------
>                 CC|                            |sergiodj at redhat dot com
>
> --- Comment #9 from Sergio Durigan Junior <sergiodj at redhat dot com>
> 2011-04-04 19:01:11 UTC ---
> (In reply to comment #3)
> > This is my first time contributing to gdb. I am an developer from IBM
> Java
> > Just-In-Time compiler team. I would like to give this defect a try. Is
> there
> > help i can resort to if I am stuck ?
>
> Hello Xin,
>
> I would like to know if you're working on this feature.
>
> Thank you very much!
>
> --
> Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug.
> You are the assignee for the bug.
>
Comment 11 Jan Kratochvil 2011-04-14 15:33:49 UTC
Another case to consider:

File name                            Line number    Starting address
4.c                                            5            0x400490
4.c                                            5            0x40049a
4.c                                            5            0x400383
4.c                                            5            0x40038a
(other line numbers filtered out)

(gdb) b f
Breakpoint 1 at 0x400490: file 4.c, line 5.

But 0x400383 - the inlind instance in main - is filtered out because the function name there is different.

-g -O2 -fno-omit-frame-pointer
gcc (GCC) 4.7.0 20110414 (experimental)
(the version should not matter much)

volatile int v;
__attribute__((always_inline)) void
f (void)
{
  v--;
}
int
main (void)
{
  v++;
  f ();
  v++;
  return 0;
}
Comment 12 Mark Wielaard 2011-04-15 09:31:09 UTC
(In reply to comment #11)
> But 0x400383 - the inlind instance in main - is filtered out because the
> function name there is different.

Why is that? The inlined_subroutine that covers 0x400383 should have
an abstract_origin with as name "f".
Comment 13 Jan Kratochvil 2011-04-15 19:04:20 UTC
(In reply to comment #12)
> Why is that? The inlined_subroutine that covers 0x400383 should have
> an abstract_origin with as name "f".

#0  block_linkage_function
#1  find_pc_sect_function
#2  find_pc_partial_function_gnu_ifunc
#3  find_pc_partial_function
#4  expand_line_sal_maybe

block_linkage_function /* The return value will not be an inlined function;
                          the containing function will be returned instead.  */

It may be a simple bug, not sure.
Comment 14 Jason Merrill 2011-05-13 14:04:21 UTC
FYI, RMS has taken an interest in this issue, as an instance of his longstanding emphasis on being able to debug optimized code.
Comment 15 Tom Tromey 2011-05-13 14:10:53 UTC
(In reply to comment #14)
> FYI, RMS has taken an interest in this issue, as an instance of his
> longstanding emphasis on being able to debug optimized code.

As a workaround, right now "break file:line" will do the right thing
for inlined functions.
Comment 16 Tom Tromey 2011-08-17 15:50:21 UTC
Note that this is related to PR 13105 now.
Comment 17 Sourceware Commits 2012-03-16 16:47:41 UTC
CVSROOT:	/cvs/src
Module name:	src
Changes by:	gary@sourceware.org	2012-03-16 16:47:34

Modified files:
	gdb            : ChangeLog NEWS dwarf2read.c linespec.c main.c 
	                 symfile.h 
	gdb/doc        : ChangeLog gdb.texinfo 
	gdb/testsuite  : ChangeLog 
	gdb/testsuite/gdb.base: annota1.exp async-shell.exp 
	gdb/testsuite/lib: mi-support.exp 
Added files:
	gdb/testsuite/gdb.dwarf2: dw2-inline-break.S 
	                          dw2-inline-break.exp 
	gdb/testsuite/gdb.opt: inline-break.c inline-break.exp 

Log message:
	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.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/ChangeLog.diff?cvsroot=src&r1=1.14019&r2=1.14020
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/NEWS.diff?cvsroot=src&r1=1.499&r2=1.500
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/dwarf2read.c.diff?cvsroot=src&r1=1.624&r2=1.625
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/linespec.c.diff?cvsroot=src&r1=1.152&r2=1.153
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/main.c.diff?cvsroot=src&r1=1.101&r2=1.102
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/symfile.h.diff?cvsroot=src&r1=1.105&r2=1.106
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/doc/ChangeLog.diff?cvsroot=src&r1=1.1286&r2=1.1287
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/doc/gdb.texinfo.diff?cvsroot=src&r1=1.933&r2=1.934
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/ChangeLog.diff?cvsroot=src&r1=1.3140&r2=1.3141
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/annota1.exp.diff?cvsroot=src&r1=1.46&r2=1.47
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.base/async-shell.exp.diff?cvsroot=src&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.dwarf2/dw2-inline-break.S.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.dwarf2/dw2-inline-break.exp.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.opt/inline-break.c.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/gdb.opt/inline-break.exp.diff?cvsroot=src&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/src/gdb/testsuite/lib/mi-support.exp.diff?cvsroot=src&r1=1.109&r2=1.110
Comment 18 Gary Benson 2012-03-16 16:52:06 UTC
I fixed it.