1/* 2 * Copyright (c) 2006-2008 Apple 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# include <mach-o/loader.h> 75# include <libkern/kernel_mach_header.h> 76#else 77# include <mach-o/ldsyms.h> 78# include <mach-o/getsect.h> 79# include <mach-o/loader.h> 80#endif 81 82 83/* 84 * Private macros, not to be used outside this header file. 85 * 86 * The objective of this macro stack is to produce the following output, 87 * given SET and SYM as arguments: 88 * 89 * void const * __set_SET_sym_SYM __attribute__((section("__DATA,SET"))) = & SYM 90 */ 91#ifdef __LS_VA_STRINGIFY__ 92# undef __LS_VA_STRINGIFY__ 93#endif 94#ifdef __LS_VA_STRCONCAT__ 95# undef __LS_VA_STRCONCAT__ 96#endif 97#define __LS_VA_STRINGIFY(_x...) #_x 98#define __LS_VA_STRCONCAT(_x,_y) __LS_VA_STRINGIFY(_x,_y) 99#define __LINKER_MAKE_SET(_set, _sym) \ 100 /*__unused*/ /*static*/ void const * /*const*/ __set_##_set##_sym_##_sym \ 101 __attribute__ ((section(__LS_VA_STRCONCAT(__DATA,_set)),used)) = (void *)&_sym 102/* the line above is very fragile - if your compiler breaks linker sets, 103 just play around with "static", "const", "used" etc. :-) */ 104 105/* 106 * Public macros. 107 */ 108#define LINKER_SET_ENTRY(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 109 110/* 111 * FreeBSD compatibility. 112 */ 113#ifdef __APPLE_API_OBSOLETE 114# define TEXT_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 115# define DATA_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 116# define BSS_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 117# define ABS_SET(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 118# define SET_ENTRY(_set, _sym) __LINKER_MAKE_SET(_set, _sym) 119#endif /* __APPLE_API_OBSOLETE */ 120 121/* 122 * Extended linker set API. 123 * 124 * Since linker sets are per-object-file, and we may have multiple 125 * object files, we need to be able to specify which object's set 126 * to scan. 127 * 128 * The set itself is a contiguous array of pointers to the objects 129 * within the set. 130 */ 131 132/* 133 * Public interface. 134 * 135 * void **LINKER_SET_OBJECT_BEGIN(_object, _set) 136 * Preferred interface to linker_set_object_begin(), takes set name unquoted. 137 * void **LINKER_SET_OBJECT_LIMIT(_object, _set) 138 * Preferred interface to linker_set_object_begin(), takes set name unquoted. 139 * LINKER_SET_OBJECT_FOREACH(_object, (set_member_type **)_pvar, _cast, _set) 140 * Iterates over the members of _set within _object. Since the set contains 141 * pointers to its elements, for a set of elements of type etyp, _pvar must 142 * be (etyp **). 143 * set_member_type **LINKER_SET_OBJECT_ITEM(_object, _set, _i) 144 * Returns a pointer to the _i'th element of _set within _object. 145 * 146 * void **LINKER_SET_BEGIN(_set) 147 * void **LINKER_SET_LIMINT(_set) 148 * LINKER_SET_FOREACH((set_member_type **)_pvar, _cast, _set) 149 * set_member_type **LINKER_SET_ITEM(_set, _i) 150 * These versions implicitly reference the kernel/application object. 151 * 152 * Example of _cast: For the _pvar "struct sysctl_oid **oidpp", _cast would be 153 * "struct sysctl_oid **" 154 * 155 */ 156 157#define LINKER_SET_OBJECT_BEGIN(_object, _set) __linker_set_object_begin(_object, _set) 158#define LINKER_SET_OBJECT_LIMIT(_object, _set) __linker_set_object_limit(_object, _set) 159 160#define LINKER_SET_OBJECT_FOREACH(_object, _pvar, _cast, _set) \ 161 for (_pvar = (_cast) LINKER_SET_OBJECT_BEGIN(_object, _set); \ 162 _pvar < (_cast) LINKER_SET_OBJECT_LIMIT(_object, _set); \ 163 _pvar++) 164 165#define LINKER_SET_OBJECT_ITEM(_object, _set, _i) \ 166 ((LINKER_SET_OBJECT_BEGIN(_object, _set))[_i]) 167 168#define LINKER_SET_BEGIN(_set) \ 169 LINKER_SET_OBJECT_BEGIN((kernel_mach_header_t *)&_mh_execute_header, _set) 170#define LINKER_SET_LIMIT(_set) \ 171 LINKER_SET_OBJECT_LIMIT((kernel_mach_header_t *)&_mh_execute_header, _set) 172#define LINKER_SET_FOREACH(_pvar, _cast, _set) \ 173 LINKER_SET_OBJECT_FOREACH((kernel_mach_header_t *)&_mh_execute_header, _pvar, _cast, _set) 174#define LINKER_SET_ITEM(_set, _i) \ 175 LINKER_SET_OBJECT_ITEM((kernel_mach_header_t *)&_mh_execute_header, _set, _i) 176 177/* 178 * Implementation. 179 * 180 * void **__linker_set_object_begin(_header, _set) 181 * Returns a pointer to the first pointer in the linker set. 182 * void **__linker_set_object_limi(_header, _set) 183 * Returns an upper bound to the linker set (base + size). 184 */ 185 186static __inline void ** 187__linker_set_object_begin(kernel_mach_header_t *_header, const char *_set) 188 __attribute__((__const__)); 189static __inline void ** 190__linker_set_object_begin(kernel_mach_header_t *_header, const char *_set) 191{ 192 void *_set_begin; 193 unsigned long _size; 194 195 _set_begin = getsectdatafromheader(_header, "__DATA", _set, &_size); 196 return( (void **) _set_begin ); 197} 198 199static __inline void ** 200__linker_set_object_limit(kernel_mach_header_t *_header, const char *_set) 201 __attribute__((__const__)); 202static __inline void ** 203__linker_set_object_limit(kernel_mach_header_t *_header, const char *_set) 204{ 205 void *_set_begin; 206 unsigned long _size; 207 208 _set_begin = getsectdatafromheader(_header, "__DATA", _set, &_size); 209 210 return ((void **) ((uintptr_t) _set_begin + _size)); 211} 212 213#endif /* !KERNEL || __APPLE_API_PRIVATE */ 214 215#endif /* _SYS_LINKER_SET_H_ */ 216 217 218