blob: 2e671cb3bce24dc56648a0284671c1a7279845a2 [file] [log] [blame]
#ifndef _LINUX_LINKER_TABLES_H
#define _LINUX_LINKER_TABLES_H
#include <linux/sections.h>
#define SECTION_TYPE_TABLES tbl
#define SECTION_TBL(section, name, level) \
SECTION_TYPE(section, SECTION_TYPE_TABLES, name, level)
#ifdef __ASSEMBLER__
#define push_section_tbl(section, name, level, flags) \
push_section_type(section, SECTION_TYPE_TABLES, name, level, flags)
#define DECLARE_SECTION_TBL(section, name) \
push_section_tbl(section, name,,) ; \
.globl name ; \
name: ; \
.popsection \
\
push_section_tbl(section, name, ~,) ; \
.popsection
#else
#ifndef __ASSEMBLY__
/*
* 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; \
})
#define push_section_tbl(section, name, level, flags) \
push_section(section, SECTION_TYPE_TABLES, name, level, flags)
#endif /* __ASSEMBLY__ */
#endif /* __ASSEMBLER__ */
#define SECTION_TBL_ALL(section) \
SECTION_TYPE_ALL(section,SECTION_TYPE_TABLES)
#endif /* _LINUX_LINKER_TABLES_H */