zephyr/include/arch/x86/linker.ld
Daniel Leung 2fed930f4e linker: allow SoC to insert linker script fragments
This allows the SoC to specify some additional linker script
fragments into the bss, data and read-only data sections.

For example, the Cypress PSOC6 has a few input sections that
must be put into bss and data sections. Without specifying
these in the linker script, they are consider orphan sections
and the placement is based on linker heuristic which is
arbitrary.

POSIX is not supported as the main linker script is
provided by the host system's binutils and we have no control
over it. Also, currently Xtensa SoCs have their own linker
scripts so there is no need to this feature.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2018-10-09 08:23:41 -04:00

397 lines
9.6 KiB
Text

/*
* Copyright (c) 2013-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Common linker sections
*
* This script defines the memory location of the various sections that make up
* a Zephyr Kernel image. This file is used by the linker.
*
* This script places the various sections of the image according to what
* features are enabled by the kernel's configuration options.
*
* For a build that does not use the execute in place (XIP) feature, the script
* generates an image suitable for loading into and executing from RAMABLE_REGION by
* placing all the sections adjacent to each other. There is also no separate
* load address for the DATA section which means it doesn't have to be copied
* into RAMABLE_REGION.
*
* For builds using XIP, there is a different load memory address (LMA) and
* virtual memory address (VMA) for the DATA section. In this case the DATA
* section is copied into RAMABLE_REGION at runtime.
*
* When building an XIP image the data section is placed into ROMABLE_REGION. In this
* case, the LMA is set to __data_rom_start so the data section is concatenated
* at the end of the RODATA section. At runtime, the DATA section is copied
* into the RAMABLE_REGION region so it can be accessed with read and write permission.
*
* Most symbols defined in the sections below are subject to be referenced in
* the Zephyr Kernel image. If a symbol is used but not defined the linker will
* emit an undefined symbol error.
*
* Please do not change the order of the section as the kernel expects this
* order when programming the MMU.
*/
#define _LINKER
#define _ASMLANGUAGE
#include <linker/linker-defs.h>
#include <offsets.h>
#include <misc/util.h>
#include <linker/linker-tool.h>
#ifdef CONFIG_XIP
#define ROMABLE_REGION ROM
#define RAMABLE_REGION RAM
#else
#define ROMABLE_REGION RAM
#define RAMABLE_REGION RAM
#endif
#ifdef CONFIG_X86_MMU
#define MMU_PAGE_SIZE KB(4)
#define MMU_PAGE_ALIGN . = ALIGN(MMU_PAGE_SIZE);
#else
#define MMU_PAGE_ALIGN
#endif
ENTRY(CONFIG_KERNEL_ENTRY)
/* SECTIONS definitions */
SECTIONS
{
GROUP_START(ROMABLE_REGION)
#ifdef CONFIG_REALMODE
/* 16-bit sections */
. = PHYS_RAM_ADDR;
SECTION_PROLOGUE(boot, (OPTIONAL),)
{
*(.boot)
. = ALIGN(16);
} GROUP_LINK_IN(ROMABLE_REGION)
#endif
. = ALIGN(8);
_image_rom_start = PHYS_LOAD_ADDR;
#ifndef CONFIG_REALMODE
_image_text_start = PHYS_LOAD_ADDR;
#else
_image_text_start = .;
#endif
SECTION_PROLOGUE(_TEXT_SECTION_NAME, (OPTIONAL),)
{
. = CONFIG_TEXT_SECTION_OFFSET;
*(.text_start)
*(".text_start.*")
*(.text)
*(".text.*")
*(.gnu.linkonce.t.*)
*(.eh_frame)
*(.init)
*(.fini)
*(.eini)
KEEP(*(.openocd_dbg))
KEEP(*(".openocd_dbg.*"))
#include <linker/kobject-text.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
_image_text_end = .;
_image_rodata_start = .;
#include <linker/common-rom.ld>
SECTION_PROLOGUE(_RODATA_SECTION_NAME, (OPTIONAL),)
{
*(.rodata)
*(".rodata.*")
*(.gnu.linkonce.r.*)
. = ALIGN(8);
_idt_base_address = .;
#ifdef LINKER_PASS2
KEEP(*(staticIdt))
#else
. += CONFIG_IDT_NUM_VECTORS * 8;
#endif
#ifndef CONFIG_X86_FIXED_IRQ_MAPPING
. = ALIGN(4);
_irq_to_interrupt_vector = .;
#ifdef LINKER_PASS2
KEEP(*(irq_int_vector_map))
#else
. += CONFIG_MAX_IRQ_LINES;
#endif
#endif
#ifdef CONFIG_SOC_RODATA_LD
#include <soc-rodata.ld>
#endif
#ifdef CONFIG_CUSTOM_RODATA_LD
/* Located in project source directory */
#include <custom-rodata.ld>
#endif
#include <linker/kobject-rom.ld>
} GROUP_LINK_IN(ROMABLE_REGION)
_image_rodata_end = .;
MMU_PAGE_ALIGN
#ifdef CONFIG_XIP
/* Kernel ROM extends to the end of flash. Need to do this to program
* the MMU
*/
_image_rom_end = _image_rom_start + KB(CONFIG_ROM_SIZE);
#else
/* ROM ends here, position counter will now be in RAM areas */
_image_rom_end = .;
#endif
_image_rom_size = _image_rom_end - _image_rom_start;
GROUP_END(ROMABLE_REGION)
/* RAMABLE_REGION */
GROUP_START(RAMABLE_REGION)
/* APP SHARED MEMORY REGION */
SECTION_PROLOGUE(_APP_SMEM_SECTION_NAME, (OPTIONAL),)
{
_image_ram_start = .;
_app_smem_start = .;
APP_SMEM_SECTION()
MMU_PAGE_ALIGN
_app_smem_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
_app_smem_size = _app_smem_end - _app_smem_start;
_app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
#ifdef CONFIG_APPLICATION_MEMORY
SECTION_DATA_PROLOGUE(_APP_DATA_SECTION_NAME, (OPTIONAL),)
{
#ifndef CONFIG_XIP
MMU_PAGE_ALIGN
#endif
__app_ram_start = .;
__app_data_ram_start = .;
APP_INPUT_SECTION(.data)
APP_INPUT_SECTION(".data.*")
__app_data_ram_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__app_data_rom_start = LOADADDR(_APP_DATA_SECTION_NAME);
SECTION_PROLOGUE(_APP_BSS_SECTION_NAME, (NOLOAD OPTIONAL),)
{
__app_bss_start = .;
APP_INPUT_SECTION(.bss)
APP_INPUT_SECTION(".bss.*")
APP_INPUT_SECTION(COMMON)
__app_bss_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
__app_bss_num_words = (__app_bss_end - __app_bss_start) >> 2;
SECTION_PROLOGUE(_APP_NOINIT_SECTION_NAME, (NOLOAD OPTIONAL),)
{
APP_INPUT_SECTION(.noinit)
APP_INPUT_SECTION(".noinit.*")
MMU_PAGE_ALIGN
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
__app_ram_end = .;
__app_ram_size = __app_ram_end - __app_ram_start;
#endif /* CONFIG_APPLICATION_MEMORY */
SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD OPTIONAL),)
{
MMU_PAGE_ALIGN
/*
* For performance, BSS section is forced to be both 4 byte aligned and
* a multiple of 4 bytes.
*/
. = ALIGN(4);
__kernel_ram_start = .;
__bss_start = .;
KERNEL_INPUT_SECTION(.bss)
KERNEL_INPUT_SECTION(".bss.*")
KERNEL_INPUT_SECTION(COMMON)
*(".kernel_bss.*")
/*
* As memory is cleared in words only, it is simpler to ensure the BSS
* section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
*/
. = ALIGN(4);
__bss_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
__bss_num_words = (__bss_end - __bss_start) >> 2;
SECTION_PROLOGUE(_NOINIT_SECTION_NAME, (NOLOAD OPTIONAL),)
{
/*
* This section is used for non-initialized objects that
* will not be cleared during the boot process.
*/
KERNEL_INPUT_SECTION(.noinit)
KERNEL_INPUT_SECTION(".noinit.*")
*(".kernel_noinit.*")
#ifdef CONFIG_SOC_NOINIT_LD
#include <soc-noinit.ld>
#endif
MMU_PAGE_ALIGN
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME, (OPTIONAL),)
{
__data_ram_start = .;
KERNEL_INPUT_SECTION(.data)
KERNEL_INPUT_SECTION(".data.*")
*(".kernel.*")
#ifdef CONFIG_SOC_RWDATA_LD
#include <soc-rwdata.ld>
#endif
#ifdef CONFIG_CUSTOM_RWDATA_LD
/* Located in project source directory */
#include <custom-rwdata.ld>
#endif
#ifdef CONFIG_GDT_DYNAMIC
KEEP(*(.tss))
. = ALIGN(8);
_gdt = .;
#ifdef LINKER_PASS2
KEEP(*(gdt_ram_data))
#else /* LINKER_PASS2 */
#ifdef CONFIG_USERSPACE
#define GDT_NUM_ENTRIES 7
#elif defined(CONFIG_HW_STACK_PROTECTION)
#define GDT_NUM_ENTRIES 5
#else
#define GDT_NUM_ENTRIES 3
#endif /* CONFIG_X86_USERSPACE */
. += GDT_NUM_ENTRIES * 8;
#endif /* LINKER_PASS2 */
#endif /* CONFIG_GDT_DYNAMIC */
. = ALIGN(4);
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
__data_rom_start = LOADADDR(_DATA_SECTION_NAME);
#include <linker/common-ram.ld>
#ifdef CONFIG_X86_MMU
/* Can't really predict the size of this section. Anything after this
* should not be affected if addresses change between builds (currently
* just the gperf tables which is fine).
*
* However, __mmu_tables_start *must* remain stable between builds,
* we can't have anything shifting the memory map beforehand.
*/
SECTION_DATA_PROLOGUE(mmu_tables, (OPTIONAL),)
{
/* Page Tables are located here if MMU is enabled.*/
MMU_PAGE_ALIGN
__mmu_tables_start = .;
KEEP(*(.mmu_data));
__mmu_tables_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif
#include <linker/kobject.ld>
MMU_PAGE_ALIGN
__data_ram_end = .;
/* All unused memory also owned by the kernel for heaps */
__kernel_ram_end = PHYS_RAM_ADDR + KB(CONFIG_RAM_SIZE);
__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
_image_ram_end = .;
_image_ram_all = (PHYS_RAM_ADDR + KB(CONFIG_RAM_SIZE)) - _image_ram_start;
_end = .; /* end of image */
GROUP_END(RAMABLE_REGION)
#ifndef LINKER_PASS2
/* static interrupts */
SECTION_PROLOGUE(intList, (OPTIONAL),)
{
KEEP(*(.spurIsr))
KEEP(*(.spurNoErrIsr))
KEEP(*(.intList))
KEEP(*(.gnu.linkonce.intList.*))
} > IDT_LIST
#ifdef CONFIG_X86_MMU
/* Memory management unit*/
SECTION_PROLOGUE(mmulist, (OPTIONAL),)
{
/* get size of the mmu lists needed for gen_mmu_x86.py*/
LONG((__MMU_LIST_END__ - __MMU_LIST_START__) / __MMU_REGION_SIZEOF)
/* Get the start of mmu tables in data section so that the address
* of the page tables can be calculated.
*/
LONG(__mmu_tables_start)
__MMU_LIST_START__ = .;
KEEP(*(.mmulist))
__MMU_LIST_END__ = .;
} > MMU_LIST
#endif /* CONFIG_X86_MMU */
#else
/DISCARD/ :
{
KEEP(*(.spurIsr))
KEEP(*(.spurNoErrIsr))
KEEP(*(.intList))
KEEP(*(.gnu.linkonce.intList.*))
KEEP(*(.mmulist))
}
#endif
#ifdef CONFIG_CUSTOM_SECTIONS_LD
/* Located in project source directory */
#include <custom-sections.ld>
#endif
}
#ifdef CONFIG_XIP
/*
* Round up number of words for DATA section to ensure that XIP copies the
* entire data section. XIP copy is done in words only, so there may be up
* to 3 extra bytes copied in next section (BSS). At run time, the XIP copy
* is done first followed by clearing the BSS section.
*/
__data_size = (__data_ram_end - __data_ram_start);
__data_num_words = (__data_size + 3) >> 2;
#ifdef CONFIG_APPLICATION_MEMORY
__app_data_size = (__app_data_ram_end - __app_data_ram_start);
__app_data_num_words = (__app_data_size + 3) >> 2;
#endif
#endif