In this lesson, you will learn how to leverage linker script directives to strip away unnecessary bloat and tighten your memory footprint, ensuring every byte of your Flash is put to productive use.
When you compile a C project, the linker often includes every function and variable present in your object files, even if your main application never actually calls them. In constrained embedded systems, this "dead code" wastes precious Flash memory. To optimize for code density, we must change how the linker treats these sections.
Pruning Unused Code
The first step is to tell the compiler and linker to be aggressive. You should use the compiler flags -ffunction-sections and -fdata-sections. These flags place every function and data item into its own unique section (e.g., .text.my_function instead of just one big .text section).
Once the code is broken into these individual pieces, you use the --gc-sections linker flag. This command instructs the linker to perform "Garbage Collection": it starts at your entry point (usually Reset_Handler) and follows the call tree. Anything it cannot reach is discarded, effectively pruning unused code.
Consolidating Memory Regions
Beyond removing dead code, you can improve density by consolidating fragmented memory. If you have several small, scattered memory regions defined in your MEMORY command, your code might end up with "holes"—gaps of unused space between sections.
You can combine these by using the > FLASH command in your linker script to group related sections together:
SECTIONS {
.text : {
*(.text.startup)
*(.text)
*(.rodata)
} > FLASH
}
By grouping your .text (code) and .rodata (constants) into a single contiguous block, you ensure that the linker fills the physical address space sequentially. This eliminates internal fragmentation and makes the most of your available memory capacity. By removing unreachable code and packing the remainder tightly, you free up space for more application features or larger data buffers.
Key Takeaway: By using -ffunction-sections with --gc-sections and ensuring contiguous section placement, you eliminate dead weight and reclaim fragmented memory for your application.