diff options
Diffstat (limited to 'include/asm-generic/vmlinux.lds.h')
| -rw-r--r-- | include/asm-generic/vmlinux.lds.h | 953 |
1 files changed, 616 insertions, 337 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index da0be9a8d1de..8ca130af301f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -3,7 +3,7 @@ * linker scripts. * * A minimal linker scripts has following content: - * [This is a sample, architectures may have special requiriements] + * [This is a sample, architectures may have special requirements] * * OUTPUT_FORMAT(...) * OUTPUT_ARCH(...) @@ -23,18 +23,18 @@ * _etext = .; * * _sdata = .; - * RO_DATA_SECTION(PAGE_SIZE) - * RW_DATA_SECTION(...) + * RO_DATA(PAGE_SIZE) + * RW_DATA(...) * _edata = .; * * EXCEPTION_TABLE(...) - * NOTES * * BSS_SECTION(0, 0, 0) * _end = .; * * STABS_DEBUG * DWARF_DEBUG + * ELF_DETAILS * * DISCARDS // must be the last * } @@ -50,132 +50,293 @@ * [__nosave_begin, __nosave_end] for the nosave data */ +#include <asm-generic/codetag.lds.h> + #ifndef LOAD_OFFSET #define LOAD_OFFSET 0 #endif -#include <linux/export.h> +/* + * Only some architectures want to have the .notes segment visible in + * a separate PT_NOTE ELF Program Header. When this happens, it needs + * to be visible in both the kernel text's PT_LOAD and the PT_NOTE + * Program Headers. In this case, though, the PT_LOAD needs to be made + * the default again so that all the following sections don't also end + * up in the PT_NOTE Program Header. + */ +#ifdef EMITS_PT_NOTE +#define NOTES_HEADERS :text :note +#define NOTES_HEADERS_RESTORE __restore_ph : { *(.__restore_ph) } :text +#else +#define NOTES_HEADERS +#define NOTES_HEADERS_RESTORE +#endif + +/* + * Some architectures have non-executable read-only exception tables. + * They can be added to the RO_DATA segment by specifying their desired + * alignment. + */ +#ifdef RO_EXCEPTION_TABLE_ALIGN +#define RO_EXCEPTION_TABLE EXCEPTION_TABLE(RO_EXCEPTION_TABLE_ALIGN) +#else +#define RO_EXCEPTION_TABLE +#endif + +/* Align . function alignment. */ +#define ALIGN_FUNCTION() . = ALIGN(CONFIG_FUNCTION_ALIGNMENT) + +/* + * Support -ffunction-sections by matching .text and .text.*, + * but exclude '.text..*', .text.startup[.*], and .text.exit[.*]. + * + * .text.startup and .text.startup.* are matched later by INIT_TEXT, and + * .text.exit and .text.exit.* are matched later by EXIT_TEXT, so they must be + * explicitly excluded here. + * + * Other .text.* sections that are typically grouped separately, such as + * .text.unlikely or .text.hot, must be matched explicitly before using + * TEXT_MAIN. + * + * NOTE: builds *with* and *without* -ffunction-sections are both supported by + * this single macro. Even with -ffunction-sections, there may be some objects + * NOT compiled with the flag due to the use of a specific Makefile override + * like cflags-y or AUTOFDO_PROFILE_foo.o. So this single catchall rule is + * needed to support mixed object builds. + * + * One implication is that functions named startup(), exit(), split(), + * unlikely(), hot(), and unknown() are not allowed in the kernel due to the + * ambiguity of their section names with -ffunction-sections. For example, + * .text.startup could be __attribute__((constructor)) code in a *non* + * ffunction-sections object, which should be placed in .init.text; or it could + * be an actual function named startup() in an ffunction-sections object, which + * should be placed in .text. The build will detect and complain about any such + * ambiguously named functions. + */ +#define TEXT_MAIN \ + .text \ + .text.[_0-9A-Za-df-rt-z]* \ + .text.s[_0-9A-Za-su-z]* .text.s .text.s.* \ + .text.st[_0-9A-Zb-z]* .text.st .text.st.* \ + .text.sta[_0-9A-Za-qs-z]* .text.sta .text.sta.* \ + .text.star[_0-9A-Za-su-z]* .text.star .text.star.* \ + .text.start[_0-9A-Za-tv-z]* .text.start .text.start.* \ + .text.startu[_0-9A-Za-oq-z]* .text.startu .text.startu.* \ + .text.startup[_0-9A-Za-z]* \ + .text.e[_0-9A-Za-wy-z]* .text.e .text.e.* \ + .text.ex[_0-9A-Za-hj-z]* .text.ex .text.ex.* \ + .text.exi[_0-9A-Za-su-z]* .text.exi .text.exi.* \ + .text.exit[_0-9A-Za-z]* -/* Align . to a 8 byte boundary equals to maximum function alignment. */ -#define ALIGN_FUNCTION() . = ALIGN(8) +/* + * Support -fdata-sections by matching .data, .data.*, and others, + * but exclude '.data..*'. + */ +#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data.rel.* .data..L* .data..compoundliteral* .data.$__unnamed_* .data.$L* +#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]* +#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* .rodata..L* +#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..L* .bss..compoundliteral* +#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]* /* - * Align to a 32 byte boundary equal to the - * alignment gcc 4.5 uses for a struct + * GCC 4.5 and later have a 32 bytes section alignment for structures. + * Except GCC 4.9, that feels the need to align on 64 bytes. */ #define STRUCT_ALIGNMENT 32 #define STRUCT_ALIGN() . = ALIGN(STRUCT_ALIGNMENT) +/* + * The order of the sched class addresses are important, as they are + * used to determine the order of the priority of each sched class in + * relation to each other. + */ +#define SCHED_DATA \ + STRUCT_ALIGN(); \ + __sched_class_highest = .; \ + *(__stop_sched_class) \ + *(__dl_sched_class) \ + *(__rt_sched_class) \ + *(__fair_sched_class) \ + *(__ext_sched_class) \ + *(__idle_sched_class) \ + __sched_class_lowest = .; + /* The actual configuration determine if the init/exit sections * are handled as text/data or they can be discarded (which * often happens at runtime) */ -#ifdef CONFIG_HOTPLUG_CPU -#define CPU_KEEP(sec) *(.cpu##sec) -#define CPU_DISCARD(sec) + +#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_NO_PATCHABLE +#define KEEP_PATCHABLE KEEP(*(__patchable_function_entries)) +#define PATCHABLE_DISCARDS #else -#define CPU_KEEP(sec) -#define CPU_DISCARD(sec) *(.cpu##sec) +#define KEEP_PATCHABLE +#define PATCHABLE_DISCARDS *(__patchable_function_entries) #endif -#if defined(CONFIG_MEMORY_HOTPLUG) -#define MEM_KEEP(sec) *(.mem##sec) -#define MEM_DISCARD(sec) +#ifndef CONFIG_ARCH_SUPPORTS_CFI +/* + * Simply points to ftrace_stub, but with the proper protocol. + * Defined by the linker script in linux/vmlinux.lds.h + */ +#define FTRACE_STUB_HACK ftrace_stub_graph = ftrace_stub; #else -#define MEM_KEEP(sec) -#define MEM_DISCARD(sec) *(.mem##sec) +#define FTRACE_STUB_HACK #endif -#ifdef CONFIG_FTRACE_MCOUNT_RECORD +#ifdef CONFIG_DYNAMIC_FTRACE +/* + * The ftrace call sites are logged to a section whose name depends on the + * compiler option used. A given kernel image will only use one, AKA + * FTRACE_CALLSITE_SECTION. We capture all of them here to avoid header + * dependencies for FTRACE_CALLSITE_SECTION's definition. + * + * ftrace_ops_list_func will be defined as arch_ftrace_ops_list_func + * as some archs will have a different prototype for that function + * but ftrace_ops_list_func() will have a single prototype. + */ #define MCOUNT_REC() . = ALIGN(8); \ - VMLINUX_SYMBOL(__start_mcount_loc) = .; \ - *(__mcount_loc) \ - VMLINUX_SYMBOL(__stop_mcount_loc) = .; + __start_mcount_loc = .; \ + KEEP(*(__mcount_loc)) \ + KEEP_PATCHABLE \ + __stop_mcount_loc = .; \ + FTRACE_STUB_HACK \ + ftrace_ops_list_func = arch_ftrace_ops_list_func; #else -#define MCOUNT_REC() +# ifdef CONFIG_FUNCTION_TRACER +# define MCOUNT_REC() FTRACE_STUB_HACK \ + ftrace_ops_list_func = arch_ftrace_ops_list_func; +# else +# define MCOUNT_REC() +# endif #endif +#define BOUNDED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_) \ + _BEGIN_##_label_ = .; \ + KEEP(*(_sec_)) \ + _END_##_label_ = .; + +#define BOUNDED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_) \ + _label_##_BEGIN_ = .; \ + KEEP(*(_sec_)) \ + _label_##_END_ = .; + +#define BOUNDED_SECTION_BY(_sec_, _label_) \ + BOUNDED_SECTION_PRE_LABEL(_sec_, _label_, __start, __stop) + +#define BOUNDED_SECTION(_sec) BOUNDED_SECTION_BY(_sec, _sec) + +#define HEADERED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_, _HDR_) \ + _HDR_##_label_ = .; \ + KEEP(*(.gnu.linkonce.##_sec_)) \ + BOUNDED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_) + +#define HEADERED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_, _HDR_) \ + _label_##_HDR_ = .; \ + KEEP(*(.gnu.linkonce.##_sec_)) \ + BOUNDED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_) + +#define HEADERED_SECTION_BY(_sec_, _label_) \ + HEADERED_SECTION_PRE_LABEL(_sec_, _label_, __start, __stop) + +#define HEADERED_SECTION(_sec) HEADERED_SECTION_BY(_sec, _sec) + #ifdef CONFIG_TRACE_BRANCH_PROFILING -#define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \ - *(_ftrace_annotated_branch) \ - VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .; +#define LIKELY_PROFILE() \ + BOUNDED_SECTION_BY(_ftrace_annotated_branch, _annotated_branch_profile) #else #define LIKELY_PROFILE() #endif #ifdef CONFIG_PROFILE_ALL_BRANCHES -#define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \ - *(_ftrace_branch) \ - VMLINUX_SYMBOL(__stop_branch_profile) = .; +#define BRANCH_PROFILE() \ + BOUNDED_SECTION_BY(_ftrace_branch, _branch_profile) #else #define BRANCH_PROFILE() #endif #ifdef CONFIG_KPROBES -#define KPROBE_BLACKLIST() . = ALIGN(8); \ - VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \ - KEEP(*(_kprobe_blacklist)) \ - VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .; +#define KPROBE_BLACKLIST() \ + . = ALIGN(8); \ + BOUNDED_SECTION(_kprobe_blacklist) #else #define KPROBE_BLACKLIST() #endif +#ifdef CONFIG_FUNCTION_ERROR_INJECTION +#define ERROR_INJECT_WHITELIST() \ + STRUCT_ALIGN(); \ + BOUNDED_SECTION(_error_injection_whitelist) +#else +#define ERROR_INJECT_WHITELIST() +#endif + #ifdef CONFIG_EVENT_TRACING -#define FTRACE_EVENTS() . = ALIGN(8); \ - VMLINUX_SYMBOL(__start_ftrace_events) = .; \ - KEEP(*(_ftrace_events)) \ - VMLINUX_SYMBOL(__stop_ftrace_events) = .; \ - VMLINUX_SYMBOL(__start_ftrace_eval_maps) = .; \ - KEEP(*(_ftrace_eval_map)) \ - VMLINUX_SYMBOL(__stop_ftrace_eval_maps) = .; +#define FTRACE_EVENTS() \ + . = ALIGN(8); \ + BOUNDED_SECTION(_ftrace_events) \ + BOUNDED_SECTION_BY(_ftrace_eval_map, _ftrace_eval_maps) #else #define FTRACE_EVENTS() #endif #ifdef CONFIG_TRACING -#define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \ - KEEP(*(__trace_printk_fmt)) /* Trace_printk fmt' pointer */ \ - VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .; -#define TRACEPOINT_STR() VMLINUX_SYMBOL(__start___tracepoint_str) = .; \ - KEEP(*(__tracepoint_str)) /* Trace_printk fmt' pointer */ \ - VMLINUX_SYMBOL(__stop___tracepoint_str) = .; +#define TRACE_PRINTKS() BOUNDED_SECTION_BY(__trace_printk_fmt, ___trace_bprintk_fmt) +#define TRACEPOINT_STR() BOUNDED_SECTION_BY(__tracepoint_str, ___tracepoint_str) #else #define TRACE_PRINTKS() #define TRACEPOINT_STR() #endif #ifdef CONFIG_FTRACE_SYSCALLS -#define TRACE_SYSCALLS() . = ALIGN(8); \ - VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \ - KEEP(*(__syscalls_metadata)) \ - VMLINUX_SYMBOL(__stop_syscalls_metadata) = .; +#define TRACE_SYSCALLS() \ + . = ALIGN(8); \ + BOUNDED_SECTION_BY(__syscalls_metadata, _syscalls_metadata) #else #define TRACE_SYSCALLS() #endif +#ifdef CONFIG_BPF_EVENTS +#define BPF_RAW_TP() STRUCT_ALIGN(); \ + BOUNDED_SECTION_BY(__bpf_raw_tp_map, __bpf_raw_tp) +#else +#define BPF_RAW_TP() +#endif + #ifdef CONFIG_SERIAL_EARLYCON -#define EARLYCON_TABLE() STRUCT_ALIGN(); \ - VMLINUX_SYMBOL(__earlycon_table) = .; \ - KEEP(*(__earlycon_table)) \ - VMLINUX_SYMBOL(__earlycon_table_end) = .; +#define EARLYCON_TABLE() \ + . = ALIGN(8); \ + BOUNDED_SECTION_POST_LABEL(__earlycon_table, __earlycon_table, , _end) #else #define EARLYCON_TABLE() #endif +#ifdef CONFIG_SECURITY +#define LSM_TABLE() \ + . = ALIGN(8); \ + BOUNDED_SECTION_PRE_LABEL(.lsm_info.init, _lsm_info, __start, __end) + +#define EARLY_LSM_TABLE() \ + . = ALIGN(8); \ + BOUNDED_SECTION_PRE_LABEL(.early_lsm_info.init, _early_lsm_info, __start, __end) +#else +#define LSM_TABLE() +#define EARLY_LSM_TABLE() +#endif + #define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name) #define __OF_TABLE(cfg, name) ___OF_TABLE(cfg, name) #define OF_TABLE(cfg, name) __OF_TABLE(IS_ENABLED(cfg), name) #define _OF_TABLE_0(name) #define _OF_TABLE_1(name) \ . = ALIGN(8); \ - VMLINUX_SYMBOL(__##name##_of_table) = .; \ + __##name##_of_table = .; \ KEEP(*(__##name##_of_table)) \ KEEP(*(__##name##_of_table_end)) #define TIMER_OF_TABLES() OF_TABLE(CONFIG_TIMER_OF, timer) #define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip) #define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk) -#define IOMMU_OF_TABLES() OF_TABLE(CONFIG_OF_IOMMU, iommu) #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) @@ -183,61 +344,74 @@ #ifdef CONFIG_ACPI #define ACPI_PROBE_TABLE(name) \ . = ALIGN(8); \ - VMLINUX_SYMBOL(__##name##_acpi_probe_table) = .; \ - KEEP(*(__##name##_acpi_probe_table)) \ - VMLINUX_SYMBOL(__##name##_acpi_probe_table_end) = .; + BOUNDED_SECTION_POST_LABEL(__##name##_acpi_probe_table, \ + __##name##_acpi_probe_table,, _end) #else #define ACPI_PROBE_TABLE(name) #endif +#ifdef CONFIG_THERMAL +#define THERMAL_TABLE(name) \ + . = ALIGN(8); \ + BOUNDED_SECTION_POST_LABEL(__##name##_thermal_table, \ + __##name##_thermal_table,, _end) +#else +#define THERMAL_TABLE(name) +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ - VMLINUX_SYMBOL(__dtb_start) = .; \ + __dtb_start = .; \ KEEP(*(.dtb.init.rodata)) \ - VMLINUX_SYMBOL(__dtb_end) = .; + __dtb_end = .; /* * .data section - * LD_DEAD_CODE_DATA_ELIMINATION option enables -fdata-sections generates - * .data.identifier which needs to be pulled in with .data, but don't want to - * pull in .data..stuff which has its own requirements. Same for bss. */ #define DATA_DATA \ - *(.data .data.[0-9a-zA-Z_]*) \ + *(.xiptext) \ + *(DATA_MAIN) \ + *(.data..decrypted) \ *(.ref.data) \ *(.data..shared_aligned) /* percpu related */ \ - MEM_KEEP(init.data) \ - MEM_KEEP(exit.data) \ - *(.data.unlikely) \ + *(.data..unlikely) \ + __start_once = .; \ + *(.data..once) \ + __end_once = .; \ + *(.data..do_once) \ STRUCT_ALIGN(); \ *(__tracepoints) \ /* implement dynamic printk debug */ \ - . = ALIGN(8); \ - VMLINUX_SYMBOL(__start___jump_table) = .; \ - KEEP(*(__jump_table)) \ - VMLINUX_SYMBOL(__stop___jump_table) = .; \ . = ALIGN(8); \ - VMLINUX_SYMBOL(__start___verbose) = .; \ - KEEP(*(__verbose)) \ - VMLINUX_SYMBOL(__stop___verbose) = .; \ + BOUNDED_SECTION_BY(__dyndbg_classes, ___dyndbg_classes) \ + BOUNDED_SECTION_BY(__dyndbg, ___dyndbg) \ + CODETAG_SECTIONS() \ LIKELY_PROFILE() \ BRANCH_PROFILE() \ TRACE_PRINTKS() \ - TRACEPOINT_STR() + BPF_RAW_TP() \ + TRACEPOINT_STR() \ + KUNIT_TABLE() /* * Data section helpers */ #define NOSAVE_DATA \ . = ALIGN(PAGE_SIZE); \ - VMLINUX_SYMBOL(__nosave_begin) = .; \ + __nosave_begin = .; \ *(.data..nosave) \ . = ALIGN(PAGE_SIZE); \ - VMLINUX_SYMBOL(__nosave_end) = .; + __nosave_end = .; + +#define CACHE_HOT_DATA(align) \ + . = ALIGN(align); \ + *(SORT_BY_ALIGNMENT(.data..hot.*)) \ + . = ALIGN(align); #define PAGE_ALIGNED_DATA(page_align) \ . = ALIGN(page_align); \ - *(.data..page_aligned) + *(.data..page_aligned) \ + . = ALIGN(page_align); #define READ_MOSTLY_DATA(align) \ . = ALIGN(align); \ @@ -250,9 +424,25 @@ #define INIT_TASK_DATA(align) \ . = ALIGN(align); \ - VMLINUX_SYMBOL(__start_init_task) = .; \ - *(.data..init_task) \ - VMLINUX_SYMBOL(__end_init_task) = .; + __start_init_stack = .; \ + init_thread_union = .; \ + init_stack = .; \ + KEEP(*(.data..init_thread_info)) \ + . = __start_init_stack + THREAD_SIZE; \ + __end_init_stack = .; + +#define JUMP_TABLE_DATA \ + . = ALIGN(8); \ + BOUNDED_SECTION_BY(__jump_table, ___jump_table) + +#ifdef CONFIG_HAVE_STATIC_CALL_INLINE +#define STATIC_CALL_DATA \ + . = ALIGN(8); \ + BOUNDED_SECTION_BY(.static_call_sites, _static_call_sites) \ + BOUNDED_SECTION_BY(.static_call_tramp_key, _static_call_tramp_key) +#else +#define STATIC_CALL_DATA +#endif /* * Allow architectures to handle ro_after_init data on their @@ -260,25 +450,40 @@ */ #ifndef RO_AFTER_INIT_DATA #define RO_AFTER_INIT_DATA \ - VMLINUX_SYMBOL(__start_ro_after_init) = .; \ + . = ALIGN(8); \ + __start_ro_after_init = .; \ *(.data..ro_after_init) \ - VMLINUX_SYMBOL(__end_ro_after_init) = .; + JUMP_TABLE_DATA \ + STATIC_CALL_DATA \ + __end_ro_after_init = .; +#endif + +/* + * .kcfi_traps contains a list KCFI trap locations. + */ +#ifndef KCFI_TRAPS +#ifdef CONFIG_ARCH_USES_CFI_TRAPS +#define KCFI_TRAPS \ + __kcfi_traps : AT(ADDR(__kcfi_traps) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.kcfi_traps, ___kcfi_traps) \ + } +#else +#define KCFI_TRAPS +#endif #endif /* * Read only Data */ -#define RO_DATA_SECTION(align) \ +#define RO_DATA(align) \ . = ALIGN((align)); \ .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start_rodata) = .; \ - *(.rodata) *(.rodata.*) \ + __start_rodata = .; \ + *(.rodata) *(.rodata.*) *(.data.rel.ro*) \ + SCHED_DATA \ RO_AFTER_INIT_DATA /* Read only after init */ \ - KEEP(*(__vermagic)) /* Kernel version magic */ \ . = ALIGN(8); \ - VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .; \ - KEEP(*(__tracepoints_ptrs)) /* Tracepoints: pointer array */ \ - VMLINUX_SYMBOL(__stop___tracepoints_ptrs) = .; \ + BOUNDED_SECTION_BY(__tracepoints_ptrs, ___tracepoints_ptrs) \ *(__tracepoints_strings)/* Tracepoints: strings */ \ } \ \ @@ -288,109 +493,47 @@ \ /* PCI quirks */ \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \ - KEEP(*(.pci_fixup_early)) \ - VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \ - KEEP(*(.pci_fixup_header)) \ - VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_final) = .; \ - KEEP(*(.pci_fixup_final)) \ - VMLINUX_SYMBOL(__end_pci_fixups_final) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_enable) = .; \ - KEEP(*(.pci_fixup_enable)) \ - VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_resume) = .; \ - KEEP(*(.pci_fixup_resume)) \ - VMLINUX_SYMBOL(__end_pci_fixups_resume) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_resume_early) = .; \ - KEEP(*(.pci_fixup_resume_early)) \ - VMLINUX_SYMBOL(__end_pci_fixups_resume_early) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_suspend) = .; \ - KEEP(*(.pci_fixup_suspend)) \ - VMLINUX_SYMBOL(__end_pci_fixups_suspend) = .; \ - VMLINUX_SYMBOL(__start_pci_fixups_suspend_late) = .; \ - KEEP(*(.pci_fixup_suspend_late)) \ - VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .; \ - } \ - \ - /* Built-in firmware blobs */ \ - .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start_builtin_fw) = .; \ - KEEP(*(.builtin_fw)) \ - VMLINUX_SYMBOL(__end_builtin_fw) = .; \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_early, _pci_fixups_early, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_header, _pci_fixups_header, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_final, _pci_fixups_final, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_enable, _pci_fixups_enable, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_resume, _pci_fixups_resume, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_suspend, _pci_fixups_suspend, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_resume_early, _pci_fixups_resume_early, __start, __end) \ + BOUNDED_SECTION_PRE_LABEL(.pci_fixup_suspend_late, _pci_fixups_suspend_late, __start, __end) \ } \ \ + FW_LOADER_BUILT_IN_DATA \ TRACEDATA \ \ + PRINTK_INDEX \ + \ /* Kernel symbol table: Normal symbols */ \ __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab) = .; \ + __start___ksymtab = .; \ KEEP(*(SORT(___ksymtab+*))) \ - VMLINUX_SYMBOL(__stop___ksymtab) = .; \ + __stop___ksymtab = .; \ } \ \ /* Kernel symbol table: GPL-only symbols */ \ __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \ + __start___ksymtab_gpl = .; \ KEEP(*(SORT(___ksymtab_gpl+*))) \ - VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ - } \ - \ - /* Kernel symbol table: Normal unused symbols */ \ - __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \ - KEEP(*(SORT(___ksymtab_unused+*))) \ - VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \ - } \ - \ - /* Kernel symbol table: GPL-only unused symbols */ \ - __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \ - KEEP(*(SORT(___ksymtab_unused_gpl+*))) \ - VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \ - } \ - \ - /* Kernel symbol table: GPL-future-only symbols */ \ - __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ - KEEP(*(SORT(___ksymtab_gpl_future+*))) \ - VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \ + __stop___ksymtab_gpl = .; \ } \ \ /* Kernel symbol table: Normal symbols */ \ __kcrctab : AT(ADDR(__kcrctab) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab) = .; \ + __start___kcrctab = .; \ KEEP(*(SORT(___kcrctab+*))) \ - VMLINUX_SYMBOL(__stop___kcrctab) = .; \ + __stop___kcrctab = .; \ } \ \ /* Kernel symbol table: GPL-only symbols */ \ __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab_gpl) = .; \ + __start___kcrctab_gpl = .; \ KEEP(*(SORT(___kcrctab_gpl+*))) \ - VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ - } \ - \ - /* Kernel symbol table: Normal unused symbols */ \ - __kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \ - KEEP(*(SORT(___kcrctab_unused+*))) \ - VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \ - } \ - \ - /* Kernel symbol table: GPL-only unused symbols */ \ - __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \ - KEEP(*(SORT(___kcrctab_unused_gpl+*))) \ - VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \ - } \ - \ - /* Kernel symbol table: GPL-future-only symbols */ \ - __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ - KEEP(*(SORT(___kcrctab_gpl_future+*))) \ - VMLINUX_SYMBOL(__stop___kcrctab_gpl_future) = .; \ + __stop___kcrctab_gpl = .; \ } \ \ /* Kernel symbol table: strings */ \ @@ -401,110 +544,126 @@ /* __*init sections */ \ __init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \ *(.ref.rodata) \ - MEM_KEEP(init.rodata) \ - MEM_KEEP(exit.rodata) \ } \ \ /* Built-in module parameters. */ \ __param : AT(ADDR(__param) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___param) = .; \ - KEEP(*(__param)) \ - VMLINUX_SYMBOL(__stop___param) = .; \ + BOUNDED_SECTION_BY(__param, ___param) \ } \ \ /* Built-in module versions. */ \ __modver : AT(ADDR(__modver) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___modver) = .; \ - KEEP(*(__modver)) \ - VMLINUX_SYMBOL(__stop___modver) = .; \ - . = ALIGN((align)); \ - VMLINUX_SYMBOL(__end_rodata) = .; \ + BOUNDED_SECTION_BY(__modver, ___modver) \ } \ - . = ALIGN((align)); - -/* RODATA & RO_DATA provided for backward compatibility. - * All archs are supposed to use RO_DATA() */ -#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) { \ - VMLINUX_SYMBOL(__security_initcall_start) = .; \ - KEEP(*(.security_initcall.init)) \ - VMLINUX_SYMBOL(__security_initcall_end) = .; \ - } + \ + KCFI_TRAPS \ + \ + RO_EXCEPTION_TABLE \ + NOTES \ + BTF \ + \ + . = ALIGN((align)); \ + __end_rodata = .; + + +/* + * Non-instrumentable text section + */ +#define NOINSTR_TEXT \ + ALIGN_FUNCTION(); \ + __noinstr_text_start = .; \ + *(.noinstr.text) \ + __cpuidle_text_start = .; \ + *(.cpuidle.text) \ + __cpuidle_text_end = .; \ + __noinstr_text_end = .; + +#define TEXT_SPLIT \ + __split_text_start = .; \ + *(.text.split .text.split.[0-9a-zA-Z_]*) \ + __split_text_end = .; -/* .text section. Map to function alignment to avoid address changes +#define TEXT_UNLIKELY \ + __unlikely_text_start = .; \ + *(.text.unlikely .text.unlikely.*) \ + __unlikely_text_end = .; + +#define TEXT_HOT \ + __hot_text_start = .; \ + *(.text.hot .text.hot.*) \ + __hot_text_end = .; + +/* + * .text section. Map to function alignment to avoid address changes * during second ld run in second ld pass when generating System.map - * LD_DEAD_CODE_DATA_ELIMINATION option enables -ffunction-sections generates - * .text.identifier which needs to be pulled in with .text , but some - * architectures define .text.foo which is not intended to be pulled in here. - * Those enabling LD_DEAD_CODE_DATA_ELIMINATION must ensure they don't have - * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */ + * + * TEXT_MAIN here will match symbols with a fixed pattern (for example, + * .text.hot or .text.unlikely). Match those before TEXT_MAIN to ensure + * they get grouped together. + * + * Also placing .text.hot section at the beginning of a page, this + * would help the TLB performance. + */ #define TEXT_TEXT \ ALIGN_FUNCTION(); \ - *(.text.hot .text .text.fixup .text.unlikely) \ - *(.ref.text) \ - MEM_KEEP(init.text) \ - MEM_KEEP(exit.text) \ - + *(.text.asan.* .text.tsan.*) \ + *(.text.unknown .text.unknown.*) \ + TEXT_SPLIT \ + TEXT_UNLIKELY \ + . = ALIGN(PAGE_SIZE); \ + TEXT_HOT \ + *(TEXT_MAIN .text.fixup) \ + NOINSTR_TEXT \ + *(.ref.text) /* sched.text is aling to function alignment to secure we have same * address even at second ld pass when generating System.map */ #define SCHED_TEXT \ ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__sched_text_start) = .; \ + __sched_text_start = .; \ *(.sched.text) \ - VMLINUX_SYMBOL(__sched_text_end) = .; + __sched_text_end = .; /* spinlock.text is aling to function alignment to secure we have same * address even at second ld pass when generating System.map */ #define LOCK_TEXT \ ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__lock_text_start) = .; \ + __lock_text_start = .; \ *(.spinlock.text) \ - VMLINUX_SYMBOL(__lock_text_end) = .; - -#define CPUIDLE_TEXT \ - ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__cpuidle_text_start) = .; \ - *(.cpuidle.text) \ - VMLINUX_SYMBOL(__cpuidle_text_end) = .; + __lock_text_end = .; #define KPROBES_TEXT \ ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__kprobes_text_start) = .; \ + __kprobes_text_start = .; \ *(.kprobes.text) \ - VMLINUX_SYMBOL(__kprobes_text_end) = .; + __kprobes_text_end = .; #define ENTRY_TEXT \ ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__entry_text_start) = .; \ + __entry_text_start = .; \ *(.entry.text) \ - VMLINUX_SYMBOL(__entry_text_end) = .; + __entry_text_end = .; -#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) #define IRQENTRY_TEXT \ ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__irqentry_text_start) = .; \ + __irqentry_text_start = .; \ *(.irqentry.text) \ - VMLINUX_SYMBOL(__irqentry_text_end) = .; -#else -#define IRQENTRY_TEXT -#endif + __irqentry_text_end = .; -#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN) #define SOFTIRQENTRY_TEXT \ ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__softirqentry_text_start) = .; \ + __softirqentry_text_start = .; \ *(.softirqentry.text) \ - VMLINUX_SYMBOL(__softirqentry_text_end) = .; -#else -#define SOFTIRQENTRY_TEXT -#endif + __softirqentry_text_end = .; + +#define STATIC_CALL_TEXT \ + ALIGN_FUNCTION(); \ + __static_call_text_start = .; \ + *(.static_call.text) \ + __static_call_text_end = .; /* Section used for early init (in .S files) */ -#define HEAD_TEXT *(.head.text) +#define HEAD_TEXT KEEP(*(.head.text)) #define HEAD_TEXT_SECTION \ .head.text : AT(ADDR(.head.text) - LOAD_OFFSET) { \ @@ -517,12 +676,27 @@ #define EXCEPTION_TABLE(align) \ . = ALIGN(align); \ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ex_table) = .; \ - KEEP(*(__ex_table)) \ - VMLINUX_SYMBOL(__stop___ex_table) = .; \ + BOUNDED_SECTION_BY(__ex_table, ___ex_table) \ } /* + * .BTF + */ +#ifdef CONFIG_DEBUG_INFO_BTF +#define BTF \ + . = ALIGN(PAGE_SIZE); \ + .BTF : AT(ADDR(.BTF) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.BTF, _BTF) \ + } \ + . = ALIGN(PAGE_SIZE); \ + .BTF_ids : AT(ADDR(.BTF_ids) - LOAD_OFFSET) { \ + *(.BTF_ids) \ + } +#else +#define BTF +#endif + +/* * Init task */ #define INIT_TASK_DATA_SECTION(align) \ @@ -533,11 +707,12 @@ #ifdef CONFIG_CONSTRUCTORS #define KERNEL_CTORS() . = ALIGN(8); \ - VMLINUX_SYMBOL(__ctors_start) = .; \ + __ctors_start = .; \ + KEEP(*(SORT(.ctors.*))) \ KEEP(*(.ctors)) \ KEEP(*(SORT(.init_array.*))) \ KEEP(*(.init_array)) \ - VMLINUX_SYMBOL(__ctors_end) = .; + __ctors_end = .; #else #define KERNEL_CTORS() #endif @@ -545,44 +720,41 @@ /* init and exit section handling */ #define INIT_DATA \ KEEP(*(SORT(___kentry+*))) \ - *(.init.data) \ - MEM_DISCARD(init.data) \ + *(.init.data .init.data.*) \ KERNEL_CTORS() \ MCOUNT_REC() \ - *(.init.rodata) \ + *(.init.rodata .init.rodata.*) \ FTRACE_EVENTS() \ TRACE_SYSCALLS() \ KPROBE_BLACKLIST() \ - MEM_DISCARD(init.rodata) \ + ERROR_INJECT_WHITELIST() \ CLK_OF_TABLES() \ RESERVEDMEM_OF_TABLES() \ TIMER_OF_TABLES() \ - IOMMU_OF_TABLES() \ CPU_METHOD_OF_TABLES() \ CPUIDLE_METHOD_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() \ ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(timer) \ - ACPI_PROBE_TABLE(iort) \ - EARLYCON_TABLE() + THERMAL_TABLE(governor) \ + EARLYCON_TABLE() \ + LSM_TABLE() \ + EARLY_LSM_TABLE() \ + KUNIT_INIT_TABLE() #define INIT_TEXT \ - *(.init.text) \ - *(.text.startup) \ - MEM_DISCARD(init.text) + *(.init.text .init.text.*) \ + *(.text.startup .text.startup.*) #define EXIT_DATA \ - *(.exit.data) \ - *(.fini_array) \ - *(.dtors) \ - MEM_DISCARD(exit.data) \ - MEM_DISCARD(exit.rodata) + *(.exit.data .exit.data.*) \ + *(.fini_array .fini_array.*) \ + *(.dtors .dtors.*) #define EXIT_TEXT \ *(.exit.text) \ - *(.text.exit) \ - MEM_DISCARD(exit.text) + *(.text.exit .text.exit.*) #define EXIT_CALL \ *(.exitcall.exit) @@ -595,7 +767,7 @@ . = ALIGN(sbss_align); \ .sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \ *(.dynsbss) \ - *(.sbss) \ + *(SBSS_MAIN) \ *(.scommon) \ } @@ -611,9 +783,11 @@ . = ALIGN(bss_align); \ .bss : AT(ADDR(.bss) - LOAD_OFFSET) { \ BSS_FIRST_SECTIONS \ + . = ALIGN(PAGE_SIZE); \ *(.bss..page_aligned) \ + . = ALIGN(PAGE_SIZE); \ *(.dynbss) \ - *(.bss .bss.[0-9a-zA-Z_]*) \ + *(BSS_MAIN) \ *(COMMON) \ } @@ -655,63 +829,124 @@ /* DWARF 4 */ \ .debug_types 0 : { *(.debug_types) } \ /* DWARF 5 */ \ + .debug_addr 0 : { *(.debug_addr) } \ + .debug_line_str 0 : { *(.debug_line_str) } \ + .debug_loclists 0 : { *(.debug_loclists) } \ .debug_macro 0 : { *(.debug_macro) } \ - .debug_addr 0 : { *(.debug_addr) } + .debug_names 0 : { *(.debug_names) } \ + .debug_rnglists 0 : { *(.debug_rnglists) } \ + .debug_str_offsets 0 : { *(.debug_str_offsets) } - /* Stabs debugging sections. */ +/* Stabs debugging sections. */ #define STABS_DEBUG \ .stab 0 : { *(.stab) } \ .stabstr 0 : { *(.stabstr) } \ .stab.excl 0 : { *(.stab.excl) } \ .stab.exclstr 0 : { *(.stab.exclstr) } \ .stab.index 0 : { *(.stab.index) } \ - .stab.indexstr 0 : { *(.stab.indexstr) } \ - .comment 0 : { *(.comment) } + .stab.indexstr 0 : { *(.stab.indexstr) } + +/* Required sections not related to debugging. */ +#define ELF_DETAILS \ + .modinfo : { *(.modinfo) . = ALIGN(8); } \ + .comment 0 : { *(.comment) } \ + .symtab 0 : { *(.symtab) } \ + .strtab 0 : { *(.strtab) } \ + .shstrtab 0 : { *(.shstrtab) } #ifdef CONFIG_GENERIC_BUG #define BUG_TABLE \ . = ALIGN(8); \ __bug_table : AT(ADDR(__bug_table) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___bug_table) = .; \ - KEEP(*(__bug_table)) \ - VMLINUX_SYMBOL(__stop___bug_table) = .; \ + BOUNDED_SECTION_BY(__bug_table, ___bug_table) \ } #else #define BUG_TABLE #endif +#ifdef CONFIG_UNWINDER_ORC +#define ORC_UNWIND_TABLE \ + .orc_header : AT(ADDR(.orc_header) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.orc_header, _orc_header) \ + } \ + . = ALIGN(4); \ + .orc_unwind_ip : AT(ADDR(.orc_unwind_ip) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.orc_unwind_ip, _orc_unwind_ip) \ + } \ + . = ALIGN(2); \ + .orc_unwind : AT(ADDR(.orc_unwind) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.orc_unwind, _orc_unwind) \ + } \ + text_size = _etext - _stext; \ + . = ALIGN(4); \ + .orc_lookup : AT(ADDR(.orc_lookup) - LOAD_OFFSET) { \ + orc_lookup = .; \ + . += (((text_size + LOOKUP_BLOCK_SIZE - 1) / \ + LOOKUP_BLOCK_SIZE) + 1) * 4; \ + orc_lookup_end = .; \ + } +#else +#define ORC_UNWIND_TABLE +#endif + +/* Built-in firmware blobs */ +#ifdef CONFIG_FW_LOADER +#define FW_LOADER_BUILT_IN_DATA \ + .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) ALIGN(8) { \ + BOUNDED_SECTION_PRE_LABEL(.builtin_fw, _builtin_fw, __start, __end) \ + } +#else +#define FW_LOADER_BUILT_IN_DATA +#endif + #ifdef CONFIG_PM_TRACE #define TRACEDATA \ . = ALIGN(4); \ .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__tracedata_start) = .; \ - KEEP(*(.tracedata)) \ - VMLINUX_SYMBOL(__tracedata_end) = .; \ + BOUNDED_SECTION_POST_LABEL(.tracedata, __tracedata, _start, _end) \ } #else #define TRACEDATA #endif +#ifdef CONFIG_PRINTK_INDEX +#define PRINTK_INDEX \ + .printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) { \ + BOUNDED_SECTION_BY(.printk_index, _printk_index) \ + } +#else +#define PRINTK_INDEX +#endif + +/* + * Discard .note.GNU-stack, which is emitted as PROGBITS by the compiler. + * Otherwise, the type of .notes section would become PROGBITS instead of NOTES. + * + * Also, discard .note.gnu.property, otherwise it forces the notes section to + * be 8-byte aligned which causes alignment mismatches with the kernel's custom + * 4-byte aligned notes. + */ #define NOTES \ + /DISCARD/ : { \ + *(.note.GNU-stack) \ + *(.note.gnu.property) \ + } \ .notes : AT(ADDR(.notes) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start_notes) = .; \ - *(.note.*) \ - VMLINUX_SYMBOL(__stop_notes) = .; \ - } + BOUNDED_SECTION_BY(.note.*, _notes) \ + } NOTES_HEADERS \ + NOTES_HEADERS_RESTORE #define INIT_SETUP(initsetup_align) \ . = ALIGN(initsetup_align); \ - VMLINUX_SYMBOL(__setup_start) = .; \ - KEEP(*(.init.setup)) \ - VMLINUX_SYMBOL(__setup_end) = .; + BOUNDED_SECTION_POST_LABEL(.init.setup, __setup, _start, _end) #define INIT_CALLS_LEVEL(level) \ - VMLINUX_SYMBOL(__initcall##level##_start) = .; \ + __initcall##level##_start = .; \ KEEP(*(.initcall##level##.init)) \ KEEP(*(.initcall##level##s.init)) \ #define INIT_CALLS \ - VMLINUX_SYMBOL(__initcall_start) = .; \ + __initcall_start = .; \ KEEP(*(.initcallearly.init)) \ INIT_CALLS_LEVEL(0) \ INIT_CALLS_LEVEL(1) \ @@ -722,22 +957,38 @@ INIT_CALLS_LEVEL(rootfs) \ INIT_CALLS_LEVEL(6) \ INIT_CALLS_LEVEL(7) \ - VMLINUX_SYMBOL(__initcall_end) = .; + __initcall_end = .; #define CON_INITCALL \ - VMLINUX_SYMBOL(__con_initcall_start) = .; \ - KEEP(*(.con_initcall.init)) \ - VMLINUX_SYMBOL(__con_initcall_end) = .; + BOUNDED_SECTION_POST_LABEL(.con_initcall.init, __con_initcall, _start, _end) + +#define NAMED_SECTION(name) \ + . = ALIGN(8); \ + name : AT(ADDR(name) - LOAD_OFFSET) \ + { BOUNDED_SECTION_PRE_LABEL(name, name, __start_, __stop_) } -#define SECURITY_INITCALL \ - VMLINUX_SYMBOL(__security_initcall_start) = .; \ - KEEP(*(.security_initcall.init)) \ - VMLINUX_SYMBOL(__security_initcall_end) = .; +#define RUNTIME_CONST(t,x) NAMED_SECTION(runtime_##t##_##x) + +#define RUNTIME_CONST_VARIABLES \ + RUNTIME_CONST(shift, d_hash_shift) \ + RUNTIME_CONST(ptr, dentry_hashtable) \ + RUNTIME_CONST(ptr, __dentry_cache) + +/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ +#define KUNIT_TABLE() \ + . = ALIGN(8); \ + BOUNDED_SECTION_POST_LABEL(.kunit_test_suites, __kunit_suites, _start, _end) + +/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */ +#define KUNIT_INIT_TABLE() \ + . = ALIGN(8); \ + BOUNDED_SECTION_POST_LABEL(.kunit_init_test_suites, \ + __kunit_init_suites, _start, _end) #ifdef CONFIG_BLK_DEV_INITRD #define INIT_RAM_FS \ . = ALIGN(4); \ - VMLINUX_SYMBOL(__initramfs_start) = .; \ + __initramfs_start = .; \ KEEP(*(.init.ramfs)) \ . = ALIGN(8); \ KEEP(*(.init.ramfs.info)) @@ -746,6 +997,24 @@ #endif /* + * Memory encryption operates on a page basis. Since we need to clear + * the memory encryption mask for this section, it needs to be aligned + * on a page boundary and be a page-size multiple in length. + * + * Note: We use a separate section so that only this section gets + * decrypted to avoid exposing more than we wish. + */ +#ifdef CONFIG_AMD_MEM_ENCRYPT +#define PERCPU_DECRYPTED_SECTION \ + . = ALIGN(PAGE_SIZE); \ + *(.data..percpu..decrypted) \ + . = ALIGN(PAGE_SIZE); +#else +#define PERCPU_DECRYPTED_SECTION +#endif + + +/* * Default discarded sections. * * Some archs want to discard exit text/data at runtime rather than @@ -754,13 +1023,55 @@ * section definitions so that such archs put those in earlier section * definitions. */ -#define DISCARDS \ - /DISCARD/ : { \ +#ifdef RUNTIME_DISCARD_EXIT +#define EXIT_DISCARDS +#else +#define EXIT_DISCARDS \ EXIT_TEXT \ - EXIT_DATA \ - EXIT_CALL \ + EXIT_DATA +#endif + +/* + * Clang's -fprofile-arcs, -fsanitize=kernel-address, and + * -fsanitize=thread produce unwanted sections (.eh_frame + * and .init_array.*), but CONFIG_CONSTRUCTORS wants to + * keep any .init_array.* sections. + * https://llvm.org/pr46478 + */ +#ifdef CONFIG_UNWIND_TABLES +#define DISCARD_EH_FRAME +#else +#define DISCARD_EH_FRAME *(.eh_frame) +#endif +#if defined(CONFIG_GCOV_KERNEL) || defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KCSAN) +# ifdef CONFIG_CONSTRUCTORS +# define SANITIZER_DISCARDS \ + DISCARD_EH_FRAME +# else +# define SANITIZER_DISCARDS \ + *(.init_array) *(.init_array.*) \ + DISCARD_EH_FRAME +# endif +#else +# define SANITIZER_DISCARDS +#endif + +#define COMMON_DISCARDS \ + SANITIZER_DISCARDS \ + PATCHABLE_DISCARDS \ *(.discard) \ *(.discard.*) \ + *(.export_symbol) \ + *(.no_trim_symbol) \ + /* ld.bfd warns about .gnu.version* even when not emitted */ \ + *(.gnu.version*) \ + *(__tracepoint_check) \ + +#define DISCARDS \ + /DISCARD/ : { \ + EXIT_DISCARDS \ + EXIT_CALL \ + COMMON_DISCARDS \ } /** @@ -774,65 +1085,33 @@ * sharing between subsections for different purposes. */ #define PERCPU_INPUT(cacheline) \ - VMLINUX_SYMBOL(__per_cpu_start) = .; \ - *(.data..percpu..first) \ + __per_cpu_start = .; \ . = ALIGN(PAGE_SIZE); \ *(.data..percpu..page_aligned) \ . = ALIGN(cacheline); \ + __per_cpu_hot_start = .; \ + *(SORT_BY_ALIGNMENT(.data..percpu..hot.*)) \ + __per_cpu_hot_end = .; \ + . = ALIGN(cacheline); \ *(.data..percpu..read_mostly) \ . = ALIGN(cacheline); \ *(.data..percpu) \ *(.data..percpu..shared_aligned) \ - VMLINUX_SYMBOL(__per_cpu_end) = .; + PERCPU_DECRYPTED_SECTION \ + __per_cpu_end = .; /** - * PERCPU_VADDR - define output section for percpu area + * PERCPU_SECTION - define output section for percpu area * @cacheline: cacheline size - * @vaddr: explicit base address (optional) - * @phdr: destination PHDR (optional) * * Macro which expands to output section for percpu area. * * @cacheline is used to align subsections to avoid false cacheline * sharing between subsections for different purposes. - * - * If @vaddr is not blank, it specifies explicit base address and all - * percpu symbols will be offset from the given address. If blank, - * @vaddr always equals @laddr + LOAD_OFFSET. - * - * @phdr defines the output PHDR to use if not blank. Be warned that - * output PHDR is sticky. If @phdr is specified, the next output - * section in the linker script will go there too. @phdr should have - * a leading colon. - * - * Note that this macros defines __per_cpu_load as an absolute symbol. - * If there is no need to put the percpu section at a predetermined - * address, use PERCPU_SECTION. - */ -#define PERCPU_VADDR(cacheline, vaddr, phdr) \ - VMLINUX_SYMBOL(__per_cpu_load) = .; \ - .data..percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load) \ - - LOAD_OFFSET) { \ - PERCPU_INPUT(cacheline) \ - } phdr \ - . = VMLINUX_SYMBOL(__per_cpu_load) + SIZEOF(.data..percpu); - -/** - * PERCPU_SECTION - define output section for percpu area, simple version - * @cacheline: cacheline size - * - * Align to PAGE_SIZE and outputs output section for percpu area. This - * macro doesn't manipulate @vaddr or @phdr and __per_cpu_load and - * __per_cpu_start will be identical. - * - * This macro is equivalent to ALIGN(PAGE_SIZE); PERCPU_VADDR(@cacheline,,) - * except that __per_cpu_load is defined as a relative symbol against - * .data..percpu which is required for relocatable x86_32 configuration. */ #define PERCPU_SECTION(cacheline) \ . = ALIGN(PAGE_SIZE); \ .data..percpu : AT(ADDR(.data..percpu) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__per_cpu_load) = .; \ PERCPU_INPUT(cacheline) \ } @@ -855,25 +1134,26 @@ * matches the requirement of PAGE_ALIGNED_DATA. * * use 0 as page_align if page_aligned data is not used */ -#define RW_DATA_SECTION(cacheline, pagealigned, inittask) \ +#define RW_DATA(cacheline, pagealigned, inittask) \ . = ALIGN(PAGE_SIZE); \ .data : AT(ADDR(.data) - LOAD_OFFSET) { \ INIT_TASK_DATA(inittask) \ NOSAVE_DATA \ PAGE_ALIGNED_DATA(pagealigned) \ + CACHE_HOT_DATA(cacheline) \ CACHELINE_ALIGNED_DATA(cacheline) \ READ_MOSTLY_DATA(cacheline) \ DATA_DATA \ CONSTRUCTORS \ } \ - BUG_TABLE + BUG_TABLE \ #define INIT_TEXT_SECTION(inittext_align) \ . = ALIGN(inittext_align); \ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(_sinittext) = .; \ + _sinittext = .; \ INIT_TEXT \ - VMLINUX_SYMBOL(_einittext) = .; \ + _einittext = .; \ } #define INIT_DATA_SECTION(initsetup_align) \ @@ -882,14 +1162,13 @@ INIT_SETUP(initsetup_align) \ INIT_CALLS \ CON_INITCALL \ - SECURITY_INITCALL \ INIT_RAM_FS \ } #define BSS_SECTION(sbss_align, bss_align, stop_align) \ . = ALIGN(sbss_align); \ - VMLINUX_SYMBOL(__bss_start) = .; \ + __bss_start = .; \ SBSS(sbss_align) \ BSS(bss_align) \ . = ALIGN(stop_align); \ - VMLINUX_SYMBOL(__bss_stop) = .; + __bss_stop = .; |
