Skip to content

Commit

Permalink
Improve vmlinux.lds.h support for arch specific linker scripts
Browse files Browse the repository at this point in the history
To support alingment of the individual architecture specific linker scripts
provide a set of general definitions in vmlinux.lds.h

With these definitions applied the diverse linekr scripts can be reduced
in line count and their readability are improved - IMO.

A sample linker script is included to give the preferred
order of the sections for the architectures that do not
have any special requirments.

These definitions are also a first step towards eventual
support for -ffunction-sections.
The definitions makes it much easier to do a global
renaming of section names - but the main purpose is
to clean up the linker scripts.

Tim Aboot has provided a lot of inputs to improve
the definitions - all faults are mine.

Signed-off-by: Sam Ravnborg <[email protected]>
Cc: Tim Abbott <[email protected]>
  • Loading branch information
sravnborg committed Jun 9, 2009
1 parent eedc9d8 commit ef53dae
Showing 1 changed file with 224 additions and 7 deletions.
231 changes: 224 additions & 7 deletions include/asm-generic/vmlinux.lds.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,58 @@
#include <linux/section-names.h>
/*
* Helper macros to support writing architecture specific
* linker scripts.
*
* A minimal linker scripts has following content:
* [This is a sample, architectures may have special requiriements]
*
* OUTPUT_FORMAT(...)
* OUTPUT_ARCH(...)
* ENTRY(...)
* SECTIONS
* {
* . = START;
* __init_begin = .;
* HEAD_SECTION
* INIT_TEXT_SECTION(PAGE_SIZE)
* INIT_DATA_SECTION(...)
* PERCPU(PAGE_SIZE)
* __init_end = .;
*
* _stext = .;
* TEXT_SECTION = 0
* _etext = .;
*
* _sdata = .;
* RO_DATA_SECTION(PAGE_SIZE)
* RW_DATA_SECTION(...)
* _edata = .;
*
* EXCEPTION_TABLE(...)
* NOTES
*
* __bss_start = .;
* BSS_SECTION(0, 0)
* __bss_stop = .;
* _end = .;
*
* /DISCARD/ : {
* EXIT_TEXT
* EXIT_DATA
* *(.exitcall.exit)
* }
* STABS_DEBUG
* DWARF_DEBUG
* }
*
* [__init_begin, __init_end] is the init section that may be freed after init
* [_stext, _etext] is the text section
* [_sdata, _edata] is the data section
*
* Some of the included output section have their own set of constants.
* Examples are: [__initramfs_start, __initramfs_end] for initramfs and
* [__nosave_begin, __nosave_end] for the nosave data
*/
#include <linux/section-names.h>

#ifndef LOAD_OFFSET
#define LOAD_OFFSET 0
Expand Down Expand Up @@ -116,7 +170,36 @@
FTRACE_EVENTS() \
TRACE_SYSCALLS()

#define RO_DATA(align) \
/*
* Data section helpers
*/
#define NOSAVE_DATA \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__nosave_begin) = .; \
*(.data.nosave) \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__nosave_end) = .;

#define PAGE_ALIGNED_DATA(page_align) \
. = ALIGN(page_align); \
*(.data.page_aligned)

#define READ_MOSTLY_DATA(align) \
. = ALIGN(align); \
*(.data.read_mostly)

#define CACHELINE_ALIGNED_DATA(align) \
. = ALIGN(align); \
*(.data.cacheline_aligned)

#define INIT_TASK(align) \
. = ALIGN(align); \
*(.data.init_task)

/*
* Read only Data
*/
#define RO_DATA_SECTION(align) \
. = ALIGN((align)); \
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rodata) = .; \
Expand Down Expand Up @@ -270,9 +353,10 @@
} \
. = ALIGN((align));

/* RODATA provided for backward compatibility.
/* RODATA & RO_DATA provided for backward compatibility.
* All archs are supposed to use RO_DATA() */
#define RODATA RO_DATA(4096)
#define RODATA RO_DATA_SECTION(4096)
#define RO_DATA(align) RO_DATA_SECTION(align)

#define SECURITY_INIT \
.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
Expand Down Expand Up @@ -332,6 +416,31 @@
/* Section used for early init (in .S files) */
#define HEAD_TEXT *(HEAD_TEXT_SECTION)

#define HEAD_SECTION \
.head.text : AT(ADDR(.head.text) - LOAD_OFFSET) { \
HEAD_TEXT \
}

/*
* Exception table
*/
#define EXCEPTION_TABLE(align) \
. = ALIGN(align); \
__ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ex_table) = .; \
*(__ex_table) \
VMLINUX_SYMBOL(__stop___ex_table) = .; \
}

