Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zig cc strips debuginfo from object files #11194

Closed
sfackler opened this issue Mar 16, 2022 · 4 comments · Fixed by #11207
Closed

zig cc strips debuginfo from object files #11194

sfackler opened this issue Mar 16, 2022 · 4 comments · Fixed by #11207
Labels
bug Observed behavior contradicts documented or intended behavior zig cc Zig as a drop-in C compiler feature
Milestone

Comments

@sfackler
Copy link
Contributor

sfackler commented Mar 16, 2022

Zig Version

0.10.0-dev.1355+8a43d67c3

Steps to Reproduce

  1. Create a C file test.c with a main function
  2. Compile it into an object file with debuginfo using GCC: gcc -c -g test.c
  3. Link it with zig cc: zig cc test.o
  4. Look at the sections in the resulting a.out: size -A a.out
  5. Link it with gcc: gcc test.o
  6. Look at the sections in the resulting a.out: size -A a.out

Expected Behavior

The binary contains the .debug_<foo> sections generated in the test.o object file both when created by gcc and by zig cc:

a.out  :
section              size    addr
.interp                28     792
.note.gnu.property     32     824
.note.gnu.build-id     36     856
.note.ABI-tag          32     892
.gnu.hash              36     928
.dynsym               168     968
.dynstr               130    1136
.gnu.version           14    1266
.gnu.version_r         32    1280
.rela.dyn             192    1312
.rela.plt              24    1504
.init                  27    4096
.plt                   32    4128
.plt.got               16    4160
.plt.sec               16    4176
.text                 389    4192
.fini                  13    4584
.rodata                16    8192
.eh_frame_hdr          68    8208
.eh_frame             264    8280
.init_array             8   15800
.fini_array             8   15808
.dynamic              496   15816
.got                   72   16312
.data                  16   16384
.bss                    8   16400
.comment               41       0
.debug_aranges         48       0
.debug_info           767       0
.debug_abbrev         204       0
.debug_line           272       0
.debug_str            640       0
Total                4145

Actual Behavior

The binary does contain debug sections when linked by gcc, but not by zig cc:

a.out  :
section          size      addr
.interp            28   2097832
.note.ABI-tag      32   2097860
.dynsym            96   2097896
.gnu.version        8   2097992
.gnu.version_r     32   2098000
.gnu.hash          28   2098032
.hash              40   2098060
.dynstr            61   2098100
.rela.dyn          48   2098168
.rela.plt          24   2098216
.rodata            12   2098240
.eh_frame_hdr      28   2098252
.eh_frame          84   2098280
.text             230   2102464
.init              23   2102696
.fini               9   2102720
.plt               32   2102736
.dynamic          336   2106864
.got               16   2107200
.got.plt           32   2111312
.comment          251         0
Total            1450
@sfackler sfackler added the bug Observed behavior contradicts documented or intended behavior label Mar 16, 2022
@sfackler
Copy link
Contributor Author

I think the issue is that zig cc is configured to strip by default: https://github.com/ziglang/zig/blob/master/src/main.zig#L1311. Could that default just be changed to false to match with gcc/clang? Alternatively, there could be a --no-strip flag or something like that.

@andrewrk andrewrk added the zig cc Zig as a drop-in C compiler feature label Mar 17, 2022
@andrewrk andrewrk added this to the 0.10.0 milestone Mar 17, 2022
@andrewrk
Copy link
Member

andrewrk commented Mar 18, 2022

Could that default just be changed to false to match with gcc/clang?

Yes it could. Happy to merge your pull request 👍

For some historical context: Zig does not have a -g flag to enable debug info; it's on by default and one uses --strip to disable it. However, until recently (366c767), Zig did not forward the strip flag to LLD. So when creating zig cc, which is a C/C++ CLI interface layer on top of the actual Zig compilation options (which do not have the option to disable debug info besides strip), it made sense that "strip" would be on by default for zig cc unless -g was used. Ultimately, I'm in favor of having strip be off by default for zig cc as well, and there will be no option to disable -g other than -s.

@sfackler
Copy link
Contributor Author

Makes sense, thanks!

