将binutils`size`输出从“ sysv”格式`size --format = sysv my_executable`转换为“ berkeley”格式`size --format = berkeley my_executable`

问题描述

我想知道如何获取此 berkeley 格式的输出:

$ size --format=berkeley /bin/ls
   text    data     bss     dec     hex filename
 124042    4728    4832  133602   209e2 /bin/ls

从此 sysv 格式输出:

$ size --format=sysv /bin/ls
/bin/ls  :
section                size      addr
.interp                  28       568
.note.ABI-tag            32       596
.note.gnu.build-id       36       628
.gnu.hash               236       664
.dynsym                3576       904
.dynstr                1666      4480
.gnu.version            298      6146
.gnu.version_r          112      6448
.rela.dyn              4944      6560
.rela.plt              2664     11504
.init                    23     14168
.plt                   1792     14192
.plt.got                 24     15984
.text                 74969     16016
.fini                     9     90988
.rodata               19997     91008
.eh_frame_hdr          2180    111008
.eh_frame             11456    113192
.init_array               8   2224112
.fini_array               8   2224120
.data.rel.ro           2616   2224128
.dynamic                512   2226744
.got                    968   2227256
.data                   616   2228224
.bss                   4832   2228864
.gnu_debuglink           52         0
Total                133654

换句话说,“ sysv”格式的哪一部分是小部分(textdatabss),是“伯克利”格式?

我试图通过观察总和来猜测。

换句话说,我想知道:

  • ? + ? + ? = text
  • ? + ? + ? = data
  • ? + ? + ? = bss

相关:

  1. [我的问题] https://electronics.stackexchange.com/questions/363931/how-do-i-find-out-at-compile-time-how-much-of-an-stm32s-flash-memory-and-dynami

解决方法

这是答案:

TLDR;

.interp + .note.ABI-tag + .note.gnu.build-id + .gnu.hash + .dynsym + .dynstr 
+ .gnu.version + .gnu.version_r + .rela.dyn + .rela.plt + .init + .plt 
+ .plt.got + .text + .fini + .rodata + .eh_frame_hdr + .eh_frame
= text

.init_array + .fini_array + .data.rel.ro + .dynamic + .got + .data
= data

.bss = bss

另请查看图像的末尾带有黄色,蓝色和红色框,以获取快速的视觉摘要。

详细信息:

首先,让我们用size -x --format=berkeley /bin/lssize -x /bin/ls以十六进制打印berkeley大小信息(同样,因为berkeley是默认格式):

$ size -x /bin/ls
   text    data     bss     dec     hex filename
0x1e48a  0x1278  0x12e0  133602   209e2 /bin/ls

这是用size -x --format=sysv /bin/ls获得的十六进制sysv大小输出:

$ size -x --format=sysv /bin/ls
/bin/ls  :
section                 size       addr
.interp                 0x1c      0x238
.note.ABI-tag           0x20      0x254
.note.gnu.build-id      0x24      0x274
.gnu.hash               0xec      0x298
.dynsym                0xdf8      0x388
.dynstr                0x682     0x1180
.gnu.version           0x12a     0x1802
.gnu.version_r          0x70     0x1930
.rela.dyn             0x1350     0x19a0
.rela.plt              0xa68     0x2cf0
.init                   0x17     0x3758
.plt                   0x700     0x3770
.plt.got                0x18     0x3e70
.text                0x124d9     0x3e90
.fini                    0x9    0x1636c
.rodata               0x4e1d    0x16380
.eh_frame_hdr          0x884    0x1b1a0
.eh_frame             0x2cc0    0x1ba28
.init_array              0x8   0x21eff0
.fini_array              0x8   0x21eff8
.data.rel.ro           0xa38   0x21f000
.dynamic               0x200   0x21fa38
.got                   0x3c8   0x21fc38
.data                  0x268   0x220000
.bss                  0x12e0   0x220280
.gnu_debuglink          0x34        0x0
Total                0x20a16

