]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-file.m
370cdf108c94947194218319d2731d41cff3f7b8
[apple/objc4.git] / runtime / objc-file.m
1 /*
2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 // Copyright 1988-1996 NeXT Software, Inc.
24
25 #include <mach-o/ldsyms.h>
26 #include <mach-o/dyld.h>
27 #include <mach-o/getsect.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <crt_externs.h>
31
32 #define OLD 1
33 #import "objc-private.h"
34
35 #ifndef __LP64__
36 #define SEGMENT_CMD LC_SEGMENT
37 #define GETSECTDATAFROMHEADER(mh, seg, sect, sizep) \
38 getsectdatafromheader(mh, seg, sect, (uint32_t *)sizep)
39 #else
40 #define SEGMENT_CMD LC_SEGMENT_64
41 #define GETSECTDATAFROMHEADER(mh, seg, sect, sizep) \
42 getsectdatafromheader_64(mh, seg, sect, (uint64_t *)sizep)
43 #endif
44
45 __private_extern__ objc_image_info *
46 _getObjcImageInfo(const headerType *head, ptrdiff_t slide, size_t *sizep)
47 {
48 objc_image_info *info = (objc_image_info *)
49 #if __OBJC2__
50 GETSECTDATAFROMHEADER(head, SEG_DATA, "__objc_imageinfo", sizep);
51 if (!info) info = (objc_image_info *)
52 #endif
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);
56 return info;
57 }
58
59 // fixme !objc2 only (used for new-abi paranoia)
60 __private_extern__ Module
61 _getObjcModules(const headerType *head, ptrdiff_t slide, size_t *nmodules)
62 {
63 size_t size;
64 void *mods =
65 GETSECTDATAFROMHEADER(head, SEG_OBJC, SECT_OBJC_MODULES, &size);
66 #if !__OBJC2__
67 *nmodules = size / sizeof(struct objc_module);
68 #endif
69 if (mods) mods = (void *)((uintptr_t)mods + slide);
70 return (Module)mods;
71 }
72
73 // fixme !objc2 only (used for new-abi paranoia)
74 __private_extern__ SEL *
75 _getObjcSelectorRefs(const header_info *hi, size_t *nmess)
76 {
77 size_t size;
78 void *refs =
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);
82 return (SEL *)refs;
83 }
84
85 #if !__OBJC2__
86
87 __private_extern__ struct old_protocol *
88 _getObjcProtocols(const header_info *hi, size_t *nprotos)
89 {
90 size_t size;
91 void *protos =
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;
96 }
97
98 __private_extern__ struct old_class **
99 _getObjcClassRefs(const header_info *hi, size_t *nclasses)
100 {
101 size_t size;
102 void *classes =
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;
107 }
108
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)
112 {
113 void *names =
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;
117 }
118
119 #endif
120
121 #if __OBJC2__
122
123 __private_extern__ SEL *
124 _getObjc2SelectorRefs(const header_info *hi, size_t *nmess)
125 {
126 size_t size;
127 void *refs =
128 GETSECTDATAFROMHEADER (hi->mhdr, SEG_DATA, "__objc_selrefs", &size);
129 if (!refs) refs =
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);
133 return (SEL *)refs;
134 }
135
136 __private_extern__ message_ref *
137 _getObjc2MessageRefs(const header_info *hi, size_t *nmess)
138 {
139 size_t size;
140 void *refs =
141 GETSECTDATAFROMHEADER (hi->mhdr, SEG_DATA, "__objc_msgrefs", &size);
142 if (!refs) refs =
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;
147 }
148
149 __private_extern__ struct class_t **
150 _getObjc2ClassRefs(const header_info *hi, size_t *nclasses)
151 {
152 size_t size;
153 void *classes =
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;
160 }
161
162 __private_extern__ struct class_t **
163 _getObjc2SuperRefs(const header_info *hi, size_t *nclasses)
164 {
165 size_t size;
166 void *classes =
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;
173 }
174
175 __private_extern__ struct class_t **
176 _getObjc2ClassList(const header_info *hi, size_t *nclasses)
177 {
178 size_t size;
179 void *classes =
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;
186 }
187
188 __private_extern__ struct class_t **
189 _getObjc2NonlazyClassList(const header_info *hi, size_t *nclasses)
190 {
191 size_t size;
192 void *classes =
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;
199 }
200
201 __private_extern__ struct category_t **
202 _getObjc2CategoryList(const header_info *hi, size_t *ncats)
203 {
204 size_t size;
205 void *cats =
206 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_catlist", &size);
207 if (!cats) cats =
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;
212 }
213
214 __private_extern__ struct category_t **
215 _getObjc2NonlazyCategoryList(const header_info *hi, size_t *ncats)
216 {
217 size_t size;
218 void *cats =
219 GETSECTDATAFROMHEADER(hi->mhdr, SEG_DATA, "__objc_nlcatlist", &size);
220 if (!cats) cats =
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;
225 }
226
227 __private_extern__ struct protocol_t **
228 _getObjc2ProtocolList(const header_info *hi, size_t *nprotos)
229 {
230 size_t size;
231 void *protos =
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;
238 }
239
240 __private_extern__ struct protocol_t **
241 _getObjc2ProtocolRefs(const header_info *hi, size_t *nprotos)
242 {
243 size_t size;
244 void *protos =
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;
251 }
252
253 #endif
254
255 __private_extern__ const segmentType *
256 getsegbynamefromheader(const headerType *head, const char *segname)
257 {
258 const segmentType *sgp;
259 unsigned long i;
260
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) {
265 return sgp;
266 }
267 }
268 sgp = (const segmentType *)((char *)sgp + sgp->cmdsize);
269 }
270 return NULL;
271 }
272
273 __private_extern__ const char *
274 _getObjcHeaderName(const headerType *header)
275 {
276 Dl_info info;
277
278 if (dladdr(header, &info)) {
279 return info.dli_fname;
280 }
281 else {
282 return (*_NSGetArgv())[0];
283 }
284 }
285
286
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)
292 {
293 unsigned long i;
294 const segmentType *sgp = (const segmentType *)(header + 1);
295
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;
300 }
301 }
302 sgp = (const segmentType *)((char *)sgp + sgp->cmdsize);
303 }
304
305 // uh-oh
306 _objc_fatal("could not calculate VM slide for image '%s'",
307 _getObjcHeaderName(header));
308 return 0; // not reached
309 }