text, data and bss: 代碼和數據的所佔空間詳解

本文原文:https://mcuoneclipse.com/2013/04/14/text-data-and-bss-code-and-data-size-explained/html

 

In 「Code Size Information with gcc for ARM/Kinetis」 I use an option in the ARM gcc tool chain for Eclipse to show me the code size:數組

在「在ARM/Kinetis項目中用GCC編譯器輸出代碼佔用空間信息」一文中我用了一個用於Eclipse的ARM gcc工具鏈選項來輸出顯示代碼大小:app

   text       data        bss        dec        hex    filename
 0x1408       0x18      0x81c       7228       1c3c    size.elf

I have been asked by a reader of this blog what these item numbers really mean. Especially: what the heck is ‘bss’???? eclipse

一個讀者在這篇博客上問我這些字段的數值的真正含義, 特別是'bss'字段。ide

Note: I’m using the ARM GNU ‘printsize’ utility for gcc, with an example for Kinetis-L (KL25Z).wordpress

注:我用來輸出這些代碼空間信息工具是ARM GNU 'printsize',而且以Kinetis-L (KL25Z)做爲示例。函數

 

text

text段工具

‘text’ is what ends up in FLASH memory. I can show this with addingthis

text段最終是存放在FLASH存儲器中的。經過增長以下代碼到程序中:lua

void foo(void) {

  /* dummy function to show how this adds to 'text' */

}


接着text段的大小增加以下:

to my program, the ‘text’ part increases so:

   text       data        bss
 0x1414       0x18      0x81c

Likewise, my new function ‘foo’ gets added to the .text segment, as I can see in the map file generated by the linker:

一樣的,在連接器產生的map文件裏也能看到我新增長的函數foo添加至text段。

 *(.text*)
 .text.foo      0x000008c8        0x8 ./Sources/main_c.o
                0x000008c8                foo

But it does not only contain functions, it has constant data as too. If I have a constant table like

但text段不只包含函數,還有常量。例如我有以下的一個常量表:

const int table[] = {5,0,1,5,6,7,9,10};


Another thing which is included in ‘text’ is the interrupt vector table (more on this later).then this adds to ‘text’ too. That variable ‘table’ will be in FLASH, initialized with the values specified in the source.

還有同樣包含在text段裏的東西是中斷向量表(後續詳細說明),所以這也被計算到text段。變量table也會放在FLASH中,並以源碼中的數據初始化。

In summary: ‘text’ is what ends up typically in FLASH and has code and constant data.

小結:text段最終存放在FLASH裏而,所包含的內容是代碼和常量。

data

data段

‘data’ is used for initialized data. This is best explained with the following (global/extern) variable:

data段是用於初始化數據。用以下的變量(全局/外部)能夠解釋得很清楚:

int32_t myVar = 0x12345678;

Adding above variable to my application will increase the ‘data’ portion by 4 bytes:

加入上述變量會致使個人應用的data部分增加四個字節:

text       data        bss
 0x1414     0x1c      0x81c

This variable ‘myVar’ is not constant, so it will end up in RAM. But the initialization (0x12345678) *is* constant, and can live in FLASH memory. The initialization of the variable is done during the normal ANSI startup code. The code will assign/copy the initialization value. This is sometimes named ‘copy-down’. For the startup code used by CodeWarrior for MCU10.3 for Kinetis-L (ARM Cortex-M0+), this is performed in __copy_rom_sections_to_ram():

變量myVar不是常量,因此最終會存放於RAM內。可是初始值(0x12345678)是一個常量,所以能夠放在FLASH裏。這個變量的初始化在常規的ANSI啓動代碼中完成。有時這叫作「原樣複製」。對用於Kinetics-L (ARM Cortex-M0+)的CodeWarrior的MCU10.3版本所用的啓動代碼而言,這種操做在__copy_rom_sections_to_ram()中進行。

ARM Startup Code Initializing Variables

ARM啓動代碼中對於變量的初始化

