Agent Skills: Linker Script Skill

GNU linker script generation and optimization for embedded systems. Expert skill for memory layout definition, section placement, multi-image linking, and memory protection configuration.

UncategorizedID: a5c-ai/babysitter/linker-script

Install this agent skill to your local

pnpm dlx add-skill https://github.com/a5c-ai/babysitter/tree/HEAD/plugins/babysitter/skills/babysit/process/specializations/embedded-systems/skills/linker-script

Skill Files

Browse the full folder contents for linker-script.

Download Skill

Loading file tree…

plugins/babysitter/skills/babysit/process/specializations/embedded-systems/skills/linker-script/SKILL.md

Skill Metadata

Name
linker-script
Description
GNU linker script generation and optimization for embedded systems. Expert skill for memory layout definition, section placement, multi-image linking, and memory protection configuration.

Linker Script Skill

Expert skill for GNU linker script generation and optimization for embedded systems. Provides deep expertise in memory layout definition, section placement, symbol management, and advanced linking scenarios.

Overview

The Linker Script skill enables comprehensive linker script development for embedded systems, supporting:

  • Memory region definition for MCU targets
  • Section placement and alignment configuration
  • Symbol generation for bootloader/application interfaces
  • Multi-image linking (bootloader + application)
  • Overlay and bank switching support
  • Custom section creation and management
  • Fill pattern and checksum placement
  • MPU-aligned region configuration

Capabilities

1. Memory Region Definition

Define memory regions based on MCU specifications:

/* Example: STM32F407 Memory Layout */
MEMORY
{
  /* Flash memory regions */
  FLASH_BOOT (rx)  : ORIGIN = 0x08000000, LENGTH = 32K   /* Bootloader */
  FLASH_APP  (rx)  : ORIGIN = 0x08008000, LENGTH = 480K  /* Application */
  FLASH_DATA (r)   : ORIGIN = 0x08080000, LENGTH = 128K  /* Config/OTA */

  /* RAM regions */
  RAM        (rwx) : ORIGIN = 0x20000000, LENGTH = 128K  /* Main SRAM */
  CCMRAM     (rwx) : ORIGIN = 0x10000000, LENGTH = 64K   /* Core-coupled RAM */
  BKPSRAM    (rw)  : ORIGIN = 0x40024000, LENGTH = 4K    /* Backup SRAM */
}

2. Section Placement Configuration

Configure section placement with alignment requirements:

SECTIONS
{
  /* Vector table at flash start */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector))
    . = ALIGN(4);
  } > FLASH_APP

  /* Code sections */
  .text :
  {
    . = ALIGN(4);
    *(.text)
    *(.text*)
    *(.glue_7)         /* ARM/Thumb interworking */
    *(.glue_7t)
    *(.eh_frame)

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

    . = ALIGN(4);
    _etext = .;
  } > FLASH_APP

  /* Read-only data */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)
    *(.rodata*)
    . = ALIGN(4);
  } > FLASH_APP
}

3. Symbol Generation

Generate symbols for firmware interfaces:

/* Symbols for bootloader/application interface */
PROVIDE(_app_start = ORIGIN(FLASH_APP));
PROVIDE(_app_end = ORIGIN(FLASH_APP) + LENGTH(FLASH_APP));
PROVIDE(_app_checksum = _app_end - 4);

/* Stack and heap boundaries */
PROVIDE(_estack = ORIGIN(RAM) + LENGTH(RAM));
PROVIDE(_Min_Heap_Size = 0x2000);  /* 8KB heap */
PROVIDE(_Min_Stack_Size = 0x1000); /* 4KB stack */

/* RAM function execution */
PROVIDE(_siramfunc = LOADADDR(.ramfunc));
PROVIDE(_sramfunc = ADDR(.ramfunc));
PROVIDE(_eramfunc = ADDR(.ramfunc) + SIZEOF(.ramfunc));

4. Multi-Image Linking

Support bootloader and application as separate images:

/* Bootloader linker script excerpt */
MEMORY
{
  FLASH_BOOT (rx) : ORIGIN = 0x08000000, LENGTH = 32K
  RAM (rwx)       : ORIGIN = 0x20000000, LENGTH = 128K
}

/* Shared data region for boot-to-app communication */
.shared_data (NOLOAD) :
{
  . = ALIGN(4);
  _shared_data_start = .;
  KEEP(*(.shared_data))
  . = ALIGN(4);
  _shared_data_end = .;
} > RAM

/* Application header location (known to bootloader) */
_app_header_addr = 0x08008000;

5. MPU Region Configuration

Define MPU-aligned memory regions:

/* MPU-aligned regions (power of 2 sizes, aligned to size) */
.mpu_region_stack (NOLOAD) :
{
  . = ALIGN(1024);  /* MPU minimum region size */
  _mpu_stack_start = .;
  . = . + 4096;     /* 4KB stack region */
  _mpu_stack_end = .;
} > RAM

.mpu_region_heap (NOLOAD) :
{
  . = ALIGN(8192);  /* 8KB aligned */
  _mpu_heap_start = .;
  . = . + 8192;
  _mpu_heap_end = .;
} > RAM

6. Overlay Support

Configure overlay sections for memory-constrained systems:

OVERLAY : NOCROSSREFS
{
  .overlay_a { *(.overlay_a) }
  .overlay_b { *(.overlay_b) }
  .overlay_c { *(.overlay_c) }
} > RAM AT > FLASH_APP

/* Overlay management symbols */
_overlay_a_load = LOADADDR(.overlay_a);
_overlay_b_load = LOADADDR(.overlay_b);
_overlay_c_load = LOADADDR(.overlay_c);

