为什么objdump二进制大小比实际ELF大小大得多



我有一个ELF文件,然后我们将其转换为二进制格式:

arm-none-eabi-objcopy -O binary MyElfFile.elf MyBinFile.bin

ELF文件不到300KB,但二进制输出文件要大446倍:134000KB,即130MB!当二进制文件的全部目的是删除符号、节表和调试信息时,这怎么可能呢?

看看Reddit和SO,看起来二进制图像应该比ELF小,而不是更大。

so.s

b .
.section .data
.word 0x12345678
arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o
so.o:     file format elf32-littlearm

Disassembly of section .text:
00000000 <.text>:
0:   eafffffe    b   0 <.text>
Disassembly of section .data:
00000000 <.data>:
0:   12345678    eorsne  r5, r4, #120, 12    ; 0x78
arm-none-eabi-readelf -a so.o
Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .text             PROGBITS        00000000 000034 000004 00  AX  0   0  4
[ 2] .data             PROGBITS        00000000 000038 000004 00  WA  0   0  1
[ 3] .bss              NOBITS          00000000 00003c 000000 00  WA  0   0  1
[ 4] .ARM.attributes   ARM_ATTRIBUTES  00000000 00003c 000012 00      0   0  1
[ 5] .symtab           SYMTAB          00000000 000050 000060 10      6   6  4
[ 6] .strtab           STRTAB          00000000 0000b0 000004 00      0   0  1
[ 7] .shstrtab         STRTAB          00000000 0000b4 00003c 00      0   0  1

所以我的";二进制";总共有8个字节。分为两部分。

-rw-rw-r-- 1 oldtimer oldtimer  560 Oct 12 16:32 so.o

相对于对象的560为8字节。

链接它。

MEMORY
{
one : ORIGIN = 0x00001000, LENGTH = 0x1000
two : ORIGIN = 0x00002000, LENGTH = 0x1000
}
SECTIONS
{
.text   : { (.text)   } > one
.data   : { (.data)   } > two
}

arm-none-eabi-ld -T so.ld so.o -o so.elf
arm-none-eabi-objdump -D so.elf
so.elf:     file format elf32-littlearm

Disassembly of section .text:
00001000 <.text>:
1000:   eafffffe    b   1000 <.text>
Disassembly of section .data:
00002000 <.data>:
2000:   12345678    eorsne  r5, r4, #120, 12    ; 0x7800000
arm-none-eabi-readelf -a so.elf
Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .text             PROGBITS        00001000 001000 000004 00  AX  0   0  4
[ 2] .data             PROGBITS        00002000 002000 000004 00  WA  0   0  1
[ 3] .ARM.attributes   ARM_ATTRIBUTES  00000000 002004 000012 00      0   0  1
[ 4] .symtab           SYMTAB          00000000 002018 000070 10      5   7  4
[ 5] .strtab           STRTAB          00000000 002088 00000c 00      0   0  1
[ 6] .shstrtab         STRTAB          00000000 002094 000037 00      0   0  1

现在。。。如果我们想使用-O二进制objcopy,则在0x1000处需要4个字节,在0x2000处需要4字节,这意味着它将占用整个内存空间,以最低地址开始文件,以最高地址结束。有了这个链接,最低的是0x1000,最高的是0x2003,总跨度为0x1004字节:

arm-none-eabi-objcopy -O binary so.elf so.bin
ls -al so.bin
-rwxrwxr-x 1 oldtimer oldtimer 4100 Oct 12 16:40 so.bin

4100=0x1004字节

hexdump -C so.bin
00000000  fe ff ff ea 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000  78 56 34 12                                       |xV4.|
00001004

这里的假设是用户知道基地址是0x1000,因为文件格式中没有地址信息。这是一个连续的内存映像,因此四个字节也位于0x2000。所以-O二进制填充文件以填充所有内容。

如果我换成这个

MEMORY
{
one : ORIGIN = 0x00000000, LENGTH = 0x1000
two : ORIGIN = 0x10000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > one
.data : { *(.data*) } > two
}

你可以很容易地看到它的发展方向。

ls -al so.bin
-rwxrwxr-x 1 oldtimer oldtimer 268435460 Oct 12 16:43 so.bin

