Search code examples
binaryfileselfobjcopycode-size

How to remove useless empty space between ELF sections after removing section?


I try to reduce the binary size by objcopy with --remove-section option. After the section is removed, it remains some empty space at the original position of deleted section. Is there any way to adjust the section's offset to avoid these empty space?

For emxaple, I removed .eh_frame_hdr section, and there are 0x03c empty space starting from 0x0764 in the stripped binary.

There are 35 section headers, starting at offset 0x1c78:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000400238 000238 00001c 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            0000000000400254 000254 000020 00   A  0   0  4
  [ 3] .note.gnu.build-id NOTE            0000000000400274 000274 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0000000000400298 000298 00001c 00   A  5   0  8
  [ 5] .dynsym           DYNSYM          00000000004002b8 0002b8 000078 18   A  6   1  8
  [ 6] .dynstr           STRTAB          0000000000400330 000330 000060 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          0000000000400390 000390 00000a 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         00000000004003a0 0003a0 000040 00   A  6   2  8
  [ 9] .rela.dyn         RELA            00000000004003e0 0003e0 000030 18   A  5   0  8
  [10] .rela.plt         RELA            0000000000400410 000410 000030 18  AI  5  27  8
  [11] .init             PROGBITS        0000000000400440 000440 000017 00  AX  0   0  4
  [12] .rela.init        RELA            0000000000000000 0018c0 000018 18   I 32  11  8
  [13] .plt              PROGBITS        0000000000400460 000460 000030 10  AX  0   0 16
  [14] .text             PROGBITS        0000000000400490 000490 0002c2 00  AX  0   0 16
  [15] .rela.text        RELA            0000000000000000 0018d8 0001c8 18   I 32  14  8
  [16] .fini             PROGBITS        0000000000400754 000754 000009 00  AX  0   0  4
  [17] .rodata           PROGBITS        0000000000400760 000760 000004 04  AM  0   0  4
  [18] .eh_frame_hdr     PROGBITS        0000000000400764 000764 00003c 00   A  0   0  4
  [19] .eh_frame         PROGBITS        00000000004007a0 0007a0 000100 00   A  0   0  8
  [20] .rela.eh_frame    RELA            0000000000000000 001aa0 000078 18   I 32  19  8
  [21] .init_array       INIT_ARRAY      0000000000600e00 000e00 000008 08  WA  0   0  8
  [22] .rela.init_array  RELA            0000000000000000 001b18 000018 18   I 32  21  8
  [23] .fini_array       FINI_ARRAY      0000000000600e08 000e08 000008 08  WA  0   0  8
  [24] .rela.fini_array  RELA            0000000000000000 001b30 000018 18   I 32  23  8
  [25] .dynamic          DYNAMIC         0000000000600e10 000e10 0001e0 10  WA  6   0  8
  [26] .got              PROGBITS        0000000000600ff0 000ff0 000010 08  WA  0   0  8
  [27] .got.plt          PROGBITS        0000000000601000 001000 000028 08  WA  0   0  8
  [28] .data             PROGBITS        0000000000601028 001028 000010 00  WA  0   0  8
  [29] .tm_clone_table   PROGBITS        0000000000601038 001038 000000 00  WA  0   0  8
  [30] .bss              NOBITS          0000000000601038 001038 000008 00  WA  0   0  1
  [31] .comment          PROGBITS        0000000000000000 001038 000029 01  MS  0   0  1
  [32] .symtab           SYMTAB          0000000000000000 001068 000630 18     33  45  8
  [33] .strtab           STRTAB          0000000000000000 001698 000227 00      0   0  1
  [34] .shstrtab         STRTAB          0000000000000000 001b48 00012c 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

After strip:

There are 34 section headers, starting at offset 0x1c28:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000400238 000238 00001c 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            0000000000400254 000254 000020 00   A  0   0  4
  [ 3] .note.gnu.build-id NOTE            0000000000400274 000274 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        0000000000400298 000298 00001c 00   A  5   0  8
  [ 5] .dynsym           DYNSYM          00000000004002b8 0002b8 000078 18   A  6   1  8
  [ 6] .dynstr           STRTAB          0000000000400330 000330 000060 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          0000000000400390 000390 00000a 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         00000000004003a0 0003a0 000040 00   A  6   2  8
  [ 9] .rela.dyn         RELA            00000000004003e0 0003e0 000030 18   A  5   0  8
  [10] .rela.plt         RELA            0000000000400410 000410 000030 18  AI  5  26  8
  [11] .init             PROGBITS        0000000000400440 000440 000017 00  AX  0   0  4
  [12] .rela.init        RELA            0000000000000000 001880 000018 18   I 31  11  8
  [13] .plt              PROGBITS        0000000000400460 000460 000030 10  AX  0   0 16
  [14] .text             PROGBITS        0000000000400490 000490 0002c2 00  AX  0   0 16
  [15] .rela.text        RELA            0000000000000000 001898 0001c8 18   I 31  14  8
  [16] .fini             PROGBITS        0000000000400754 000754 000009 00  AX  0   0  4
  [17] .rodata           PROGBITS        0000000000400760 000760 000004 04  AM  0   0  4
  [18] .eh_frame         PROGBITS        00000000004007a0 0007a0 000100 00   A  0   0  8
  [19] .rela.eh_frame    RELA            0000000000000000 001a60 000078 18   I 31  18  8
  [20] .init_array       INIT_ARRAY      0000000000600e00 000e00 000008 08  WA  0   0  8
  [21] .rela.init_array  RELA            0000000000000000 001ad8 000018 18   I 31  20  8
  [22] .fini_array       FINI_ARRAY      0000000000600e08 000e08 000008 08  WA  0   0  8
  [23] .rela.fini_array  RELA            0000000000000000 001af0 000018 18   I 31  22  8
  [24] .dynamic          DYNAMIC         0000000000600e10 000e10 0001e0 10  WA  6   0  8
  [25] .got              PROGBITS        0000000000600ff0 000ff0 000010 08  WA  0   0  8
  [26] .got.plt          PROGBITS        0000000000601000 001000 000028 08  WA  0   0  8
  [27] .data             PROGBITS        0000000000601028 001028 000010 00  WA  0   0  8
  [28] .tm_clone_table   PROGBITS        0000000000601038 001038 000000 00  WA  0   0  8
  [29] .bss              NOBITS          0000000000601038 001038 000008 00  WA  0   0  1
  [30] .comment          PROGBITS        0000000000000000 001038 000029 01  MS  0   0  1
  [31] .symtab           SYMTAB          0000000000000000 001068 000600 18     32  43  8
  [32] .strtab           STRTAB          0000000000000000 001668 000214 00      0   0  1
  [33] .shstrtab         STRTAB          0000000000000000 001b08 00011e 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)


Solution

  • Linking is a lossy process. A relocation in .o may be resolved in the linked image. objcopy does not know whether the hidden references. Therefore, it just tries to be extremely conservative: not alter addresses after --remove-section.

    If you want to avoid .eh_frame_hdr and .eh_frame, the best is to use -fno-exceptions -fno-asynchronous-unwind-tables.