]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-file.m
objc4-267.tar.gz
[apple/objc4.git] / runtime / objc-file.m
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 // Copyright 1988-1996 NeXT Software, Inc.
26
27 #import "objc-private.h"
28 #import <mach-o/ldsyms.h>
29 #import <mach-o/dyld.h>
30 #import <mach-o/getsect.h>
31 #include <string.h>
32 #include <stdlib.h>
33
34 #import <crt_externs.h>
35
36
37 /* Returns an array of all the objc headers in the executable
38 * Caller is responsible for freeing.
39 */
40 headerType **_getObjcHeaders()
41 {
42 const struct mach_header **headers;
43 headers = malloc(sizeof(struct mach_header *) * 2);
44 headers[0] = (const struct mach_header *)_NSGetMachExecuteHeader();
45 headers[1] = 0;
46 return (headerType**)headers;
47 }
48
49 Module _getObjcModules(const headerType *head, int *nmodules)
50 {
51 uint32_t size;
52 void *mods = getsectdatafromheader((headerType *)head,
53 SEG_OBJC,
54 SECT_OBJC_MODULES,
55 &size);
56 *nmodules = size / sizeof(struct objc_module);
57 return (Module)mods;
58 }
59
60 SEL *_getObjcMessageRefs(headerType *head, int *nmess)
61 {
62 uint32_t size;
63 void *refs = getsectdatafromheader ((headerType *)head,
64 SEG_OBJC, "__message_refs", &size);
65 *nmess = size / sizeof(SEL);
66 return (SEL *)refs;
67 }
68
69 ProtocolTemplate *_getObjcProtocols(headerType *head, int *nprotos)
70 {
71 uint32_t size;
72 void *protos = getsectdatafromheader ((headerType *)head,
73 SEG_OBJC, "__protocol", &size);
74 *nprotos = size / sizeof(ProtocolTemplate);
75 return (ProtocolTemplate *)protos;
76 }
77
78 NXConstantStringTemplate *_getObjcStringObjects(headerType *head, int *nstrs)
79 {
80 *nstrs = 0;
81 return NULL;
82 }
83
84 Class *_getObjcClassRefs(headerType *head, int *nclasses)
85 {
86 uint32_t size;
87 void *classes = getsectdatafromheader ((headerType *)head,
88 SEG_OBJC, "__cls_refs", &size);
89 *nclasses = size / sizeof(Class);
90 return (Class *)classes;
91 }
92
93 objc_image_info *_getObjcImageInfo(const headerType *head, uint32_t *sizep)
94 {
95 objc_image_info *info = (objc_image_info *)
96 getsectdatafromheader(head, SEG_OBJC, "__image_info", sizep);
97 return info;
98 }
99
100 const struct segment_command *getsegbynamefromheader(const headerType *head,
101 const char *segname)
102 {
103 const struct segment_command *sgp;
104 unsigned long i;
105
106 sgp = (const struct segment_command *) ((char *)head + sizeof(headerType));
107 for (i = 0; i < head->ncmds; i++){
108 if (sgp->cmd == LC_SEGMENT) {
109 if (strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0) {
110 return sgp;
111 }
112 }
113 sgp = (const struct segment_command *)((char *)sgp + sgp->cmdsize);
114 }
115 return NULL;
116 }
117
118 static const headerType *_getExecHeader (void)
119 {
120 return (const struct mach_header *)_NSGetMachExecuteHeader();
121 }
122
123 const char *_getObjcHeaderName(const headerType *header)
124 {
125 const headerType *execHeader;
126 const struct fvmlib_command *libCmd, *endOfCmds;
127
128 if (header && ((headerType *)header)->filetype == MH_FVMLIB) {
129 execHeader = _getExecHeader();
130 for (libCmd = (const struct fvmlib_command *)(execHeader + 1),
131 endOfCmds = ((void *)libCmd) + execHeader->sizeofcmds;
132 libCmd < endOfCmds; ((void *)libCmd) += libCmd->cmdsize) {
133 if ((libCmd->cmd == LC_LOADFVMLIB) && (libCmd->fvmlib.header_addr
134 == (unsigned long)header)) {
135 return (char *)libCmd
136 + libCmd->fvmlib.name.offset;
137 }
138 }
139 return NULL;
140 } else {
141 unsigned long i, n = _dyld_image_count();
142 for( i = 0; i < n ; i++ ) {
143 if ( _dyld_get_image_header(i) == header )
144 return _dyld_get_image_name(i);
145 }
146
147 return (*_NSGetArgv())[0];
148 }
149 }
150
151
152 // 1. Find segment with file offset == 0 and file size != 0. This segment's
153 // contents span the Mach-O header. (File size of 0 is .bss, for example)
154 // 2. Slide is header's address - segment's preferred address
155 ptrdiff_t _getImageSlide(const headerType *header)
156 {
157 int i;
158 const struct segment_command *sgp =
159 (const struct segment_command *)(header + 1);
160
161 for (i = 0; i < header->ncmds; i++){
162 if (sgp->cmd == LC_SEGMENT) {
163 if (sgp->fileoff == 0 && sgp->filesize != 0) {
164 return (uintptr_t)header - (uintptr_t)sgp->vmaddr;
165 }
166 }
167 sgp = (const struct segment_command *)((char *)sgp + sgp->cmdsize);
168 }
169
170 // uh-oh
171 _objc_fatal("could not calculate VM slide for image '%s'",
172 _getObjcHeaderName(header));
173 return 0; // not reached
174 }