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.

results matching ""

    No results matching ""