| #ifndef _LINUX_LINKER_TABLES_H |
| #define _LINUX_LINKER_TABLES_H |
| |
| #include <linux/sections.h> |
| |
| /* |
| * Linux linker tables |
| * |
| * Copyright (C) 2005-2009 Michael Brown <mcb30@ipxe.org> |
| * 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 GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * Due to this file being licensed under the GPL 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_ALIGNMENT(name) __alignof__(__typeof__(name[0])) |
| #define LINKTABLE_SIZE(name) ((name##__end) - (name)) |
| #define LINKTABLE_EMPTY(name) (LINKTABLE_SIZE(name) == 0) |
| #define LINKTABLE_START(tbl) tbl |
| #define LINKTABLE_END(tbl) tbl##__end |
| |
| #define LINKTABLE_ADDR_WITHIN(tbl, addr) \ |
| (addr >= (unsigned long) LINKTABLE_START(tbl) && \ |
| addr < (unsigned long) LINKTABLE_END(tbl)) |
| |
| #define LINKTABLE_DATA_WEAK(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_DATA, name, level)))) |
| |
| #define LINKTABLE_TEXT_WEAK(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_TEXT, name, level)))) |
| |
| |
| #define LINKTABLE_RO_WEAK(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_RODATA, name, level)))) |
| |
| #define LINKTABLE_INIT_WEAK(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_INIT, name, level)))) |
| |
| #define LINKTABLE_INIT_DATA_WEAK(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| weak, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_INIT_DATA, name, level)))) |
| |
| #define LINKTABLE_TEXT(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_TEXT, name, level)))) |
| |
| #define LINKTABLE_DATA(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_DATA, name, level)))) |
| #define LINKTABLE_RO(name, level) \ |
| const __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_RODATA, name, level)))) |
| |
| #define LINKTABLE_INIT(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_INIT, name, level)))) |
| #define LINKTABLE_INIT_DATA(name, level) \ |
| __typeof__(name[0]) \ |
| __attribute__((used, \ |
| __aligned__(LINKTABLE_ALIGNMENT(name)), \ |
| section(SECTION_TBL(SECTION_INIT_DATA, name, level)))) |
| |
| #define DECLARE_LINKTABLE_TEXT(type, name) \ |
| extern type name[], name##__end[]; |
| |
| #define DECLARE_LINKTABLE_DATA(type, name) \ |
| extern type name[], name##__end[]; |
| |
| #define DECLARE_LINKTABLE_RO(type, name) \ |
| extern const type name[], name##__end[]; |
| |
| #define DECLARE_LINKTABLE_INIT(type, name) \ |
| extern type name[], name##__end[]; |
| |
| #define DECLARE_LINKTABLE_INIT_DATA(type, name) \ |
| extern type name[], name##__end[]; |
| |
| |
| #define DEFINE_LINKTABLE_TEXT(type, name) \ |
| DECLARE_LINKTABLE_TEXT(type, name); \ |
| LINKTABLE_TEXT_WEAK(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_DATA(type, name) \ |
| DECLARE_LINKTABLE_DATA(type, name); \ |
| LINKTABLE_DATA_WEAK(name, ) VMLINUX_SYMBOL(name)[0] = {}; \ |
| LTO_REFERENCE_INITCALL(name); \ |
| LINKTABLE_DATA(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_INIT(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_INIT_DATA(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 = LINKTABLE_START(tbl); \ |
| pointer < LINKTABLE_END(tbl); \ |
| pointer++) |
| |
| #define LINKTABLE_RUN_ALL(tbl, func, args...) \ |
| do { \ |
| size_t i; \ |
| for (i = 0; i < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++) \ |
| err = (tbl[i]).func (args); \ |
| err; \ |
| }) |
| |
| #endif /* _LINUX_LINKER_TABLES_H */ |