/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef RLD #include #include #include #ifdef __DYNAMIC__ #include /* defines _dyld_lookup_and_bind() */ #endif /* defined(__DYNAMIC__) */ #ifndef __OPENSTEP__ #include #else /* defined(__OPENSTEP__) */ #if !defined(__DYNAMIC__) #define DECLARE_VAR(var, type) \ extern type var #define SETUP_VAR(var) #define USE_VAR(var) var #else #define STRINGIFY(a) # a #define DECLARE_VAR(var, type) \ static type * var ## _pointer = NULL #define SETUP_VAR(var) \ if ( var ## _pointer == NULL) { \ _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ (uint32_t *) & var ## _pointer, NULL); \ } #define USE_VAR(var) (* var ## _pointer) #endif #endif /* __OPENSTEP__ */ /* * This routine returns the section structure for the named section in the * named segment for the mach_header pointer passed to it if it exist. * Otherwise it returns zero. */ const struct section * getsectbynamefromheader( struct mach_header *mhp, const char *segname, const char *sectname) { struct segment_command *sgp; struct section *sp; uint32_t i, j; sgp = (struct segment_command *) ((char *)mhp + sizeof(struct mach_header)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == LC_SEGMENT) if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || mhp->filetype == MH_OBJECT){ sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); for(j = 0; j < sgp->nsects; j++){ if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && strncmp(sp->segname, segname, sizeof(sp->segname)) == 0) return(sp); sp = (struct section *)((char *)sp + sizeof(struct section)); } } sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); } return((struct section *)0); } /* * This routine returns the section structure for the named section in the * named segment for the mach_header_64 pointer passed to it if it exist. * Otherwise it returns zero. */ const struct section_64 * getsectbynamefromheader_64( struct mach_header_64 *mhp, const char *segname, const char *sectname) { struct segment_command_64 *sgp; struct section_64 *sp; uint32_t i, j; sgp = (struct segment_command_64 *) ((char *)mhp + sizeof(struct mach_header_64)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == LC_SEGMENT_64) if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || mhp->filetype == MH_OBJECT){ sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64)); for(j = 0; j < sgp->nsects; j++){ if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && strncmp(sp->segname, segname, sizeof(sp->segname)) == 0) return(sp); sp = (struct section_64 *)((char *)sp + sizeof(struct section_64)); } } sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); } return((struct section_64 *)0); } /* * This routine returns the section structure for the named section in the * named segment for the mach_header pointer passed to it if it exist. * Otherwise it returns zero. If fSwap == YES (the mach header has been * swapped to the endiannes of the current machine, but the segments and * sections are different) then the segment and sections are swapped. */ const struct section * getsectbynamefromheaderwithswap( struct mach_header *mhp, const char *segname, const char *sectname, int fSwap) { struct segment_command *sgp; struct section *sp; uint32_t i, j; sgp = (struct segment_command *) ((char *)mhp + sizeof(struct mach_header)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { if (fSwap) { #ifdef __LITTLE_ENDIAN__ swap_segment_command(sgp, NX_BigEndian); #else swap_segment_command(sgp, NX_LittleEndian); #endif /* __LITTLE_ENDIAN__ */ } if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || mhp->filetype == MH_OBJECT){ sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); if (fSwap) { #ifdef __LITTLE_ENDIAN__ swap_section(sp, sgp->nsects, NX_BigEndian); #else swap_section(sp, sgp->nsects, NX_LittleEndian); #endif /* __LITTLE_ENDIAN__ */ } for(j = 0; j < sgp->nsects; j++){ if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && strncmp(sp->segname, segname, sizeof(sp->segname)) == 0) return(sp); sp = (struct section *)((char *)sp + sizeof(struct section)); } } sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); } else { sgp = (struct segment_command *)((char *)sgp + (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); } } return((struct section *)0); } /* * This routine returns the a pointer the section structure of the named * section in the named segment if it exist in the mach executable it is * linked into. Otherwise it returns zero. */ #ifndef __LP64__ const struct section * getsectbyname( const char *segname, const char *sectname) { #ifndef __OPENSTEP__ struct mach_header *mhp = _NSGetMachExecuteHeader(); #else /* defined(__OPENSTEP__) */ static struct mach_header *mhp = NULL; DECLARE_VAR(_mh_execute_header, struct mach_header); SETUP_VAR(_mh_execute_header); mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); #endif /* __OPENSTEP__ */ return(getsectbynamefromheader(mhp, segname, sectname)); } #else /* defined(__LP64__) */ const struct section_64 * getsectbyname( const char *segname, const char *sectname) { struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); return(getsectbynamefromheader_64(mhp, segname, sectname)); } #endif /* defined(__LP64__) */ /* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the mach executable it is linked into. Also * it returns the size of the section data indirectly through the pointer size. * Otherwise it returns zero for the pointer and the size. */ char * getsectdata( const char *segname, const char *sectname, unsigned long *size) { #ifndef __LP64__ const struct section *sp; #else /* defined(__LP64__) */ const struct section_64 *sp; #endif /* defined(__LP64__) */ sp = getsectbyname(segname, sectname); if(sp == NULL){ *size = 0; return(NULL); } *size = sp->size; return((char *)(sp->addr)); } /* * This routine returns the a pointer to the section contents of the named * section in the named segment if it exists in the image pointed to by the * mach header. Otherwise it returns zero. */ #ifndef __LP64__ uint8_t * getsectiondata( const struct mach_header *mhp, const char *segname, const char *sectname, unsigned long *size) { struct segment_command *sgp, *zero; struct section *sp, *find; uint32_t i, j; zero = 0; find = 0; sp = 0; sgp = (struct segment_command *) ((char *)mhp + sizeof(struct mach_header)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == LC_SEGMENT){ if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ zero = sgp; if(find != 0) goto done; } if(find == 0 && strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); for(j = 0; j < sgp->nsects; j++){ if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && strncmp(sp->segname, segname, sizeof(sp->segname)) == 0){ find = sp; if(zero != 0) goto done; } sp = (struct section *)((char *)sp + sizeof(struct section)); } } } sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); } return(0); done: *size = sp->size; return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr)); } uint8_t * getsegmentdata( const struct mach_header *mhp, const char *segname, unsigned long *size) { struct segment_command *sgp, *zero, *find; uint32_t i; zero = 0; find = 0; sgp = (struct segment_command *) ((char *)mhp + sizeof(struct mach_header)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == LC_SEGMENT){ if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ zero = sgp; if(find != 0) goto done; } if(find == 0 && strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ find = sgp; if(zero != 0) goto done; } } sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); } return(0); done: *size = sgp->vmsize; return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr)); } #else /* defined(__LP64__) */ uint8_t * getsectiondata( const struct mach_header_64 *mhp, const char *segname, const char *sectname, unsigned long *size) { struct segment_command_64 *sgp, *zero; struct section_64 *sp, *find; uint32_t i, j; zero = 0; find = 0; sp = 0; sgp = (struct segment_command_64 *) ((char *)mhp + sizeof(struct mach_header_64)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == LC_SEGMENT_64){ if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ zero = sgp; if(find != 0) goto done; } if(find == 0 && strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ sp = (struct section_64 *)((char *)sgp + sizeof(struct segment_command_64)); for(j = 0; j < sgp->nsects; j++){ if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && strncmp(sp->segname, segname, sizeof(sp->segname)) == 0){ find = sp; if(zero != 0) goto done; } sp = (struct section_64 *)((char *)sp + sizeof(struct section_64)); } } } sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); } return(0); done: *size = sp->size; return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr)); } uint8_t * getsegmentdata( const struct mach_header_64 *mhp, const char *segname, unsigned long *size) { struct segment_command_64 *sgp, *zero, *find; uint32_t i; zero = 0; find = 0; sgp = (struct segment_command_64 *) ((char *)mhp + sizeof(struct mach_header_64)); for(i = 0; i < mhp->ncmds; i++){ if(sgp->cmd == LC_SEGMENT_64){ if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ zero = sgp; if(find != 0) goto done; } if(find == 0 && strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ find = sgp; if(zero != 0) goto done; } } sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); } return(0); done: *size = sgp->vmsize; return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr)); } #endif /* defined(__LP64__) */ /* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the mach header passed to it. Also it returns * the size of the section data indirectly through the pointer size. Otherwise * it returns zero for the pointer and the size. */ char * getsectdatafromheader( struct mach_header *mhp, const char *segname, const char *sectname, unsigned long *size) { const struct section *sp; sp = getsectbynamefromheader(mhp, segname, sectname); if(sp == NULL){ *size = 0; return(NULL); } *size = sp->size; return((char *)((uintptr_t)(sp->addr))); } /* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the 64-bit mach header passed to it. Also it * returns the size of the section data indirectly through the pointer size. * Otherwise it returns zero for the pointer and the size. */ char * getsectdatafromheader_64( struct mach_header_64 *mhp, const char *segname, const char *sectname, unsigned long *size) { const struct section_64 *sp; sp = getsectbynamefromheader_64(mhp, segname, sectname); if(sp == NULL){ *size = 0; return(NULL); } *size = sp->size; return((char *)((uintptr_t)(sp->addr))); } #ifdef __DYNAMIC__ /* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the named Framework. Also it returns the size * of the section data indirectly through the pointer size. Otherwise it * returns zero for the pointer and the size. The last component of the path * of the Framework is passed as FrameworkName. */ void * getsectdatafromFramework( const char *FrameworkName, const char *segname, const char *sectname, unsigned long *size) { uint32_t i, n; uintptr_t vmaddr_slide; #ifndef __LP64__ struct mach_header *mh; const struct section *s; #else /* defined(__LP64__) */ struct mach_header_64 *mh; const struct section_64 *s; #endif /* defined(__LP64__) */ char *name, *p; n = _dyld_image_count(); for(i = 0; i < n ; i++){ name = _dyld_get_image_name(i); p = strrchr(name, '/'); if(p != NULL && p[1] != '\0') name = p + 1; if(strcmp(name, FrameworkName) != 0) continue; mh = _dyld_get_image_header(i); vmaddr_slide = _dyld_get_image_vmaddr_slide(i); #ifndef __LP64__ s = getsectbynamefromheader(mh, segname, sectname); #else /* defined(__LP64__) */ s = getsectbynamefromheader_64(mh, segname, sectname); #endif /* defined(__LP64__) */ if(s == NULL){ *size = 0; return(NULL); } *size = s->size; return((void *)(s->addr + vmaddr_slide)); } *size = 0; return(NULL); } #endif /* __DYNAMIC__ */ #endif /* !defined(RLD) */