Compressing DWARF Data
Compared to DWARF v1, the encoding scheme used in newer versions of DWARF has greatly reduced the size of debugging information. However, unfortunately, the debugging information generated by compilers is still very large, often larger than the storage footprint of executable code and data. Newer versions of DWARF provide methods to further reduce the size of debugging data, such as using zlib data compression.
Below is an example of a production environment service (about 147MB after compilation), which is still 147MB even after using DWARF v4 and enabling DWARF data compression (Flags==C). The large file size after building is due to multiple factors, such as this Go program using static linking, symbol table information, and debugging information being preserved.
root🦀 bin $ readelf -S grpc_admin_svr
There are 36 section headers, starting at offset 0x238:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[24] .debug_abbrev PROGBITS 0000000000000000 0688d000
0000000000000135 0000000000000000 C 0 0 1
[25] .debug_line PROGBITS 0000000000000000 0688d135
00000000006538d5 0000000000000000 C 0 0 1
[26] .debug_frame PROGBITS 0000000000000000 06ee0a0a
000000000012ada4 0000000000000000 C 0 0 1
[27] .debug_gdb_script PROGBITS 0000000000000000 0700b7ae
0000000000000030 0000000000000000 0 0 1
[28] .debug_info PROGBITS 0000000000000000 0700b7de
0000000000ace1cb 0000000000000000 C 0 0 1
[29] .debug_loc PROGBITS 0000000000000000 07ad99a9
0000000000881add 0000000000000000 C 0 0 1
[30] .debug_ranges PROGBITS 0000000000000000 0835b486
00000000004836ee 0000000000000000 C 0 0 1
...
Let's see how much storage space we can save by removing the DWARF data. Using objcopy to remove all DWARF debug sections, then checking the file size - 32MB!!!
root🦀 bin $ objcopy --strip-debug grpc_admin_svr grpc_admin_svr.stripped
root🦀 bin $ ll -h
total 262M
drwxr-xr-x 2 root root 4.0K May 18 11:34 ./
drwxr-xr-x 4 root root 4.0K Apr 28 16:05 ../
-rwxr-xr-x 1 root root 147M May 12 13:01 grpc_admin_svr
-rwxr-xr-x 1 root root 115M May 18 11:34 grpc_admin_svr.stripped
32MB is still quite large. Most programming languages don't generate debugging information by default, with Go being an exception.
There has been discussion in golang/go issues about whether DWARF data generation should be disabled by default. As for whether newer versions of Go will disable DWARF generation by default, it's likely they won't, as this would also increase debugging costs and the management overhead of maintaining one-to-one correspondence between artifact repositories, code versions, and debugging symbol information. In today's era of low storage costs, the strategy of disabling DWARF debugging information generation by default might be a case of solving one problem while creating another, and may not be particularly valuable in practice.
Of course, if you want to explicitly disable DWARF debugging information generation, you can use go build -ldflags='-w'
to turn off debugging information generation.