| #ifndef _LINUX_LINKER_TABLES_H |
| #define _LINUX_LINKER_TABLES_H |
| |
| #include <linux/sections.h> |
| |
| #define SECTION_TYPE_TABLES tbl |
| |
| #ifndef __ASSEMBLY__ |
| |
| #define SECTION_TBL(section, name, level) \ |
| SECTION_TYPE(section, SECTION_TYPE_TABLES, name, level) |
| |
| /* |
| * Linux linker tables |
| * |
| * Copyright (C) 2015-2016 Luis R. Rodriguez <mcgrof@kernel.org> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the copyleft-next >= 0.3.1 license as published |
| * online and available at the following URL: |
| * |
| * https://github.com/copyleft-next/copyleft-next |
| * |
| * Due to this file being licensed under coplyleft-next there is controversy |
| * over whether this permits you to write a module that #includes this file |
| * without placing your module under the GPL. Please consult a lawyer for |
| * advice before doing this. |
| */ |
| |
| /* This is a trimmed version with no documentation */ |
| |
| #define LINKTABLE_ADDR_WITHIN(tbl, addr) \ |
| (addr >= (unsigned long) LINUX_SECTION_START(tbl) && \ |
| addr < (unsigned long) LINUX_SECTION_END(tbl)) |
| |
| #define LINKTABLE_WEAK(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_DATA, name, level)))) |
| |
| #define LINKTABLE_TEXT_WEAK(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_TEXT, name, level)))) |
| |
| |
| #define LINKTABLE_RO_WEAK(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_RODATA, name, level)))) |
| |
| #define LINKTABLE_INIT_WEAK(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_INIT, name, level)))) |
| |
| #define LINKTABLE_INIT_DATA_WEAK(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_INIT_DATA, name, level)))) |
| |
| #define LINKTABLE(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_DATA, name, level)))) |
| |
| #define LINKTABLE_TEXT(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_TEXT, name, level)))) |
| |
| #define LINKTABLE_RO(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_RODATA, name, level)))) |
| |
| #define LINKTABLE_INIT(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINUX_SECTION_ALIGN_FUNC), \ |
| section(SECTION_TBL(SECTION_INIT, name, level)))) |
| #define LINKTABLE_INIT_DATA(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINUX_SECTION_ALIGNMENT(name)),\ |
| section(SECTION_TBL(SECTION_INIT_DATA, name, level)))) |
| |
| #define DECLARE_LINKTABLE(type, name) \ |
| DECLARE_LINUX_SECTION(type, name) |
| |
| #define DECLARE_LINKTABLE_RO(type, name) \ |
| DECLARE_LINUX_SECTION_RO(type, name) |
| |
| #define DEFINE_LINKTABLE(type, name) \ |
| DECLARE_LINKTABLE(type, name); \ |
| LINKTABLE_WEAK(name, ) VMLINUX_SYMBOL(name)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name); \ |
| LINKTABLE(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name##__end); |
| |
| #define DEFINE_LINKTABLE_TEXT(type, name) \ |
| DECLARE_LINKTABLE_RO(type, name); \ |
| LINKTABLE_WEAK_TEXT(name, ) VMLINUX_SYMBOL(name)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name); \ |
| LINKTABLE_TEXT(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name##__end); |
| |
| #define DEFINE_LINKTABLE_RO(type, name) \ |
| DECLARE_LINKTABLE_RO(type, name); \ |
| LINKTABLE_RO_WEAK(name, ) VMLINUX_SYMBOL(name)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name); \ |
| LINKTABLE_RO(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name##__end); |
| |
| #define DEFINE_LINKTABLE_INIT(type, name) \ |
| DECLARE_LINKTABLE(type, name); \ |
| LINKTABLE_INIT_WEAK(name, ) VMLINUX_SYMBOL(name)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name); \ |
| LINKTABLE_INIT(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name##__end); |
| |
| #define DEFINE_LINKTABLE_INIT_DATA(type, name) \ |
| DECLARE_LINKTABLE(type, name); \ |
| LINKTABLE_INIT_DATA_WEAK(name, ) VMLINUX_SYMBOL(name)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name); \ |
| LINKTABLE_INIT_DATA(name, ~) VMLINUX_SYMBOL(name##__end)[0] = {};\ |
| LTO_REFERENCE_INITCALL(name##__end); |
| |
| #define LINKTABLE_FOR_EACH(pointer, tbl) \ |
| for (pointer = LINUX_SECTION_START(tbl); \ |
| pointer < LINUX_SECTION_END(tbl); \ |
| pointer++) |
| |
| #define LINKTABLE_RUN_ALL(tbl, func, args...) \ |
| do { \ |
| size_t i; \ |
| for (i = 0; i < LINUX_SECTION_SIZE(tbl); i++) \ |
| (tbl[i]).func (args); \ |
| } while (0); |
| |
| #define LINKTABLE_RUN_ERR(tbl, func, args...) \ |
| ({ \ |
| size_t i; \ |
| int err = 0; \ |
| for (i = 0; !err && i < LINUX_SECTION_SIZE(tbl); i++) \ |
| err = (tbl[i]).func (args); \ |
| err; \ |
| }) |
| |
| #endif /* __ASSEMBLY__ */ |
| |
| #define SECTION_TBL_ALL(section) \ |
| SECTION_TYPE_ALL(section,SECTION_TYPE_TABLES) |
| |
| #endif /* _LINUX_LINKER_TABLES_H */ |