Just one thing to consider: my variable ‘myVar’ will use space in RAM (4 bytes in my case), *plus* space in FLASH/ROM for the initialization value (0x12345678). So I need to count the ‘data’ size twice: that size will end up in RAM, plus will occupy FLASH/ROM. That amount of data in FLASH is *not* counted in the text portion.

還有一件事情須要考慮:變量myVar將佔用RAM的空間(本例中佔4個字節),還需累加在FLASH/ROM中初始值(0x12345678)所佔用的空間。因此我須要計算data的段的大小兩次:即RAM中佔的加上FLASH/ROM中佔的。並且FLASH中所佔的部分並不會計入text部分。

The ‘data’ only has the initialization data (in my example 0x12345678. And not the variable (myVar).

data段僅包含初始化所用的數據(本例中的0x12345678),而且不含變量(myVar)。

 

bss

bss段

The ‘bss’ contains all the uninitalized data.

bss段包含着全部未初始化的數據。

bss (or .bss, or BSS) is the abbreviation for ‘Block Started by Symbol’ by an old assembler (see this link).

bss(.bss, BSS ) 是舊式彙編器中‘Block Started by Symbol’的簡稱(詳情參看 link)。

This is best explained with following (global/extern) variable:

用以下的變量(全局/外部)能夠解釋得很清楚:

int32_t myGlobal;

Adding this variable will increase the ‘bss’ portion by 4:

加入上述變量會致使bss部分增加4個字節:

text       data        bss
 0x1414     0x18      0x820

I like to remember ‘bss’ as ‘Better Save Space’ :-). As bss ends up in RAM, and RAM is very valuable for a microcontroller, I want to keep the amount of variables which end up in the .bss at the absolute minimum.

我喜歡把bss看成‘Better Save Space’(最好節省空間)的簡稱。由於bss最終存放在RAM內,並且RAM對於單片機來說是一種寶貴的資源,因此我會令存放在bss中的變量數量儘量的少。

The bss segment is initialized in the startup code by the zero_fill_bss() function:

啓動代碼中調用zero_fill_bss()函數初始化bss段:

static void zero_fill_bss(void)

{

    extern char __START_BSS[];

    extern char __END_BSS[];



    memset(__START_BSS, 0, (__END_BSS - __START_BSS));

}

 

dec

dec段

The ‘dec’ (as a decimal number) is the sum of text, data and bss:

dec(decimal的縮寫,即十進制數)是text,data和bss的算術和。

dec = text + data + bss

Size – GNU Utility

Size —— GNU工具

The size (or printsize) GNU utility has more options:

GNU工具 size ( printsize)有許多選項:

size [-A|-B|--format=compatibility]
          [--help]
          [-d|-o|-x|--radix=number]
          [--common]
          [-t|--totals]
          [--target=bfdname] [-V|--version]
          [objfile...]

The ‘System V’ option can be set directly in the Eclipse panel:

‘System V'選項能直接在Eclipse中設置:

GNU Print Size Option in CodeWarrior for MCU10.3

GNU Print Size Option in CodeWarrior for MCU10.3

CodeWarrior MCU10.3版中GNU Print Size的選項界面

It produces similar information as shown above, but with greater detail.

這將會輸出和上面差很少的代碼尺寸信息,可是會更詳細。

To illustrate this, I use

爲了解釋這點,我用以下數組變量作示例:

int table[] = {1,2,3,4,5};

While in ‘Berkeley’ mode I get:

當選擇‘Berkeley’模式時輸出以下:

   text       data        bss        dec        hex    filename
 0x140c       0x2c      0x81c       7252       1c54    size.elf

當選擇’System V’模式時輸出以下:

