llvm / llvm/llvm-project

More DW_TAG_inlined_subroutine DIEs than inlined function calls

Open
#184,580 3 comments 0 reactions 0 assignees View on GitHub
debuginfo wrong-debug
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

With clang 17.0.6/19.1.7/21.1.8, I ran into a [problem](https://sourceware.org/bugzilla/show_bug.cgi?id=33953) with gdb testcase gdb.opt/inline-entry.exp.

This is a standalone version of source file [inline-entry.c](https://sourceware.org/git/?p=binutils-gdb.git;a=blob_plain;f=gdb/testsuite/gdb.opt/inline-entry.c;hb=HEAD):
```
/* Copyright 2024-2026 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 . */

volatile int global = 0;

__attribute__((noinline)) void
foo (int arg)
{
global += arg;
}

inline __attribute__((always_inline)) int
bar (int val)
{
if (global == val)
return 1;
foo (1);
return 1;
}

int
main (void)
{
if ((global && bar (1)) || bar (2))
return 0;
return 1;
}
```
and this demonstrates the problem (with gdb, I get the same with lldb):
```
$ clang-17 inline-entry.c -g -O2
$ gdb -q -batch a.out -ex "break bar"
Breakpoint 1 at 0x1147: bar. (3 locations)
```

While there are just two calls to bar, there are three corresponding breakpoint locations.

This is due to the debug info, which incorrectly lists 3 DW_TAG_inlined_subroutine DIEs:
```
<2><27d>: Abbrev Number: 10 (DW_TAG_inlined_subroutine)
<27e> DW_AT_abstract_origin: <0x25d>
<282> DW_AT_ranges : (index: 0): 0x31
<283> DW_AT_call_file : 0
<284> DW_AT_call_line : 36
<2><285>: Abbrev Number: 11 (DW_TAG_inlined_subroutine)
<286> DW_AT_abstract_origin: <0x25d>
<28a> DW_AT_low_pc : (index: 0x3): 0x114f
<28b> DW_AT_high_pc : 0x5
<28f> DW_AT_call_file : 0
<290> DW_AT_call_line : 36
<291> DW_AT_call_column : 18
<3><292>: Abbrev Number: 12 (DW_TAG_formal_parameter)
<293> DW_AT_const_value : 1
<294> DW_AT_abstract_origin: <0x265>
<3><298>: Abbrev Number: 0
<2><299>: Abbrev Number: 11 (DW_TAG_inlined_subroutine)
<29a> DW_AT_abstract_origin: <0x25d>
<29e> DW_AT_low_pc : (index: 0x4): 0x1166
<29f> DW_AT_high_pc : 0x7
<2a3> DW_AT_call_file : 0
<2a4> DW_AT_call_line : 36
<2a5> DW_AT_call_column : 30
<3><2a6>: Abbrev Number: 12 (DW_TAG_formal_parameter)
<2a7> DW_AT_const_value : 2
<2a8> DW_AT_abstract_origin: <0x265>
```

Contributor guide

Open the contributing guide

Research direction

Reproduce the behavior with the standalone inline-entry.c example and the clang command shown, then compare the emitted DWARF with gdb/testsuite/gdb.opt/inline-entry.exp. Trace how the compiler represents the two bar calls and validate the result using the breakpoint-location behavior described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.