1/* 2 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/*- 29 * Copyright (c) 1999 John D. Polstra 30 * All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 */ 54 55#ifndef _SYS_LINKER_SET_H_ 56#define _SYS_LINKER_SET_H_ 57 58#include <sys/appleapiopts.h> 59#if !defined(KERNEL) || defined(__APPLE_API_PRIVATE) 60 61/* 62 * The following macros are used to declare global sets of objects, which 63 * are collected by the linker into a `linker set' as defined below. 64 * For Mach-O, this is done by constructing a separate segment inside the 65 * __DATA section for each set. The contents of this segment are an array 66 * of pointers to the objects in the set. 67 * 68 * Note that due to limitations of the Mach-O format, there cannot 69 * be more than 255 sections in a segment, so linker set usage should be 70 * conserved. Set names may not exceed 16 characters. 71 */ 72 73#ifdef KERNEL 74# define MACH_KERNEL 1 75# include "mach-o/loader.h" 76typedef int _ls_size_t; 77# ifndef _KERN_MACH_HEADER_ 78extern void *getsectdatafromheader(struct mach_header *, const char *, const char *, _ls_size_t *); 79extern struct mach_header _mh_execute_header; 80# endif 81#else 82# include <mach-o/ldsyms.h> 83# include <mach-o/getsect.h> 84# include <mach-o/loader.h> 85typedef unsigned long _ls_size_t; 86#endif 87 88 89/* 90 * Private macros, not to be used outside this header file. 91 * 92 * The objective of this macro stack is to produce the following output, 93 * given SET and SYM as arguments: 94 * 95 * void const * __set_SET_sym_SYM __attribute__((section("__DATA,SET"))) = & SYM 96 */ 97#ifdef __LS_VA_STRINGIFY__ 98# undef __LS_VA_STRINGIFY__ 99#endif 100#ifdef __LS_VA_STRCONCAT__ 101# undef __LS_VA_STRCONCAT__ 102#endif 103#define __LS_VA_STRINGIFY(_x...) #_x 104#define __LS_VA_STRCONCAT(_x,_y) __LS_VA_STRINGIFY(_x,_y) 105#define __LINKER_MAKE_SET(_set, _sym) \ 106 /*__unused*/ /*static*/ void const * /*const*/ __set_##_set##_sym_##_sym \ 107 __attribute__ ((section(__LS_VA_STRCONCAT(__DATA,_set)))) = (void *)&_sym 108/* the line above is very fragile - if your compiler breaks linker sets, 109 just play around with "static", "const" etc. :-) */ 110 111/* 112 * Public macros. 113 */ 114#define LINKER_SET_ENTRY(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 115 116/* 117 * FreeBSD compatibility. 118 */ 119#ifdef __APPLE_API_OBSOLETE 120# define TEXT_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 121# define DATA_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 122# define BSS_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 123# define ABS_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 124# define SET_ENTRY(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 125#endif /* __APPLE_API_OBSOLETE */ 126 127/* 128 * Extended linker set API. 129 * 130 * Since linker sets are per-object-file, and we may have multiple 131 * object files, we need to be able to specify which object's set 132 * to scan. 133 * 134 * The set itself is a contiguous array of pointers to the objects 135 * within the set. 136 */ 137 138/* 139 * Public interface. 140 * 141 * void **LINKER_SET_OBJECT_BEGIN(_object, _set) 142 * Preferred interface to linker_set_object_begin(), takes set name unquoted. 143 * void **LINKER_SET_OBJECT_LIMIT(_object, _set) 144 * Preferred interface to linker_set_object_begin(), takes set name unquoted. 145 * LINKER_SET_OBJECT_FOREACH(_object, (set_member_type **)_pvar, _set) 146 * Iterates over the members of _set within _object. Since the set contains 147 * pointers to its elements, for a set of elements of type etyp, _pvar must 148 * be (etyp **). 149 * set_member_type **LINKER_SET_OBJECT_ITEM(_object, _set, _i) 150 * Returns a pointer to the _i'th element of _set within _object. 151 * 152 * void **LINKER_SET_BEGIN(_set) 153 * void **LINKER_SET_LIMINT(_set) 154 * LINKER_SET_FOREACH((set_member_type **)_pvar, _set) 155 * set_member_type **LINKER_SET_ITEM(_set, _i) 156 * These versions implicitly reference the kernel/application object. 157 */ 158 159#define LINKER_SET_OBJECT_BEGIN(_object, _set) __linker_set_object_begin(_object, _set) 160#define LINKER_SET_OBJECT_LIMIT(_object, _set) __linker_set_object_limit(_object, _set) 161 162#define LINKER_SET_OBJECT_FOREACH(_object, _pvar, _set) \ 163 for ((void **)_pvar = LINKER_SET_OBJECT_BEGIN(_object, _set); \ 164 (void **)_pvar < LINKER_SET_OBJECT_LIMIT(_object, _set); \ 165 ((void **)_pvar)++) 166 167#define LINKER_SET_OBJECT_ITEM(_object, _set, _i) \ 168 ((LINKER_SET_OBJECT_BEGIN(_object, _set))[_i]) 169 170#define LINKER_SET_BEGIN(_set) \ 171 LINKER_SET_OBJECT_BEGIN((struct mach_header *)&_mh_execute_header, _set) 172#define LINKER_SET_LIMIT(_set) \ 173 LINKER_SET_OBJECT_LIMIT((struct mach_header *)&_mh_execute_header, _set) 174#define LINKER_SET_FOREACH(_pvar, _set) \ 175 LINKER_SET_OBJECT_FOREACH((struct mach_header *)&_mh_execute_header, _pvar, _set) 176#define LINKER_SET_ITEM(_set, _i) \ 177 LINKER_SET_OBJECT_ITEM((struct mach_header *)&_mh_execute_header, _set, _i) 178 179/* 180 * Implementation. 181 * 182 * void **__linker_set_object_begin(_header, _set) 183 * Returns a pointer to the first pointer in the linker set. 184 * void **__linker_set_object_limi(_header, _set) 185 * Returns an upper bound to the linker set (base + size). 186 */ 187 188static __inline void ** 189__linker_set_object_begin(struct mach_header *_header, const char *_set) 190 __attribute__((__const__)); 191static __inline void ** 192__linker_set_object_begin(struct mach_header *_header, const char *_set) 193{ 194 void *_set_begin; 195 _ls_size_t _size; 196 197 _set_begin = getsectdatafromheader(_header, "__DATA", _set, &_size); 198 return((void **)_set_begin); 199} 200 201static __inline void ** 202__linker_set_object_limit(struct mach_header *_header, const char *_set) 203 __attribute__((__const__)); 204static __inline void ** 205__linker_set_object_limit(struct mach_header *_header, const char *_set) 206{ 207 void *_set_begin; 208 _ls_size_t _size; 209 210 _set_begin = getsectdatafromheader(_header, "__DATA", _set, &_size); 211 return((void **)((uintptr_t)_set_begin + _size)); 212} 213 214#endif /* !KERNEL || __APPLE_API_PRIVATE */ 215 216#endif /* _SYS_LINKER_SET_H_ */ 217 218 219