2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 // Copyright 1988-1996 NeXT Software, Inc.
25 #include <mach-o/ldsyms.h>
26 #include <mach-o/dyld.h>
27 #include <mach-o/getsect.h>
30 #include <crt_externs.h>
33 #import "objc-private.h"
36 #define SEGMENT_CMD LC_SEGMENT
37 #define GETSECTDATAFROMHEADER(mh, seg, sect, sizep) \
38 getsectdatafromheader(mh, seg, sect, (uint32_t *)sizep)
40 #define SEGMENT_CMD LC_SEGMENT_64
41 #define GETSECTDATAFROMHEADER(mh, seg, sect, sizep) \
42 getsectdatafromheader_64(mh, seg, sect, (uint64_t *)sizep)
45 __private_extern__ objc_image_info *
46 _getObjcImageInfo(const headerType *head, ptrdiff_t slide, size_t *sizep)
48 objc_image_info *info = (objc_image_info *)
50 GETSECTDATAFROMHEADER(head, SEG_DATA, "__objc_imageinfo", sizep);
51 if (!info) info = (objc_image_info *)
53 GETSECTDATAFROMHEADER(head, SEG_OBJC, "__image_info", sizep);
54 // size is BYTES, not count!
55 if (info) info = (objc_image_info *)((uintptr_t)info + slide);
59 // fixme !objc2 only (used for new-abi paranoia)
60 __private_extern__ Module
61 _getObjcModules(const headerType *head, ptrdiff_t slide, size_t *nmodules)
65 GETSECTDATAFROMHEADER(head, SEG_OBJC, SECT_OBJC_MODULES, &size);
67 *nmodules = size / sizeof(struct objc_module);
69 if (mods) mods = (void *)((uintptr_t)mods + slide);
73 // fixme !objc2 only (used for new-abi paranoia)
74 __private_extern__ SEL *
75 _getObjcSelectorRefs(const header_info *hi, size_t *nmess)
79 GETSECTDATAFROMHEADER (hi->mhdr, SEG_OBJC, "__message_refs", &size);
80 if (refs) refs = (void *)((uintptr_t)refs + hi->image_slide);
81 *nmess = size / sizeof(SEL);
87 __private_extern__ struct old_protocol *
88 _getObjcProtocols(const header_info *hi, size_t *nprotos)
92 GETSECTDATAFROMHEADER (hi->mhdr, SEG_OBJC, "__protocol", &size);
93 *nprotos = size / sizeof(struct old_protocol);
94 if (protos) protos = (struct old_protocol *)((uintptr_t)protos+hi->image_slide);
95 return (struct old_protocol *)protos;
98 __private_extern__ struct old_class **
99 _getObjcClassRefs(const header_info *hi, size_t *nclasses)
103 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC, "__cls_refs", &size);
104 *nclasses = size / sizeof(struct old_class *);
105 if (classes) classes = (void *)((uintptr_t)classes + hi->image_slide);
106 return (struct old_class **)classes;
109 // __OBJC,__class_names section only emitted by CodeWarrior rdar://4951638
110 __private_extern__ const char *
111 _getObjcClassNames(const header_info *hi, size_t *size)
114 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC, "__class_names", size);
115 if (names) names = (void *)((uintptr_t)names + hi->image_slide);
116 return (const char *)names;
123 __private_extern__ SEL *
124 _getObjc2SelectorRefs(const header_info *hi, size_t *nmess)
128 GETSECTDATAFROMHEADER (hi->mhdr, SEG_DATA, "__objc_selrefs", &size);
130 GETSECTDATAFROMHEADER (hi->mhdr, SEG_OBJC2, "__selector_refs", &size);
131 if (refs) refs = (void *)((uintptr_t)refs + hi->image_slide);
132 *nmess = size / sizeof(SEL);
136 __private_extern__ message_ref *
137 _getObjc2MessageRefs(const header_info *hi, size_t *nmess)
141 GETSECTDATAFROMHEADER (hi->mhdr, SEG_DATA, "__objc_msgrefs", &size);
143 GETSECTDATAFROMHEADER (hi->mhdr, SEG_OBJC2, "__message_refs", &size);
144 if (refs) refs = (void *)((uintptr_t)refs + hi->image_slide);
145 *nmess = size / sizeof(message_ref);
146 return (message_ref *)refs;
149 __private_extern__ struct class_t **
150 _getObjc2ClassRefs(const header_info *hi, size_t *nclasses)
154 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_classrefs", &size);
155 if (!classes) classes =
156 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC2, "__class_refs", &size);
157 *nclasses = size / sizeof(struct class_t *);
158 if (classes) classes = (void *)((uintptr_t)classes + hi->image_slide);
159 return (struct class_t **)classes;
162 __private_extern__ struct class_t **
163 _getObjc2SuperRefs(const header_info *hi, size_t *nclasses)
167 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_superrefs", &size);
168 if (!classes) classes =
169 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC2, "__super_refs", &size);
170 *nclasses = size / sizeof(struct class_t *);
171 if (classes) classes = (void *)((uintptr_t)classes + hi->image_slide);
172 return (struct class_t **)classes;
175 __private_extern__ struct class_t **
176 _getObjc2ClassList(const header_info *hi, size_t *nclasses)
180 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_classlist", &size);
181 if (!classes) classes =
182 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC2, "__class_list", &size);
183 *nclasses = size / sizeof(struct class_t *);
184 if (classes) classes = (void *)((uintptr_t)classes + hi->image_slide);
185 return (struct class_t **)classes;
188 __private_extern__ struct class_t **
189 _getObjc2NonlazyClassList(const header_info *hi, size_t *nclasses)
193 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_nlclslist", &size);
194 if (!classes) classes =
195 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC2, "__nonlazy_class", &size);
196 *nclasses = size / sizeof(struct class_t *);
197 if (classes) classes = (void *)((uintptr_t)classes + hi->image_slide);
198 return (struct class_t **)classes;
201 __private_extern__ struct category_t **
202 _getObjc2CategoryList(const header_info *hi, size_t *ncats)
206 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_catlist", &size);
208 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC2, "__category_list", &size);
209 *ncats = size / sizeof(struct category_t *);
210 if (cats) cats = (void *)((uintptr_t)cats + hi->image_slide);
211 return (struct category_t **)cats;
214 __private_extern__ struct category_t **
215 _getObjc2NonlazyCategoryList(const header_info *hi, size_t *ncats)
219 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_nlcatlist", &size);
221 GETSECTDATAFROMHEADER(hi->mhdr, SEG_OBJC2, "__nonlazy_catgry", &size);
222 *ncats = size / sizeof(struct category_t *);
223 if (cats) cats = (void *)((uintptr_t)cats + hi->image_slide);
224 return (struct category_t **)cats;
227 __private_extern__ struct protocol_t **
228 _getObjc2ProtocolList(const header_info *hi, size_t *nprotos)
232 GETSECTDATAFROMHEADER (hi->mhdr, SEG_DATA, "__objc_protolist", &size);
233 if (!protos) protos =
234 GETSECTDATAFROMHEADER (hi->mhdr, SEG_OBJC2, "__protocol_list", &size);
235 *nprotos = size / sizeof(struct protocol_t *);
236 if (protos) protos = (struct protocol_t **)((uintptr_t)protos+hi->image_slide);
237 return (struct protocol_t **)protos;
240 __private_extern__ struct protocol_t **
241 _getObjc2ProtocolRefs(const header_info *hi, size_t *nprotos)
245 GETSECTDATAFROMHEADER (hi->mhdr, SEG_DATA, "__objc_protorefs", &size);
246 if (!protos) protos =
247 GETSECTDATAFROMHEADER (hi->mhdr, SEG_OBJC2, "__protocol_refs", &size);
248 *nprotos = size / sizeof(struct protocol_t *);
249 if (protos) protos = (struct protocol_t **)((uintptr_t)protos+hi->image_slide);
250 return (struct protocol_t **)protos;
255 __private_extern__ const segmentType *
256 getsegbynamefromheader(const headerType *head, const char *segname)
258 const segmentType *sgp;
261 sgp = (const segmentType *) (head + 1);
262 for (i = 0; i < head->ncmds; i++){
263 if (sgp->cmd == SEGMENT_CMD) {
264 if (strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0) {
268 sgp = (const segmentType *)((char *)sgp + sgp->cmdsize);
273 __private_extern__ const char *
274 _getObjcHeaderName(const headerType *header)
278 if (dladdr(header, &info)) {
279 return info.dli_fname;
282 return (*_NSGetArgv())[0];
287 // 1. Find segment with file offset == 0 and file size != 0. This segment's
288 // contents span the Mach-O header. (File size of 0 is .bss, for example)
289 // 2. Slide is header's address - segment's preferred address
290 __private_extern__ ptrdiff_t
291 _getImageSlide(const headerType *header)
294 const segmentType *sgp = (const segmentType *)(header + 1);
296 for (i = 0; i < header->ncmds; i++){
297 if (sgp->cmd == SEGMENT_CMD) {
298 if (sgp->fileoff == 0 && sgp->filesize != 0) {
299 return (uintptr_t)header - (uintptr_t)sgp->vmaddr;
302 sgp = (const segmentType *)((char *)sgp + sgp->cmdsize);
306 _objc_fatal("could not calculate VM slide for image '%s'",
307 _getObjcHeaderName(header));
308 return 0; // not reached