接下来,如果您运行objdump -h /bin/ls,则会得到以下内容,其中显示了/bin/ls 目标文件或可执行。这些输出部分与size -x --format=sysv /bin/ls命令的输出匹配,但是具有更详细的信息,例如VMA(虚拟内存地址)和LMA(加载内存地址),以及其他内容:

$ objdump -h /bin/ls

/bin/ls:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000000238  0000000000000238  00000238  2**0
                  CONTENTS,ALLOC,LOAD,READONLY,DATA
  1 .note.ABI-tag 00000020  0000000000000254  0000000000000254  00000254  2**2
                  CONTENTS,DATA
  2 .note.gnu.build-id 00000024  0000000000000274  0000000000000274  00000274  2**2
                  CONTENTS,DATA
  3 .gnu.hash     000000ec  0000000000000298  0000000000000298  00000298  2**3
                  CONTENTS,DATA
  4 .dynsym       00000df8  0000000000000388  0000000000000388  00000388  2**3
                  CONTENTS,DATA
  5 .dynstr       00000682  0000000000001180  0000000000001180  00001180  2**0
                  CONTENTS,DATA
  6 .gnu.version  0000012a  0000000000001802  0000000000001802  00001802  2**1
                  CONTENTS,DATA
  7 .gnu.version_r 00000070  0000000000001930  0000000000001930  00001930  2**3
                  CONTENTS,DATA
  8 .rela.dyn     00001350  00000000000019a0  00000000000019a0  000019a0  2**3
                  CONTENTS,DATA
  9 .rela.plt     00000a68  0000000000002cf0  0000000000002cf0  00002cf0  2**3
                  CONTENTS,DATA
 10 .init         00000017  0000000000003758  0000000000003758  00003758  2**2
                  CONTENTS,CODE
 11 .plt          00000700  0000000000003770  0000000000003770  00003770  2**4
                  CONTENTS,CODE
 12 .plt.got      00000018  0000000000003e70  0000000000003e70  00003e70  2**3
                  CONTENTS,CODE
 13 .text         000124d9  0000000000003e90  0000000000003e90  00003e90  2**4
                  CONTENTS,CODE
 14 .fini         00000009  000000000001636c  000000000001636c  0001636c  2**2
                  CONTENTS,CODE
 15 .rodata       00004e1d  0000000000016380  0000000000016380  00016380  2**5
                  CONTENTS,DATA
 16 .eh_frame_hdr 00000884  000000000001b1a0  000000000001b1a0  0001b1a0  2**2
                  CONTENTS,DATA
 17 .eh_frame     00002cc0  000000000001ba28  000000000001ba28  0001ba28  2**3
                  CONTENTS,DATA
 18 .init_array   00000008  000000000021eff0  000000000021eff0  0001eff0  2**3
                  CONTENTS,DATA
 19 .fini_array   00000008  000000000021eff8  000000000021eff8  0001eff8  2**3
                  CONTENTS,DATA
 20 .data.rel.ro  00000a38  000000000021f000  000000000021f000  0001f000  2**5
                  CONTENTS,DATA
 21 .dynamic      00000200  000000000021fa38  000000000021fa38  0001fa38  2**3
                  CONTENTS,DATA
 22 .got          000003c8  000000000021fc38  000000000021fc38  0001fc38  2**3
                  CONTENTS,DATA
 23 .data         00000268  0000000000220000  0000000000220000  00020000  2**5
                  CONTENTS,DATA
 24 .bss          000012e0  0000000000220280  0000000000220280  00020268  2**5
                  ALLOC
 25 .gnu_debuglink 00000034  0000000000000000  0000000000000000  00020268  2**2
                  CONTENTS,READONLY

一个Google search for "vma and lma meaning"带我去this site,它引自GNU ld链接器手册的有用引用。 Searching for that quote带给我here,它很方便地提供了报价来源。因此,我们直接引用其原始报价:

