]>
Commit | Line | Data |
---|---|---|
13d88034 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
390d5862 A |
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. | |
13d88034 A |
14 | * |
15 | * The Original Code and all software distributed under the License are | |
390d5862 | 16 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
13d88034 A |
17 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
18 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
390d5862 A |
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. | |
13d88034 A |
22 | * |
23 | * @APPLE_LICENSE_HEADER_END@ | |
24 | */ | |
25 | // Copyright 1988-1996 NeXT Software, Inc. | |
26 | ||
13d88034 A |
27 | #import "objc-private.h" |
28 | #import <mach-o/ldsyms.h> | |
29 | #import <mach-o/dyld.h> | |
2bfd4448 | 30 | #import <mach-o/getsect.h> |
13d88034 A |
31 | #include <string.h> |
32 | #include <stdlib.h> | |
33 | ||
34 | #import <crt_externs.h> | |
35 | ||
13d88034 A |
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 | ||
2bfd4448 | 49 | Module _getObjcModules(const headerType *head, int *nmodules) |
13d88034 | 50 | { |
2bfd4448 | 51 | uint32_t size; |
13d88034 A |
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 | { | |
2bfd4448 | 62 | uint32_t size; |
13d88034 A |
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 | { | |
2bfd4448 | 71 | uint32_t size; |
13d88034 A |
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 | { | |
2bfd4448 | 86 | uint32_t size; |
13d88034 A |
87 | void *classes = getsectdatafromheader ((headerType *)head, |
88 | SEG_OBJC, "__cls_refs", &size); | |
89 | *nclasses = size / sizeof(Class); | |
90 | return (Class *)classes; | |
91 | } | |
92 | ||
2bfd4448 | 93 | objc_image_info *_getObjcImageInfo(const headerType *head, uint32_t *sizep) |
390d5862 | 94 | { |
2bfd4448 A |
95 | objc_image_info *info = (objc_image_info *) |
96 | getsectdatafromheader(head, SEG_OBJC, "__image_info", sizep); | |
97 | return info; | |
390d5862 A |
98 | } |
99 | ||
2bfd4448 A |
100 | const struct segment_command *getsegbynamefromheader(const headerType *head, |
101 | const char *segname) | |
13d88034 | 102 | { |
2bfd4448 A |
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; | |
13d88034 A |
116 | } |
117 | ||
118 | static const headerType *_getExecHeader (void) | |
119 | { | |
120 | return (const struct mach_header *)_NSGetMachExecuteHeader(); | |
121 | } | |
122 | ||
2bfd4448 | 123 | const char *_getObjcHeaderName(const headerType *header) |
13d88034 A |
124 | { |
125 | const headerType *execHeader; | |
126 | const struct fvmlib_command *libCmd, *endOfCmds; | |
13d88034 A |
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 | } | |
2bfd4448 A |
146 | |
147 | return (*_NSGetArgv())[0]; | |
13d88034 A |
148 | } |
149 | } | |
150 | ||
2bfd4448 A |
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 | } |