【问题标题】:Why is the objdump binary size so much larger than the actual ELF size?为什么 objdump 二进制大小比实际的 ELF 大小大得多?
【发布时间】:2022-10-13 05:06:03
【问题描述】:

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

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

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

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

【问题讨论】:

  • 查看 elf 文件中的部分。你会有类似'isr@0:4k'和'code@128M:128k'的东西。两个部分之间有一个大洞。对于二进制文件,没有空洞并且用零填充。你需要确保所有已分配部分是连续的,并且有代码将它们从加载地址复制到运行地址(还有其他可能的解释)。尝试发布精灵的objdump -h。您需要注意部分标志。它将解释原因。
  • 对于特定的 -O 二进制文件格式,一件事的大小与另一件事无关。可加载部分的数量(实际上也可能大于精灵)和 -O 二进制输出之间的巨大差异

标签: compilation linker arm cross-compiling binaryfiles


【解决方案1】:

所以.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

8 字节相对于对象的 560。

链接它。

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

现在......我们需要 0x1000 处的 4 个字节和 0x2000 处的 4 个字节,如果我们想使用 -O 二进制 objcopy,这意味着它将占用整个内存空间并以最低地址开始文件并以最高地址的东西。通过这个链接,最低的是 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 binary的性质必须要填充中间。

由于事物的大小和空间因您的项目和链接器脚本而异,因此无法针对 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-13
    • 2011-02-24
    • 2020-04-12
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 2021-07-20
    相关资源
    最近更新 更多