每个可加载或可分配的输出节都有两个地址。第一个是 VMA ,即虚拟内存地址。这是运行输出文件时该节将具有的地址。第二个是 LMA ,即加载内存地址。这是将加载该节的地址。在大多数情况下,这两个地址是相同的。当它们可能不同时,一个示例是将数据段加载到ROM中,然后在程序启动时将其复制到RAM中(此技术通常用于在基于ROM的系统中初始化全局变量)。在这种情况下,ROM地址为LMA,RAM地址为VMA。

通过将objdump程序与“ -h”选项一起使用,您可以在目标文件中查看各个部分。

(来源:GNU linker script ld manual

这意味着objdump -h所示的任何没有VMA的输出节都不是程序的一部分。这样就省去了.gnu_debuglink部分。

接下来,我们可以看到.bss部分的大小(0x12e0)与berkeley bss部分的大小完全相同,所以这是一个匹配项:

.bss = bss

bss包含零初始化的全局变量和静态变量

那么data输出节呢?该节包含所有非零初始化(即:已用一些非零值初始化)的全局变量和静态变量

>

然后,text输出部分包含所有程序代码以及常量(只读)静态和全局变量 ,该怎么办?

通过逻辑推论和分析,并使用我的prior knowledge about which sections go into Flash vs RAM vs both on microcontrollers,我确定READONLY输出节中标记为objdump -h的所有节(其中包含一些DATA(非零初始化,const(只读)静态和全局变量)和一些CODE(实际程序逻辑)(也为只读)) 存储在text输出节中。

所以:

.interp + .note.ABI-tag + .note.gnu.build-id + .gnu.hash + .dynsym + .dynstr 
+ .gnu.version + .gnu.version_r + .rela.dyn + .rela.plt + .init + .plt 
+ .plt.got + .text + .fini + .rodata + .eh_frame_hdr + .eh_frame
= text

您可以在数学上求和所有大小来确认这一点。十六进制:

1c + 20 + 24 + ec + df8 + 682 + 12a + 70 + 1350 + a68 + 17 + 700 + 18 + 124d9 + 9 + 4e1d 
+ 884 + 2cc0 = 1e48a

...这是伯克利大小输出中显示的text部分的大小。

您可以在下图中看到它们以黄色框出。

因此,标记为DATA和NOT READONLY的其余部分是data部分:

.init_array + .fini_array + .data.rel.ro + .dynamic + .got + .data
= data

同样,十六进制大小总和确认了这一点:

8 + 8 + a38 + 200 + 3c8 + 268 = 1278

...这是伯克利大小输出中data部分的大小。

您可以在下图中看到它们以蓝色框出。

在此图像中,您可以看到所有3个以不同颜色包装的berkely输出部分:

  1. berkeley格式的text输出节(只读,程序逻辑以及const静态和全局变量)以黄色框出。
  2. berkeley格式的data输出节(非零初始化(即非零初始化)的静态变量和全局变量)用蓝色框起来。
  3. berkeley格式的bss输出节(零初始化的静态变量和全局变量)用红色框出。

在查看微控制器目标文件(例如STM32 MCU)的情况下:

  1. 闪存使用量= text + data,并且
  2. 静态和全局变量的RAM内存使用量= bss + data
    1. 这意味着剩余用于堆栈(局部变量)和堆(动态内存分配)= RAM_total - (bss + data)的RAM。

enter image description here

主要参考文献:

  1. GNU链接器(ld)手册,“ 3.1基本链接器脚本概念”部分:https://sourceware.org/binutils/docs/ld/Basic-Script-Concepts.html#Basic-Script-Concepts
  2. [这里是我自己的问题] https://electronics.stackexchange.com/questions/363931/how-do-i-find-out-at-compile-time-how-much-of-an-stm32s-flash-memory-and-dynami

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...