7. Checksum Placement

Configure checksum/CRC placement for firmware validation:

/* Reserved space for firmware checksum */
.checksum :
{
  . = ALIGN(4);
  _firmware_checksum = .;
  LONG(0xFFFFFFFF);  /* Placeholder, filled post-build */
  . = ALIGN(4);
} > FLASH_APP

/* Image length for checksum calculation */
_firmware_length = _firmware_checksum - ORIGIN(FLASH_APP);

Process Integration

This skill integrates with the following processes:

| Process | Integration Point | |---------|-------------------| | memory-architecture-planning.js | Memory map design and validation | | bootloader-implementation.js | Boot/app interface definition | | bsp-development.js | BSP memory configuration | | code-size-optimization.js | Section optimization analysis |

Workflow

1. Gather MCU Specifications

# Extract memory map from datasheet or reference manual
# Key information needed:
# - Flash base address and size
# - RAM regions (main SRAM, CCMRAM, backup SRAM)
# - Peripheral memory regions
# - MPU region requirements

2. Define Memory Requirements

## Memory Requirements Analysis

| Component | Flash | RAM | Notes |
|-----------|-------|-----|-------|
| Bootloader | 32K | 8K | Fixed location |
| Application | 480K | 96K | Main firmware |
| Config data | 8K | - | Non-volatile settings |
| OTA staging | 120K | - | A/B update support |

Total Flash: 640K / 1024K (62.5% utilized)
Total RAM: 104K / 128K (81.3% utilized)

3. Generate Linker Script

The skill generates a complete linker script based on requirements:

# Output files:
# - memory.ld       - Memory region definitions (included by main)
# - sections.ld     - Section definitions (included by main)
# - application.ld  - Main application linker script
# - bootloader.ld   - Bootloader linker script (if needed)

4. Validate Memory Usage

# Analyze binary size
arm-none-eabi-size firmware.elf

# Detailed map file analysis
arm-none-eabi-nm -S --size-sort firmware.elf

# Generate memory usage report
python scripts/analyze_map.py build/firmware.map

Output Schema

{
  "linkerScript": {
    "mainScript": "application.ld",
    "includes": ["memory.ld", "sections.ld"],
    "bootloaderScript": "bootloader.ld"
  },
  "memoryMap": {
    "flash": {
      "total": 1048576,
      "regions": [
        { "name": "FLASH_BOOT", "origin": "0x08000000", "length": 32768 },
        { "name": "FLASH_APP", "origin": "0x08008000", "length": 491520 }
      ]
    },
    "ram": {
      "total": 131072,
      "regions": [
        { "name": "RAM", "origin": "0x20000000", "length": 131072 }
      ]
    }
  },
  "symbols": {
    "exportedToBootloader": ["_app_start", "_app_end", "_app_checksum"],
    "importedFromBootloader": ["_shared_data"],
    "stackHeap": ["_estack", "_Min_Heap_Size", "_Min_Stack_Size"]
  },
  "validation": {
    "flashUtilization": 0.625,
    "ramUtilization": 0.813,
    "mpuCompatible": true,
    "warnings": []
  },
  "artifacts": [
    "application.ld",
    "bootloader.ld",
    "memory.ld",
    "sections.ld",
    "memory-map.md"
  ]
}

Common Patterns

RAM Functions (Execute from RAM)

/* Functions copied to RAM for execution (e.g., flash programming) */
.ramfunc :
{
  . = ALIGN(4);
  _sramfunc = .;
  *(.ramfunc)
  *(.ramfunc*)
  . = ALIGN(4);
  _eramfunc = .;
} > RAM AT > FLASH_APP

_siramfunc = LOADADDR(.ramfunc);

Initialized Data (.data section)

.data :
{
  . = ALIGN(4);
  _sdata = .;
  *(.data)
  *(.data*)
  . = ALIGN(4);
  _edata = .;
} > RAM AT > FLASH_APP

_sidata = LOADADDR(.data);

Zero-Initialized Data (.bss section)

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

Stack and Heap

/* User heap and stack */
._user_heap_stack (NOLOAD) :
{
  . = ALIGN(8);
  PROVIDE(end = .);
  PROVIDE(_end = .);
  . = . + _Min_Heap_Size;
  . = . + _Min_Stack_Size;
  . = ALIGN(8);
} > RAM

/* Verify sufficient space */
ASSERT((_estack - _ebss) >= (_Min_Heap_Size + _Min_Stack_Size),
       "Insufficient RAM for heap and stack")

Best Practices

Memory Alignment

  • Align vector table to power of 2 (typically 256 or 512 bytes)
  • Align code sections to 4 bytes for ARM
  • Align MPU regions to their size (power of 2)
  • Align DMA buffers to cache line size

Section Organization

  • Keep interrupt vector table at fixed location
  • Place frequently executed code in faster memory
  • Group related functions to minimize cache misses
  • Use KEEP() for sections that might be garbage collected

Safety

  • Add ASSERT statements to catch memory overflow
  • Define symbols for runtime stack checking
  • Reserve space for checksum/signature
  • Document all magic numbers

References

  • GNU LD Manual: https://sourceware.org/binutils/docs/ld/
  • ARM Cortex-M Linker Scripts Application Note
  • STM32 Linker Configuration Examples
  • Zephyr Memory Configuration Documentation

See Also

  • memory-architecture-planning.js - Memory planning process
  • bootloader-implementation.js - Bootloader development
  • SK-010: Memory Analysis skill
  • AG-001: Firmware Architect agent