2 * Copyright (c) 1999 Apple Computer, 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@
24 #include <mach-o/ldsyms.h>
25 #include <mach-o/swap.h>
28 #include <mach-o/dyld.h> /* defines _dyld_lookup_and_bind() */
29 #endif /* defined(__DYNAMIC__) */
31 #include <crt_externs.h>
32 #else /* defined(__OPENSTEP__) */
34 #if !defined(__DYNAMIC__)
35 #define DECLARE_VAR(var, type) \
37 #define SETUP_VAR(var)
38 #define USE_VAR(var) var
40 #define STRINGIFY(a) # a
41 #define DECLARE_VAR(var, type) \
42 static type * var ## _pointer = NULL
43 #define SETUP_VAR(var) \
44 if ( var ## _pointer == NULL) { \
45 _dyld_lookup_and_bind( STRINGIFY(_ ## var), \
46 (uint32_t *) & var ## _pointer, NULL); \
48 #define USE_VAR(var) (* var ## _pointer)
50 #endif /* __OPENSTEP__ */
53 * This routine returns the section structure for the named section in the
54 * named segment for the mach_header pointer passed to it if it exist.
55 * Otherwise it returns zero.
57 const struct section
*
58 getsectbynamefromheader(
59 struct mach_header
*mhp
,
63 struct segment_command
*sgp
;
67 sgp
= (struct segment_command
*)
68 ((char *)mhp
+ sizeof(struct mach_header
));
69 for(i
= 0; i
< mhp
->ncmds
; i
++){
70 if(sgp
->cmd
== LC_SEGMENT
)
71 if(strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0 ||
72 mhp
->filetype
== MH_OBJECT
){
73 sp
= (struct section
*)((char *)sgp
+
74 sizeof(struct segment_command
));
75 for(j
= 0; j
< sgp
->nsects
; j
++){
76 if(strncmp(sp
->sectname
, sectname
,
77 sizeof(sp
->sectname
)) == 0 &&
78 strncmp(sp
->segname
, segname
,
79 sizeof(sp
->segname
)) == 0)
81 sp
= (struct section
*)((char *)sp
+
82 sizeof(struct section
));
85 sgp
= (struct segment_command
*)((char *)sgp
+ sgp
->cmdsize
);
87 return((struct section
*)0);
91 * This routine returns the section structure for the named section in the
92 * named segment for the mach_header_64 pointer passed to it if it exist.
93 * Otherwise it returns zero.
95 const struct section_64
*
96 getsectbynamefromheader_64(
97 struct mach_header_64
*mhp
,
101 struct segment_command_64
*sgp
;
102 struct section_64
*sp
;
105 sgp
= (struct segment_command_64
*)
106 ((char *)mhp
+ sizeof(struct mach_header_64
));
107 for(i
= 0; i
< mhp
->ncmds
; i
++){
108 if(sgp
->cmd
== LC_SEGMENT_64
)
109 if(strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0 ||
110 mhp
->filetype
== MH_OBJECT
){
111 sp
= (struct section_64
*)((char *)sgp
+
112 sizeof(struct segment_command_64
));
113 for(j
= 0; j
< sgp
->nsects
; j
++){
114 if(strncmp(sp
->sectname
, sectname
,
115 sizeof(sp
->sectname
)) == 0 &&
116 strncmp(sp
->segname
, segname
,
117 sizeof(sp
->segname
)) == 0)
119 sp
= (struct section_64
*)((char *)sp
+
120 sizeof(struct section_64
));
123 sgp
= (struct segment_command_64
*)((char *)sgp
+ sgp
->cmdsize
);
125 return((struct section_64
*)0);
129 * This routine returns the section structure for the named section in the
130 * named segment for the mach_header pointer passed to it if it exist.
131 * Otherwise it returns zero. If fSwap == YES (the mach header has been
132 * swapped to the endiannes of the current machine, but the segments and
133 * sections are different) then the segment and sections are swapped.
135 const struct section
*
136 getsectbynamefromheaderwithswap(
137 struct mach_header
*mhp
,
139 const char *sectname
,
142 struct segment_command
*sgp
;
146 sgp
= (struct segment_command
*)
147 ((char *)mhp
+ sizeof(struct mach_header
));
148 for(i
= 0; i
< mhp
->ncmds
; i
++){
149 if(sgp
->cmd
== (fSwap
? OSSwapInt32(LC_SEGMENT
) : LC_SEGMENT
)) {
152 #ifdef __LITTLE_ENDIAN__
153 swap_segment_command(sgp
, NX_BigEndian
);
155 swap_segment_command(sgp
, NX_LittleEndian
);
156 #endif /* __LITTLE_ENDIAN__ */
159 if(strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0 ||
160 mhp
->filetype
== MH_OBJECT
){
161 sp
= (struct section
*)((char *)sgp
+
162 sizeof(struct segment_command
));
165 #ifdef __LITTLE_ENDIAN__
166 swap_section(sp
, sgp
->nsects
, NX_BigEndian
);
168 swap_section(sp
, sgp
->nsects
, NX_LittleEndian
);
169 #endif /* __LITTLE_ENDIAN__ */
172 for(j
= 0; j
< sgp
->nsects
; j
++){
173 if(strncmp(sp
->sectname
, sectname
,
174 sizeof(sp
->sectname
)) == 0 &&
175 strncmp(sp
->segname
, segname
,
176 sizeof(sp
->segname
)) == 0)
178 sp
= (struct section
*)((char *)sp
+
179 sizeof(struct section
));
182 sgp
= (struct segment_command
*)((char *)sgp
+ sgp
->cmdsize
);
184 sgp
= (struct segment_command
*)((char *)sgp
+
185 (fSwap
? OSSwapInt32(sgp
->cmdsize
) : sgp
->cmdsize
));
188 return((struct section
*)0);
192 * This routine returns the a pointer the section structure of the named
193 * section in the named segment if it exist in the mach executable it is
194 * linked into. Otherwise it returns zero.
198 const struct section
*
201 const char *sectname
)
204 struct mach_header
*mhp
= _NSGetMachExecuteHeader();
205 #else /* defined(__OPENSTEP__) */
206 static struct mach_header
*mhp
= NULL
;
207 DECLARE_VAR(_mh_execute_header
, struct mach_header
);
208 SETUP_VAR(_mh_execute_header
);
209 mhp
= (struct mach_header
*)(& USE_VAR(_mh_execute_header
));
210 #endif /* __OPENSTEP__ */
211 return(getsectbynamefromheader(mhp
, segname
, sectname
));
214 #else /* defined(__LP64__) */
216 const struct section_64
*
219 const char *sectname
)
221 struct mach_header_64
*mhp
= _NSGetMachExecuteHeader();
223 return(getsectbynamefromheader_64(mhp
, segname
, sectname
));
226 #endif /* defined(__LP64__) */
229 * This routine returns the a pointer to the data for the named section in the
230 * named segment if it exist in the mach executable it is linked into. Also
231 * it returns the size of the section data indirectly through the pointer size.
232 * Otherwise it returns zero for the pointer and the size.
237 const char *sectname
,
241 const struct section
*sp
;
242 #else /* defined(__LP64__) */
243 const struct section_64
*sp
;
244 #endif /* defined(__LP64__) */
246 sp
= getsectbyname(segname
, sectname
);
252 return((char *)(sp
->addr
));
256 * This routine returns the a pointer to the section contents of the named
257 * section in the named segment if it exists in the image pointed to by the
258 * mach header. Otherwise it returns zero.
264 const struct mach_header
*mhp
,
266 const char *sectname
,
269 struct segment_command
*sgp
, *zero
;
270 struct section
*sp
, *find
;
276 sgp
= (struct segment_command
*)
277 ((char *)mhp
+ sizeof(struct mach_header
));
278 for(i
= 0; i
< mhp
->ncmds
; i
++){
279 if(sgp
->cmd
== LC_SEGMENT
){
280 if(zero
== 0 && sgp
->fileoff
== 0 && sgp
->nsects
!= 0){
286 strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0){
287 sp
= (struct section
*)((char *)sgp
+
288 sizeof(struct segment_command
));
289 for(j
= 0; j
< sgp
->nsects
; j
++){
290 if(strncmp(sp
->sectname
, sectname
,
291 sizeof(sp
->sectname
)) == 0 &&
292 strncmp(sp
->segname
, segname
,
293 sizeof(sp
->segname
)) == 0){
298 sp
= (struct section
*)((char *)sp
+
299 sizeof(struct section
));
303 sgp
= (struct segment_command
*)((char *)sgp
+ sgp
->cmdsize
);
308 return((uint8_t *)((uintptr_t)mhp
- zero
->vmaddr
+ sp
->addr
));
313 const struct mach_header
*mhp
,
317 struct segment_command
*sgp
, *zero
, *find
;
322 sgp
= (struct segment_command
*)
323 ((char *)mhp
+ sizeof(struct mach_header
));
324 for(i
= 0; i
< mhp
->ncmds
; i
++){
325 if(sgp
->cmd
== LC_SEGMENT
){
326 if(zero
== 0 && sgp
->fileoff
== 0 && sgp
->nsects
!= 0){
332 strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0){
338 sgp
= (struct segment_command
*)((char *)sgp
+ sgp
->cmdsize
);
343 return((uint8_t *)((uintptr_t)mhp
- zero
->vmaddr
+ sgp
->vmaddr
));
346 #else /* defined(__LP64__) */
350 const struct mach_header_64
*mhp
,
352 const char *sectname
,
355 struct segment_command_64
*sgp
, *zero
;
356 struct section_64
*sp
, *find
;
362 sgp
= (struct segment_command_64
*)
363 ((char *)mhp
+ sizeof(struct mach_header_64
));
364 for(i
= 0; i
< mhp
->ncmds
; i
++){
365 if(sgp
->cmd
== LC_SEGMENT_64
){
366 if(zero
== 0 && sgp
->fileoff
== 0 && sgp
->nsects
!= 0){
372 strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0){
373 sp
= (struct section_64
*)((char *)sgp
+
374 sizeof(struct segment_command_64
));
375 for(j
= 0; j
< sgp
->nsects
; j
++){
376 if(strncmp(sp
->sectname
, sectname
,
377 sizeof(sp
->sectname
)) == 0 &&
378 strncmp(sp
->segname
, segname
,
379 sizeof(sp
->segname
)) == 0){
384 sp
= (struct section_64
*)((char *)sp
+
385 sizeof(struct section_64
));
389 sgp
= (struct segment_command_64
*)((char *)sgp
+ sgp
->cmdsize
);
394 return((uint8_t *)((uintptr_t)mhp
- zero
->vmaddr
+ sp
->addr
));
399 const struct mach_header_64
*mhp
,
403 struct segment_command_64
*sgp
, *zero
, *find
;
408 sgp
= (struct segment_command_64
*)
409 ((char *)mhp
+ sizeof(struct mach_header_64
));
410 for(i
= 0; i
< mhp
->ncmds
; i
++){
411 if(sgp
->cmd
== LC_SEGMENT_64
){
412 if(zero
== 0 && sgp
->fileoff
== 0 && sgp
->nsects
!= 0){
418 strncmp(sgp
->segname
, segname
, sizeof(sgp
->segname
)) == 0){
424 sgp
= (struct segment_command_64
*)((char *)sgp
+ sgp
->cmdsize
);
429 return((uint8_t *)((uintptr_t)mhp
- zero
->vmaddr
+ sgp
->vmaddr
));
432 #endif /* defined(__LP64__) */
435 * This routine returns the a pointer to the data for the named section in the
436 * named segment if it exist in the mach header passed to it. Also it returns
437 * the size of the section data indirectly through the pointer size. Otherwise
438 * it returns zero for the pointer and the size.
441 getsectdatafromheader(
442 struct mach_header
*mhp
,
444 const char *sectname
,
447 const struct section
*sp
;
449 sp
= getsectbynamefromheader(mhp
, segname
, sectname
);
455 return((char *)((uintptr_t)(sp
->addr
)));
459 * This routine returns the a pointer to the data for the named section in the
460 * named segment if it exist in the 64-bit mach header passed to it. Also it
461 * returns the size of the section data indirectly through the pointer size.
462 * Otherwise it returns zero for the pointer and the size.
465 getsectdatafromheader_64(
466 struct mach_header_64
*mhp
,
468 const char *sectname
,
471 const struct section_64
*sp
;
473 sp
= getsectbynamefromheader_64(mhp
, segname
, sectname
);
479 return((char *)((uintptr_t)(sp
->addr
)));
484 * This routine returns the a pointer to the data for the named section in the
485 * named segment if it exist in the named Framework. Also it returns the size
486 * of the section data indirectly through the pointer size. Otherwise it
487 * returns zero for the pointer and the size. The last component of the path
488 * of the Framework is passed as FrameworkName.
491 getsectdatafromFramework(
492 const char *FrameworkName
,
494 const char *sectname
,
498 uintptr_t vmaddr_slide
;
500 struct mach_header
*mh
;
501 const struct section
*s
;
502 #else /* defined(__LP64__) */
503 struct mach_header_64
*mh
;
504 const struct section_64
*s
;
505 #endif /* defined(__LP64__) */
508 n
= _dyld_image_count();
509 for(i
= 0; i
< n
; i
++){
510 name
= _dyld_get_image_name(i
);
511 p
= strrchr(name
, '/');
512 if(p
!= NULL
&& p
[1] != '\0')
514 if(strcmp(name
, FrameworkName
) != 0)
516 mh
= _dyld_get_image_header(i
);
517 vmaddr_slide
= _dyld_get_image_vmaddr_slide(i
);
519 s
= getsectbynamefromheader(mh
, segname
, sectname
);
520 #else /* defined(__LP64__) */
521 s
= getsectbynamefromheader_64(mh
, segname
, sectname
);
522 #endif /* defined(__LP64__) */
528 return((void *)(s
->addr
+ vmaddr_slide
));
533 #endif /* __DYNAMIC__ */
534 #endif /* !defined(RLD) */