/*
* Init task
*/
#define INIT_TASK_DATA(align) \
. = ALIGN(align); \
.data.init_task : { \
INIT_TASK \
}

/* init and exit section handling */
#define INIT_DATA \
*(.init.data) \
Expand Down Expand Up @@ -364,9 +473,32 @@
CPU_DISCARD(exit.text) \
MEM_DISCARD(exit.text)

/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to
the beginning of the section so we begin them at 0. */
/*
* bss (Block Started by Symbol) - uninitialized data
* zeroed during startup
*/
#define SBSS \
.sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \
*(.sbss) \
*(.scommon) \
}

#define BSS(bss_align) \
. = ALIGN(bss_align); \
.bss : AT(ADDR(.bss) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__bss_start) = .; \
*(.bss.page_aligned) \
*(.dynbss) \
*(.bss) \
*(COMMON) \
VMLINUX_SYMBOL(__bss_stop) = .; \
}

/*
* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to
* the beginning of the section so we begin them at 0.
*/
#define DWARF_DEBUG \
/* DWARF 1 */ \
.debug 0 : { *(.debug) } \
Expand Down Expand Up @@ -433,6 +565,12 @@
VMLINUX_SYMBOL(__stop_notes) = .; \
}

#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
VMLINUX_SYMBOL(__setup_start) = .; \
*(.init.setup) \
VMLINUX_SYMBOL(__setup_end) = .;

#define INITCALLS \
*(.initcallearly.init) \
VMLINUX_SYMBOL(__early_initcall_end) = .; \
Expand All @@ -454,6 +592,31 @@
*(.initcall7.init) \
*(.initcall7s.init)

#define INIT_CALLS \
VMLINUX_SYMBOL(__initcall_start) = .; \
INITCALLS \
VMLINUX_SYMBOL(__initcall_end) = .;

#define CON_INITCALL \
VMLINUX_SYMBOL(__con_initcall_start) = .; \
*(.con_initcall.init) \
VMLINUX_SYMBOL(__con_initcall_end) = .;

#define SECURITY_INITCALL \
VMLINUX_SYMBOL(__security_initcall_start) = .; \
*(.security_initcall.init) \
VMLINUX_SYMBOL(__security_initcall_end) = .;

#ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \
. = ALIGN(PAGE_SIZE); \
VMLINUX_SYMBOL(__initramfs_start) = .; \
*(.init.ramfs) \
VMLINUX_SYMBOL(__initramfs_end) = .;
#else
#define INITRAMFS
#endif

/**
* PERCPU_VADDR - define output section for percpu area
* @vaddr: explicit base address (optional)
Expand Down Expand Up @@ -510,3 +673,57 @@
*(.data.percpu.shared_aligned) \
VMLINUX_SYMBOL(__per_cpu_end) = .; \
}


/*
* Definition of the high level *_SECTION macros
* They will fit only a subset of the architectures
*/


/*
* Writeable data.
* All sections are combined in a single .data section.
* The sections following CONSTRUCTORS are arranged so their
* typical alignment matches.
* A cacheline is typical/always less than a PAGE_SIZE so
* the sections that has this restriction (or similar)
* is located before the ones requiring PAGE_SIZE alignment.
* NOSAVE_DATA starts and ends with a PAGE_SIZE alignment which
* matches the requirment of PAGE_ALIGNED_DATA.
*
/* use 0 as page_align if page_aligned data is not used */
#define RW_DATA_SECTION(cacheline, nosave, pagealigned, inittask) \
. = ALIGN(PAGE_SIZE); \
.data : AT(ADDR(.data) - LOAD_OFFSET) { \
INIT_TASK(inittask) \
CACHELINE_ALIGNED_DATA(cacheline) \
READ_MOSTLY_DATA(cacheline) \
DATA_DATA \
CONSTRUCTORS \
NOSAVE_DATA(nosave) \
PAGE_ALIGNED_DATA(pagealigned) \
}

#define INIT_TEXT_SECTION(inittext_align) \
. = ALIGN(inittext_align); \
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(_sinittext) = .; \
INIT_TEXT \
VMLINUX_SYMBOL(_einittext) = .; \
}

#define INIT_DATA_SECTION(initsetup_align) \
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { \
INIT_DATA \
INIT_SETUP(initsetup_align) \
INIT_CALLS \
CON_INITCALL \
SECURITY_INITCALL \
INIT_RAM_FS \
}

#define BSS_SECTION(sbss_align, bss_align) \
SBSS \
BSS(bss_align) \
. = ALIGN(4); \

0 comments on commit ef53dae

Please sign in to comment.