xref: /freebsd-src/tools/build/cross-build/include/mac/sys/linker_set.h (revision 881ec81372e0748f2869fe6c18e909afa8304e7a)
1*881ec813SJessica Clarke /*-
2*881ec813SJessica Clarke  * SPDX-License-Identifier: BSD-2-Clause
3*881ec813SJessica Clarke  *
4*881ec813SJessica Clarke  * Copyright (c) 1999 John D. Polstra
5*881ec813SJessica Clarke  * Copyright (c) 1999,2001 Peter Wemm <peter@FreeBSD.org>
6*881ec813SJessica Clarke  * All rights reserved.
7*881ec813SJessica Clarke  * Copyright (c) 2023 Jessica Clarke <jrtc27@FreeBSD.org>
8*881ec813SJessica Clarke  *
9*881ec813SJessica Clarke  * Redistribution and use in source and binary forms, with or without
10*881ec813SJessica Clarke  * modification, are permitted provided that the following conditions
11*881ec813SJessica Clarke  * are met:
12*881ec813SJessica Clarke  * 1. Redistributions of source code must retain the above copyright
13*881ec813SJessica Clarke  *    notice, this list of conditions and the following disclaimer.
14*881ec813SJessica Clarke  * 2. Redistributions in binary form must reproduce the above copyright
15*881ec813SJessica Clarke  *    notice, this list of conditions and the following disclaimer in the
16*881ec813SJessica Clarke  *    documentation and/or other materials provided with the distribution.
17*881ec813SJessica Clarke  *
18*881ec813SJessica Clarke  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*881ec813SJessica Clarke  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*881ec813SJessica Clarke  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*881ec813SJessica Clarke  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*881ec813SJessica Clarke  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*881ec813SJessica Clarke  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*881ec813SJessica Clarke  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*881ec813SJessica Clarke  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*881ec813SJessica Clarke  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*881ec813SJessica Clarke  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*881ec813SJessica Clarke  * SUCH DAMAGE.
29*881ec813SJessica Clarke  */
30*881ec813SJessica Clarke 
31*881ec813SJessica Clarke #ifndef _SYS_LINKER_SET_H_
32*881ec813SJessica Clarke #define _SYS_LINKER_SET_H_
33*881ec813SJessica Clarke 
34*881ec813SJessica Clarke #include <mach-o/dyld.h>
35*881ec813SJessica Clarke #include <mach-o/getsect.h>
36*881ec813SJessica Clarke 
37*881ec813SJessica Clarke /*
38*881ec813SJessica Clarke  * The following macros are used to declare global sets of objects, which
39*881ec813SJessica Clarke  * are collected by the linker into a `linker_set' as defined below.
40*881ec813SJessica Clarke  * For Mach-O, this is done by constructing a separate section for each set.
41*881ec813SJessica Clarke  */
42*881ec813SJessica Clarke 
43*881ec813SJessica Clarke #define	__MAKE_SET_CONST const
44*881ec813SJessica Clarke 
45*881ec813SJessica Clarke /*
46*881ec813SJessica Clarke  * Private macros, not to be used outside this header file.
47*881ec813SJessica Clarke  */
48*881ec813SJessica Clarke 
49*881ec813SJessica Clarke /*
50*881ec813SJessica Clarke  * The userspace address sanitizer inserts redzones around global variables,
51*881ec813SJessica Clarke  * violating the assumption that linker set elements are packed.
52*881ec813SJessica Clarke  */
53*881ec813SJessica Clarke #define	__NOASAN	__nosanitizeaddress
54*881ec813SJessica Clarke 
55*881ec813SJessica Clarke #define __MAKE_SET_QV(set, sym, qv)				\
56*881ec813SJessica Clarke 	static void const * qv					\
57*881ec813SJessica Clarke 	__NOASAN						\
58*881ec813SJessica Clarke 	__set_##set##_sym_##sym __section("__DATA,set_" #set)	\
59*881ec813SJessica Clarke 	__used = &(sym)
60*881ec813SJessica Clarke #define __MAKE_SET(set, sym)	__MAKE_SET_QV(set, sym, __MAKE_SET_CONST)
61*881ec813SJessica Clarke 
62*881ec813SJessica Clarke static inline __pure2 uint8_t *
__set_getsectiondata(const char * segname,const char * sectname,unsigned long * size)63*881ec813SJessica Clarke __set_getsectiondata(const char *segname, const char *sectname,
64*881ec813SJessica Clarke     unsigned long *size)
65*881ec813SJessica Clarke {
66*881ec813SJessica Clarke 	uint32_t image_count, image_index;
67*881ec813SJessica Clarke 	const struct mach_header *mh;
68*881ec813SJessica Clarke 	uint8_t *ret;
69*881ec813SJessica Clarke 
70*881ec813SJessica Clarke 	image_count = _dyld_image_count();
71*881ec813SJessica Clarke 	for (image_index = 0; image_index < image_count; ++image_index) {
72*881ec813SJessica Clarke 		mh = _dyld_get_image_header(image_index);
73*881ec813SJessica Clarke 		if (mh == NULL)
74*881ec813SJessica Clarke 			continue;
75*881ec813SJessica Clarke 
76*881ec813SJessica Clarke 		ret = getsectiondata((const struct mach_header_64 *)mh,
77*881ec813SJessica Clarke 		    segname, sectname, size);
78*881ec813SJessica Clarke 		if (ret != NULL)
79*881ec813SJessica Clarke 			return (ret);
80*881ec813SJessica Clarke 	}
81*881ec813SJessica Clarke 
82*881ec813SJessica Clarke 	return (NULL);
83*881ec813SJessica Clarke }
84*881ec813SJessica Clarke 
85*881ec813SJessica Clarke #define __SET_RANGE(set)	({					\
86*881ec813SJessica Clarke 	unsigned long __set_size;					\
87*881ec813SJessica Clarke 	char *__set_data;						\
88*881ec813SJessica Clarke 	__set_data = __set_getsectiondata("__DATA",			\
89*881ec813SJessica Clarke 	    "set_" #set, &__set_size);					\
90*881ec813SJessica Clarke 	(struct {							\
91*881ec813SJessica Clarke 		__CONCAT(__typeof_set_,set)	**begin;		\
92*881ec813SJessica Clarke 		__CONCAT(__typeof_set_,set)	**limit;		\
93*881ec813SJessica Clarke 	}){								\
94*881ec813SJessica Clarke 		.begin = (__CONCAT(__typeof_set_,set) **)__set_data,	\
95*881ec813SJessica Clarke 		.limit = (__CONCAT(__typeof_set_,set) **)(__set_data +	\
96*881ec813SJessica Clarke 		    __set_size)						\
97*881ec813SJessica Clarke 	};								\
98*881ec813SJessica Clarke })
99*881ec813SJessica Clarke 
100*881ec813SJessica Clarke /*
101*881ec813SJessica Clarke  * Public macros.
102*881ec813SJessica Clarke  */
103*881ec813SJessica Clarke #define TEXT_SET(set, sym)	__MAKE_SET(set, sym)
104*881ec813SJessica Clarke #define DATA_SET(set, sym)	__MAKE_SET(set, sym)
105*881ec813SJessica Clarke #define DATA_WSET(set, sym)	__MAKE_SET_QV(set, sym, )
106*881ec813SJessica Clarke #define BSS_SET(set, sym)	__MAKE_SET(set, sym)
107*881ec813SJessica Clarke #define ABS_SET(set, sym)	__MAKE_SET(set, sym)
108*881ec813SJessica Clarke #define SET_ENTRY(set, sym)	__MAKE_SET(set, sym)
109*881ec813SJessica Clarke 
110*881ec813SJessica Clarke /*
111*881ec813SJessica Clarke  * Initialize before referring to a given linker set.
112*881ec813SJessica Clarke  */
113*881ec813SJessica Clarke #define SET_DECLARE(set, ptype)					\
114*881ec813SJessica Clarke 	typedef ptype __CONCAT(__typeof_set_,set)
115*881ec813SJessica Clarke 
116*881ec813SJessica Clarke #define SET_BEGIN(set)							\
117*881ec813SJessica Clarke 	(__SET_RANGE(set).begin)
118*881ec813SJessica Clarke #define SET_LIMIT(set)							\
119*881ec813SJessica Clarke 	(__SET_RANGE(set).limit)
120*881ec813SJessica Clarke 
121*881ec813SJessica Clarke /*
122*881ec813SJessica Clarke  * Iterate over all the elements of a set.
123*881ec813SJessica Clarke  *
124*881ec813SJessica Clarke  * Sets always contain addresses of things, and "pvar" points to words
125*881ec813SJessica Clarke  * containing those addresses.  Thus is must be declared as "type **pvar",
126*881ec813SJessica Clarke  * and the address of each set item is obtained inside the loop by "*pvar".
127*881ec813SJessica Clarke  */
128*881ec813SJessica Clarke #define SET_FOREACH(pvar, set)						\
129*881ec813SJessica Clarke 	for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
130*881ec813SJessica Clarke 
131*881ec813SJessica Clarke #define SET_ITEM(set, i)						\
132*881ec813SJessica Clarke 	((SET_BEGIN(set))[i])
133*881ec813SJessica Clarke 
134*881ec813SJessica Clarke /*
135*881ec813SJessica Clarke  * Provide a count of the items in a set.
136*881ec813SJessica Clarke  */
137*881ec813SJessica Clarke #define SET_COUNT(set)							\
138*881ec813SJessica Clarke 	(SET_LIMIT(set) - SET_BEGIN(set))
139*881ec813SJessica Clarke 
140*881ec813SJessica Clarke #endif	/* _SYS_LINKER_SET_H_ */
141