Bug 1091989

Summary: package build with -O0 -g results in corrupted -debuginfo package
Product: [Fedora] Fedora Reporter: Petr Spacek <pspacek>
Component: rpmAssignee: Packaging Maintenance Team <packaging-team-maint>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 20CC: jan.kratochvil, jzeleny, laurent.rineau__fedora, novyjindrich, packaging-team-maint, pknirsch, pspacek, samuel-rhbugs
Target Milestone: ---Keywords: Reopened
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2014-06-12 14:46:12 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Petr Spacek 2014-04-28 12:52:05 UTC
Description of problem:
package/gcc build with -O0 -g results in corrupted -debuginfo package

Version-Release number of selected component (if applicable):
rpm-build-4.11.2-2.fc20.x86_64

How reproducible:
100 % with bind package

Steps to Reproduce:
1. Apply following diff to SPEC file from bind-9.9.4-12.P2.fc20.x86_64:
@@ -345,3 +345,3 @@
 %build
-export CFLAGS="$CFLAGS $RPM_OPT_FLAGS"
+export CFLAGS="-O0 -g"
 export CPPFLAGS="$CPPFLAGS -DDIG_SIGCHASE"

2. build package:
$ rpmbuild -ba bind.spec


Actual results:
The package builds and BIND itself seems to work. The problem is that new debuginfo package is missing 118 out of 283 header files in /usr/src/debug/bind-9.9.4-P2. 

Expected results:
Headers in debuginfo package are the same as for build with -O2.

Additional info:
Thread on fedora-devel:
https://lists.fedoraproject.org/pipermail/devel/2014-April/198569.html

I have tested the same thing with CFLAGS="$CFLAGS -O0 -ggdb" (at the beginning) and the results were exactly the same.

