/* * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights * Reserved. 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 1.1 (the "License"). You may not use this file * except in compliance with the License. Please obtain a copy of the * License at http://www.apple.com/publicsource 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 OR NON- INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #import <mach-o/loader.h> #import <sys/types.h> #import <sys/stat.h> #ifdef EGREGIOUS_HACK_FOR_SAMPLER #import <dyld/bool.h> #else #import "stuff/bool.h" #endif #import <sys/types.h> enum link_state { UNLINKED, /* the starting point for UNLINKED modules */ BEING_LINKED, /* moduled selected to be link into the program */ RELOCATED, /* moduled relocated dyld can now use the module */ REGISTERING, /* functions registered for modules being link called */ INITIALIZING, /* module initializers being called */ LINKED, /* module initializers called user can now use module */ FULLY_LINKED, /* module fully linked (all lazy symbols resolved) */ PREBOUND_UNLINKED, /* the module is prebound image but unlinked after */ /* the program was launch. */ BEING_UNLINKED, /* not yet used. TODO unlinking */ REPLACED, /* not yet used. TODO replacing */ UNUSED /* a module handle that is now unused */ }; struct image { char *name; /* Image name for reporting errors. */ unsigned long vmaddr_slide; /* The amount the vmaddresses are slid in the */ /* image from the staticly link addresses. */ struct mach_header *mh; /* The mach header of the image. */ unsigned long valid; /* TRUE if this is struct is valid */ /* * The above four fields can't change without breaking gdb(1) see the * comments in <mach-o/dyld_gdb.h>. */ unsigned long vmaddr_size; /* The size of the vm this image uses */ unsigned long seg1addr; /* The address of the first segment */ unsigned long /* The address of the first read-write segment*/ segs_read_write_addr; /* used only for MH_SPLIT_SEGS images. */ struct symtab_command *st; /* The symbol table command for the image. */ struct dysymtab_command /* The dynamic symbol table command for the */ *dyst; /* image. */ struct segment_command /* The link edit segment command for the */ *linkedit_segment; /* image. */ struct routines_command *rc;/* The routines command for the image */ struct twolevel_hints_command/* The twolevel hints command for the image */ *hints_cmd; struct section *init; /* The mod init section */ struct section *term; /* The mod term section */ #ifdef __ppc__ unsigned long /* the image's dyld_stub_binding_helper */ dyld_stub_binding_helper; /* address */ #endif unsigned long prebound:1, /* Link states set from prebound state */ change_protect_on_reloc:1,/* The image has relocations in read-only */ /* segments and protection needs to change. */ cache_sync_on_reloc:1, /* The image has relocations for instructions */ /* and the i cache needs to sync with d cache*/ registered:1, /* The functions registered for add images */ /* have been called */ private:1, /* global symbols are not used for linking */ init_bound:1, /* the image init routine has been bound */ init_called:1, /* the image init routine has been called */ lazy_init:1, /* the image init routine to be called lazy */ has_coalesced_sections:1, /* the image has coalesced sections */ sub_images_setup:1, /* the sub images have been set up */ umbrella_images_setup:1, /* the umbrella_images have been set up */ two_level_debug_printed:1,/* printed when TWO_LEVEL_DEBUG is on */ undone_prebound_lazy_pointers:1, /* all prebound lazy pointer un done */ subtrees_twolevel_prebound_setup:1, /* state of this and deps setup */ subtrees_twolevel_prebound:1, /* this and deps twolevel and prebound */ image_can_use_hints:1, /* set when the hints are usable in this image*/ subs_can_use_hints:1, /* set when the hints are usable for images */ /* that have this image as a sub image */ unused:16; /* * For two-level namespace images this is the array of pointers to the * dependent images and the count of them. */ struct image **dependent_images; unsigned long ndependent_images; /* * If this is a library image which has a framework name or library name * then this is the part that would be the umbrella name or library name * and the size of the name. This points into the name and since framework * and library names may have suffixes the size is needed to exclude it. * This is only needed for two-level namespace images. umbrella_name and * or library_name will be NULL and name_size will be 0 if there is no * umbrella name. */ char *umbrella_name; char *library_name; unsigned long name_size; /* array of pointers to sub-frameworks and sub-umbrellas and count */ struct image **sub_images; unsigned long nsub_images; /* array of pointers to back to umbrella frameworks and sub-umbrellas if any which the image is a part of and the count of them. */ struct image **umbrella_images; unsigned long numbrella_images; /* * This fields is only used to point back to the library image or object * image structure. This is so that the for two-level namespace lookups * the library_image and object_image can be quickly obtained from the image * structure for a calls to lookup_symbol_in_library_image() and * lookup_symbol_in_object_image(). */ void *outer_image; }; /* * This is really an enum link_state. Originally there was a module structure * that had an enum link_state field. Because the minimum structure aligment * is more than one-byte aligned this wasted space. Since this is one of the * few allocated and written data structures of dyld it is important it is as * small as reasonable. It needs to be addressable so using less than a byte * is not acceptable. */ typedef char module_state; /* * To keep track of which modules are being fully bound the 0x80 bit of the * module state is used. Fully bound is where all of the dependent references * are bound into the program. Where fully linked in here means that the single * module has all it's lazy as well as it's not lazy symbols linked. If an * image has an image initialization routine then the module containing that * routine is full bound before it is called. */ #define GET_LINK_STATE(m) ((enum link_state)((m) & 0xf)) #define SET_LINK_STATE(m,l) m = (((m) & 0xf0) | ((l) & 0xf)) #define GET_FULLYBOUND_STATE(m) ((m) & 0x80) #define SET_FULLYBOUND_STATE(m) m = ((m) | 0x80) #define CLEAR_FULLYBOUND_STATE(m) m = ((m) & 0x7f) /* * To allow image initialization routines (shared library init routines) to * force modules in there image to have there module initialization routines * run (C++ initializers, via a call to __initializeCplusplus) the 0x40 bit of * the module state is used to keep track of if the module initialization * routine as been run. The module initialization routines are normally run * after the the image initialization routines so this bit is needed to make * sure a module initialization routine is not run twice. */ #define GET_MODINIT_STATE(m) ((m) & 0x40) #define SET_MODINIT_STATE(m) m = ((m) | 0x40) /* * To support module termination routines (to be used for C++ destructors) the * 0x20 bit of the module state is used to keep track of if the module * termination routine has been run. */ #define GET_MODTERM_STATE(m) ((m) & 0x20) #define SET_MODTERM_STATE(m) m = ((m) | 0x20) /* * To support calling image initialization routines (shared library init * routines) in their dependency order each module that defines a shared library * init routine and its dependents needs to be checked. As each module is * checked it is marked so that is only checked once. */ #define GET_IMAGE_INIT_DEPEND_STATE(m) ((m) & 0x10) #define SET_IMAGE_INIT_DEPEND_STATE(m) m = ((m) | 0x10) struct object_image { struct image image; module_state module; enum bool module_state_saved; module_state saved_module_state; }; struct library_image { struct image image; unsigned long nmodules; module_state *modules; struct dylib_command *dlid; dev_t dev; ino_t ino; enum bool dependent_libraries_loaded; enum bool remove_on_error; enum bool module_states_saved; module_state *saved_module_states; unsigned long library_offset; }; /* * Using /System/Library/CoreServices/Desktop.app/Contents/MacOS/Desktop from * MacOS X Public Beta (Kodiak1G7) * TOTAL number of bundles 4 * TOTAL number of libraries 58 */ enum nobject_images { NOBJECT_IMAGES = 5 }; struct object_images { struct object_image images[NOBJECT_IMAGES]; unsigned long nimages; struct object_images *next_images; /* * The above three fields can't change without breaking gdb(1) see the * comments in <mach-o/dyld_gdb.h>. */ }; extern struct object_images object_images; enum nlibrary_images { NLIBRARY_IMAGES = 60 }; struct library_images { struct library_image images[NLIBRARY_IMAGES]; unsigned long nimages; struct library_images *next_images; /* * The above three fields can't change without breaking gdb(1) see the * comments in <mach-o/dyld_gdb.h>. */ }; extern struct library_images library_images; extern void (*dyld_monaddition)(char *lowpc, char *highpc); extern void load_executable_image( char *name, struct mach_header *mh_execute, unsigned long *entry_point); extern enum bool load_dependent_libraries( void); extern enum bool load_library_image( struct dylib_command *dl, char *dylib_name, enum bool force_searching, struct image **image_pointer); extern void unload_remove_on_error_libraries( void); extern void clear_remove_on_error_libraries( void); extern struct object_image *map_bundle_image( char *name, char *object_addr, unsigned long object_size); extern void unload_bundle_image( struct object_image *object_image, enum bool keepMemoryMapped, enum bool reset_lazy_references); extern void shared_pcsample_buffer( char *name, struct section *s, unsigned long slide_value); extern enum bool set_images_to_prebound( void); extern void undo_prebound_images( void); extern void find_twolevel_prebound_lib_subtrees( void); extern void try_to_use_prebound_libraries( void); extern void call_image_init_routines( enum bool make_delayed_calls); extern char *executables_name; extern char *save_string( char *name); extern void create_executables_path( char *exec_path); extern struct object_image *find_object_image( struct image *image); extern enum bool is_library_loaded_by_name( char *dylib_name, struct dylib_command *dl, struct image **image_pointer); extern enum bool is_library_loaded_by_stat( char *dylib_name, struct dylib_command *dl, struct stat *stat_buf, struct image **image_pointer);