您的位置:首页 > 大数据 > 人工智能

text, data and bss: Code and Data Size Explained

2016-11-03 13:53 330 查看
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:
   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’?

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


text

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

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:
 *(.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

then this adds to ‘text’ too. That variable ‘table’ will be in FLASH, initialized with the values specified in the source.

Another thing which is included in ‘text’ is the interrupt vector table (more on this later).

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


data

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

Adding above variable to my application will increase the ‘data’ portion by 4 bytes:
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()
:





ARM Startup Code Initializing Variables

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.


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


bss

The ‘bss’ contains all the uninitalized data.

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

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

Adding this variable will increase the ‘bss’ portion by 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.


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


Size – GNU Utility

The size (or
printsize) GNU utility has more options:
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:





GNU Print Size Option in CodeWarrior for MCU10.3

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

To illustrate this, I use

While in ‘Berkeley’ mode I get:
   text       data        bss        dec        hex    filename
 0x140c       0x2c      0x81c       7252       1c54    size.elf


I get this in ‘System V’ mode:
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.

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

.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’.

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

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

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           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!


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:

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

‘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.

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

Happy Sizing
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编程