@motiejus
Copy link
Contributor

motiejus commented Jun 14, 2022

Note that this may interact poorly with -gsplit-dwarf. This is useful when the binaries are becoming big, and one wants to split the debug info to other files (e.g. debian).

I just ran a "size test" for sqlite3: clang-13 vs zig cc:

clang-13 -gsplit-dwarf: 3.5 MB

$ CC="clang-13" CFLAGS="-ggdb3 -gsplit-dwarf -O2" ./configure --disable-tcl && make
<...>
$ bloaty sqlite3
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  35.0%  1.23Mi  80.6%  1.23Mi    .text
  24.5%   880Ki   0.0%       0    .debug_line
  17.3%   619Ki   0.0%       0    .debug_addr
   9.2%   330Ki   0.0%       0    .debug_ranges
   4.2%   149Ki   9.6%   149Ki    .rodata
   2.9%   105Ki   6.8%   105Ki    .eh_frame
   2.4%  86.0Ki   0.0%       0    .debug_gnu_pubnames
   1.6%  56.4Ki   0.0%       0    .symtab
   1.2%  42.2Ki   0.0%       0    .strtab
   0.4%  15.4Ki   1.0%  15.4Ki    .eh_frame_hdr
   0.4%  15.2Ki   1.0%  15.2Ki    .data
   0.2%  8.38Ki   0.0%       0    .debug_gnu_pubtypes
   0.1%  4.83Ki   0.3%  4.18Ki    [22 Others]
   0.1%  4.22Ki   0.0%       0    [Unmapped]
   0.1%  3.61Ki   0.2%  3.61Ki    .dynsym
   0.1%  2.62Ki   0.2%  2.62Ki    .rela.plt
   0.1%  2.44Ki   0.0%       0    [ELF Section Headers]
   0.0%       0   0.1%  2.13Ki    .bss
   0.0%  1.77Ki   0.1%  1.77Ki    .plt
   0.0%  1.45Ki   0.1%  1.45Ki    .dynstr
   0.0%  1.12Ki   0.1%  1.12Ki    .hash
 100.0%  3.50Mi 100.0%  1.52Mi    TOTAL

zig cc -gsplit-dwarf: 8.66 MB

$ CC="zig cc" CFLAGS="-ggdb3 -gsplit-dwarf -O2" ./configure --disable-tcl; make
$ bloaty sqlite3
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  40.7%  3.52Mi   0.0%       0    .debug_loc
  18.3%  1.59Mi   0.0%       0    .debug_info
  16.5%  1.43Mi  88.4%  1.43Mi    .text
  11.7%  1.01Mi   0.0%       0    .debug_line
   5.8%   515Ki   0.0%       0    .debug_ranges
   1.8%   157Ki   9.5%   157Ki    .rodata
   1.3%   118Ki   0.0%       0    .debug_frame
   1.2%   110Ki   0.0%       0    .debug_str
   1.0%  85.8Ki   0.0%       0    .debug_gnu_pubnames
   0.6%  56.2Ki   0.0%       0    .symtab
   0.5%  40.2Ki   0.0%       0    .strtab
   0.2%  15.3Ki   0.9%  15.3Ki    .data
   0.1%  7.97Ki   0.0%       0    .debug_gnu_pubtypes
   0.1%  6.38Ki   0.4%  5.82Ki    [18 Others]
   0.1%  4.71Ki   0.3%  4.71Ki    .dynsym
   0.0%  2.98Ki   0.0%       0    .debug_abbrev
   0.0%  2.55Ki   0.2%  2.55Ki    .rela.plt
   0.0%  2.25Ki   0.0%       0    [ELF Section Headers]
   0.0%       0   0.1%  2.02Ki    .bss
   0.0%  1.84Ki   0.1%  1.84Ki    .dynstr
   0.0%  1.72Ki   0.1%  1.72Ki    .plt
 100.0%  8.66Mi 100.0%  1.62Mi    TOTAL

As we can see, the debug info remains in the final binary, and, while -gsplit-dwarf creates the file, it does not have any effect on the resulting size of the actual binary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior zig cc Zig as a drop-in C compiler feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants