BSS section larger than expected

As a followup question to this post, I’m trying to work out why the .bss section of my Elf file is being reported as so large. My test program is CMSIS based and is minimal - it reads a value from one of the peripherals. Yet when I use arm-none-eabi-size, it gets reported as 32K.

arm-none-eabi-size bringup.o
text    data     bss     dec     hex filename
2476    1108   31672   35256    89b8 bringup.o

Yet, if I look at the output from objdump, I get a much more realistic number:

arm-none-eabi-objdump -h bringup.o | grep bss
5 .bss          00000040  20000448  00000e00  00020448  2**2

What am I doing wrong here?

Hi @sjalloq! I split this into its own topic. Could you share your linker script? I expect this is where the issue is.

@francois Hi and thanks for this. However, I managed to track down the issue yesterday.

The linker script I’m using, the CMSIS gcc_arm.ld, seems to set the stack size correctly but the tools report it as taking up the full extent of RAM. Here’s the linker script for reference but this is just what ships with CMSIS.

/******************************************************************************
* @file     gcc_arm.ld
* @brief    GNU Linker Script for Cortex-M based device
* @version  V2.0.0
* @date     21. May 2019
******************************************************************************/
/*
* Copyright (c) 2009-2019 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
;-------- <<< Use Configuration Wizard in Context Menu >>> -------------------
*/

/*--------------------- Flash Configuration ----------------------------------
; <h> Flash Configuration
;   <o0> Flash Base Address <0x0-0xFFFFFFFF:8>
;   <o1> Flash Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
-----------------------------------------------------------------------------*/
__ROM_BASE = 0x00000000;
__ROM_SIZE = 0x00008000;

/*--------------------- Embedded RAM Configuration ---------------------------
; <h> RAM Configuration
;   <o0> RAM Base Address    <0x0-0xFFFFFFFF:8>
;   <o1> RAM Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
-----------------------------------------------------------------------------*/
__RAM_BASE = 0x20000000;
__RAM_SIZE = 0x00004000;

/*--------------------- Stack / Heap Configuration ---------------------------
; <h> Stack / Heap Configuration
;   <o0> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;   <o1> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
-----------------------------------------------------------------------------*/
__STACK_SIZE = 0x00000400;
__HEAP_SIZE  = 0x00000000;

/*
;-------------------- <<< end of configuration section >>> --------------------
*/

INCLUDE "lib-nosys.ld"

