Where is the definition of "_stack_size" used in linker script?

Go To Last Post
6 posts / 0 new
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I'm trying to fully understand the building process, and so far I'm stuck on understanding where and how the stack size is defined by (or for) the linker script. I've done my homework and searched the forums, and google, without finding any concrete answer, so I could use a bit of help here.


My MCU is an AT32UC3C1512C, and I'm using Atmel Studio 7.0.790.


The linker script (located at C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\avr32\lib\ldscripts\avr32elf_uc3c1512c.x) does NOT define the symbol "_stack_size", it only uses it in these lines:

__heap_start__ = ALIGN(8);
. = ORIGIN(CPUSRAM) + LENGTH(CPUSRAM) - _stack_size;
__heap_end__ = .;
.stack         ORIGIN(CPUSRAM) + LENGTH(CPUSRAM) - _stack_size :
    _stack = .;
    . = _stack_size;
    _estack = .;

Clearly, the first lines are defining the start and the end area for the HEAP of the program; meanwhile, the second set of lines are defining the .stack section, which starts at (SRAM_SIZE - STACK_SIZE). So where does that "_stack_size" symbol come from?


I've done an inside-files search on the whole folder of the linker scripts (C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32) for the text "_stack_size", and although most linker scripts make the same use of this variable, they don't define it. Similarly, I've searched inside all files of my project directory without results, which means that it is not a value set as some type of linker flag as part of the project properties.


Funny thing is, opening the project.MAP file, this is found:

Memory Configuration

Name                  Origin      Length      Attributes
FLASH                 0x80000000  0x00080000  axrl !w
CPUSRAM               0x00000004  0x0000fffc  axw !rl
USERPAGE              0x80800000  0x00000200
FACTORYPAGE           0x80800200  0x00000200
FLASHVAULT_FLASH_SIZE 0x80800400  0x00000008  r
FLASHVAULT_RAM_SIZE   0x80800408  0x00000008  r
*default*             0x00000000  0xffffffff

Linker script and memory map
0x00001000    _stack_size = 0x1000

So SOMETHING must be telling the linker to define "_stack_size" with the value 0x1000 (ie. a stack of 4096 bytes)...

This topic has a solution.
Last Edited: Wed. Aug 10, 2016 - 04:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr32-ld.exe ... --defsym=_stack_size=$(STACK_SIZE)


[Edit] As far as I know the Makefile is generated dynamically by the Studio.




Last Edited: Mon. Aug 8, 2016 - 06:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not really; as I said, I did a "search in files" to the word "_stack_size" (and also "stack_size") would have appeared as a result if it was present in any of the build files (so well, I didn't explicitly say that the search was done after building the project, but it was).


These are the relevant parts of the linkage procedure in the automatically generated Makefile; as you'll see, no mention to the stack configuration:

OUTPUT_FILE_PATH += my_program.elf
OUTPUT_FILE_PATH_AS_ARGS += my_program.elf
OBJS += (All *.o files)
OBJS_AS_ARGS += (All *.o files)
OUTPUT_FILE_DEP := ./makedep.mk


    @echo Building target: $@
    @echo Invoking: AVR32/GNU Linker : 4.4.7
    $(QUOTE)C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\bin\avr32-gcc.exe$(QUOTE) \
        -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS) -nostartfiles -Wl,-Map="my_program.map" \
        -Wl,--start-group -lm  -Wl,--end-group -Wl,--gc-sections --rodata-writable -Wl,--direct-data -mpart=uc3c1512c \
        -Wl,--relax -Wl,-e,_trampoline  
    @echo Finished building target: $@
    "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\bin\avr32-objcopy.exe" -O ihex \
        -R .eeprom -R .fuse -R .lock -R .signature "my_program.elf" "my_program.hex"
    "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\bin\avr32-objcopy.exe" -j .eeprom \
        --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex \
        "my_program.elf" "my_program.eep" || exit 0
    "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\bin\avr32-objdump.exe" \
        -h -S "my_program.elf" > "my_program.lss"
    "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\bin\avr32-objcopy.exe" \
        -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "my_program.elf" "my_program.srec"
    "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr32\avr32-gnu-toolchain\bin\avr32-size.exe" "my_program.elf"


  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From what I can determine it is a default in the AVR32 linker.
Do a avr32-ld --help and there is an --stack keyword that changes the final stack size.
You can pass -Wl,--stack=nnnn to the linker via 'Toolchain -> AVR32/Gnu linker -> miscellaneous -> other options'

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's partly unrelated, but I want to advise you to have a look at "pandafruits".

He/She made a tutorial to get going with GCC for ARM processors and has made a very good & compact tutorial which also handles linker scripts.

If nothing else, it will give you an idea on the similarities & differences for GCC on another processor.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for given pointers, I got the correct direction where to keep investigating:


You are right, turns out that it is a value hardcoded in the GNU Linker binary.


From the "32-bit AVR UC3 Tools" page on the Atmel website, it's possible to download the source code for their version of GNU Binutils, the package which includes the GNU Linker:


The GNU Linker source code is separated in several modules called "emulations", which implement the peculiarities of each different platform. This is the file for the AVR32: "binutils-2.23.1\ld\emultempl\avr32elf.em".
And inside, the relevant parts of this file show how the symbol "_stack_size" gets defined with a default value:

static int stack_size = 0x1000;
static void avr32_elf_set_symbols (void)
    /* Glue the assignments into the abs section. */
    lang_statement_list_type *save = stat_ptr;
    stat_ptr = &(abs_output_section->children);
    lang_add_assignment (exp_assign ("_stack_size", exp_intop (stack_size), FALSE));
    stat_ptr = save;


As explained by mikech, it is possible to override this value, by using the option "-Wl,--stack=N" on the GCC command line. Eg. for 8KB of stack:

    - Open the project properties
    - Go to Toolchain -> AVR32/GNU Linker -> Miscellaneous
    - Add in Linker Flags: -Wl,--stack=8192


With this option enabled, "_stack_size" is defined as seen in the project.MAP memory map file:

Linker script and memory map
    0x00002000  _stack_size = 0x2000