Bugzilla will be upgraded to version 5.0. The upgrade date is tentatively scheduled for 2 December 2018, pending final testing and feedback.
Bug 586558 - missing debug info for member functions defined in header file for shared library
missing debug info for member functions defined in header file for shared lib...
Status: CLOSED NOTABUG
Product: Red Hat Enterprise Linux 5
Classification: Red Hat
Component: gcc (Show other bugs)
5.5
All Linux
medium Severity medium
: rc
: ---
Assigned To: Jakub Jelinek
qe-baseos-tools
: Reopened
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2010-04-27 16:54 EDT by Jeff Bastian
Modified: 2018-10-27 08:10 EDT (History)
1 user (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2010-05-19 05:31:59 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
demo program (664 bytes, application/x-gzip)
2010-04-27 16:54 EDT, Jeff Bastian
no flags Details

  None (edit)
Description Jeff Bastian 2010-04-27 16:54:34 EDT
Created attachment 409586 [details]
demo program

Description of problem:
If the body of a constructor or other member function is defined in-line within the class definition in a header file, and then the class is compiled into a shared library, the debug info is missing for the constructor and other member functions.

For example, given this foo class defined in foo.h:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class foo
{
  public:
        int f;

        foo() { f = 3; }
        foo(int x) : f(x) { }
        ~foo() { }

        bool operator == (const foo& rhs) const { return f == rhs.f; }
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When compiled into a shared library, the debug info is missing for the constructors, destructor, and == operator.  The only function shown is somefunc (a dummy function so we can at least see one function).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$ readelf -wp foo.so
Contents of the .debug_pubnames section:

  Length:                              27
  Version:                             2
  Offset into .debug_info section:     0
  Size of area in .debug_info section: 205

    Offset      Name
    154                 somefunc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If the member function bodies are moved into the foo.cpp file, there is a lot more debug info to work with:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$ readelf -wp foo-modified.so
Contents of the .debug_pubnames section:

  Length:                              127
  Version:                             2
  Offset into .debug_info section:     0
  Size of area in .debug_info section: 803

    Offset      Name
    360                 foo::foo
    398                 foo::foo
    469                 foo::foo
    515                 foo::foo
    606                 foo::~foo
    644                 foo::~foo
    682                 foo::operator==
    752                 somefunc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The missing debug info makes it difficult to set breakpoints on the member functions.

Version-Release number of selected component (if applicable):
gcc-4.1.2-48.el5.x86_64
gcc-c++-4.1.2-48.el5.x86_64

How reproducible:
every time

Steps to Reproduce:
1. tar xzf foo-members.tar.gz           (see attached)
2. cd foo-members
3. make
 
Actual results:
no debug info for member functions in foo.so

Expected results:
full debug info for member functions in foo.so

Additional info:
Comment 1 Jeff Bastian 2010-04-27 17:08:53 EDT
gdb doesn't know anything about the member functions with foo.so:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$ gdb foo.so
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-23.el5)
...
Reading symbols from /home/jbastian/scratch/it724583/foo-members/foo.so...done.
(gdb) info functions foo
All functions matching regular expression "foo":
(gdb) 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

But it works much better with foo-modified.so:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$ gdb foo-modified.so
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-23.el5)
...
Reading symbols from /home/jbastian/scratch/it724583/foo-members/foo-modified.so...done.
(gdb) info functions foo
All functions matching regular expression "foo":

File foo-modified.cpp:
void foo::foo();
void foo::foo();
void foo::foo(int);
void foo::foo(int);
bool foo::operator==(foo const&) const;
void foo::~foo();
void foo::~foo();
(gdb)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


On a side note, it's curious that the constructors and destructor are listed twice...
Comment 2 Jakub Jelinek 2010-05-17 06:31:17 EDT
That's by design, because foo class isn't used at all.
Unused types are pruned by default to avoid debug info being very large.

You can use -fno-eliminate-unused-debug-types to force all types into the debug info.
Comment 3 Jeff Bastian 2010-05-17 09:09:42 EDT
That flag doesn't help.  I also tried -fno-eliminate-unused-debug-symbols.

$ g++ -g -fno-eliminate-unused-debug-types \
         -fno-eliminate-unused-debug-symbols \
         -fPIC -c -o foo.o foo.cpp
$ g++ -g -fno-eliminate-unused-debug-types \
         -fno-eliminate-unused-debug-symbols \
         -shared -o foo.so foo.o
$ readelf -wp foo.so
Contents of the .debug_pubnames section:

  Length:                              27
  Version:                             2
  Offset into .debug_info section:     0
  Size of area in .debug_info section: 375

    Offset      Name
    324                 somefunc
Comment 4 Jakub Jelinek 2010-05-19 05:31:59 EDT
Why are you looking at .debug_pubnames rather than .debug_info?  AFAIK gdb never uses this section and the section has lots of inherent issues that prevent it from being actually used.  If you add foo var; into a CU that just includes that header, you'll see it doesn't emit further .debug_pubnames items either, yet have the DW_TAG_subprogram/DW_TAG_*_type that is needed.
Comment 5 Jakub Jelinek 2010-05-19 09:24:36 EDT
As I said earlier, -fno-eliminate-unused-debug-types makes sure the unused type is emitted in the debug info.

Now, if you want to put a breakpoint on the methods or call them from inferior, you want those methods to be actually emitted.  If they are inline methods, they aren't emitted at all when not used and when used, they are usually inlined and only when not inlined they are emitted out of line.  -g shouldn't affect generated code, it just tells the compiler to describe to the debugger what has been emitted.

If for debugging purposes you need bodies of the inline methods, you can use -fkeep-inline-functions which will grow the size of the generated code considerably (emits everything out of line in addition to all the successful inlines).

Note You need to log in before you can comment on or make changes to this bug.