MEMORY
{
FLASH (rx)  : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE
RAM   (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE
}

/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
*   Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
*   __exidx_start
*   __exidx_end
*   __copy_table_start__
*   __copy_table_end__
*   __zero_table_start__
*   __zero_table_end__
*   __etext
*   __data_start__
*   __preinit_array_start
*   __preinit_array_end
*   __init_array_start
*   __init_array_end
*   __fini_array_start
*   __fini_array_end
*   __data_end__
*   __bss_start__
*   __bss_end__
*   __end__
*   end
*   __HeapLimit
*   __StackLimit
*   __StackTop
*   __stack
*/
ENTRY(Reset_Handler)

SECTIONS
{
	.text :
	{
		KEEP(*(.vectors))
		*(.text*)

		KEEP(*(.init))
		KEEP(*(.fini))

		/* .ctors */
		*crtbegin.o(.ctors)
		*crtbegin?.o(.ctors)
		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
		*(SORT(.ctors.*))
		*(.ctors)

		/* .dtors */
		*crtbegin.o(.dtors)
		*crtbegin?.o(.dtors)
		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
		*(SORT(.dtors.*))
		*(.dtors)

		*(.rodata*)

		KEEP(*(.eh_frame*))
	} > FLASH

/* SG veneers:
All SG veneers are placed in the special output section .gnu.sgstubs. Its start address
must be set, either with the command line option ‘--section-start’ or in a linker script,
to indicate where to place these veneers in memory.
*/
/*
	.gnu.sgstubs :
	{
		. = ALIGN(32);
	} > FLASH
*/
	.ARM.extab :
	{
		*(.ARM.extab* .gnu.linkonce.armextab.*)
	} > FLASH

	__exidx_start = .;
	.ARM.exidx :
	{
		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
	} > FLASH
	__exidx_end = .;

	.copy.table :
	{
		. = ALIGN(4);
		__copy_table_start__ = .;
		LONG (__etext)
		LONG (__data_start__)
		LONG (__data_end__ - __data_start__)
	/** Add each additional data section here */
	/*
		LONG (__etext2)
		LONG (__data2_start__)
		LONG (__data2_end__ - __data2_start__)
	*/
		__copy_table_end__ = .;
	} > FLASH

	.zero.table :
	{
		. = ALIGN(4);
		__zero_table_start__ = .;
	/** Add each additional bss section here */
	/*
	LONG (__bss2_start__)
		LONG (__bss2_end__ - __bss2_start__)
	*/
		__zero_table_end__ = .;
	} > FLASH

	/* Location counter can end up 2byte aligned with narrow Thumb code but
	__etext is assumed by startup code to be the LMA of a section in RAM
	which must be 4byte aligned */
	__etext = ALIGN (4);

	.data : AT (__etext)
	{
		__data_start__ = .;
		*(vtable)
		*(.data)
	*(.data.*)

		. = ALIGN(4);
		/* preinit data */
		PROVIDE_HIDDEN (__preinit_array_start = .);
		KEEP(*(.preinit_array))
		PROVIDE_HIDDEN (__preinit_array_end = .);

		. = ALIGN(4);
		/* init data */
		PROVIDE_HIDDEN (__init_array_start = .);
		KEEP(*(SORT(.init_array.*)))
		KEEP(*(.init_array))
		PROVIDE_HIDDEN (__init_array_end = .);


		. = ALIGN(4);
		/* finit data */
		PROVIDE_HIDDEN (__fini_array_start = .);
		KEEP(*(SORT(.fini_array.*)))
		KEEP(*(.fini_array))
		PROVIDE_HIDDEN (__fini_array_end = .);

		KEEP(*(.jcr*))
		. = ALIGN(4);
		/* All data end */
		__data_end__ = .;

	} > RAM

/**
* Secondary data section, optional
*
* Remember to add each additional data section
* to the .copy.table above to asure proper
* initialization during startup.
*/
/*
__etext2 = ALIGN (4);

	.data2 : AT (__etext2)
	{
	. = ALIGN(4);
		__data2_start__ = .;
	*(.data2)
	*(.data2.*)
		. = ALIGN(4);
		__data2_end__ = .;

	} > RAM
*/

	.bss :
	{
		. = ALIGN(4);
		__bss_start__ = .;
	*(.bss)
		*(.bss.*)
		*(COMMON)
		. = ALIGN(4);
		__bss_end__ = .;
	} > RAM

/**
* Secondary bss section, optional
*
* Remember to add each additional bss section
* to the .zero.table above to asure proper
* initialization during startup.
*/
/*
	.bss2 :
	{
		. = ALIGN(4);
		__bss2_start__ = .;
	*(.bss2)
		*(.bss2.*)
		. = ALIGN(4);
		__bss2_end__ = .;
	} > RAM2
*/

	.heap :
	{
	. = ALIGN(4);
		__end__ = .;
		PROVIDE(end = .);
		. = . + __HEAP_SIZE;
	. = ALIGN(4);
		__HeapLimit = .;
	} > RAM

	.stack :
	{
	. = ORIGIN(RAM) + LENGTH(RAM) - __STACK_SIZE;
	. = ALIGN(4);
	__StackLimit = .;
	. = . + __STACK_SIZE;
	. = ALIGN(4);
	__StackTop = .;
	} > RAM
	PROVIDE(__stack = __StackTop);

	/* Check if data + heap + stack exceeds RAM limit */
	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}

The output from bloaty follows:

FILE SIZE        VM SIZE    
--------------  -------------- 
60.1%   110Ki   0.0%       0    [Unmapped]
 9.3%  17.1Ki  51.6%  17.1Ki    .text
 9.0%  16.5Ki   0.0%       0    .debug_loc
 0.0%       0  47.9%  15.9Ki    .stack
 6.7%  12.4Ki   0.0%       0    .debug_info
 5.3%  9.76Ki   0.0%       0    .debug_line
 2.8%  5.13Ki   0.0%       0    .symtab
 1.8%  3.25Ki   0.0%       0    .debug_abbrev
 1.6%  2.91Ki   0.0%       0    .strtab
 1.1%  1.95Ki   0.0%       0    .debug_str
 1.0%  1.92Ki   0.0%       0    .debug_frame
 0.7%  1.29Ki   0.0%       0    .debug_ranges
 0.2%     296   0.0%       0    .debug_aranges
 0.1%     268   0.0%       0    [ELF Headers]
 0.1%     262   0.0%       0    .shstrtab
 0.1%     160   0.0%       0    .ARM.attributes
 0.1%     156   0.3%     116    .data
 0.1%     116   0.0%       0    .comment
 0.0%      52   0.0%      12    .copy.table
 0.0%      48   0.0%       8    .ARM.exidx
 0.0%       0   0.1%      28    [1 Others]
100.0%   184Ki 100.0%  33.1Ki    TOTAL

Glad to hear you tracked it down!