836
[darwin-xtools.git] / cctools / libmacho / getsecbyname.c
blob8b37e5087fb603f55f54126c4a6036415126ac19
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
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.
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 #ifndef RLD
24 #include <mach-o/ldsyms.h>
25 #include <mach-o/swap.h>
26 #include <string.h>
27 #ifdef __DYNAMIC__
28 #include <mach-o/dyld.h> /* defines _dyld_lookup_and_bind() */
29 #endif /* defined(__DYNAMIC__) */
30 #ifndef __OPENSTEP__
31 #include <crt_externs.h>
32 #else /* defined(__OPENSTEP__) */
34 #if !defined(__DYNAMIC__)
35 #define DECLARE_VAR(var, type) \
36 extern type var
37 #define SETUP_VAR(var)
38 #define USE_VAR(var) var
39 #else
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)
49 #endif
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,
60 const char *segname,
61 const char *sectname)
63 struct segment_command *sgp;
64 struct section *sp;
65 uint32_t i, j;
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)
80 return(sp);
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,
98 const char *segname,
99 const char *sectname)
101 struct segment_command_64 *sgp;
102 struct section_64 *sp;
103 uint32_t i, j;
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)
118 return(sp);
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,
138 const char *segname,
139 const char *sectname,
140 int fSwap)
142 struct segment_command *sgp;
143 struct section *sp;
144 uint32_t i, j;
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)) {
151 if (fSwap) {
152 #ifdef __LITTLE_ENDIAN__
153 swap_segment_command(sgp, NX_BigEndian);
154 #else
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));
164 if (fSwap) {
165 #ifdef __LITTLE_ENDIAN__
166 swap_section(sp, sgp->nsects, NX_BigEndian);
167 #else
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)
177 return(sp);
178 sp = (struct section *)((char *)sp +
179 sizeof(struct section));
182 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
183 } else {
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.
196 #ifndef __LP64__
198 const struct section *
199 getsectbyname(
200 const char *segname,
201 const char *sectname)
203 #ifndef __OPENSTEP__
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 *
217 getsectbyname(
218 const char *segname,
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.
234 char *
235 getsectdata(
236 const char *segname,
237 const char *sectname,
238 unsigned long *size)
240 #ifndef __LP64__
241 const struct section *sp;
242 #else /* defined(__LP64__) */
243 const struct section_64 *sp;
244 #endif /* defined(__LP64__) */
246 sp = getsectbyname(segname, sectname);
247 if(sp == NULL){
248 *size = 0;
249 return(NULL);
251 *size = sp->size;
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.
260 #ifndef __LP64__
262 uint8_t *
263 getsectiondata(
264 const struct mach_header *mhp,
265 const char *segname,
266 const char *sectname,
267 unsigned long *size)
269 struct segment_command *sgp, *zero;
270 struct section *sp, *find;
271 uint32_t i, j;
273 zero = 0;
274 find = 0;
275 sp = 0;
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){
281 zero = sgp;
282 if(find != 0)
283 goto done;
285 if(find == 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){
294 find = sp;
295 if(zero != 0)
296 goto done;
298 sp = (struct section *)((char *)sp +
299 sizeof(struct section));
303 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
305 return(0);
306 done:
307 *size = sp->size;
308 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr));
311 uint8_t *
312 getsegmentdata(
313 const struct mach_header *mhp,
314 const char *segname,
315 unsigned long *size)
317 struct segment_command *sgp, *zero, *find;
318 uint32_t i;
320 zero = 0;
321 find = 0;
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){
327 zero = sgp;
328 if(find != 0)
329 goto done;
331 if(find == 0 &&
332 strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){
333 find = sgp;
334 if(zero != 0)
335 goto done;
338 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize);
340 return(0);
341 done:
342 *size = sgp->vmsize;
343 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr));
346 #else /* defined(__LP64__) */
348 uint8_t *
349 getsectiondata(
350 const struct mach_header_64 *mhp,
351 const char *segname,
352 const char *sectname,
353 unsigned long *size)
355 struct segment_command_64 *sgp, *zero;
356 struct section_64 *sp, *find;
357 uint32_t i, j;
359 zero = 0;
360 find = 0;
361 sp = 0;
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){
367 zero = sgp;
368 if(find != 0)
369 goto done;
371 if(find == 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){
380 find = sp;
381 if(zero != 0)
382 goto done;
384 sp = (struct section_64 *)((char *)sp +
385 sizeof(struct section_64));
389 sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize);
391 return(0);
392 done:
393 *size = sp->size;
394 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr));
397 uint8_t *
398 getsegmentdata(
399 const struct mach_header_64 *mhp,
400 const char *segname,
401 unsigned long *size)
403 struct segment_command_64 *sgp, *zero, *find;
404 uint32_t i;
406 zero = 0;
407 find = 0;
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){
413 zero = sgp;
414 if(find != 0)
415 goto done;
417 if(find == 0 &&
418 strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){
419 find = sgp;
420 if(zero != 0)
421 goto done;
424 sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize);
426 return(0);
427 done:
428 *size = sgp->vmsize;
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.
440 char *
441 getsectdatafromheader(
442 struct mach_header *mhp,
443 const char *segname,
444 const char *sectname,
445 unsigned long *size)
447 const struct section *sp;
449 sp = getsectbynamefromheader(mhp, segname, sectname);
450 if(sp == NULL){
451 *size = 0;
452 return(NULL);
454 *size = sp->size;
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.
464 char *
465 getsectdatafromheader_64(
466 struct mach_header_64 *mhp,
467 const char *segname,
468 const char *sectname,
469 unsigned long *size)
471 const struct section_64 *sp;
473 sp = getsectbynamefromheader_64(mhp, segname, sectname);
474 if(sp == NULL){
475 *size = 0;
476 return(NULL);
478 *size = sp->size;
479 return((char *)((uintptr_t)(sp->addr)));
482 #ifdef __DYNAMIC__
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.
490 void *
491 getsectdatafromFramework(
492 const char *FrameworkName,
493 const char *segname,
494 const char *sectname,
495 unsigned long *size)
497 uint32_t i, n;
498 uintptr_t vmaddr_slide;
499 #ifndef __LP64__
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__) */
506 char *name, *p;
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')
513 name = p + 1;
514 if(strcmp(name, FrameworkName) != 0)
515 continue;
516 mh = _dyld_get_image_header(i);
517 vmaddr_slide = _dyld_get_image_vmaddr_slide(i);
518 #ifndef __LP64__
519 s = getsectbynamefromheader(mh, segname, sectname);
520 #else /* defined(__LP64__) */
521 s = getsectbynamefromheader_64(mh, segname, sectname);
522 #endif /* defined(__LP64__) */
523 if(s == NULL){
524 *size = 0;
525 return(NULL);
527 *size = s->size;
528 return((void *)(s->addr + vmaddr_slide));
530 *size = 0;
531 return(NULL);
533 #endif /* __DYNAMIC__ */
534 #endif /* !defined(RLD) */