所以我的elf不改变大小,但-O二进制格式的大小是0x10000004字节,我只关心8个字节,但objcopy-O二进制的性质必须填充中间。

由于项目和链接器脚本的大小和空间各不相同,因此无法对elf文件的大小和-O二进制文件的大小进行通用语句。

ls -al so.elf
-rwxrwxr-x 1 oldtimer oldtimer 131556 Oct 12 16:49 so.elf
arm-none-eabi-strip so.elf
ls -al so.elf
-rwxrwxr-x 1 oldtimer oldtimer 131336 Oct 12 16:50 so.elf
arm-none-eabi-as -g so.s -o so.o
ls -al so.o
-rw-rw-r-- 1 oldtimer oldtimer 1300 Oct 12 16:51 so.o
arm-none-eabi-ld -T so.ld so.o -o so.elf
ls -al so.elf
-rwxrwxr-x 1 oldtimer oldtimer 132088 Oct 12 16:51 so.elf
arm-none-eabi-strip so.elf
ls -al so.elf
-rwxrwxr-x 1 oldtimer oldtimer 131336 Oct 12 16:52 so.elf

elf二进制文件格式对内容没有绝对的规则,文件的使用者可以有规则来决定你必须把什么放在哪里,如果必须有任何特定的物品名称,等等。这是一种有点开放的文件格式,它是一个像纸箱一样的容器,你可以在某种程度上随心所欲地填充它。你不能在里面放一艘游轮,但你可以放书或玩具,有时你可以选择如何把书或玩具放进去。

Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .text             PROGBITS        00000000 010000 000004 00  AX  0   0  4
[ 2] .data             PROGBITS        10000000 020000 000004 00  WA  0   0  1
[ 3] .ARM.attributes   ARM_ATTRIBUTES  00000000 020004 000012 00      0   0  1
[ 4] .shstrtab         STRTAB          00000000 020016 000027 00      0   0  1

即使在剥离之后,仍然有额外的东西,如果你研究文件格式,你会有一个标题,相对较小的程序标题和节标题的数量,然后是那么多程序标题和那么多节标题。根据文件的使用者,例如,在这种情况下,您可能只需要主标题和两个程序标题,也就是说,一个小得多的文件(正如您在文件的对象版本中看到的那样(。

arm-none-eabi-as so.s -o so.o
ls -al so.o
-rw-rw-r-- 1 oldtimer oldtimer 560 Oct 12 16:57 so.o
arm-none-eabi-strip so.o
ls -al so.o
-rw-rw-r-- 1 oldtimer oldtimer 364 Oct 12 16:57 so.o

准备

Size of this header:               52 (bytes)
Size of program headers:           0 (bytes)
Number of program headers:         0
Size of section headers:           40 (bytes)
Number of section headers:         6
Section Headers:
[Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
[ 0]                   NULL            00000000 000000 000000 00      0   0  0
[ 1] .text             PROGBITS        00000000 000034 000004 00  AX  0   0  4
[ 2] .data             PROGBITS        00000000 000038 000004 00  WA  0   0  1
[ 3] .bss              NOBITS          00000000 00003c 000000 00  WA  0   0  1
[ 4] .ARM.attributes   ARM_ATTRIBUTES  00000000 00003c 000012 00      0   0  1
[ 5] .shstrtab         STRTAB          00000000 00004e 00002c 00      0   0  1

我们不需要的额外节头,可能可以在链接器脚本中删除。但我想对于一些消费者来说,你只需要两个程序头

Size of this header:               52 (bytes)
Size of program headers:           32 (bytes)
Number of program headers:         2

加上此文件格式的8个字节和任何填充。

另请注意

arm-none-eabi-objcopy --only-section=.text -O binary so.elf text.bin
arm-none-eabi-objcopy --only-section=.data -O binary so.elf data.bin
ls -al text.bin
-rwxrwxr-x 1 oldtimer oldtimer 4 Oct 12 17:03 text.bin
ls -al data.bin
-rwxrwxr-x 1 oldtimer oldtimer 4 Oct 12 17:03 data.bin
hexdump -C text.bin
00000000  fe ff ff ea                                       |....|
00000004
hexdump -C data.bin
00000000  78 56 34 12                                       |xV4.|
00000004