section                size         addr
.interrupts            0xc0          0x0
.text                0x134c        0x800
.data                  0x14   0x1ffff000
.bss                   0x1c   0x1ffff014
.romp                  0x18   0x1ffff030
._user_heap_stack     0x800   0x1ffff048
.ARM.attributes        0x31          0x0
.debug_info          0x2293          0x0
.debug_abbrev         0xe66          0x0
.debug_loc           0x27df          0x0
.debug_aranges        0x318          0x0
.debug_macinfo      0x53bf3          0x0
.debug_line          0x1866          0x0
.debug_str            0xc23          0x0
.comment               0x79          0x0
.debug_frame          0x594          0x0
Total               0x5defe

I’m using an ARM Cortex-M0+ in my example, so addresses greater 0x1ffff000 are in RAM.

例子中我用的是ARM Cortex-M0+內核,故在RAM中的地址從0x1ffff000開始。

The lines from .ARM.attributes up to .debug_frame are not ending up in the target, they are debug and other information.

其中.ARM.attributes up 到 .debug_frame所列內容最終不會放在目標硬件中,這些事調試或者其餘信息。

.interrupts is my interrupt vector table, and .text is my code plus constants, and is in FLASH memory. That makes the 0xc0+0x134c=0x140c for text in ‘Berkeley’.

.interrupts其是本例的中斷向量表,.text是存放在FLASH裏的代碼和常量。故‘Berkeley’下text段的大小即爲:0xc0+0x134c=0x140c。

.bss is my uninitialized (zero-outed) variable area. Additionally there is .user_heap_stack: this is the heap defined in the ANSI library for malloc() calls. That makes the total of 0x1c+0x800=0x81c shown in ‘Berkeley’ format.

.bss是本例中未初始化(爲0)變量區域。此外還有一個.user_heap_stack:段用於預留ANSI庫中malloc()調用分配的內存。故‘Berkeley’下bss段的大小即爲:0x1c+0x800=0x81c。

.data is for my initialized ‘table[]’ variable in RAM (5*4 bytes=0x14)

.data存放了本例中存放在RAM內的初始化了的table[]變量。

The .romp is used by the linker for the ‘copy-down’ and initialization of .data. But it looks confusing: it is shown with addresses in RAM? Checking the linker map file shows:

romp是連接器用於須要‘copy-down’的data中的初始化數據。可是這看起來有點迷:這顯示的地址是RAM的地址?連接器生成的map文件說如是:

.romp           0x1ffff030       0x18 load address 0x00001b60
                0x00001b60                __S_romp = _romp_at
                0x1ffff030        0x4 LONG 0x1b4c ___ROM_AT
                0x1ffff034        0x4 LONG 0x1ffff000 _sdata
                0x1ffff038        0x4 LONG 0x14 ___data_size
                0x1ffff03c        0x4 LONG 0x0
                0x1ffff040        0x4 LONG 0x0
                0x1ffff044        0x4 LONG 0x0

Ah! That actually is not in RAM, but in FLASH: the linker maps this to the FLASH address 0x1b60! So this size 0x18 really needs to be added to the FLASH size too!

啊!實際上這並非在RAM裏,而是在FLASH裏:連接器映射這段到FLASH地址0x1b60中!故這個0x18大小的尺寸實際上也須要加到FLASH所佔空間裏去!

Summary

總結

I hope I have sorted out things in a correct way. The way how the initialized data is reported might be confusing. But with the right knowledge (and .map file in mind), things get much clearer:

我但願我把事情表達正確了。雖然初始化數據的報告信息可能挺迷的,可是經過正確的分析(腦中的 .mao文件),事情反而更清楚了。

‘text’ is my code, vector table plus constants.

text放的是是代碼,向量表及常量。

‘data’ is for initialized variables, and it counts for RAM and FLASH. The linker allocates the data in FLASH which then is copied from ROM to RAM in the startup code.

data放的是初始化的變量,且同時計入RAM和FLASH。連接器把數據分配在FLASH中而後在啓動代碼中從ROM拷貝到RAM。

‘bss’ is for the uninitialized data in RAM which is initialized with zero in the startup code.

bss放的是RAM中未初始化的變量,這些變量將在啓動代碼中填充0。

Happy Sizing 

相關文章
相關標籤/搜索