blob: 45857f0a800b8eb80f99c206c0fea385ddefad79 [file] [log] [blame]
#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 */