Comment 1 Jan Kratochvil 2014-05-05 19:19:59 UTC
(In reply to Petr Spacek from comment #0)
> Expected results:
> Headers in debuginfo package are the same as for build with -O2.

Why is it needed?  There is no need to guarantee that.  gcc outputs only the minimal set of necessary DWARF content and as -O2 contains more debug info (as it needs to describe more complicated optimized code) it needs to output also more filenames for it.

Here is a reproducer - if 'gcc -O0 -g' and 'gcc -O2 -g' produced the same filenames list one should see both 'O0.wil' and 'O2.wil' lines from grep.  But one does not:
echo >header.h 'void f(void);';for O in 0 2;do echo -e '#include "header.h"\nvoid g(void){f();}'|gcc -o O$O.o -O$O -c -g -Wall -x c -;readelf -wil O$O.o >O$O.wil;done;grep -l header.h O{0,2}.wil
O2.wil

The reason is DW_TAG_GNU_call_site debug information which is produced only with -O2 -g (and not -O0 -g) because such debug info is not needed for debugging of the simple code produced using -O0 -g. Particularly -O0 does not use tail calls and -O0 also does use stack frame memory slots for all variables (and not callee-clobbered registers only like -O2).

readelf -wil O2.o
Contents of the .debug_info section:
 <2><44>: Abbrev Number: 3 (DW_TAG_GNU_call_site)
    <45>   DW_AT_low_pc      : 0x5
    <4d>   DW_AT_GNU_tail_call: 1
    <4d>   DW_AT_abstract_origin: <0x52>
 <1><52>: Abbrev Number: 4 (DW_TAG_subprogram)
    <53>   DW_AT_external    : 1
    <53>   DW_AT_name        : f
    <55>   DW_AT_decl_file   : 2
    <56>   DW_AT_decl_line   : 1
 The File Name Table:
  Entry Dir     Time    Size    Name
  2     0       0       0       header.h

Comment 2 Petr Spacek 2014-05-06 08:00:40 UTC
(In reply to Jan Kratochvil from comment #1)
> (In reply to Petr Spacek from comment #0)
> > Expected results:
> > Headers in debuginfo package are the same as for build with -O2.
> Why is it needed?  There is no need to guarantee that.

Right, Expected results can be too strict/poorly formulated. 

Do I understand correctly that debuginfo package should contain all headers necessary for undestanding the compiled code?

In my case, debuginfo package generated with -O0 -g is missing some important headers, e.g. bin/named/include/named/control.h. The code without this header is hard to read because it is missing important #defines, e.g. NS_COMMAND_STOP.

In that case lines like:
} else if (command_compare(command, NS_COMMAND_STOP)) {
doesn't make much sense because you can't see value of NS_COMMAND_STOP.

Debuginfo package is missing 118 out of 283 header files in /usr/src/debug/bind-9.9.4-P2 which seems way too much.

Does it explain my problem?

P.S. Of course, the value is somewhere in the binary code, but isn't the purpose of debuginfo package to make debugging easier? :-)

Comment 3 Jan Kratochvil 2014-05-07 15:50:45 UTC
(In reply to Petr Spacek from comment #2)
> Do I understand correctly that debuginfo package should contain all headers
> necessary for undestanding the compiled code?

IMO *-debuginfo should contain enough sources to understand a crash.
This Bug rather gave me an idea we should drop the header files required only for DW_TAG_GNU_call_site as they needlessly enlarge the *-debuginfo rpms.


> In my case, debuginfo package generated with -O0 -g is missing some
> important headers, e.g. bin/named/include/named/control.h. The code without
> this header is hard to read because it is missing important #defines, e.g.
> NS_COMMAND_STOP.
> 
> In that case lines like:
> } else if (command_compare(command, NS_COMMAND_STOP)) {
> doesn't make much sense because you can't see value of NS_COMMAND_STOP.

It was discussed in:
  Shall we modify '-g' to '-g3' to have gcc save the macro info?
  https://lists.fedoraproject.org/pipermail/devel/2013-January/176313.html
and also shortly in
  https://bugzilla.redhat.com/show_bug.cgi?id=833311
and the conclusion was that macro information is too big vs. its usefulness.
(Personally I think macro info (-g3) would be useful in *-debuginfo rpms.)

With bind-debuginfo.rpm rebuilt using -g3 (even with -O0):

Breakpoint 1, command_compare (text=0x7fffd0000e60 "null", command=0x5555555e08b3 "null") at control.c:48
48              unsigned int commandlen = strlen(command);
(gdb) up
#1  0x00005555555779f5 in ns_control_docommand (message=0x7fffd0000900, text=0x7ffff2405940) at control.c:90
90              if (command_compare(command, NS_COMMAND_NULL) ||
(gdb) p NS_COMMAND_NULL
$1 = "null"
(gdb) info macro NS_COMMAND_NULL
Defined at /usr/src/debug/bind-9.9.4-P2/bin/named/include/named/control.h:59
  included at /usr/src/debug/bind-9.9.4-P2/bin/named/control.c:38
#define NS_COMMAND_NULL "null"
(gdb) _

Standard Fedora bind-debuginfo.rpm:

Breakpoint 1, command_compare (text=0x7fffd0000e60 "null", command=0x5555555d2ff4 "null") at control.c:47
47	command_compare(const char *text, const char *command) {
(gdb) up
#1  0x000055555558156e in ns_control_docommand (message=<optimized out>, text=text@entry=0x7ffff1eb7890)
    at control.c:90
90		if (command_compare(command, NS_COMMAND_NULL) ||
(gdb) p NS_COMMAND_NULL
No symbol "NS_COMMAND_NULL" in current context.
(gdb) info macro NS_COMMAND_NULL
The symbol `NS_COMMAND_NULL' has no definition as a C/C++ preprocessor macro
at <user-defined>:-1
(gdb) _

This Bug should be renamed to "-g3" if you think the macro info is worth the increased Fedora *-debuginfo.rpm size.

I still do not understand how the default "-g -O2" *-debuginfo.rpm is useful for you. If you grep 'NS_COMMAND_NULL' out of /usr/src/debug/bind-9.9.4-P2/ I do not think it is a good enough justification - .src.rpm is IMO more appropriate to use in such case.

Comment 4 Petr Spacek 2014-06-09 12:50:17 UTC
> This Bug should be renamed to "-g3" if you think the macro info is worth the
> increased Fedora *-debuginfo.rpm size.
> 
> I still do not understand how the default "-g -O2" *-debuginfo.rpm is useful
> for you. If you grep 'NS_COMMAND_NULL' out of /usr/src/debug/bind-9.9.4-P2/
> I do not think it is a good enough justification - .src.rpm is IMO more
> appropriate to use in such case.

Maybe we don't understand each other.
grep -R 'NS_COMMAND_NULL' /usr/src/debug/bind-9.9.4-P2/
yields nothing if I compile the package with -O0. It is perfectly okay if I use -O2 but is it not okay if I compile it with -O0.

I hope this clears the confusion and I'm sorry for the delay.

Comment 5 Jan Kratochvil 2014-06-09 14:20:49 UTC
(In reply to Petr Spacek from comment #4)
> grep -R 'NS_COMMAND_NULL' /usr/src/debug/bind-9.9.4-P2/
> yields nothing

It is irrelevant what 'grep ... /usr/src/debug/...' yields.
That directory is only for debugging tools like GDB.  Never access it by hand.  If you find it useful by hand fine, if you do not use something else.

Do you have any other concerns about debuginfo?

Comment 6 Petr Spacek 2014-06-12 11:43:57 UTC
To make sure I understand you:
Are you saying that I should always download src.rpm and do "rpmbuild -bp" and grep there?

Comment 7 Jan Kratochvil 2014-06-12 14:46:12 UTC
(In reply to Petr Spacek from comment #6)
> Are you saying that I should always download src.rpm and do "rpmbuild -bp"
> and grep there?

Yes.  This is the only way and this is what I have always been doing.