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
100*0c7d7cc2SQuanyang 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
113*0c7d7cc2SQuanyang Wang if (virt < end && vend > begin)
114*0c7d7cc2SQuanyang Wang return true;
115*0c7d7cc2SQuanyang Wang
116*0c7d7cc2SQuanyang 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
183b9ad8fe7SKefeng Wang /**
184b9ad8fe7SKefeng Wang * is_kernel_inittext - checks if the pointer address is located in the
185b9ad8fe7SKefeng Wang * .init.text section
186b9ad8fe7SKefeng Wang *
187b9ad8fe7SKefeng Wang * @addr: address to check
188b9ad8fe7SKefeng Wang *
189b9ad8fe7SKefeng Wang * Returns: true if the address is located in .init.text, false otherwise.
190b9ad8fe7SKefeng Wang */
is_kernel_inittext(unsigned long addr)191b9ad8fe7SKefeng Wang static inline bool is_kernel_inittext(unsigned long addr)
192b9ad8fe7SKefeng Wang {
193b9ad8fe7SKefeng Wang return addr >= (unsigned long)_sinittext &&
194b9ad8fe7SKefeng Wang addr < (unsigned long)_einittext;
195b9ad8fe7SKefeng Wang }
196b9ad8fe7SKefeng Wang
1978f6e42e8SKefeng Wang /**
1988f6e42e8SKefeng Wang * __is_kernel_text - checks if the pointer address is located in the
1998f6e42e8SKefeng Wang * .text section
2008f6e42e8SKefeng Wang *
2018f6e42e8SKefeng Wang * @addr: address to check
2028f6e42e8SKefeng Wang *
2038f6e42e8SKefeng Wang * Returns: true if the address is located in .text, false otherwise.
2048f6e42e8SKefeng Wang * Note: an internal helper, only check the range of _stext to _etext.
2058f6e42e8SKefeng Wang */
__is_kernel_text(unsigned long addr)2068f6e42e8SKefeng Wang static inline bool __is_kernel_text(unsigned long addr)
2078f6e42e8SKefeng Wang {
2088f6e42e8SKefeng Wang return addr >= (unsigned long)_stext &&
2098f6e42e8SKefeng Wang addr < (unsigned long)_etext;
2108f6e42e8SKefeng Wang }
2118f6e42e8SKefeng Wang
2128f6e42e8SKefeng Wang /**
2138f6e42e8SKefeng Wang * __is_kernel - checks if the pointer address is located in the kernel range
2148f6e42e8SKefeng Wang *
2158f6e42e8SKefeng Wang * @addr: address to check
2168f6e42e8SKefeng Wang *
2178f6e42e8SKefeng Wang * Returns: true if the address is located in the kernel range, false otherwise.
21816f035d9SHelge Deller * Note: an internal helper, check the range of _stext to _end,
21916f035d9SHelge Deller * and range from __init_begin to __init_end, which can be outside
22016f035d9SHelge Deller * of the _stext to _end range.
2218f6e42e8SKefeng Wang */
__is_kernel(unsigned long addr)2228f6e42e8SKefeng Wang static inline bool __is_kernel(unsigned long addr)
2238f6e42e8SKefeng Wang {
22416f035d9SHelge Deller return ((addr >= (unsigned long)_stext &&
22516f035d9SHelge Deller addr < (unsigned long)_end) ||
22616f035d9SHelge Deller (addr >= (unsigned long)__init_begin &&
22716f035d9SHelge Deller addr < (unsigned long)__init_end));
2288f6e42e8SKefeng Wang }
2298f6e42e8SKefeng Wang
2301da177e4SLinus Torvalds #endif /* _ASM_GENERIC_SECTIONS_H_ */
231