xref: /linux/include/asm-generic/sections.h (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds #ifndef _ASM_GENERIC_SECTIONS_H_
31da177e4SLinus Torvalds #define _ASM_GENERIC_SECTIONS_H_
41da177e4SLinus Torvalds 
51da177e4SLinus Torvalds /* References to section boundaries */
61da177e4SLinus Torvalds 
77f8998c7SGeert Uytterhoeven #include <linux/compiler.h>
897955936SThierry Reding #include <linux/types.h>
97f8998c7SGeert Uytterhoeven 
101622d1abSJiang Liu /*
111622d1abSJiang Liu  * Usage guidelines:
121622d1abSJiang Liu  * _text, _data: architecture specific, don't use them in arch-independent code
131622d1abSJiang Liu  * [_stext, _etext]: contains .text.* sections, may also contain .rodata.*
141622d1abSJiang Liu  *                   and/or .init.* sections
151622d1abSJiang Liu  * [_sdata, _edata]: contains .data.* sections, may also contain .rodata.*
161622d1abSJiang Liu  *                   and/or .init.* sections.
171622d1abSJiang Liu  * [__start_rodata, __end_rodata]: contains .rodata.* sections
18906f2a51SKees Cook  * [__start_ro_after_init, __end_ro_after_init]:
19906f2a51SKees Cook  *		     contains .data..ro_after_init section
201622d1abSJiang Liu  * [__init_begin, __init_end]: contains .init.* sections, but .init.text.*
211622d1abSJiang Liu  *                   may be out of this range on some architectures.
221622d1abSJiang Liu  * [_sinittext, _einittext]: contains .init.text.* sections
231622d1abSJiang Liu  * [__bss_start, __bss_stop]: contains BSS sections
241622d1abSJiang Liu  *
251622d1abSJiang Liu  * Following global variables are optional and may be unavailable on some
261622d1abSJiang Liu  * architectures and/or kernel configurations.
271622d1abSJiang Liu  *	_text, _data
281622d1abSJiang Liu  *	__kprobes_text_start, __kprobes_text_end
291622d1abSJiang Liu  *	__entry_text_start, __entry_text_end
301622d1abSJiang Liu  *	__ctors_start, __ctors_end
31229a7186SMasami Hiramatsu  *	__irqentry_text_start, __irqentry_text_end
32229a7186SMasami Hiramatsu  *	__softirqentry_text_start, __softirqentry_text_end
33b865ea64SSergey Senozhatsky  *	__start_opd, __end_opd
341622d1abSJiang Liu  */
351da177e4SLinus Torvalds extern char _text[], _stext[], _etext[];
361da177e4SLinus Torvalds extern char _data[], _sdata[], _edata[];
371da177e4SLinus Torvalds extern char __bss_start[], __bss_stop[];
381da177e4SLinus Torvalds extern char __init_begin[], __init_end[];
391da177e4SLinus Torvalds extern char _sinittext[], _einittext[];
40906f2a51SKees Cook extern char __start_ro_after_init[], __end_ro_after_init[];
411da177e4SLinus Torvalds extern char _end[];
423e5d8f97STejun Heo extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
43d0aaff97SPrasanna S Panchamukhi extern char __kprobes_text_start[], __kprobes_text_end[];
44ea714547SJiri Olsa extern char __entry_text_start[], __entry_text_end[];
45a581c2a4SHeiko Carstens extern char __start_rodata[], __end_rodata[];
46229a7186SMasami Hiramatsu extern char __irqentry_text_start[], __irqentry_text_end[];
47229a7186SMasami Hiramatsu extern char __softirqentry_text_start[], __softirqentry_text_end[];
48b1fca27dSAndi Kleen extern char __start_once[], __end_once[];
491da177e4SLinus Torvalds 
50b99b87f7SPeter Oberparleiter /* Start and end of .ctors section - used for constructor calls. */
51b99b87f7SPeter Oberparleiter extern char __ctors_start[], __ctors_end[];
52b99b87f7SPeter Oberparleiter 
53b865ea64SSergey Senozhatsky /* Start and end of .opd section - used for function descriptors. */
54b865ea64SSergey Senozhatsky extern char __start_opd[], __end_opd[];
55b865ea64SSergey Senozhatsky 
5665538966SThomas Gleixner /* Start and end of instrumentation protected text section */
5765538966SThomas Gleixner extern char __noinstr_text_start[], __noinstr_text_end[];
5865538966SThomas Gleixner 
597f8998c7SGeert Uytterhoeven extern __visible const void __nosave_begin, __nosave_end;
607f8998c7SGeert Uytterhoeven 
61b865ea64SSergey Senozhatsky /* Function descriptor handling (if any).  Override in asm/sections.h */
62a257caccSChristophe Leroy #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS
63e1478d8eSChristophe Leroy void *dereference_function_descriptor(void *ptr);
64e1478d8eSChristophe Leroy void *dereference_kernel_function_descriptor(void *ptr);
65a257caccSChristophe Leroy #else
6660e5da62SHelge Deller #define dereference_function_descriptor(p) ((void *)(p))
6760e5da62SHelge Deller #define dereference_kernel_function_descriptor(p) ((void *)(p))
680dc690e4SChristophe Leroy 
690dc690e4SChristophe Leroy /* An address is simply the address of the function. */
700dc690e4SChristophe Leroy typedef struct {
710dc690e4SChristophe Leroy 	unsigned long addr;
720dc690e4SChristophe Leroy } func_desc_t;
73deac93dfSJames Bottomley #endif
74deac93dfSJames Bottomley 
have_function_descriptors(void)75a257caccSChristophe Leroy static inline bool have_function_descriptors(void)
76a257caccSChristophe Leroy {
77a257caccSChristophe Leroy 	return IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS);
78a257caccSChristophe Leroy }
79a257caccSChristophe Leroy 
8097955936SThierry Reding /**
8197955936SThierry Reding  * memory_contains - checks if an object is contained within a memory region
8297955936SThierry Reding  * @begin: virtual address of the beginning of the memory region
8397955936SThierry Reding  * @end: virtual address of the end of the memory region
8497955936SThierry Reding  * @virt: virtual address of the memory object
8597955936SThierry Reding  * @size: size of the memory object
8697955936SThierry Reding  *
8797955936SThierry Reding  * Returns: true if the object specified by @virt and @size is entirely
8897955936SThierry Reding  * contained within the memory region defined by @begin and @end, false
8997955936SThierry Reding  * otherwise.
9097955936SThierry Reding  */
memory_contains(void * begin,void * end,void * virt,size_t size)9197955936SThierry Reding static inline bool memory_contains(void *begin, void *end, void *virt,
9297955936SThierry Reding 				   size_t size)
9397955936SThierry Reding {
9497955936SThierry Reding 	return virt >= begin && virt + size <= end;
9597955936SThierry Reding }
9697955936SThierry Reding 
9797955936SThierry Reding /**
9897955936SThierry Reding  * memory_intersects - checks if the region occupied by an object intersects
9997955936SThierry Reding  *                     with another memory region
1000c7d7cc2SQuanyang Wang  * @begin: virtual address of the beginning of the memory region
10197955936SThierry Reding  * @end: virtual address of the end of the memory region
10297955936SThierry Reding  * @virt: virtual address of the memory object
10397955936SThierry Reding  * @size: size of the memory object
10497955936SThierry Reding  *
10597955936SThierry Reding  * Returns: true if an object's memory region, specified by @virt and @size,
10697955936SThierry Reding  * intersects with the region specified by @begin and @end, false otherwise.
10797955936SThierry Reding  */
memory_intersects(void * begin,void * end,void * virt,size_t size)10897955936SThierry Reding static inline bool memory_intersects(void *begin, void *end, void *virt,
10997955936SThierry Reding 				     size_t size)
11097955936SThierry Reding {
11197955936SThierry Reding 	void *vend = virt + size;
11297955936SThierry Reding 
1130c7d7cc2SQuanyang Wang 	if (virt < end && vend > begin)
1140c7d7cc2SQuanyang Wang 		return true;
1150c7d7cc2SQuanyang Wang 
1160c7d7cc2SQuanyang Wang 	return false;
11797955936SThierry Reding }
11897955936SThierry Reding 
11997955936SThierry Reding /**
12097955936SThierry Reding  * init_section_contains - checks if an object is contained within the init
12197955936SThierry Reding  *                         section
12297955936SThierry Reding  * @virt: virtual address of the memory object
12397955936SThierry Reding  * @size: size of the memory object
12497955936SThierry Reding  *
12597955936SThierry Reding  * Returns: true if the object specified by @virt and @size is entirely
12697955936SThierry Reding  * contained within the init section, false otherwise.
12797955936SThierry Reding  */
init_section_contains(void * virt,size_t size)12897955936SThierry Reding static inline bool init_section_contains(void *virt, size_t size)
12997955936SThierry Reding {
13097955936SThierry Reding 	return memory_contains(__init_begin, __init_end, virt, size);
13197955936SThierry Reding }
13297955936SThierry Reding 
13397955936SThierry Reding /**
13497955936SThierry Reding  * init_section_intersects - checks if the region occupied by an object
13597955936SThierry Reding  *                           intersects with the init section
13697955936SThierry Reding  * @virt: virtual address of the memory object
13797955936SThierry Reding  * @size: size of the memory object
13897955936SThierry Reding  *
13997955936SThierry Reding  * Returns: true if an object's memory region, specified by @virt and @size,
14097955936SThierry Reding  * intersects with the init section, false otherwise.
14197955936SThierry Reding  */
init_section_intersects(void * virt,size_t size)14297955936SThierry Reding static inline bool init_section_intersects(void *virt, size_t size)
14397955936SThierry Reding {
14497955936SThierry Reding 	return memory_intersects(__init_begin, __init_end, virt, size);
14597955936SThierry Reding }
14697955936SThierry Reding 
14759c3f82aSBartosz Golaszewski /**
148a20deb3aSKefeng Wang  * is_kernel_core_data - checks if the pointer address is located in the
149cb902b33SAntoine Tenart  *			 .data or .bss section
150a20deb3aSKefeng Wang  *
151a20deb3aSKefeng Wang  * @addr: address to check
152a20deb3aSKefeng Wang  *
153cb902b33SAntoine Tenart  * Returns: true if the address is located in .data or .bss, false otherwise.
154a20deb3aSKefeng Wang  * Note: On some archs it may return true for core RODATA, and false
155a20deb3aSKefeng Wang  *       for others. But will always be true for core RW data.
156a20deb3aSKefeng Wang  */
is_kernel_core_data(unsigned long addr)157a20deb3aSKefeng Wang static inline bool is_kernel_core_data(unsigned long addr)
158a20deb3aSKefeng Wang {
159cb902b33SAntoine Tenart 	if (addr >= (unsigned long)_sdata && addr < (unsigned long)_edata)
160cb902b33SAntoine Tenart 		return true;
161cb902b33SAntoine Tenart 
162cb902b33SAntoine Tenart 	if (addr >= (unsigned long)__bss_start &&
163cb902b33SAntoine Tenart 	    addr < (unsigned long)__bss_stop)
164cb902b33SAntoine Tenart 		return true;
165cb902b33SAntoine Tenart 
166cb902b33SAntoine Tenart 	return false;
167a20deb3aSKefeng Wang }
168a20deb3aSKefeng Wang 
169a20deb3aSKefeng Wang /**
17059c3f82aSBartosz Golaszewski  * is_kernel_rodata - checks if the pointer address is located in the
17159c3f82aSBartosz Golaszewski  *                    .rodata section
17259c3f82aSBartosz Golaszewski  *
17359c3f82aSBartosz Golaszewski  * @addr: address to check
17459c3f82aSBartosz Golaszewski  *
17559c3f82aSBartosz Golaszewski  * Returns: true if the address is located in .rodata, false otherwise.
17659c3f82aSBartosz Golaszewski  */
is_kernel_rodata(unsigned long addr)17759c3f82aSBartosz Golaszewski static inline bool is_kernel_rodata(unsigned long addr)
17859c3f82aSBartosz Golaszewski {
17959c3f82aSBartosz Golaszewski 	return addr >= (unsigned long)__start_rodata &&
18059c3f82aSBartosz Golaszewski 	       addr < (unsigned long)__end_rodata;
18159c3f82aSBartosz Golaszewski }
18259c3f82aSBartosz Golaszewski 
is_kernel_ro_after_init(unsigned long addr)183*91a1d97eSPeter Zijlstra static inline bool is_kernel_ro_after_init(unsigned long addr)
184*91a1d97eSPeter Zijlstra {
185*91a1d97eSPeter Zijlstra 	return addr >= (unsigned long)__start_ro_after_init &&
186*91a1d97eSPeter Zijlstra 	       addr < (unsigned long)__end_ro_after_init;
187*91a1d97eSPeter Zijlstra }
188b9ad8fe7SKefeng Wang /**
189b9ad8fe7SKefeng Wang  * is_kernel_inittext - checks if the pointer address is located in the
190b9ad8fe7SKefeng Wang  *                      .init.text section
191b9ad8fe7SKefeng Wang  *
192b9ad8fe7SKefeng Wang  * @addr: address to check
193b9ad8fe7SKefeng Wang  *
194b9ad8fe7SKefeng Wang  * Returns: true if the address is located in .init.text, false otherwise.
195b9ad8fe7SKefeng Wang  */
is_kernel_inittext(unsigned long addr)196b9ad8fe7SKefeng Wang static inline bool is_kernel_inittext(unsigned long addr)
197b9ad8fe7SKefeng Wang {
198b9ad8fe7SKefeng Wang 	return addr >= (unsigned long)_sinittext &&
199b9ad8fe7SKefeng Wang 	       addr < (unsigned long)_einittext;
200b9ad8fe7SKefeng Wang }
201b9ad8fe7SKefeng Wang 
2028f6e42e8SKefeng Wang /**
2038f6e42e8SKefeng Wang  * __is_kernel_text - checks if the pointer address is located in the
2048f6e42e8SKefeng Wang  *                    .text section
2058f6e42e8SKefeng Wang  *
2068f6e42e8SKefeng Wang  * @addr: address to check
2078f6e42e8SKefeng Wang  *
2088f6e42e8SKefeng Wang  * Returns: true if the address is located in .text, false otherwise.
2098f6e42e8SKefeng Wang  * Note: an internal helper, only check the range of _stext to _etext.
2108f6e42e8SKefeng Wang  */
__is_kernel_text(unsigned long addr)2118f6e42e8SKefeng Wang static inline bool __is_kernel_text(unsigned long addr)
2128f6e42e8SKefeng Wang {
2138f6e42e8SKefeng Wang 	return addr >= (unsigned long)_stext &&
2148f6e42e8SKefeng Wang 	       addr < (unsigned long)_etext;
2158f6e42e8SKefeng Wang }
2168f6e42e8SKefeng Wang 
2178f6e42e8SKefeng Wang /**
2188f6e42e8SKefeng Wang  * __is_kernel - checks if the pointer address is located in the kernel range
2198f6e42e8SKefeng Wang  *
2208f6e42e8SKefeng Wang  * @addr: address to check
2218f6e42e8SKefeng Wang  *
2228f6e42e8SKefeng Wang  * Returns: true if the address is located in the kernel range, false otherwise.
22316f035d9SHelge Deller  * Note: an internal helper, check the range of _stext to _end,
22416f035d9SHelge Deller  *       and range from __init_begin to __init_end, which can be outside
22516f035d9SHelge Deller  *       of the _stext to _end range.
2268f6e42e8SKefeng Wang  */
__is_kernel(unsigned long addr)2278f6e42e8SKefeng Wang static inline bool __is_kernel(unsigned long addr)
2288f6e42e8SKefeng Wang {
22916f035d9SHelge Deller 	return ((addr >= (unsigned long)_stext &&
23016f035d9SHelge Deller 	         addr < (unsigned long)_end) ||
23116f035d9SHelge Deller 		(addr >= (unsigned long)__init_begin &&
23216f035d9SHelge Deller 		 addr < (unsigned long)__init_end));
2338f6e42e8SKefeng Wang }
2348f6e42e8SKefeng Wang 
2351da177e4SLinus Torvalds #endif /* _ASM_GENERIC_SECTIONS_H_ */
236