#import <stdlib.h>
#import <mach/mach.h>
#import "stuff/openstep_mach.h"
#import "mach-o/loader.h"
#import "mach-o/dyld_gdb.h"
#import "stuff/bool.h"
#import "inline_strcmp.h"
#import "images.h"
#import "symbols.h"
#import "errors.h"
#import "reloc.h"
#import "lock.h"
#import "register_funcs.h"
#import "mod_init_funcs.h"
#import "dyld_init.h"
#import "debug.h"
#import "allocate.h"
#import "trace.h"
static unsigned long _dyld_image_count(
void);
static struct mach_header * _dyld_get_image_header(
unsigned long image_index);
static unsigned long _dyld_get_image_vmaddr_slide(
unsigned long image_index);
static char * _dyld_get_image_name(
unsigned long image_index);
static void _dyld_lookup_and_bind(
char *symbol_name,
unsigned long *address,
module_state **module);
static void _dyld_lookup_and_bind_with_hint(
char *symbol_name,
char *library_name_hint,
unsigned long *address,
module_state **module);
static void _dyld_lookup_and_bind_objc(
char *symbol_name,
unsigned long *address,
module_state **module);
static void _dyld_lookup_and_bind_fully(
char *symbol_name,
unsigned long *address,
module_state **module);
static void _dyld_install_handlers(
void (*undefined_handler)(
const char *symbol_name),
module_state * (*multiple_handler)(
struct nlist *symbol,
module_state *old_module,
module_state *new_module),
void (*linkEdit_handler)(
enum link_edit_error_class error_class,
int error_number,
const char *file_name,
const char *error_string));
static void _dyld_link_edit_error(
enum link_edit_error_class *error_class,
int *error_number,
const char **file_name,
const char **error_string);
static module_state * _dyld_link_module(
char *object_addr,
unsigned long object_size,
char *moduleName,
unsigned long options);
#define LINK_OPTION_BINDNOW 0x1
#define LINK_OPTION_PRIVATE 0x2
#define LINK_OPTION_RETURN_ON_ERROR 0x4
#define LINK_OPTION_DONT_CALL_MOD_INIT 0x8
#define LINK_OPTION_TRAILING_PHYS_NAME 0x10
#define LINK_OPTION_RELOC_JUST_THIS_MODULE 0x80000000
static enum bool _dyld_unlink_module(
module_state *module,
unsigned long options);
#define UNLINK_OPTION_KEEP_MEMORY_MAPPED 0x1
#define UNLINK_OPTION_RESET_LAZY_REFERENCES 0x2
static void _dyld_register_func_for_add_image(
void (*func)(struct mach_header *mh, unsigned long vmaddr_slide));
static void _dyld_register_func_for_remove_image(
void (*func)(struct mach_header *mh, unsigned long vmaddr_slide));
static void _dyld_register_func_for_link_module(
void (*func)(module_state *module));
static void _dyld_register_func_for_unlink_module(
void (*func)(module_state *module));
static void _dyld_register_func_for_replace_module(
void (*func)(module_state *oldmodule, module_state *newmodule));
static void _dyld_get_objc_module_sect_for_module(
module_state *module,
unsigned long *objc_module,
unsigned long *size);
static void _dyld_bind_objc_module(
unsigned long objc_module);
static enum bool _dyld_bind_fully_image_containing_address(
unsigned long address);
static enum bool _dyld_image_containing_address(
unsigned long address);
static struct mach_header * _dyld_get_image_header_containing_address(
unsigned long address);
static void _dyld_moninit(
void (*monaddition)(char *lowpc, char *highpc));
static void _dyld_fork_prepare(
void);
static void _dyld_fork_parent(
void);
static void _dyld_fork_child(
void);
static void _dyld_fork_child_final(
void);
static void _dyld_fork_mach_init(
void);
static void _dyld_make_delayed_module_initializer_calls(
void);
static char * _dyld_NSNameOfSymbol(
struct nlist *symbol);
static unsigned long _dyld_NSAddressOfSymbol(
struct nlist *symbol);
static module_state * _dyld_NSModuleForSymbol(
struct nlist *symbol);
static struct nlist * _dyld_NSLookupAndBindSymbol(
char *symbol_name);
static struct nlist * _dyld_NSLookupAndBindSymbolWithHint(
char *symbol_name,
char *libraryNameHint);
static struct nlist * _dyld_NSLookupSymbolInModule(
module_state *module,
char *symbol_name);
static struct nlist * _dyld_NSLookupSymbolInImage(
struct mach_header *mh,
char *symbol_name,
unsigned long options);
#define LOOKUP_OPTION_BIND 0x0
#define LOOKUP_OPTION_BIND_NOW 0x1
#define LOOKUP_OPTION_BIND_FULLY 0x2
#define LOOKUP_OPTION_RETURN_ON_ERROR 0x4
static enum bool _dyld_NSMakePrivateModulePublic(
module_state *module);
static enum bool _dyld_NSIsSymbolNameDefined(
char *symbol_name);
static enum bool _dyld_NSIsSymbolNameDefinedWithHint(
char *symbol_name,
char *libraryNameHint);
static enum bool _dyld_NSIsSymbolNameDefinedInImage(
struct mach_header *mh,
char *symbol_name);
static char * _dyld_NSNameOfModule(
module_state *module);
static char * _dyld_NSLibraryNameForModule(
module_state *module);
static enum bool _dyld_NSAddLibrary(
char *dylib_name);
static enum bool _dyld_NSAddLibraryWithSearching(
char *dylib_name);
static struct mach_header * _dyld_NSAddImage(
char *dylib_name,
unsigned long options);
#define ADDIMAGE_OPTION_NONE 0x0
#define ADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
#define ADDIMAGE_OPTION_WITH_SEARCHING 0x2
#define ADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
#define ADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
static int _dyld_NSGetExecutablePath(
char *buf,
unsigned long *bufsize);
static enum bool _dyld_launched_prebound(
void);
static enum bool _dyld_all_twolevel_modules_prebound(
void);
static void _dyld_install_link_edit_symbol_handlers(
object_image_register_proc newImageHandler,
object_image_locator_proc findDefinitionHandler);
struct dyld_func {
char *funcname;
void (*address)(void);
};
static
struct dyld_func dyld_funcs[] = {
{"__dyld_image_count", (void (*)(void))_dyld_image_count },
{"__dyld_get_image_header", (void (*)(void))_dyld_get_image_header },
{"__dyld_get_image_vmaddr_slide",
(void (*)(void))_dyld_get_image_vmaddr_slide },
{"__dyld_get_image_name", (void (*)(void))_dyld_get_image_name },
{"__dyld_lookup_and_bind", (void (*)(void))_dyld_lookup_and_bind },
{"__dyld_lookup_and_bind_with_hint",
(void (*)(void))_dyld_lookup_and_bind_with_hint },
{"__dyld_lookup_and_bind_objc",
(void (*)(void))_dyld_lookup_and_bind_objc },
{"__dyld_lookup_and_bind_fully",
(void (*)(void))_dyld_lookup_and_bind_fully },
{"__dyld_install_handlers", (void (*)(void))_dyld_install_handlers },
{"__dyld_link_edit_error", (void (*)(void))_dyld_link_edit_error },
{"__dyld_link_module", (void (*)(void))_dyld_link_module },
{"__dyld_unlink_module", (void (*)(void))_dyld_unlink_module },
{"__dyld_register_func_for_add_image",
(void (*)(void))_dyld_register_func_for_add_image },
{"__dyld_register_func_for_remove_image",
(void (*)(void))_dyld_register_func_for_remove_image },
{"__dyld_register_func_for_link_module",
(void (*)(void))_dyld_register_func_for_link_module },
{"__dyld_register_func_for_unlink_module",
(void (*)(void))_dyld_register_func_for_unlink_module },
{"__dyld_register_func_for_replace_module",
(void (*)(void))_dyld_register_func_for_replace_module },
{"__dyld_get_objc_module_sect_for_module",
(void (*)(void))_dyld_get_objc_module_sect_for_module },
{"__dyld_bind_objc_module", (void (*)(void))_dyld_bind_objc_module },
{"__dyld_bind_fully_image_containing_address",
(void (*)(void))_dyld_bind_fully_image_containing_address },
{"__dyld_image_containing_address",
(void (*)(void))_dyld_image_containing_address },
{"__dyld_get_image_header_containing_address",
(void (*)(void))_dyld_get_image_header_containing_address },
{"__dyld_moninit", (void (*)(void))_dyld_moninit },
{"__dyld_fork_prepare", (void (*)(void))_dyld_fork_prepare },
{"__dyld_fork_parent", (void (*)(void))_dyld_fork_parent },
{"__dyld_fork_child", (void (*)(void))_dyld_fork_child },
{"__dyld_fork_child_final", (void (*)(void))_dyld_fork_child_final },
{"__dyld_fork_mach_init", (void (*)(void))_dyld_fork_mach_init },
{"__dyld_make_delayed_module_initializer_calls",
(void (*)(void))_dyld_make_delayed_module_initializer_calls },
{"__dyld_NSNameOfSymbol", (void (*)(void))_dyld_NSNameOfSymbol },
{"__dyld_NSAddressOfSymbol",(void (*)(void))_dyld_NSAddressOfSymbol },
{"__dyld_NSModuleForSymbol",(void (*)(void))_dyld_NSModuleForSymbol },
{"__dyld_NSLookupAndBindSymbol",
(void (*)(void))_dyld_NSLookupAndBindSymbol},
{"__dyld_NSLookupAndBindSymbolWithHint",
(void (*)(void))_dyld_NSLookupAndBindSymbolWithHint},
{"__dyld_NSLookupSymbolInModule",
(void (*)(void))_dyld_NSLookupSymbolInModule},
{"__dyld_NSLookupSymbolInImage",
(void (*)(void))_dyld_NSLookupSymbolInImage},
{"__dyld_NSMakePrivateModulePublic",
(void (*)(void))_dyld_NSMakePrivateModulePublic},
{"__dyld_NSIsSymbolNameDefined",
(void (*)(void))_dyld_NSIsSymbolNameDefined},
{"__dyld_NSIsSymbolNameDefinedWithHint",
(void (*)(void))_dyld_NSIsSymbolNameDefinedWithHint},
{"__dyld_NSIsSymbolNameDefinedInImage",
(void (*)(void))_dyld_NSIsSymbolNameDefinedInImage},
{"__dyld_NSNameOfModule", (void (*)(void))_dyld_NSNameOfModule },
{"__dyld_NSLibraryNameForModule",
(void (*)(void))_dyld_NSLibraryNameForModule },
{"__dyld_NSAddLibrary", (void (*)(void))_dyld_NSAddLibrary },
{"__dyld_NSAddLibraryWithSearching",
(void (*)(void))_dyld_NSAddLibraryWithSearching },
{"__dyld_NSAddImage", (void (*)(void))_dyld_NSAddImage },
{"__dyld__NSGetExecutablePath", (void (*)(void))_dyld_NSGetExecutablePath },
{"__dyld_launched_prebound",(void (*)(void))_dyld_launched_prebound },
{"__dyld_all_twolevel_modules_prebound",
(void (*)(void))_dyld_all_twolevel_modules_prebound },
{"__dyld_call_module_initializers_for_dylib",
(void (*)(void))_dyld_call_module_initializers_for_dylib },
{"__dyld_mod_term_funcs", (void (*)(void))_dyld_mod_term_funcs },
{"__dyld_install_link_edit_symbol_handlers",
(void (*)(void))_dyld_install_link_edit_symbol_handlers },
{NULL, 0}
};
static enum bool saved_dyld_mem_protect;
enum bool
_dyld_func_lookup(
char *dyld_func_name,
void (**address)(void))
{
unsigned long i;
*address = (void (*)(void))0;
for(i = 0; dyld_funcs[i].funcname != NULL; i++){
if(strcmp(dyld_funcs[i].funcname, dyld_func_name) == 0){
*address = dyld_funcs[i].address;
return(TRUE);
}
}
return(FALSE);
}
static
unsigned long
_dyld_image_count(
void)
{
unsigned nimages, i;
struct object_images *p;
struct library_images *q;
enum link_state link_state;
set_lock();
nimages = 0;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
nimages++;
}
}
for(q = &library_images; q != NULL; q = q->next_images){
nimages += q->nimages;
}
release_lock();
return(nimages);
}
static
struct mach_header *
_dyld_get_image_header(
unsigned long image_index)
{
unsigned nimages, i;
struct object_images *p;
struct library_images *q;
enum link_state link_state;
set_lock();
nimages = 0;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
if(image_index == nimages){
release_lock();
return(p->images[i].image.mh);
}
nimages++;
}
}
for(q = &library_images; q != NULL; q = q->next_images){
if(image_index >= nimages && image_index < nimages + q->nimages){
release_lock();
return(q->images[image_index - nimages].image.mh);
}
nimages += q->nimages;
}
release_lock();
return(NULL);
}
static
unsigned long
_dyld_get_image_vmaddr_slide(
unsigned long image_index)
{
unsigned nimages, i;
struct object_images *p;
struct library_images *q;
enum link_state link_state;
set_lock();
nimages = 0;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
if(image_index == nimages){
release_lock();
return(p->images[i].image.vmaddr_slide);
}
nimages++;
}
}
for(q = &library_images; q != NULL; q = q->next_images){
if(image_index >= nimages && image_index < nimages + q->nimages){
release_lock();
return(q->images[image_index - nimages].image.vmaddr_slide);
}
nimages += q->nimages;
}
release_lock();
return(0);
}
static
char *
_dyld_get_image_name(
unsigned long image_index)
{
unsigned nimages, i;
struct object_images *p;
struct library_images *q;
enum link_state link_state;
set_lock();
nimages = 0;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
if(image_index == nimages){
release_lock();
return(p->images[i].image.name);
}
nimages++;
}
}
for(q = &library_images; q != NULL; q = q->next_images){
if(image_index >= nimages && image_index < nimages + q->nimages){
release_lock();
return(q->images[image_index - nimages].image.name);
}
nimages += q->nimages;
}
release_lock();
return(NULL);
}
static
void
_dyld_lookup_and_bind(
char *symbol_name,
unsigned long *address,
module_state **module)
{
bind_symbol_by_name(symbol_name, address, module, NULL, TRUE);
}
static
void
_dyld_lookup_and_bind_with_hint(
char *symbol_name,
char *library_name_hint,
unsigned long *address,
module_state **module)
{
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
unsigned long value;
enum link_state link_state;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_lookup_and_bind_with_hint,
symbol_name);
lookup_symbol_in_hinted_library(symbol_name, library_name_hint,
&defined_symbol, &defined_module, &defined_image,
&defined_library_image);
if(defined_symbol != NULL){
link_state = GET_LINK_STATE(*defined_module);
if(link_state == LINKED || link_state == FULLY_LINKED){
value = defined_symbol->n_value;
if((defined_symbol->n_type & N_TYPE) != N_ABS)
value += defined_image->vmaddr_slide;
if(address != NULL)
*address = value;
if(module != NULL)
*module = defined_module;
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_lookup_and_bind_with_hint);
release_lock();
return;
}
}
release_lock();
bind_symbol_by_name(symbol_name, address, module, NULL, TRUE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_lookup_and_bind_with_hint);
}
static
void
_dyld_lookup_and_bind_objc(
char *symbol_name,
unsigned long *address,
module_state **module)
{
bind_symbol_by_name(symbol_name, address, module, NULL, FALSE);
}
static
void
_dyld_lookup_and_bind_fully(
char *symbol_name,
unsigned long *address,
module_state **module)
{
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
enum link_state link_state;
struct object_image *object_image;
unsigned long i;
struct object_images *p;
if(dyld_trace)
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_lookup_and_bind_fully,
symbol_name);
if(dyld_trace)
release_lock();
bind_symbol_by_name(symbol_name, address, module, NULL, TRUE);
set_lock();
lookup_symbol(symbol_name, NULL, NULL, FALSE, &defined_symbol,
&defined_module, &defined_image, &defined_library_image,
NULL);
link_state = GET_LINK_STATE(*defined_module);
if(link_state == FULLY_LINKED){
release_lock();
return;
}
if(defined_symbol != NULL){
if(defined_library_image == NULL){
object_image = NULL;
for(p = &object_images;
p != NULL && object_image == NULL;
p = p->next_images){
for(i = 0; i < p->nimages && object_image == NULL; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
if(defined_image == &(p->images[i].image))
object_image = p->images + i;
}
}
if(object_image == NULL){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_lookup_and_bind_fully);
release_lock();
return;
}
link_object_module(object_image, TRUE, FALSE);
}
else
link_library_module(defined_library_image, defined_image,
defined_module, TRUE, FALSE, FALSE);
link_in_need_modules(TRUE, TRUE, NULL);
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_lookup_and_bind_fully);
}
static
void
_dyld_install_handlers(
void (*undefined_handler)(
const char *symbol_name),
module_state * (*multiple_handler)(
struct nlist *symbol,
module_state *old_module,
module_state *new_module),
void (*linkEdit_handler)(
enum link_edit_error_class error_class,
int error_number,
const char *file_name,
const char *error_string))
{
set_lock();
user_undefined_handler = undefined_handler;
user_multiple_handler = multiple_handler;
user_linkEdit_handler = linkEdit_handler;
release_lock();
}
static void _dyld_link_edit_error(
enum link_edit_error_class *error_class,
int *error_number,
const char **file_name,
const char **ptr_error_string)
{
set_lock();
*error_class = NSLinkEditError_errorClass;
*error_number = NSLinkEditError_errorNumber;
*file_name = NSLinkEditError_fileName;
*ptr_error_string = error_string;
release_lock();
}
static module_state *
_dyld_link_module(
char *object_addr,
unsigned long object_size,
char *moduleName,
unsigned long options)
{
struct object_image *object_image, *reloc_just_this_object_image;
enum bool bind_now;
char *physical_name;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_link_module, moduleName);
if(options & LINK_OPTION_RETURN_ON_ERROR){
clear_module_states_saved();
return_on_error = TRUE;
}
else
return_on_error = FALSE;
if((options & LINK_OPTION_TRAILING_PHYS_NAME) ==
LINK_OPTION_TRAILING_PHYS_NAME)
physical_name = moduleName + strlen(moduleName) + 1;
else
physical_name = moduleName;
object_image = map_bundle_image(moduleName, physical_name, object_addr,
object_size);
if(object_image == NULL){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_link_module);
release_lock();
return(NULL);
}
if((object_image->image.mh->flags & MH_BINDATLOAD) != 0 ||
(options & LINK_OPTION_BINDNOW) == LINK_OPTION_BINDNOW)
bind_now = TRUE;
else
bind_now = FALSE;
if((options & LINK_OPTION_PRIVATE) == LINK_OPTION_PRIVATE)
object_image->image.private = TRUE;
else
object_image->image.private = FALSE;
if((options & LINK_OPTION_DONT_CALL_MOD_INIT) ==
LINK_OPTION_DONT_CALL_MOD_INIT)
object_image->image.dont_call_mod_init = TRUE;
else
object_image->image.dont_call_mod_init = FALSE;
if((options & LINK_OPTION_RELOC_JUST_THIS_MODULE) ==
LINK_OPTION_RELOC_JUST_THIS_MODULE &&
return_on_error == FALSE &&
all_twolevel_modules_prebound == TRUE)
reloc_just_this_object_image = object_image;
else
reloc_just_this_object_image = NULL;
if(object_image_register != NULL){
release_lock();
(*object_image_register)(moduleName, object_image);
set_lock();
}
if(load_dependent_libraries() == FALSE &&
return_on_error == TRUE){
object_image->image.private = TRUE;
unload_bundle_image(object_image, FALSE, FALSE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_link_module);
release_lock();
return(NULL);
}
if(force_flat_namespace == FALSE){
if((object_image->image.mh->flags & MH_TWOLEVEL) == MH_TWOLEVEL &&
(object_image->image.hints_cmd != NULL))
object_image->image.image_can_use_hints = TRUE;
else
object_image->image.image_can_use_hints = FALSE;
}
if(link_object_module(object_image, bind_now, FALSE) == FALSE &&
return_on_error == TRUE){
clear_being_linked_list(TRUE);
object_image->image.private = TRUE;
unload_bundle_image(object_image, FALSE, FALSE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_link_module);
release_lock();
return(NULL);
}
if(return_on_error == TRUE){
if(link_in_need_modules(FALSE, FALSE, NULL) == FALSE){
clear_being_linked_list(TRUE);
clear_undefined_list(TRUE);
object_image->image.private = TRUE;
unload_bundle_image(object_image, FALSE, FALSE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_link_module);
release_lock();
return(NULL);
}
else{
release_lock();
}
}
else{
(void)link_in_need_modules(FALSE, TRUE,
reloc_just_this_object_image);
}
if(undefined_handler_recursion_level <= 1)
gdb_dyld_state_changed();
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_link_module);
return(&object_image->module);
}
static
enum bool
_dyld_unlink_module(
module_state *module,
unsigned long options)
{
unsigned long i;
struct object_images *p;
enum bool retval;
enum link_state link_state;
enum bool keepMemoryMapped, reset_lazy_references;
set_lock();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_unlink_module);
if(options & UNLINK_OPTION_KEEP_MEMORY_MAPPED)
keepMemoryMapped = TRUE;
else
keepMemoryMapped = FALSE;
if(options & UNLINK_OPTION_RESET_LAZY_REFERENCES)
reset_lazy_references = TRUE;
else
reset_lazy_references = FALSE;
retval = FALSE;
if(module == &(object_images.images[0].module))
goto done;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
if(module == &(p->images[i].module)){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
goto done;
call_module_terminator_for_object(&(p->images[i]));
call_funcs_for_remove_image(p->images[i].image.mh,
p->images[i].image.vmaddr_slide);
unload_bundle_image(&(p->images[i]),
keepMemoryMapped,
reset_lazy_references);
retval = TRUE;
goto done;
}
}
}
done:
gdb_dyld_state_changed();
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_unlink_module);
release_lock();
return(retval);
}
static
void
_dyld_register_func_for_add_image(
void (*func)(struct mach_header *mh, unsigned long vmaddr_slide))
{
register_func_for_add_image(func);
}
static
void
_dyld_register_func_for_remove_image(
void (*func)(struct mach_header *mh, unsigned long vmaddr_slide))
{
register_func_for_remove_image(func);
}
static
void
_dyld_register_func_for_link_module(
void (*func)(module_state *module))
{
register_func_for_link_module(func);
}
static
void
_dyld_register_func_for_unlink_module(
void (*func)(module_state *module))
{
}
static
void
_dyld_register_func_for_replace_module(
void (*func)(module_state *oldmodule, module_state *newmodule))
{
}
static
void
_dyld_get_objc_module_sect_for_module(
module_state *module,
unsigned long *objc_module,
unsigned long *size)
{
unsigned long i, j, k;
struct object_images *p;
struct library_images *q;
struct load_command *lc;
struct segment_command *sg;
struct section *s;
struct dylib_module *dylib_modules;
enum link_state link_state;
set_lock();
*objc_module = 0;
*size = 0;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
if(module == &(p->images[i].module)){
lc = (struct load_command *)((char *)p->images[i].image.mh +
sizeof(struct mach_header));
for(j = 0; j < p->images[i].image.mh->ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
s = (struct section *)
((char *)sg + sizeof(struct segment_command));
for(k = 0; k < sg->nsects; k++){
if(strcmp(s->segname, SEG_OBJC) == 0 &&
strcmp(s->sectname, SECT_OBJC_MODULES) == 0){
if(s->size != 0){
*objc_module = s->addr +
p->images[i].image.vmaddr_slide;
*size = s->size;
}
release_lock();
return;
}
s++;
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
release_lock();
return;
}
}
}
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
if(module >= q->images[i].modules &&
module < q->images[i].modules +
q->images[i].image.dyst->nmodtab){
j = module - q->images[i].modules;
dylib_modules = (struct dylib_module *)
(q->images[i].image.vmaddr_slide +
q->images[i].image.linkedit_segment->vmaddr +
q->images[i].image.dyst->modtaboff -
q->images[i].image.linkedit_segment->fileoff);
if(dylib_modules[j].objc_module_info_size != 0){
*objc_module = dylib_modules[j].objc_module_info_addr +
q->images[i].image.vmaddr_slide;
*size = dylib_modules[j].objc_module_info_size;
}
release_lock();
return;
}
}
}
release_lock();
}
static
void
_dyld_bind_objc_module(
unsigned long objc_module)
{
unsigned long i, j;
struct library_images *q;
struct dylib_module *dylib_modules;
enum link_state link_state;
set_lock();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_bind_objc_module);
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
dylib_modules = (struct dylib_module *)
(q->images[i].image.vmaddr_slide +
q->images[i].image.linkedit_segment->vmaddr +
q->images[i].image.dyst->modtaboff -
q->images[i].image.linkedit_segment->fileoff);
for(j = 0; j < q->images[i].image.dyst->nmodtab; j++){
if(objc_module >= dylib_modules[j].objc_module_info_addr +
q->images[i].image.vmaddr_slide &&
objc_module < dylib_modules[j].objc_module_info_addr +
dylib_modules[j].objc_module_info_size +
q->images[i].image.vmaddr_slide)
break;
}
if(j == q->images[i].image.dyst->nmodtab)
continue;
link_state = GET_LINK_STATE(q->images[i].modules[j]);
if(link_state == LINKED || link_state == FULLY_LINKED){
release_lock();
return;
}
if(link_state != UNLINKED &&
link_state != PREBOUND_UNLINKED){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_bind_objc_module);
release_lock();
return;
}
if(link_state == PREBOUND_UNLINKED){
undo_prebinding_for_library_module(
q->images[i].modules + j,
&(q->images[i].image),
q->images + i);
SET_LINK_STATE(q->images[i].modules[j], UNLINKED);
}
link_library_module(q->images + i,
&(q->images[i].image),
q->images[i].modules + j,
FALSE, FALSE, FALSE);
resolve_undefineds(FALSE, FALSE);
relocate_modules_being_linked(FALSE);
check_and_report_undefineds(FALSE);
call_registered_funcs_for_add_images();
call_registered_funcs_for_linked_modules();
call_image_init_routines(FALSE);
call_module_initializers(FALSE, FALSE, FALSE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_bind_objc_module);
release_lock();
return;
}
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_bind_objc_module);
release_lock();
}
static
enum bool
_dyld_bind_fully_image_containing_address(
unsigned long address)
{
unsigned long i, j;
struct object_images *p;
struct library_images *q;
struct load_command *lc;
struct segment_command *sg;
enum link_state link_state;
set_lock();
DYLD_TRACE_LIBFUNC_START(
DYLD_TRACE_bind_fully_image_containing_address);
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
lc = (struct load_command *)((char *)p->images[i].image.mh +
sizeof(struct mach_header));
for(j = 0; j < p->images[i].image.mh->ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
if(address >= sg->vmaddr +
p->images[i].image.vmaddr_slide &&
address < sg->vmaddr + sg->vmsize +
p->images[i].image.vmaddr_slide){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == FULLY_LINKED){
release_lock();
DYLD_TRACE_LIBFUNC_END(
DYLD_TRACE_bind_fully_image_containing_address);
return(TRUE);
}
link_object_module(&(p->images[i]), TRUE, FALSE);
link_in_need_modules(TRUE, TRUE, NULL);
DYLD_TRACE_LIBFUNC_END(
DYLD_TRACE_bind_fully_image_containing_address);
return(TRUE);
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
}
}
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
lc = (struct load_command *)((char *)q->images[i].image.mh +
sizeof(struct mach_header));
for(j = 0; j < q->images[i].image.mh->ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
if(address >= sg->vmaddr +
q->images[i].image.vmaddr_slide &&
address < sg->vmaddr + sg->vmsize +
q->images[i].image.vmaddr_slide){
for(j=0; j < q->images[i].image.dyst->nmodtab; j++){
link_state =
GET_LINK_STATE(q->images[i].modules[j]);
if(link_state == PREBOUND_UNLINKED){
undo_prebinding_for_library_module(
q->images[i].modules + j,
&(q->images[i].image),
q->images + i);
link_state = UNLINKED;
SET_LINK_STATE(q->images[i].modules[j],
link_state);
}
if(link_state != FULLY_LINKED)
link_library_module(q->images + i,
&(q->images[i].image),
q->images[i].modules + j,
TRUE, FALSE, FALSE);
}
link_in_need_modules(TRUE, TRUE, NULL);
DYLD_TRACE_LIBFUNC_END(
DYLD_TRACE_bind_fully_image_containing_address);
return(TRUE);
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
}
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_bind_fully_image_containing_address);
release_lock();
return(FALSE);
}
static
enum bool
_dyld_image_containing_address(
unsigned long address)
{
if(_dyld_get_image_header_containing_address(address) != NULL)
return(TRUE);
else
return(FALSE);
}
static struct mach_header *
_dyld_get_image_header_containing_address(
unsigned long address)
{
unsigned long i, j, ncmds, vmaddr_slide;
struct object_images *p;
struct library_images *q;
struct image *image;
struct load_command *lc;
struct segment_command *sg;
enum bool first_object_image;
enum link_state link_state;
set_lock();
first_object_image = TRUE;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
image = &(p->images[i].image);
vmaddr_slide = image->vmaddr_slide;
if((image->mh->flags & MH_SPLIT_SEGS) != 0 ||
first_object_image == TRUE){
lc = (struct load_command *)((char *)image->mh +
sizeof(struct mach_header));
ncmds = image->mh->ncmds;
for(j = 0; j < ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
if(address >= sg->vmaddr + vmaddr_slide &&
address < sg->vmaddr + sg->vmsize +vmaddr_slide){
release_lock();
return(image->mh);
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
first_object_image = FALSE;
}
else{
if(address >= ((unsigned long)image->mh) &&
address < ((unsigned long)image->mh) +
image->vmaddr_size){
release_lock();
return(image->mh);
}
}
}
}
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
image = &(q->images[i].image);
vmaddr_slide = image->vmaddr_slide;
if((image->mh->flags & MH_SPLIT_SEGS) != 0){
lc = (struct load_command *)((char *)image->mh +
sizeof(struct mach_header));
ncmds = image->mh->ncmds;
for(j = 0; j < ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
if(address >= sg->vmaddr + vmaddr_slide &&
address < sg->vmaddr + sg->vmsize +vmaddr_slide){
release_lock();
return(image->mh);
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
}
else{
if(address >= ((unsigned long)image->mh) &&
address < ((unsigned long)image->mh) +
image->vmaddr_size){
release_lock();
return(image->mh);
}
}
}
}
release_lock();
return(NULL);
}
static
void
_dyld_moninit(
void (*monaddition)(char *lowpc, char *highpc))
{
unsigned long i, j, k;
struct object_images *p;
struct library_images *q;
struct load_command *lc;
struct segment_command *sg;
struct section *s;
enum link_state link_state;
set_lock();
dyld_monaddition = monaddition;
if(dyld_monaddition == NULL){
release_lock();
return;
}
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
continue;
if(p == &object_images && i == 0)
continue;
lc = (struct load_command *)((char *)p->images[i].image.mh +
sizeof(struct mach_header));
for(j = 0; j < p->images[i].image.mh->ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
s = (struct section *)
((char *)sg + sizeof(struct segment_command));
for(k = 0; k < sg->nsects; k++){
if(strcmp(s->segname, SEG_TEXT) == 0 &&
strcmp(s->sectname, SECT_TEXT) == 0){
if(s->size != 0){
release_lock();
dyld_monaddition(
(char *)(s->addr +
p->images[i].image.vmaddr_slide),
(char *)(s->addr +
p->images[i].image.vmaddr_slide +
s->size));
set_lock();
}
}
s++;
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
}
}
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
lc = (struct load_command *)((char *)q->images[i].image.mh +
sizeof(struct mach_header));
for(j = 0; j < q->images[i].image.mh->ncmds; j++){
switch(lc->cmd){
case LC_SEGMENT:
sg = (struct segment_command *)lc;
s = (struct section *)
((char *)sg + sizeof(struct segment_command));
for(k = 0; k < sg->nsects; k++){
if(strcmp(s->segname, SEG_TEXT) == 0 &&
strcmp(s->sectname, SECT_TEXT) == 0){
if(s->size != 0){
release_lock();
dyld_monaddition(
(char *)(s->addr +
q->images[i].image.vmaddr_slide),
(char *)(s->addr +
q->images[i].image.vmaddr_slide +
s->size));
set_lock();
}
}
s++;
}
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
}
}
release_lock();
}
static
void
_dyld_fork_prepare(
void)
{
set_lock();
}
static
void
_dyld_fork_parent(
void)
{
release_lock();
}
static
void
_dyld_fork_child(
void)
{
#ifdef __MACH30__
#undef mach_task_self
extern mach_port_t mach_task_self(void);
mach_task_self_ = mach_task_self();
#else
#undef task_self
extern int task_self(void);
task_self_ = task_self();
#endif
cached_thread = MACH_PORT_NULL;
cached_stack = 0;
saved_dyld_mem_protect = dyld_mem_protect;
dyld_mem_protect = FALSE;
clear_lock(global_lock);
release_lock();
}
static
void
_dyld_fork_child_final(
void)
{
#ifdef __MACH30__
#undef mach_task_self
extern mach_port_t mach_task_self(void);
#else
#undef task_self
extern int task_self(void);
#endif
set_lock();
#ifdef __MACH30__
mach_task_self_ = mach_task_self();
#else
task_self_ = task_self();
#endif
dyld_mem_protect = saved_dyld_mem_protect;
release_lock();
}
static
void
_dyld_fork_mach_init(
void)
{
extern void mach_init(void);
set_lock();
mach_init();
release_lock();
}
static
void
_dyld_make_delayed_module_initializer_calls(
void)
{
set_lock();
DYLD_TRACE_LIBFUNC_START(
DYLD_TRACE_make_delayed_module_initializer_calls);
call_image_init_routines(TRUE);
call_module_initializers(TRUE, FALSE, FALSE);
DYLD_TRACE_LIBFUNC_END(
DYLD_TRACE_make_delayed_module_initializer_calls);
release_lock();
}
static
char *
_dyld_NSNameOfSymbol(
struct nlist *symbol)
{
enum bool lock_set;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
char *symbol_name;
lock_set = set_lock_or_in_multiply_defined_handler();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_NSNameOfSymbol);
symbol_name = NULL;
if(validate_NSSymbol(symbol, &defined_module,
&defined_image, &defined_library_image) == TRUE){
symbol_name = (char *)
(defined_image->vmaddr_slide +
defined_image->linkedit_segment->vmaddr +
defined_image->st->stroff -
defined_image->linkedit_segment->fileoff) +
symbol->n_un.n_strx;
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSNameOfSymbol);
if(lock_set == TRUE)
release_lock();
return(symbol_name);
}
static
unsigned long
_dyld_NSAddressOfSymbol(
struct nlist *symbol)
{
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
unsigned long value;
set_lock();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_NSAddressOfSymbol);
value = 0;
if(validate_NSSymbol(symbol, &defined_module,
&defined_image, &defined_library_image) == TRUE){
value = symbol->n_value;
if((symbol->n_type & N_TYPE) != N_ABS)
value += defined_image->vmaddr_slide;
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddressOfSymbol);
release_lock();
return(value);
}
static
module_state *
_dyld_NSModuleForSymbol(
struct nlist *symbol)
{
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
set_lock();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_NSModuleForSymbol);
defined_module = NULL;
(void)validate_NSSymbol(symbol, &defined_module,
&defined_image, &defined_library_image);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSModuleForSymbol);
release_lock();
return(defined_module);
}
static
struct nlist *
_dyld_NSLookupAndBindSymbol(
char *symbol_name)
{
struct nlist *symbol;
bind_symbol_by_name(symbol_name, NULL, NULL, &symbol, TRUE);
return(symbol);
}
static
struct nlist *
_dyld_NSLookupAndBindSymbolWithHint(
char *symbol_name,
char *libraryNameHint)
{
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
enum link_state link_state;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSLookupAndBindSymbolWithHint,
symbol_name);
lookup_symbol_in_hinted_library(symbol_name, libraryNameHint,
&defined_symbol, &defined_module, &defined_image,
&defined_library_image);
if(defined_symbol != NULL){
link_state = GET_LINK_STATE(*defined_module);
if(link_state == LINKED || link_state == FULLY_LINKED){
DYLD_TRACE_LIBFUNC_END(
DYLD_TRACE_NSLookupAndBindSymbolWithHint);
release_lock();
return(defined_symbol);
}
}
release_lock();
bind_symbol_by_name(symbol_name, NULL, NULL, &defined_symbol, TRUE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupAndBindSymbolWithHint);
return(defined_symbol);
}
static
struct nlist *
_dyld_NSLookupSymbolInModule(
module_state *module,
char *symbol_name)
{
unsigned long i;
struct object_images *p;
enum link_state link_state;
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSLookupSymbolInModule,
symbol_name);
defined_symbol = NULL;
if(module == &(object_images.images[0].module))
goto done;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
if(module == &(p->images[i].module)){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
goto done;
(void)lookup_symbol_in_object_image(symbol_name,
&(p->images[i].image), &(p->images[i].module),
&defined_symbol, &defined_module, &defined_image,
&defined_library_image, NULL);
goto done;
}
}
}
done:
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupSymbolInModule);
release_lock();
return(defined_symbol);
}
static struct nlist *
_dyld_NSLookupSymbolInImage(
struct mach_header *mh,
char *symbol_name,
unsigned long options)
{
unsigned long i;
enum bool image_found, return_value, bind_now, bind_fully, module_index;
struct object_images *p;
struct library_images *q;
enum link_state link_state;
struct image *defined_image, *lookup_image;
struct nlist *defined_symbol;
module_state *defined_module;
struct library_image *defined_library_image;
struct object_image *object_image;
char *image_name;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSLookupSymbolInImage,
symbol_name);
defined_symbol = NULL;
image_name = NULL;
defined_library_image = NULL;
i = 0;
image_found = FALSE;
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
if(q->images[i].image.mh == mh){
image_name = q->images[i].image.name;
if(force_flat_namespace == FALSE)
lookup_image = &(q->images[i].image);
else
lookup_image = NULL;
lookup_symbol(symbol_name, lookup_image, NULL, FALSE,
&defined_symbol, &defined_module,
&defined_image, &defined_library_image, NULL);
image_found = TRUE;
goto down;
}
}
}
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
if(p->images[i].image.mh == mh){
image_name = p->images[i].image.name;
if(force_flat_namespace == FALSE ||
p->images[i].image.private == TRUE)
lookup_image = &(p->images[i].image);
else
lookup_image = NULL;
lookup_symbol(symbol_name, lookup_image, NULL, FALSE,
&defined_symbol, &defined_module,
&defined_image, &defined_library_image, NULL);
image_found = TRUE;
goto down;
}
}
}
down:
if(image_found == FALSE){
if(options & LOOKUP_OPTION_RETURN_ON_ERROR){
error("NSLookupSymbolInImage() invalid struct mach_header * "
"argument: 0x%x", (unsigned int)mh);
return_on_error = TRUE;
link_edit_error(DYLD_OTHER_ERROR, DYLD_INVALID_ARGS, NULL);
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupSymbolInImage);
release_lock();
return(NULL);
}
if(defined_image == NULL){
if(options & LOOKUP_OPTION_RETURN_ON_ERROR){
error("NSLookupSymbolInImage() dynamic library: %s does not "
"define symbol: %s", image_name, symbol_name);
return_on_error = TRUE;
link_edit_error(DYLD_OTHER_ERROR, DYLD_INVALID_ARGS,
image_name);
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupSymbolInImage);
release_lock();
return(NULL);
}
link_state = GET_LINK_STATE(*defined_module);
if((link_state == FULLY_LINKED &&
(options & LOOKUP_OPTION_BIND_FULLY) == 0) ||
(link_state == LINKED &&
(options & LOOKUP_OPTION_BIND_FULLY) == 0 &&
(options & LOOKUP_OPTION_BIND_NOW) == 0) ){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupSymbolInImage);
release_lock();
return(defined_symbol);
}
if(options & LOOKUP_OPTION_RETURN_ON_ERROR)
return_on_error = TRUE;
else
return_on_error = FALSE;
if(options & LOOKUP_OPTION_BIND_NOW)
bind_now = TRUE;
else
bind_now = FALSE;
if(options & LOOKUP_OPTION_BIND_FULLY){
bind_fully = TRUE;
bind_now = TRUE;
}
else
bind_fully = FALSE;
if(return_on_error == TRUE){
clear_module_states_saved();
if(defined_library_image != NULL){
if(defined_library_image->saved_module_states == NULL){
defined_library_image->saved_module_states =
allocate(defined_library_image->nmodules *
sizeof(module_state));
}
memcpy(defined_library_image->saved_module_states,
defined_library_image->modules,
defined_library_image->nmodules *
sizeof(module_state));
defined_library_image->module_states_saved = TRUE;
}
if(defined_image->mh->filetype != MH_DYLIB){
object_image = (struct object_image *)
defined_image->outer_image;
object_image->saved_module_state = object_image->module;
object_image->module_state_saved = TRUE;
}
}
if(defined_image->mh->filetype == MH_DYLIB){
if(link_state == PREBOUND_UNLINKED){
undo_prebinding_for_library_module(
defined_module,
defined_image,
defined_library_image);
module_index = defined_module - defined_library_image->modules;
SET_LINK_STATE(*defined_module, UNLINKED);
link_state = UNLINKED;
if(return_on_error == TRUE &&
defined_library_image->saved_module_states != NULL)
SET_LINK_STATE(defined_library_image->saved_module_states
[module_index], UNLINKED);
}
if(link_state == UNLINKED ||
(bind_now == TRUE && link_state == LINKED) ||
(bind_fully == TRUE &&
GET_FULLYBOUND_STATE(*defined_module) == 0) ){
return_value = link_library_module(defined_library_image,
defined_image, defined_module,
bind_now, bind_fully, FALSE);
}
else{
return_value = TRUE;
}
}
else{
if(bind_fully == TRUE && GET_FULLYBOUND_STATE(*defined_module)==0){
object_image = (struct object_image *)
defined_image->outer_image;
return_value = link_object_module(object_image, bind_now,
bind_fully);
}
else{
return_value = TRUE;
}
}
if(return_on_error == TRUE && return_value == FALSE)
goto back_out_changes;
return_value = link_in_need_modules(bind_fully, FALSE, NULL);
if(return_on_error == TRUE && return_value == FALSE)
goto back_out_changes;
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupSymbolInImage);
release_lock();
return(defined_symbol);
back_out_changes:
clear_state_changes_to_the_modules();
clear_being_linked_list(TRUE);
clear_undefined_list(TRUE);
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLookupSymbolInImage);
release_lock();
return(NULL);
}
static
enum bool
_dyld_NSMakePrivateModulePublic(
module_state *module)
{
unsigned long i;
struct object_images *p;
enum link_state link_state;
enum bool retval;
set_lock();
retval = FALSE;
if(module == &(object_images.images[0].module))
goto done;
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
if(module == &(p->images[i].module)){
link_state = GET_LINK_STATE(p->images[i].module);
if(link_state == UNUSED)
goto done;
if(p->images[i].image.private == FALSE)
goto done;
p->images[i].image.private = FALSE;
retval = TRUE;
goto done;
}
}
}
done:
release_lock();
return(retval);
}
static
enum bool
_dyld_NSIsSymbolNameDefined(
char *symbol_name)
{
enum bool defined;
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSIsSymbolNameDefined,
symbol_name);
defined = FALSE;
lookup_symbol(symbol_name, NULL, NULL, FALSE, &defined_symbol,
&defined_module, &defined_image, &defined_library_image,
NULL);
if(defined_symbol != NULL)
defined = TRUE;
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSIsSymbolNameDefined);
release_lock();
return(defined);
}
static
enum bool
_dyld_NSIsSymbolNameDefinedWithHint(
char *symbol_name,
char *libraryNameHint)
{
enum bool defined;
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image;
struct library_image *defined_library_image;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSIsSymbolNameDefinedWithHint,
symbol_name);
defined = FALSE;
lookup_symbol_in_hinted_library(symbol_name, libraryNameHint,
&defined_symbol, &defined_module, &defined_image,
&defined_library_image);
if(defined_symbol != NULL){
defined = TRUE;
}
else{
lookup_symbol(symbol_name, NULL, NULL, FALSE, &defined_symbol,
&defined_module, &defined_image,
&defined_library_image, NULL);
if(defined_symbol != NULL)
defined = TRUE;
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSIsSymbolNameDefinedWithHint);
release_lock();
return(defined);
}
static
enum bool
_dyld_NSIsSymbolNameDefinedInImage(
struct mach_header *mh,
char *symbol_name)
{
unsigned long i;
struct library_images *q;
struct object_images *p;
struct nlist *defined_symbol;
module_state *defined_module;
struct image *defined_image, *lookup_image;
struct library_image *defined_library_image;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSIsSymbolNameDefinedInImage,
symbol_name);
defined_symbol = NULL;
i = 0;
for(q = &library_images; q != NULL; q = q->next_images){
for(i = 0; i < q->nimages; i++){
if(q->images[i].image.mh == mh){
if(force_flat_namespace == FALSE)
lookup_image = &(q->images[i].image);
else
lookup_image = NULL;
lookup_symbol(symbol_name, lookup_image, NULL, FALSE,
&defined_symbol, &defined_module,
&defined_image, &defined_library_image, NULL);
goto down;
}
}
}
for(p = &object_images; p != NULL; p = p->next_images){
for(i = 0; i < p->nimages; i++){
if(p->images[i].image.mh == mh){
if(force_flat_namespace == FALSE ||
p->images[i].image.private == TRUE)
lookup_image = &(p->images[i].image);
else
lookup_image = NULL;
lookup_symbol(symbol_name, lookup_image, NULL, FALSE,
&defined_symbol, &defined_module,
&defined_image, &defined_library_image, NULL);
goto down;
}
}
}
down:
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSIsSymbolNameDefinedInImage);
release_lock();
return(defined_image != NULL);
}
static
char *
_dyld_NSNameOfModule(
module_state *module)
{
enum bool lock_set;
struct image *defined_image;
struct library_image *defined_library_image;
struct dylib_module *dylib_modules;
unsigned long module_index;
char *strings;
char *module_name;
lock_set = set_lock_or_in_multiply_defined_handler();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_NSNameOfModule);
module_name = NULL;
if(validate_NSModule(module, &defined_image,
&defined_library_image) == TRUE){
if(defined_library_image != NULL){
dylib_modules = (struct dylib_module *)
(defined_image->vmaddr_slide +
defined_image->linkedit_segment->vmaddr +
defined_image->dyst->modtaboff -
defined_image->linkedit_segment->fileoff);
module_index = module - defined_library_image->modules;
strings = (char *)
(defined_image->vmaddr_slide +
defined_image->linkedit_segment->vmaddr +
defined_image->st->stroff -
defined_image->linkedit_segment->fileoff);
module_name = strings + dylib_modules[module_index].module_name;
}
else{
module_name = defined_image->name;
}
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSNameOfModule);
if(lock_set == TRUE)
release_lock();
return(module_name);
}
static
char *
_dyld_NSLibraryNameForModule(
module_state *module)
{
enum bool lock_set;
struct image *defined_image;
struct library_image *defined_library_image;
char *library_name;
lock_set = set_lock_or_in_multiply_defined_handler();
DYLD_TRACE_LIBFUNC_START(DYLD_TRACE_NSLibraryNameForModule);
library_name = NULL;
if(validate_NSModule(module, &defined_image,
&defined_library_image) == TRUE){
if(defined_library_image != NULL){
library_name = defined_image->name;
}
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSLibraryNameForModule);
if(lock_set == TRUE)
release_lock();
return(library_name);
}
static
enum bool
_dyld_NSAddLibrary(
char *dylib_name)
{
enum bool return_value;
enum bool tried_to_use_prebinding_post_launch;
enum bool already_loaded;
char *p;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSAddLibrary, dylib_name);
p = allocate(strlen(dylib_name) + 1);
strcpy(p, dylib_name);
return_value = load_library_image(NULL, p, FALSE, FALSE, NULL,
&already_loaded, FALSE);
load_dependent_libraries();
tried_to_use_prebinding_post_launch =
trying_to_use_prebinding_post_launch;
if(tried_to_use_prebinding_post_launch == TRUE){
find_twolevel_prebound_lib_subtrees();
undo_prebound_images(TRUE);
}
call_registered_funcs_for_add_images();
if(tried_to_use_prebinding_post_launch == TRUE){
call_registered_funcs_for_linked_modules();
call_image_init_routines(FALSE);
call_module_initializers(FALSE, FALSE, TRUE);
clear_trying_to_use_prebinding_post_launch();
}
if(already_loaded == FALSE)
gdb_dyld_state_changed();
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddLibrary);
release_lock();
return(return_value);
}
static
enum bool
_dyld_NSAddLibraryWithSearching(
char *dylib_name)
{
enum bool return_value;
enum bool tried_to_use_prebinding_post_launch;
char *p;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSAddLibraryWithSearching,
dylib_name);
p = allocate(strlen(dylib_name) + 1);
strcpy(p, dylib_name);
return_value = load_library_image(NULL, p, TRUE, FALSE, NULL, NULL,
FALSE);
load_dependent_libraries();
tried_to_use_prebinding_post_launch =
trying_to_use_prebinding_post_launch;
if(tried_to_use_prebinding_post_launch == TRUE){
find_twolevel_prebound_lib_subtrees();
undo_prebound_images(TRUE);
}
call_registered_funcs_for_add_images();
if(tried_to_use_prebinding_post_launch == TRUE){
call_registered_funcs_for_linked_modules();
call_image_init_routines(FALSE);
call_module_initializers(FALSE, FALSE, TRUE);
clear_trying_to_use_prebinding_post_launch();
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddLibraryWithSearching);
release_lock();
return(return_value);
}
static
struct mach_header *
_dyld_NSAddImage(
char *dylib_name,
unsigned long options)
{
enum bool return_value, force_searching, match_filename_by_installname;
enum bool tried_to_use_prebinding_post_launch;
struct image *image;
struct stat stat_buf;
char *p;
enum bool already_loaded;
set_lock();
DYLD_TRACE_LIBFUNC_NAMED_START(DYLD_TRACE_NSAddImage, dylib_name);
if(options & ADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED){
return_value = is_library_loaded_by_name(dylib_name, NULL, &image,
FALSE);
if(return_value == TRUE){
release_lock();
return(image->mh);
}
if(stat(dylib_name, &stat_buf) == -1){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddImage);
release_lock();
return(NULL);
}
return_value = is_library_loaded_by_stat(dylib_name, NULL,
&stat_buf, &image, FALSE);
if(return_value == TRUE){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddImage);
release_lock();
return(image->mh);
}
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddImage);
release_lock();
return(NULL);
}
p = allocate(strlen(dylib_name) + 1);
strcpy(p, dylib_name);
if(options & ADDIMAGE_OPTION_WITH_SEARCHING)
force_searching = TRUE;
else
force_searching = FALSE;
if(options & ADDIMAGE_OPTION_RETURN_ON_ERROR)
return_on_error = TRUE;
else
return_on_error = FALSE;
if(options & ADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME)
match_filename_by_installname = TRUE;
else
match_filename_by_installname = FALSE;
return_value = load_library_image(NULL, p, force_searching,
match_filename_by_installname, &image,
&already_loaded, FALSE);
if(return_on_error == TRUE && return_value == FALSE){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddImage);
release_lock();
return(NULL);
}
return_value = load_dependent_libraries();
if(return_on_error == TRUE && return_value == FALSE){
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddImage);
release_lock();
return(NULL);
}
if(return_on_error == TRUE){
clear_remove_on_error_libraries();
return_on_error = FALSE;
}
tried_to_use_prebinding_post_launch =
trying_to_use_prebinding_post_launch;
if(tried_to_use_prebinding_post_launch == TRUE){
find_twolevel_prebound_lib_subtrees();
undo_prebound_images(TRUE);
}
call_registered_funcs_for_add_images();
if(tried_to_use_prebinding_post_launch == TRUE){
call_registered_funcs_for_linked_modules();
call_image_init_routines(FALSE);
call_module_initializers(FALSE, FALSE, TRUE);
clear_trying_to_use_prebinding_post_launch();
}
release_lock();
if(already_loaded == FALSE)
gdb_dyld_state_changed();
DYLD_TRACE_LIBFUNC_END(DYLD_TRACE_NSAddImage);
return(image->mh);
}
static
int
_dyld_NSGetExecutablePath(
char *buf,
unsigned long *bufsize)
{
if(*bufsize < strlen(executables_path) + 1){
*bufsize = strlen(executables_path) + 1;
return(-1);
}
strcpy(buf, executables_path);
return(0);
}
static
enum bool
_dyld_launched_prebound(
void)
{
return(prebinding);
}
static
enum bool
_dyld_all_twolevel_modules_prebound(
void)
{
return(all_twolevel_modules_prebound);
}
static
void
_dyld_install_link_edit_symbol_handlers(
object_image_register_proc newImageHandler,
object_image_locator_proc findDefinitionHandler)
{
object_image_register = newImageHandler;
object_image_locator = findDefinitionHandler;
}