2

我想知道如何得到这个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”格式的哪些小部分(部分)进入了“berkeley”格式的哪些大部分(text、、databss部分)?

我试图通过查看什么总和来猜测这里。

换句话说,我想知道:

  • ? + ? + ? = 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-动态
4

1 回答 1

1

这是答案:

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/lsor size -x /bin/ls(同样的,因为 berkeley 是默认格式):

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

这是十六进制的 sysv 大小输出,通过以下方式获得size -x --format=sysv /bin/ls

$ 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,您将得到以下内容,其中显示了目标文件可执行文件中的所有输出部分。这些输出部分与命令的输出相匹配,但具有更详细的信息,例如 VMA(虚拟内存地址)和 LMA(加载内存地址)等:/bin/ls size -x --format=sysv /bin/ls

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

谷歌搜索“vma 和 lma 含义”将我带到这个站点ld,它有一个有用的 GNU链接器手册引用。搜索该引文将我引至此处,该引文的来源很方便。所以让我们直接从它的原始来源引用引用:

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

您可以使用带有“-h”选项的 objdump 程序查看目标文件中的部分。

(来源:GNU 链接器脚本ld手册

这意味着任何objdump -h没有 VMA 的输出部分都不是程序的一部分。这消除了该.gnu_debuglink部分。

接下来,我们可以看到该.bss部分与 berkeley 部分具有完全相同的大小 (0x12e0) bss,因此这是匹配的:

.bss = bss

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

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

而且,text包含所有程序代码和常量(只读)静态和全局变量的输出部分呢?

好吧,通过逻辑推论和分析,并利用我关于哪些部分进入闪存、RAM 和微控制器上的先验知识,我确定了输出部分中标记的所有READONLYobjdump -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伯克利大小输出中显示的部分的大小。

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

因此,标记为DATANOT的其余部分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 单片机:

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

在此处输入图像描述

主要参考资料:

  1. GNU Linker ( 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-动态
于 2020-09-26T17:43:48.337 回答