]> git.saurik.com Git - apple/dyld.git/commitdiff
dyld-43.tar.gz mac-os-x-104 mac-os-x-1041 v43
authorApple <opensource@apple.com>
Wed, 13 Apr 2005 15:47:24 +0000 (15:47 +0000)
committerApple <opensource@apple.com>
Wed, 13 Apr 2005 15:47:24 +0000 (15:47 +0000)
259 files changed:
APPLE_LICENSE [new file with mode: 0644]
doc/man/man1/dyld.1 [new file with mode: 0644]
doc/man/man3/NSModule.3 [new file with mode: 0644]
doc/man/man3/NSObjectFileImage.3 [new file with mode: 0644]
doc/man/man3/NSObjectFileImage_priv.3 [new file with mode: 0644]
doc/man/man3/dladdr.3 [new file with mode: 0644]
doc/man/man3/dlclose.3 [new file with mode: 0644]
doc/man/man3/dlerror.3 [new file with mode: 0644]
doc/man/man3/dlopen.3 [new file with mode: 0644]
doc/man/man3/dlsym.3 [new file with mode: 0644]
doc/man/man3/dyld.3 [new file with mode: 0644]
dyld.xcode/project.pbxproj [new file with mode: 0644]
include/dlfcn.h [new file with mode: 0644]
include/mach-o/dyld.h [new file with mode: 0644]
include/mach-o/dyld_debug.h [new file with mode: 0644]
include/mach-o/dyld_gdb.h [new file with mode: 0644]
include/mach-o/dyld_priv.h [new file with mode: 0644]
src/ImageLoader.cpp [new file with mode: 0644]
src/ImageLoader.h [new file with mode: 0644]
src/ImageLoaderMachO.cpp [new file with mode: 0644]
src/ImageLoaderMachO.h [new file with mode: 0644]
src/dyld.cpp [new file with mode: 0644]
src/dyld.exp [new file with mode: 0644]
src/dyld.h [new file with mode: 0644]
src/dyldAPIs.cpp [new file with mode: 0644]
src/dyldAPIsInLibSystem.cpp [new file with mode: 0644]
src/dyldExceptions.c [new file with mode: 0644]
src/dyldInitialization.cpp [new file with mode: 0644]
src/dyldLibSystemThreadHelpers.h [new file with mode: 0644]
src/dyldLock.cpp [new file with mode: 0644]
src/dyldLock.h [new file with mode: 0644]
src/dyldNew.cpp [new file with mode: 0644]
src/dyldStartup.s [new file with mode: 0644]
src/dyld_debug.c [new file with mode: 0644]
src/dyld_gdb.cpp [new file with mode: 0644]
src/glue.c [new file with mode: 0644]
src/stub_binding_helper.s [new file with mode: 0644]
unit-tests/bin/exit-non-zero-pass.pl [new file with mode: 0755]
unit-tests/bin/exit-zero-pass.pl [new file with mode: 0755]
unit-tests/bin/make-recursive.pl [new file with mode: 0755]
unit-tests/bin/result-filter.pl [new file with mode: 0755]
unit-tests/include/common.makefile [new file with mode: 0644]
unit-tests/include/test.h [new file with mode: 0644]
unit-tests/run-all-unit-tests [new file with mode: 0755]
unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/Makefile [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/bar.c [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/foo.c [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/main.c [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-RETURN_ONLY_IF_LOADED/Makefile [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-RETURN_ONLY_IF_LOADED/main.c [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-leafname/Makefile [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-leafname/main.c [new file with mode: 0644]
unit-tests/test-cases/NSAddImage-leafname/zzz.c [new file with mode: 0644]
unit-tests/test-cases/bundle-basic/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-basic/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-basic/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-memory-load/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-memory-load/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-memory-load/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-multi-link/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-multi-link/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-multi-link/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-multi-load/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-multi-load/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-multi-load/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-private/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-private/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-private/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-unlinkable/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-unlinkable/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-unlinkable/lib.c [new file with mode: 0644]
unit-tests/test-cases/bundle-unlinkable/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-unload-keep-mapped/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-unload-keep-mapped/bundle.c [new file with mode: 0644]
unit-tests/test-cases/bundle-unload-keep-mapped/main.c [new file with mode: 0644]
unit-tests/test-cases/bundle-v-dylib/Makefile [new file with mode: 0644]
unit-tests/test-cases/bundle-v-dylib/bar.c [new file with mode: 0644]
unit-tests/test-cases/bundle-v-dylib/foo.c [new file with mode: 0644]
unit-tests/test-cases/bundle-v-dylib/main.c [new file with mode: 0644]
unit-tests/test-cases/deadlock/Makefile [new file with mode: 0644]
unit-tests/test-cases/deadlock/bar.c [new file with mode: 0644]
unit-tests/test-cases/deadlock/foo.c [new file with mode: 0644]
unit-tests/test-cases/deadlock/main.c [new file with mode: 0644]
unit-tests/test-cases/dladdr/Makefile [new file with mode: 0644]
unit-tests/test-cases/dladdr/main.c [new file with mode: 0644]
unit-tests/test-cases/dlclose-basic/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlclose-basic/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlclose-basic/main.c [new file with mode: 0644]
unit-tests/test-cases/dlclose-bundle-unload/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlclose-bundle-unload/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlclose-bundle-unload/main.c [new file with mode: 0644]
unit-tests/test-cases/dlerror/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlerror/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_GLOBAL/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_GLOBAL/bar.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_GLOBAL/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_GLOBAL/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/bar.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL/bar.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_LOCAL/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NODELETE/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NODELETE/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NODELETE/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOLOAD/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOLOAD/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOLOAD/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOW/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOW/bundle.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOW/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-RTLD_NOW/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-basic/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-basic/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-basic/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-initializer/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-initializer/bar.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-initializer/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-initializer/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-local-and-global/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-local-and-global/bar.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-local-and-global/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-local-and-global/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-multi/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-multi/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-multi/main.c [new file with mode: 0644]
unit-tests/test-cases/dlopen-zero/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen-zero/main.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_DEFAULT/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_DEFAULT/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_DEFAULT/main.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_NEXT/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_NEXT/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_NEXT/main.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_NEXT/test.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_SELF/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_SELF/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_SELF/main.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-RTLD_SELF/test.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-error/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlsym-error/main.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-indirect/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlsym-indirect/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-indirect/foo1.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-indirect/foo2.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-indirect/foo3.c [new file with mode: 0644]
unit-tests/test-cases/dlsym-indirect/main.c [new file with mode: 0644]
unit-tests/test-cases/dyld-launched-prebound/Makefile [new file with mode: 0644]
unit-tests/test-cases/dyld-launched-prebound/main.c [new file with mode: 0644]
unit-tests/test-cases/dyld-slide/Makefile [new file with mode: 0644]
unit-tests/test-cases/dyld-slide/main.c [new file with mode: 0644]
unit-tests/test-cases/fallback-with-suid/Makefile [new file with mode: 0644]
unit-tests/test-cases/fallback-with-suid/foo.c [new file with mode: 0644]
unit-tests/test-cases/fallback-with-suid/main.c [new file with mode: 0644]
unit-tests/test-cases/flat-data/Makefile [new file with mode: 0644]
unit-tests/test-cases/flat-data/bar.c [new file with mode: 0644]
unit-tests/test-cases/flat-data/getbar.c [new file with mode: 0644]
unit-tests/test-cases/flat-data/main.c [new file with mode: 0644]
unit-tests/test-cases/flat-lookup-everywhere/Makefile [new file with mode: 0644]
unit-tests/test-cases/flat-lookup-everywhere/main.c [new file with mode: 0644]
unit-tests/test-cases/flat-prebound/Makefile [new file with mode: 0644]
unit-tests/test-cases/flat-prebound/bar.c [new file with mode: 0644]
unit-tests/test-cases/flat-prebound/foo.c [new file with mode: 0644]
unit-tests/test-cases/flat-prebound/main.c [new file with mode: 0644]
unit-tests/test-cases/framework-fallback/Makefile [new file with mode: 0644]
unit-tests/test-cases/framework-fallback/main.c [new file with mode: 0644]
unit-tests/test-cases/ignore-bad-files/Makefile [new file with mode: 0644]
unit-tests/test-cases/ignore-bad-files/foo.c [new file with mode: 0644]
unit-tests/test-cases/ignore-bad-files/main.c [new file with mode: 0644]
unit-tests/test-cases/image-suffix/Makefile [new file with mode: 0644]
unit-tests/test-cases/image-suffix/foo.c [new file with mode: 0644]
unit-tests/test-cases/image-suffix/main.c [new file with mode: 0644]
unit-tests/test-cases/init-order/Makefile [new file with mode: 0644]
unit-tests/test-cases/init-order/base.c [new file with mode: 0644]
unit-tests/test-cases/init-order/base.h [new file with mode: 0644]
unit-tests/test-cases/init-order/foo1.c [new file with mode: 0644]
unit-tests/test-cases/init-order/foo2.c [new file with mode: 0644]
unit-tests/test-cases/init-order/foo3.c [new file with mode: 0644]
unit-tests/test-cases/init-order/main.c [new file with mode: 0644]
unit-tests/test-cases/initializer-args/Makefile [new file with mode: 0644]
unit-tests/test-cases/initializer-args/main.c [new file with mode: 0644]
unit-tests/test-cases/insert-libraries-with-initializer/Makefile [new file with mode: 0644]
unit-tests/test-cases/insert-libraries-with-initializer/foo.c [new file with mode: 0644]
unit-tests/test-cases/insert-libraries-with-initializer/main.c [new file with mode: 0644]
unit-tests/test-cases/insert-libraries-with-suid/Makefile [new file with mode: 0644]
unit-tests/test-cases/insert-libraries-with-suid/main.c [new file with mode: 0644]
unit-tests/test-cases/lazy-pointer-binding/Makefile [new file with mode: 0644]
unit-tests/test-cases/lazy-pointer-binding/foo.c [new file with mode: 0644]
unit-tests/test-cases/lazy-pointer-binding/main.c [new file with mode: 0644]
unit-tests/test-cases/lib-name-overload/Makefile [new file with mode: 0644]
unit-tests/test-cases/lib-name-overload/foo.c [new file with mode: 0644]
unit-tests/test-cases/lib-name-overload/foo2.c [new file with mode: 0644]
unit-tests/test-cases/lib-name-overload/main.c [new file with mode: 0644]
unit-tests/test-cases/loader_path-dup/Makefile [new file with mode: 0644]
unit-tests/test-cases/loader_path-dup/bar.c [new file with mode: 0644]
unit-tests/test-cases/loader_path-dup/base.c [new file with mode: 0644]
unit-tests/test-cases/loader_path-dup/foo.c [new file with mode: 0644]
unit-tests/test-cases/loader_path-dup/main.c [new file with mode: 0644]
unit-tests/test-cases/loader_path/Makefile [new file with mode: 0644]
unit-tests/test-cases/loader_path/bar.c [new file with mode: 0644]
unit-tests/test-cases/loader_path/foo.c [new file with mode: 0644]
unit-tests/test-cases/loader_path/main.c [new file with mode: 0644]
unit-tests/test-cases/missing-symlink-framework-fallback-path/Foo.c [new file with mode: 0644]
unit-tests/test-cases/missing-symlink-framework-fallback-path/Makefile [new file with mode: 0644]
unit-tests/test-cases/missing-symlink-framework-fallback-path/main.c [new file with mode: 0644]
unit-tests/test-cases/non-weak-library/Makefile [new file with mode: 0644]
unit-tests/test-cases/non-weak-library/foo.c [new file with mode: 0644]
unit-tests/test-cases/non-weak-library/main.c [new file with mode: 0644]
unit-tests/test-cases/partial-library-load/Makefile [new file with mode: 0644]
unit-tests/test-cases/partial-library-load/bar.c [new file with mode: 0644]
unit-tests/test-cases/partial-library-load/bundle.c [new file with mode: 0644]
unit-tests/test-cases/partial-library-load/foo.c [new file with mode: 0644]
unit-tests/test-cases/partial-library-load/main.c [new file with mode: 0644]
unit-tests/test-cases/sym-link-load/Makefile [new file with mode: 0644]
unit-tests/test-cases/sym-link-load/base.c [new file with mode: 0644]
unit-tests/test-cases/sym-link-load/base.h [new file with mode: 0644]
unit-tests/test-cases/sym-link-load/link.c [new file with mode: 0644]
unit-tests/test-cases/sym-link-load/main.c [new file with mode: 0644]
unit-tests/test-cases/sym-link-load/test.c [new file with mode: 0644]
unit-tests/test-cases/text-relocs/Makefile [new file with mode: 0644]
unit-tests/test-cases/text-relocs/bar.c [new file with mode: 0644]
unit-tests/test-cases/text-relocs/foo.s [new file with mode: 0644]
unit-tests/test-cases/text-relocs/main.c [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce-c++/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce-c++/a.h [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce-c++/a1.cc [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce-c++/a2.cc [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce-c++/main.cc [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/base.c [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/base.h [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/foo1.c [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/foo2.c [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/foo3.c [new file with mode: 0644]
unit-tests/test-cases/weak-coalesce/main.c [new file with mode: 0644]
unit-tests/test-cases/weak-library/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-library/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak-library/foo.h [new file with mode: 0644]
unit-tests/test-cases/weak-library/main.c [new file with mode: 0644]
unit-tests/test-cases/weak-override/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-override/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak-override/main.c [new file with mode: 0644]
unit-tests/test-cases/weak-symbol-flat/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-symbol-flat/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak-symbol-flat/foo.h [new file with mode: 0644]
unit-tests/test-cases/weak-symbol-flat/main.c [new file with mode: 0644]
unit-tests/test-cases/weak-symbol/Makefile [new file with mode: 0644]
unit-tests/test-cases/weak-symbol/foo.c [new file with mode: 0644]
unit-tests/test-cases/weak-symbol/foo.h [new file with mode: 0644]
unit-tests/test-cases/weak-symbol/main.c [new file with mode: 0644]

diff --git a/APPLE_LICENSE b/APPLE_LICENSE
new file mode 100644 (file)
index 0000000..fe81a60
--- /dev/null
@@ -0,0 +1,367 @@
+APPLE PUBLIC SOURCE LICENSE
+Version 2.0 - August 6, 2003
+
+Please read this License carefully before downloading this software.
+By downloading or using this software, you are agreeing to be bound by
+the terms of this License. If you do not or cannot agree to the terms
+of this License, please do not download or use the software.
+
+1. General; Definitions. This License applies to any program or other
+work which Apple Computer, Inc. ("Apple") makes publicly available and
+which contains a notice placed by Apple identifying such program or
+work as "Original Code" and stating that it is subject to the terms of
+this Apple Public Source License version 2.0 ("License"). As used in
+this License:
+
+1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
+the grantor of rights, (i) claims of patents that are now or hereafter
+acquired, owned by or assigned to Apple and (ii) that cover subject
+matter contained in the Original Code, but only to the extent
+necessary to use, reproduce and/or distribute the Original Code
+without infringement; and (b) in the case where You are the grantor of
+rights, (i) claims of patents that are now or hereafter acquired,
+owned by or assigned to You and (ii) that cover subject matter in Your
+Modifications, taken alone or in combination with Original Code.
+
+1.2 "Contributor" means any person or entity that creates or
+contributes to the creation of Modifications.
+
+1.3 "Covered Code" means the Original Code, Modifications, the
+combination of Original Code and any Modifications, and/or any
+respective portions thereof.
+
+1.4 "Externally Deploy" means: (a) to sublicense, distribute or
+otherwise make Covered Code available, directly or indirectly, to
+anyone other than You; and/or (b) to use Covered Code, alone or as
+part of a Larger Work, in any way to provide a service, including but
+not limited to delivery of content, through electronic communication
+with a client other than You.
+
+1.5 "Larger Work" means a work which combines Covered Code or portions
+thereof with code not governed by the terms of this License.
+
+1.6 "Modifications" mean any addition to, deletion from, and/or change
+to, the substance and/or structure of the Original Code, any previous
+Modifications, the combination of Original Code and any previous
+Modifications, and/or any respective portions thereof. When code is
+released as a series of files, a Modification is: (a) any addition to
+or deletion from the contents of a file containing Covered Code;
+and/or (b) any new file or other representation of computer program
+statements that contains any part of Covered Code.
+
+1.7 "Original Code" means (a) the Source Code of a program or other
+work as originally made available by Apple under this License,
+including the Source Code of any updates or upgrades to such programs
+or works made available by Apple under this License, and that has been
+expressly identified by Apple as such in the header file(s) of such
+work; and (b) the object code compiled from such Source Code and
+originally made available by Apple under this License.
+
+1.8 "Source Code" means the human readable form of a program or other
+work that is suitable for making modifications to it, including all
+modules it contains, plus any associated interface definition files,
+scripts used to control compilation and installation of an executable
+(object code).
+
+1.9 "You" or "Your" means an individual or a legal entity exercising
+rights under this License. For legal entities, "You" or "Your"
+includes any entity which controls, is controlled by, or is under
+common control with, You, where "control" means (a) the power, direct
+or indirect, to cause the direction or management of such entity,
+whether by contract or otherwise, or (b) ownership of fifty percent
+(50%) or more of the outstanding shares or beneficial ownership of
+such entity.
+
+2. Permitted Uses; Conditions & Restrictions. Subject to the terms
+and conditions of this License, Apple hereby grants You, effective on
+the date You accept this License and download the Original Code, a
+world-wide, royalty-free, non-exclusive license, to the extent of
+Apple's Applicable Patent Rights and copyrights covering the Original
+Code, to do the following:
+
+2.1 Unmodified Code. You may use, reproduce, display, perform,
+internally distribute within Your organization, and Externally Deploy
+verbatim, unmodified copies of the Original Code, for commercial or
+non-commercial purposes, provided that in each instance:
+
+(a) You must retain and reproduce in all copies of Original Code the
+copyright and other proprietary notices and disclaimers of Apple as
+they appear in the Original Code, and keep intact all notices in the
+Original Code that refer to this License; and
+
+(b) You must include a copy of this License with every copy of Source
+Code of Covered Code and documentation You distribute or Externally
+Deploy, and You may not offer or impose any terms on such Source Code
+that alter or restrict this License or the recipients' rights
+hereunder, except as permitted under Section 6.
+
+2.2 Modified Code. You may modify Covered Code and use, reproduce,
+display, perform, internally distribute within Your organization, and
+Externally Deploy Your Modifications and Covered Code, for commercial
+or non-commercial purposes, provided that in each instance You also
+meet all of these conditions:
+
+(a) You must satisfy all the conditions of Section 2.1 with respect to
+the Source Code of the Covered Code;
+
+(b) You must duplicate, to the extent it does not already exist, the
+notice in Exhibit A in each file of the Source Code of all Your
+Modifications, and cause the modified files to carry prominent notices
+stating that You changed the files and the date of any change; and
+
+(c) If You Externally Deploy Your Modifications, You must make
+Source Code of all Your Externally Deployed Modifications either
+available to those to whom You have Externally Deployed Your
+Modifications, or publicly available. Source Code of Your Externally
+Deployed Modifications must be released under the terms set forth in
+this License, including the license grants set forth in Section 3
+below, for as long as you Externally Deploy the Covered Code or twelve
+(12) months from the date of initial External Deployment, whichever is
+longer. You should preferably distribute the Source Code of Your
+Externally Deployed Modifications electronically (e.g. download from a
+web site).
+
+2.3 Distribution of Executable Versions. In addition, if You
+Externally Deploy Covered Code (Original Code and/or Modifications) in
+object code, executable form only, You must include a prominent
+notice, in the code itself as well as in related documentation,
+stating that Source Code of the Covered Code is available under the
+terms of this License with information on how and where to obtain such
+Source Code.
+
+2.4 Third Party Rights. You expressly acknowledge and agree that
+although Apple and each Contributor grants the licenses to their
+respective portions of the Covered Code set forth herein, no
+assurances are provided by Apple or any Contributor that the Covered
+Code does not infringe the patent or other intellectual property
+rights of any other entity. Apple and each Contributor disclaim any
+liability to You for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a
+condition to exercising the rights and licenses granted hereunder, You
+hereby assume sole responsibility to secure any other intellectual
+property rights needed, if any. For example, if a third party patent
+license is required to allow You to distribute the Covered Code, it is
+Your responsibility to acquire that license before distributing the
+Covered Code.
+
+3. Your Grants. In consideration of, and as a condition to, the
+licenses granted to You under this License, You hereby grant to any
+person or entity receiving or distributing Covered Code under this
+License a non-exclusive, royalty-free, perpetual, irrevocable license,
+under Your Applicable Patent Rights and other intellectual property
+rights (other than patent) owned or controlled by You, to use,
+reproduce, display, perform, modify, sublicense, distribute and
+Externally Deploy Your Modifications of the same scope and extent as
+Apple's licenses under Sections 2.1 and 2.2 above.
+
+4. Larger Works. You may create a Larger Work by combining Covered
+Code with other code not governed by the terms of this License and
+distribute the Larger Work as a single product. In each such instance,
+You must make sure the requirements of this License are fulfilled for
+the Covered Code or any portion thereof.
+
+5. Limitations on Patent License. Except as expressly stated in
+Section 2, no other patent rights, express or implied, are granted by
+Apple herein. Modifications and/or Larger Works may require additional
+patent licenses from Apple which Apple may grant in its sole
+discretion.
+
+6. Additional Terms. You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations and/or other
+rights consistent with the scope of the license granted herein
+("Additional Terms") to one or more recipients of Covered Code.
+However, You may do so only on Your own behalf and as Your sole
+responsibility, and not on behalf of Apple or any Contributor. You
+must obtain the recipient's agreement that any such Additional Terms
+are offered by You alone, and You hereby agree to indemnify, defend
+and hold Apple and every Contributor harmless for any liability
+incurred by or claims asserted against Apple or such Contributor by
+reason of any such Additional Terms.
+
+7. Versions of the License. Apple may publish revised and/or new
+versions of this License from time to time. Each version will be given
+a distinguishing version number. Once Original Code has been published
+under a particular version of this License, You may continue to use it
+under the terms of that version. You may also choose to use such
+Original Code under the terms of any subsequent version of this
+License published by Apple. No one other than Apple has the right to
+modify the terms applicable to Covered Code created under this
+License.
+
+8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
+part pre-release, untested, or not fully tested works. The Covered
+Code may contain errors that could cause failures or loss of data, and
+may be incomplete or contain inaccuracies. You expressly acknowledge
+and agree that use of the Covered Code, or any portion thereof, is at
+Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
+WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
+APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
+PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
+ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
+MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
+PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
+PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
+INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
+FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
+THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
+ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
+ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
+AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
+You acknowledge that the Covered Code is not intended for use in the
+operation of nuclear facilities, aircraft navigation, communication
+systems, or air traffic control machines in which case the failure of
+the Covered Code could lead to death, personal injury, or severe
+physical or environmental damage.
+
+9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
+TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
+ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
+TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
+APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
+REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
+TO YOU. In no event shall Apple's total liability to You for all
+damages (other than as may be required by applicable law) under this
+License exceed the amount of fifty dollars ($50.00).
+
+10. Trademarks. This License does not grant any rights to use the
+trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
+"QuickTime", "QuickTime Streaming Server" or any other trademarks,
+service marks, logos or trade names belonging to Apple (collectively
+"Apple Marks") or to any trademark, service mark, logo or trade name
+belonging to any Contributor. You agree not to use any Apple Marks in
+or as part of the name of products derived from the Original Code or
+to endorse or promote products derived from the Original Code other
+than as expressly permitted by and in strict compliance at all times
+with Apple's third party trademark usage guidelines which are posted
+at http://www.apple.com/legal/guidelinesfor3rdparties.html.
+
+11. Ownership. Subject to the licenses granted under this License,
+each Contributor retains all rights, title and interest in and to any
+Modifications made by such Contributor. Apple retains all rights,
+title and interest in and to the Original Code and any Modifications
+made by or on behalf of Apple ("Apple Modifications"), and such Apple
+Modifications will not be automatically subject to this License. Apple
+may, at its sole discretion, choose to license such Apple
+Modifications under this License, or on different terms from those
+contained in this License or may choose not to license them at all.
+
+12. Termination.
+
+12.1 Termination. This License and the rights granted hereunder will
+terminate:
+
+(a) automatically without notice from Apple if You fail to comply with
+any term(s) of this License and fail to cure such breach within 30
+days of becoming aware of such breach;
+
+(b) immediately in the event of the circumstances described in Section
+13.5(b); or
+
+(c) automatically without notice from Apple if You, at any time during
+the term of this License, commence an action for patent infringement
+against Apple; provided that Apple did not first commence
+an action for patent infringement against You in that instance.
+
+12.2 Effect of Termination. Upon termination, You agree to immediately
+stop any further use, reproduction, modification, sublicensing and
+distribution of the Covered Code. All sublicenses to the Covered Code
+which have been properly granted prior to termination shall survive
+any termination of this License. Provisions which, by their nature,
+should remain in effect beyond the termination of this License shall
+survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
+12.2 and 13. No party will be liable to any other for compensation,
+indemnity or damages of any sort solely as a result of terminating
+this License in accordance with its terms, and termination of this
+License will be without prejudice to any other right or remedy of
+any party.
+
+13. Miscellaneous.
+
+13.1 Government End Users. The Covered Code is a "commercial item" as
+defined in FAR 2.101. Government software and technical data rights in
+the Covered Code include only those rights customarily provided to the
+public as defined in this License. This customary commercial license
+in technical data and software is provided in accordance with FAR
+12.211 (Technical Data) and 12.212 (Computer Software) and, for
+Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
+Commercial Items) and 227.7202-3 (Rights in Commercial Computer
+Software or Computer Software Documentation). Accordingly, all U.S.
+Government End Users acquire Covered Code with only those rights set
+forth herein.
+
+13.2 Relationship of Parties. This License will not be construed as
+creating an agency, partnership, joint venture or any other form of
+legal association between or among You, Apple or any Contributor, and
+You will not represent to the contrary, whether expressly, by
+implication, appearance or otherwise.
+
+13.3 Independent Development. Nothing in this License will impair
+Apple's right to acquire, license, develop, have others develop for
+it, market and/or distribute technology or products that perform the
+same or similar functions as, or otherwise compete with,
+Modifications, Larger Works, technology or products that You may
+develop, produce, market or distribute.
+
+13.4 Waiver; Construction. Failure by Apple or any Contributor to
+enforce any provision of this License will not be deemed a waiver of
+future enforcement of that or any other provision. Any law or
+regulation which provides that the language of a contract shall be
+construed against the drafter will not apply to this License.
+
+13.5 Severability. (a) If for any reason a court of competent
+jurisdiction finds any provision of this License, or portion thereof,
+to be unenforceable, that provision of the License will be enforced to
+the maximum extent permissible so as to effect the economic benefits
+and intent of the parties, and the remainder of this License will
+continue in full force and effect. (b) Notwithstanding the foregoing,
+if applicable law prohibits or restricts You from fully and/or
+specifically complying with Sections 2 and/or 3 or prevents the
+enforceability of either of those Sections, this License will
+immediately terminate and You must immediately discontinue any use of
+the Covered Code and destroy all copies of it that are in your
+possession or control.
+
+13.6 Dispute Resolution. Any litigation or other dispute resolution
+between You and Apple relating to this License shall take place in the
+Northern District of California, and You and Apple hereby consent to
+the personal jurisdiction of, and venue in, the state and federal
+courts within that District with respect to this License. The
+application of the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded.
+
+13.7 Entire Agreement; Governing Law. This License constitutes the
+entire agreement between the parties with respect to the subject
+matter hereof. This License shall be governed by the laws of the
+United States and the State of California, except that body of
+California law concerning conflicts of law.
+
+Where You are located in the province of Quebec, Canada, the following
+clause applies: The parties hereby confirm that they have requested
+that this License and all related documents be drafted in English. Les
+parties ont exige que le present contrat et tous les documents
+connexes soient rediges en anglais.
+
+EXHIBIT A.
+
+"Portions Copyright (c) 1999-2003 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 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."
diff --git a/doc/man/man1/dyld.1 b/doc/man/man1/dyld.1
new file mode 100644 (file)
index 0000000..9e0b776
--- /dev/null
@@ -0,0 +1,253 @@
+.TH DYLD 1 "January 15, 2005" "Apple Computer, Inc."
+.SH NAME
+dyld \- the dynamic link editor
+.SH SYNOPSIS
+DYLD_FRAMEWORK_PATH
+.br
+DYLD_FALLBACK_FRAMEWORK_PATH
+.br
+DYLD_LIBRARY_PATH
+.br
+DYLD_FALLBACK_LIBRARY_PATH
+.br
+DYLD_ROOT_PATH
+.br
+DYLD_INSERT_LIBRARIES
+.br
+DYLD_FORCE_FLAT_NAMESPACE
+.br
+DYLD_IMAGE_SUFFIX
+.br
+DYLD_PRINT_OPTS
+.br
+DYLD_PRINT_ENV
+.br
+DYLD_PRINT_LIBRARIES
+.br
+DYLD_PRINT_LIBRARIES_POST_LAUNCH
+.br
+DYLD_BIND_AT_LAUNCH
+.br
+DYLD_PREBIND_DEBUG
+.br
+DYLD_NEW_LOCAL_SHARED_REGIONS
+.br
+DYLD_IGNORE_PREBINDING
+.br
+DYLD_PRINT_APIS
+.br
+DYLD_PRINT_BINDINGS
+.br
+DYLD_PRINT_INITIALIZERS
+.br
+DYLD_PRINT_REBASINGS
+.br
+DYLD_PRINT_SEGMENTS
+.br
+DYLD_PRINT_STATISTICS
+.SH DESCRIPTION
+The dynamic linker uses the following environment variables.
+They affect any program that uses the dynamic linker.
+.TP
+.B DYLD_FRAMEWORK_PATH
+This is a colon separated list of directories that contain frameworks.
+The dynamic linker searches these directories before it searches for the
+framework by its install name.
+It allows you to test new versions of existing
+frameworks. (A framework is a library install name that ends in the form
+XXX.framework/Versions/YYY/XXX or XXX.framework/XXX, where XXX and YYY are any
+name.)
+.IP
+For each framework that a program uses, the dynamic linker looks for the
+framework in each directory in 
+.SM DYLD_FRAMEWORK_PATH
+in turn. If it looks in all the directories and can't find the framework, it
+searches the directories in  
+.SM DYLD_LIBRARY_PATH
+in turn. If it still can't find the framework, it then searches 
+.SM DYLD_FALLBACK_FRAMEWORK_PATH
+and
+.SM DYLD_FALLBACK_LIBRARY_PATH
+in turn.
+.IP
+Use the
+.B \-L
+option to 
+.IR otool (1).
+to discover the frameworks and shared libraries that the executable
+is linked against.
+.TP
+.B DYLD_FALLBACK_FRAMEWORK_PATH
+This is a colon separated list of directories that contain frameworks.
+It is used as the default location for frameworks not found in their install
+path.
+
+By default, it is set to
+/Library/Frameworks:/Network/Library/Frameworks:/System/Library/Frameworks
+.TP
+.B DYLD_LIBRARY_PATH
+This is a colon separated list of directories that contain libraries. The
+dynamic linker searches these directories before it searches the default
+locations for libraries. It allows you to test new versions of existing
+libraries. 
+.IP
+For each library that a program uses, the dynamic linker looks for it in each
+directory in 
+.SM DYLD_LIBRARY_PATH
+in turn. If it still can't find the library, it then searches 
+.SM DYLD_FALLBACK_FRAMEWORK_PATH
+and
+.SM DYLD_FALLBACK_LIBRARY_PATH
+in turn.
+.IP
+Use the
+.B \-L
+option to 
+.IR otool (1).
+to discover the frameworks and shared libraries that the executable
+is linked against.
+.TP
+.B DYLD_FALLBACK_LIBRARY_PATH
+This is a colon separated list of directories that contain libraries.
+It is used as the default location for libraries not found in their install
+path.
+By default, it is set
+to $(HOME)/lib:/usr/local/lib:/lib:/usr/lib.
+.TP
+.B DYLD_ROOT_PATH
+This is a colon separated list of directories.  The dynamic linker will prepend each of
+this directory paths to every image access until a file is found.    
+.TP
+.B DYLD_INSERT_LIBRARIES
+This is a colon separated list of dynamic libraries to load before the ones
+specified in the program.  This lets you test new modules of existing dynamic
+shared libraries that are used in flat-namespace images by loading a temporary
+dynamic shared library with just the new modules.  Note that this has no
+effect on images built a two-level namespace images using a dynamic shared
+library unless
+.SM DYLD_FORCE_FLAT_NAMESPACE
+is also used.
+.TP
+.B DYLD_FORCE_FLAT_NAMESPACE
+Force all images in the program to be linked as flat-namespace images and ignore
+any two-level namespace bindings.  This may cause programs to fail to execute
+with a multiply defined symbol error if two-level namespace images are used to
+allow the images to have multiply defined symbols.
+.TP
+.B DYLD_IMAGE_SUFFIX
+This is set to a string of a suffix to try to be used for all shared libraries
+used by the program.  For libraries ending in ".dylib" the suffix is applied
+just before the ".dylib".  For all other libraries the suffix is appended to the
+library name.  This is useful for using conventional "_profile" and "_debug"
+libraries and frameworks.
+.TP
+.B DYLD_PRINT_OPTS
+When this is set, the dynamic linker writes to file descriptor 2 (normally
+standard error) the command line options.
+.TP
+.B DYLD_PRINT_ENV
+When this is set, the dynamic linker writes to file descriptor 2 (normally
+standard error) the environment variables.
+.TP
+.B DYLD_PRINT_LIBRARIES
+When this is set, the dynamic linker writes to file descriptor 2 (normally
+standard error) the filenames of the libraries the program is using.
+This is useful to make sure that the use of
+.SM DYLD_LIBRARY_PATH
+is getting what you want.
+.TP
+.B DYLD_PRINT_LIBRARIES_POST_LAUNCH
+This does the same as
+.SM DYLD_PRINT_LIBRARIES
+but the printing starts after the program gets to its entry point.
+.TP
+.B DYLD_BIND_AT_LAUNCH
+When this is set, the dynamic linker binds all undefined symbols
+the program needs at launch time. This includes function symbols that can are normally lazily bound at the time of their first call.
+.TP
+.B DYLD_PREBIND_DEBUG
+When this is set, the dynamic linker prints diagnostics about 
+launching prebound programs and libraries. This lets you determine why a
+program is not being launched prebound.
+You can view the recorded library time stamps with the
+.B \-Lv
+option to
+.IR otool (1).
+.TP
+.PP
+For secure programs that are UNIX set uid or set gid, the dynamic linker will
+not use the dyld environment variables for path searching and library insertion,
+unless the program is run as the real user.  For secure programs, the dynamic
+linker clears out the value of the dyld path and insertion environment
+variables.  This is so that if a program is
+.IR exec (2)'ed
+from a secure program too will not have it's libraries searched for, as well.
+For statically linked secure programs that
+.IR exec (2) 
+other programs that might use the dynamic linker, they too should clear out the
+values of the dyld path and insertion environment variables.
+.TP
+.B DYLD_NEW_LOCAL_SHARED_REGIONS
+When set, the dynamic linker directs the system to provide a new set of shared
+regions as the repository for library load requests for dynamic libraries
+built with
+.SM MH_SPLIT_SEGS
+(split shared libraries).
+
+Split shared libraries reside in a defined contiguous region of address space
+in all dynamic linker runtime processes.  This space is backed by named regions
+or sub-maps.  These sub-maps are owned by the system and items which are to
+mapped into them must be mapped via the
+.IR load_shared_file (2)
+call.  The use of
+sub-maps promotes a high degree of system resource sharing between the
+processes which incorporate and use them.  However, some processes require
+either additional or different libraries to be loaded into the shared region.
+While there is some space available within the shared region for alternate and
+new shared libraries, it is inappropriate to use that area for temporary or
+private libraries.  Setting the
+.SM DYLD_NEW_LOCAL_SHARED_REGIONS
+flag will cause
+all children of the current process to have their own set of sub-maps.  In this
+way the libraries found in the children's submaps will not be caused to be
+present in the submaps shared by the rest of the system.
+
+.SM DYLD_NEW_LOCAL_SHARED_REGIONS
+should be set by anyone wishing to run
+non-standard or temporary split shared libraries by setting an explicit path to
+point to them.  i.e. by using the DYLD_LIBRARY_PATH environment variable
+instead of changing the root by executing a
+.IR chroot (2)
+call.
+.TP
+.B DYLD_PRINT_STATISTICS
+Right before the process's main() is called, dyld prints out information about how
+dyld spent its time.  Useful for analyzing launch performance.
+.TP
+.B DYLD_IGNORE_PREBINDING { app | all }
+Valid values are "app", "all", and "" (empty).  The variable is useful for testing 
+how various mixes of prebound and unprebound libraries perform.  When set to "all", 
+all prebinding is ignored.  That is, dyld fixes up any prebound images as if the prebinding
+in it was invalid.  When set to "all", just the prebinding information in main 
+executables is ignored. When set the nothing, the prebinding in split-seg libraries 
+is used, by all other prebinding is ignored.
+.TP
+.B DYLD_PRINT_INITIALIZERS
+Causes dyld to print out a line when running each initializers in every image.  Initializers
+run by dyld included constructors for C++ statically allocated objects, functions marked with
+__attribute__((constructor)), and -init functions.
+.TP
+.B DYLD_PRINT_APIS
+Causes dyld to print a line whenever a dyld API is called (e.g. NSAddImage()).
+.TP
+.B DYLD_PRINT_SEGMENTS
+Causes dyld to print out a line containing the name and address range of each mach-o segment
+that dyld maps in.
+.TP
+.B DYLD_PRINT_BINDINGS 
+Causes dyld to print a line each time a symbolic name is bound.  
+
+
+
+.SH "SEE ALSO"
+libtool(1), ld(1), otool(1)
diff --git a/doc/man/man3/NSModule.3 b/doc/man/man3/NSModule.3
new file mode 100644 (file)
index 0000000..3677477
--- /dev/null
@@ -0,0 +1,610 @@
+.TH NSModule 3 "October 6, 2003" "Apple Computer, Inc."
+.SH NAME
+NSModule \- programmatic interface for working with modules and symbols
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld.h>
+.sp .5
+typedef void * NSModule;
+.sp .5
+extern NSModule NSLinkModule(
+       NSObjectFileImage objectFileImage, 
+       const char *moduleName,
+       unsigned long options);
+.sp .5
+extern enum DYLD_BOOL NSUnLinkModule(
+       NSModule module, 
+       unsigned long options);
+.sp .5
+extern const char * NSNameOfModule(
+       NSModule m); 
+.sp .5
+extern const char * NSLibraryNameForModule(
+       NSModule m);
+.sp 2
+typedef void * NSSymbol;
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolNameDefined(
+       const char *symbolName);
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolNameDefinedWithHint(
+       const char *symbolName
+       const char *libraryNameHint);
+.sp .5 
+extern enum DYLD_BOOL NSIsSymbolNameDefinedInImage(
+       const struct mach_header *image,
+       const char *symbolName);
+.sp .5
+extern NSSymbol NSLookupAndBindSymbol(
+       const char *symbolName);
+.sp .5
+extern NSSymbol NSLookupAndBindSymbolWithHint(
+       const char *symbolName
+       const char *libraryNameHint);
+.sp .5
+extern NSSymbol NSLookupSymbolInModule(
+       NSModule module,
+       const char *symbolName);
+.sp .5
+extern NSSymbol NSLookupSymbolInImage(
+       const struct mach_header *image,
+       const char *symbolName,
+       unsigned long options);
+.sp .5
+extern const char * NSNameOfSymbol(
+       NSSymbol symbol);
+.sp .5
+extern void * NSAddressOfSymbol(
+       NSSymbol symbol);
+.sp .5
+extern NSModule NSModuleForSymbol(
+       NSSymbol symbol);
+.sp .5
+extern enum DYLD_BOOL NSAddLibrary(
+       const char *pathName);
+.sp .5
+extern enum DYLD_BOOL NSAddLibraryWithSearching(
+       const char *pathName);
+.sp .5
+extern const struct mach_header * NSAddImage(
+       const char *image_name,
+       unsigned long options);
+.sp .5
+extern long NSVersionOfRunTimeLibrary(
+       const char *libraryName);
+.sp .5
+extern long NSVersionOfLinkTimeLibrary(
+       const char *libraryName);
+.sp .5
+extern int _NSGetExecutablePath(
+       char *buf,
+       unsigned long *bufsize)
+.sp 2
+extern void NSInstallLinkEditErrorHandlers(
+       NSLinkEditErrorHandlers *handlers);
+.sp .5
+extern void NSLinkEditError(
+       NSLinkEditErrors *c,
+       int *errorNumber, 
+       const char **fileName,
+       const char **errorString);
+.if
+.SH "FUTURE SYNOPSIS"
+.nf
+.PP
+extern NSModule NSReplaceModule(
+       NSModule moduleToReplace,
+       NSObjectFileImage newObjectFileImage, 
+       unsigned long options);
+.fi
+.PP
+These routines are the programmatic interface for working with modules and
+symbols in a program.  A program is composed of a set of images, an executable,
+plugins, and dynamic shared libraries.  An image which is an executable or a
+plugin is composed of one module containing a collection of symbols.  A dynamic
+shared library is composed of one or more modules with each of those modules
+containing a separate collection of symbols.  If a symbol is used from a module
+then all the symbols from that module are used.
+.PP
+When a program is executed it selectively binds the symbols it needs from the
+modules in the dynamic libraries that are loaded.  Normally a program is
+staticly linked against a set of dynamic shared libraries when it is built.
+So when the program is executed the dynamic linker will automaticly load those
+dynamic shared libraries.
+.PP
+A program may programmatically load plugins after it starts executing and that
+is done with two sets of API's.  The first is the API's of
+.IR NSObjectFileImage (3)
+and the second is
+.I NSLinkModule.
+Unlike modules in the dynamic libraries when a plugin is loaded it is not
+selectively bound to but always bound into the program.
+.PP
+.I NSLinkModule
+links the specified object file image into the program and returns the module
+handle for it.
+Currently the implementation is limited to only Mach-O MH_BUNDLE types which
+are used for plugins.
+A module name is specified when a module is linked so that later
+.I NSNameOfModule
+can be used with the module handle and to do things like report errors.
+If you want 
+.IR gdb (1)
+to be able to debug your module, when calling
+.I NSLinkModule
+you should pass the image path as the module name.
+When a module is linked, all libraries referenced by the module are added to
+the list of libraries to be searched.
+The parameter,
+.I options,
+can have a set of options or'ed together.  The options for
+.I NSLinkModule
+are as follows:
+.TP
+.B NSLINKMODULE_OPTION_NONE
+This specifies no options.  With this the global symbols from the module are
+made part of the global symbol table of the program.  If any errors occur the
+handlers installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+.TP
+.B NSLINKMODULE_OPTION_BINDNOW
+This option causes the dynamic link editor to bind all undefined references for
+the loaded module and not allow references to be bound as needed.  This affects
+all the references in the module and all of the dependent references.
+.TP
+.B NSLINKMODULE_OPTION_PRIVATE
+With this option the global symbols from the module are not made part of
+the global symbol table of the program.  The global symbols of the
+module can then be looked up using
+.I NSLookupSymbolInModule.
+.TP
+.B NSLINKMODULE_OPTION_RETURN_ON_ERROR
+With this option if errors occur while binding this module it is automaticly
+unloaded and
+.SM NULL
+is returned as the module handle.  To get the error information for the module
+that failed to load the routine
+.I NSLinkEditError
+is then used.  It has the same parameters as the link edit error handler (see
+below) except all the parameters are pointers in which the information is
+returned indirectly.
+.TP
+.B NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
+With this option the module init routines are not called.  This is only useful
+to the fix-and-continue implementation.
+.TP 
+.B NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
+With this option the parameter,
+.I moduleName
+is assumed to be a string with the logical name of the image with the physical
+name of the object file tailing after the NULL character of the logical name.
+This is only useful to the zero-link implementation.
+.PP
+.I NSUnLinkModule
+unlinks the specified module handle from the program.  Currently the 
+implementation is limited to only allow modules linked with
+.I NSLinkModule
+to be unlinked.  The parameter,
+.I options,
+can have a set of options or'ed together.  The options for
+.I NSUnLinkModule
+are as follows:
+.TP
+.B NSUNLINKMODULE_OPTION_NONE
+This specifies no options.  With this the module is unlinked from the program
+and the memory for the module is deallocated.  If any errors occur the
+handlers installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+.TP
+.B NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
+With this option the memory for the module is not deallocated allowing pointers
+into the module to still be valid.
+.TP
+.B NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
+With this option any lazy references (direct function calls) to symbols defined
+in the module are reset to be bound on first call again and not cause any
+undefined symbol errors.  Currently this is only implemented for the PowerPC
+architecture.
+.PP
+.I NSNameOfModule
+is passed a module handle and returns the name of the module.  If the module
+handle is invalid
+.SM NULL
+is returned.
+.PP
+.I NSLibraryNameForModule
+is passed a module handle and returns the name of the library the module is in
+if any.  If the module handle is for a module that is not in a library (in the
+executable or a plugin) or the module handle is invalid
+.SM NULL
+is returned.
+.PP
+.I NSIsSymbolNameDefined
+is passed a global symbol name (global 'C' symbols names are preceded with an
+underbar '\_') and returns
+.SM TRUE
+or
+.SM FALSE
+based on if the symbol is defined in the program's global symbol table.
+If the symbol is not defined no error occurs.
+.PP
+.I NSIsSymbolNameDefinedWithHint
+is the same as
+.I NSIsSymbolNameDefined
+but the
+.I libraryNameHint
+parameter provides a hint as to where to start the lookup in a prebound
+program.  The
+.I libraryNameHint
+parameter is matched up with the actual library install names with
+.IR strstr (3).
+.PP
+.I NSIsSymbolNameDefinedInImage
+is passed a pointer to the mach_header of a mach_header structure of a
+dynamic library being used by the program and a symbol name.  This returns
+.SM TRUE
+or FALSE
+based on if the symbol is defined in the specified image or one of the image's
+sub-frameworks or sub-umbrellas.
+If the program was built with the
+.IR ld (1)
+.B \-force_flat_namespace
+flag or executed with the environment variable
+.SM DYLD_FORCE_FLAT_NAMESPACE
+set and the pointer to a mach_header structure is not of a bundle loaded with
+the 
+.B NSLINKMODULE_OPTION_PRIVATE
+option of
+.IR NSLinkModule (3)
+then the pointer to a mach_header is ignored and the symbol is looked up in
+all the images using the first definition if found.
+.PP
+The image handle parameter for
+.I NSLookupSymbolInImage
+and
+.I NSIsSymbolNameDefinedInImage
+is a pointer to a read-only mach header structure of a dynamic library being
+used by the program.  Besides the
+.IR NSAddImage (3)
+routine the pointer to a mach header can also be obtained by using a link editor
+defined symbol as in <mach-o/ldsym.h> and described on the
+.IR ld (1)
+man page.
+Also the
+.IR dyld (3)
+routine
+.IR _dyld_get_image_header (3)
+and the mach_header pointer arguments to the call back routines called from 
+.IR _dyld_register_func_for_add_image (3)
+routines can also be used.
+.PP
+.I NSLookupAndBindSymbol
+is passed a global symbol name and looks up and binds the symbol into the
+program.
+It returns an NSSymbol for the symbol.  If any errors occur the handlers
+installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+.PP
+.I NSLookupAndBindSymbolWithHint
+is the same as
+.I NSLookupAndBindSymbol
+but the
+.I libraryNameHint
+parameter provides a hint as to where to start the lookup in a prebound
+program.  The
+.I libraryNameHint
+parameter is matched up with the actual library install names with
+.IR strstr (3).
+.PP
+.I NSLookupSymbolInModule
+is passed a symbol name and a module handle and looks up the symbol in that
+module.  Currently this is only implemented for module handles returned with
+.I NSLinkModule.
+If the symbol is found an NSSymbol for the symbol is returned otherwise
+.SM NULL
+is returned and no error occurs.
+.PP
+.I NSLookupSymbolInImage
+is passed a pointer to a mach_header structure of a dynamic library being used
+by the program and a symbol name.  It returns an NSSymbol for the symbol for
+defined in the specified image or the image's sub-frameworks or sub-umbrellas.
+If the program was built with the
+.IR ld (1)
+.B \-force_flat_namespace
+flag or executed with the environment variable
+.SM DYLD_FORCE_FLAT_NAMESPACE
+set and the pointer to a mach_header structure is not of a bundle loaded with
+the 
+.B NSLINKMODULE_OPTION_PRIVATE
+option of
+.IR NSLinkModule (3)
+then the pointer to a mach_header is ignored and the symbol is looked up in
+all the images using the first definition found.
+If the option
+.SM NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+is not used if any errors occur the handlers installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+The options of
+.I NSLookupSymbolInImage
+are as follows:
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+Just bind the non-lazy symbols of module that defines the
+.I symbolName
+and let all lazy symbols in the module be bound on first call.  This should be
+used in the normal case for a trusted module expected to bind without any errors
+like a module in a system supplied library.
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
+Bind all the non-lazy and lazy symbols of module that defines the
+.I symbolName
+and let all dependent symbols in the needed libraries be bound as needed.  This
+would be used for a module that might not be expected bind without errors but
+links against only system supplied libraries which are expected to bind without
+any errors.
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
+Bind all the symbols of the module that defines the
+.I symbolName
+and all the dependent symbols of all needed libraries.  This should only be
+used for things like signal handlers and linkedit error handlers that can't
+bind other symbols when executing to handle the signal or error.
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+With this option if errors occur while binding the module that defines the
+.I symbolName
+then the module is automaticly unloaded and
+.SM NULL
+is returned as the NSSymbol.  To get the error information for why the module
+that failed to bind the routine
+.I NSLinkEditError
+is then used.  It has the same parameters as the link edit error handler (see
+below) except all the parameters are pointers in which the information is
+returned indirectly.
+.PP
+.I NSNameOfSymbol
+is passed an NSSymbol and returns the name of the symbol.
+.PP
+.I NSAddressOfSymbol
+is passed an NSSymbol and returns the address of the symbol.
+.PP
+.I NSModuleForSymbol
+is passed an NSSymbol and returns the NSModule that symbol is defined in.
+.PP
+.I NSAddLibrary
+is passed the file name of a dynamic shared library to be added to the search
+list.  If it is successful it returns
+.SM TRUE
+else it returns
+.SM FALSE.
+.PP
+.I NSAddLibraryWithSearching
+is passed the file name of a dynamic shared library to be added to the search
+list the file name passed will be effected by the various
+.SM DYLD
+environment variables as if this library were linked into the program.  If it
+is successful it returns
+.SM TRUE
+else it returns
+.SM FALSE.
+.PP
+.I NSAddImage
+is passed the file name of a dynamic shared library to be added to the search
+list of the program if not already loaded.  It returns a pointer to the
+mach_header structure of the dynamic library being used by the program.
+For best performance of this routine if the library is expected to be already
+loaded by the program the
+.I image_name
+should be a full path name and the same as the name recorded by the program.
+If it is a symlink then an
+.IR open (2)
+and an
+.IR fstat (2)
+are needed to determine it is the same file as one already loaded.
+.PP
+If the dynamic shared library has not already been loaded it along with all the
+needed dependent libraries are loaded.  With the options parameter
+.SM NSADDIMAGE_OPTION_NONE
+then any error in loading will cause the linkEdit error handler set by
+.IR NSInstallLinkEditErrorHandlers (3)
+to be called or the default action of printing the error and exiting to be
+taken.  The other options of
+.I NSAddImage
+are as follows:
+.TP
+.B NSADDIMAGE_OPTION_RETURN_ON_ERROR
+With this option if errors occur while loading this library it is automatically
+unloaded and
+.SM NULL
+is returned.  To get the error information for the library that failed to load
+the routine
+.I NSLinkEditError
+is then used.  It has the same parameters as the link edit error handler (see
+below) except all the parameters are pointers in which the information is
+returned indirectly.
+.TP
+.B NSADDIMAGE_OPTION_WITH_SEARCHING
+With this option the
+.I image_name
+passed for the library and all its dependents will be effected by the various
+.SM DYLD
+environment variables as if this library were linked into the program.
+.TP
+.B NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+With this option if the
+.I image_name
+passed for the library has not already been loaded it is not loaded.  Only if
+it has been loaded the pointer to the mach_header will not be
+.SM NULL.
+.TP
+.B NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
+When this option is specified if a later load of a dependent dynamic library
+with a file system path is needed by an image that matches the install name of
+the dynamic library loaded with this option, then the dynamic library loaded
+with the call to NSAddImage() is used in place of the dependent dynamic library.
+.PP
+.I NSVersionOfRunTimeLibrary
+is passed the install name of a dynamic shared library and returns
+current_version number of the library the program is using or \-1 if the
+program is not using that library.
+.PP
+.I NSVersionOfLinkTimeLibrary
+is passed the install name of a dynamic shared library and returns the
+current_version number of the library the executable program was built
+with or \-1 if the program was not built with that library.
+.PP
+.I _NSGetExecutablePath
+copies the path of the executable into the buffer and
+returns 0 if the path was successfully copied in the provided buffer. If the
+buffer is not large enough, \-1 is returned and the expected buffer size is
+copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
+the executable not a "real path" to the executable. That is the path may be
+a symbolic link and not the real file. And with deep directories the total
+bufsize needed could be more than MAXPATHLEN.
+.SH ERROR HANDLING
+.PP
+.I NSInstallLinkEditErrorHandlers
+is passed a pointer to a NSLinkEditErrorHandlers which contains three function
+pointers to be used for handling dynamic link errors.  The prototypes for these
+functions are given in the following typedef:
+.RS
+.nf
+typedef struct {
+     void     (*undefined)(const char *symbolName);
+     NSModule (*multiple)(NSSymbol s, NSModule oldModule, NSModule newModule); 
+     void     (*linkEdit)(NSLinkEditErrors errorClass, int errorNumber,
+                          const char *fileName, const char *errorString);
+} NSLinkEditErrorHandlers;
+.fi
+.RE
+.PP
+The first two functions allow the programmer to direct the link edit processing
+of undefined symbols and multiply defined symbols.
+The third function allows the programmer to catch all other link editor
+errors.
+.PP
+The state when one of the user error functions gets called will be such that no
+module will be partially loaded (except in the case of resource errors like out
+of memory and other relocation errors).
+However, with undefined symbol errors those modules referencing undefined
+symbols will be partially bound, and use of such modules can and will crash the
+program.
+.PP
+Great care should be taken when implementing these functions, as the program is
+running in a state that will crash if it uses an unbound symbol.
+To be safe, these functions should only rely on other things in the same module
+or in the executable.
+.PP
+If the user does not supply these functions, the default will be to write an
+error message on to file descriptor 2 (usually stderr) and exit the program
+(except for the
+.I linkEdit
+error handler when the
+.I NSLinkEditErrors
+is NSLinkEditWarningError, then the default is to do nothing).
+.PP
+The specified undefined handler may make calls to any of the runtime loading
+functions to add modules based on the undefined symbol name.
+After dealing with this symbol name successfully (by doing a runtime loading
+operation to resolve the undefined reference) the handler simply returns.
+If more symbol's names remain undefined the handler will be called repeatedly
+with an undefined symbol name.
+If the handler can't deal with the symbol it should not return (put up a panel,
+abort, etc) and cause the program to exit.
+Or it can remove itself as the undefined handler and return which will cause
+the default action of printing the undefined symbol names and exiting.
+.PP
+The specified multiply defined symbol handler is called during the process of
+runtime linking and thus it may not call any of the runtime loading functions
+as only one set of linking operations can be performed in the task at a time.
+The only programmatic functions that can be called from a multiply defined
+symbol handler are
+.I NSNameOfSymbol,
+.I NSNameOfModule
+and
+.I NSLibraryNameForModule
+(provided they are linked into the program before the handler is called).
+This handler returns the module handle for the symbol that is to be used for
+further link editing, either the
+.I oldModule
+or the
+.I newModule.
+It may also record one of the module handles to later take action after the 
+runtime linking process has completed (for example later unlink the module).
+The dynamic link editor updates the references to the symbol if the handler
+specifies the new symbol is to be used.
+The references which are updated are those that the compiler system generated
+as indirect references.  Initialized data and references that were created at
+runtime are not effected.
+.PP
+The specified
+.I linkEdit
+error handler is called for all other runtime linking errors.
+These other runtime linking errors are either warnings or fatal errors.
+If the user's link edit error handler function returns
+for a fatal error it will cause the program to exit.
+There is small set of major error classes which have specific error numbers.
+These numbers are be passed in the parameter
+.I errorClass.
+These major error classes include:
+.RS
+.nf
+typedef enum {
+       NSLinkEditFileAccessError,
+       NSLinkEditFileFormatError,
+       NSLinkEditMachResourceError,
+       NSLinkEditUnixResourceError,
+       NSLinkEditOtherError,
+       NSLinkEditWarningError,
+       NSLinkEditMultiplyDefinedError,
+       NSLinkEditUndefinedError
+} NSLinkEditErrors;
+.fi
+.RE
+.PP
+For the error class NSLinkEditUnixResourceError the
+.I errorNumber
+parameter will be an
+.I errno
+value (see
+.IR intro (2)).
+For the error class NSLinkEditMachResourceError the
+.I errorNumber
+parameter will be a
+.I kern_return_t
+value.
+For the error class NSLinkEditOtherError the
+.I errorNumber
+parameter will be a one of the following values:
+.RS
+.nf
+typedef enum {
+    NSOtherErrorRelocation, 
+    NSOtherErrorLazyBind,
+    NSOtherErrorIndrLoop,
+    NSOtherErrorLazyInit,
+    NSOtherErrorInvalidArgs
+} NSOtherErrorNumbers;
+.fi
+.RE
+.PP
+For all errors, an attempt to pass an error string will be made.
+In some cases such as resource errors, it may not be possible to return a
+string.
+In those cases the
+.I errorString
+parameter will be
+.sm NULL.
+.PP
+For file access errors and file format errors, an attempt to return a file name 
+will also be passed, and if that is not possible the
+.I filename
+parameter will be
+.sm NULL.
+.SH ALSO SEE
+NSObjectFileImage(3), dyld(3)
diff --git a/doc/man/man3/NSObjectFileImage.3 b/doc/man/man3/NSObjectFileImage.3
new file mode 100644 (file)
index 0000000..c235960
--- /dev/null
@@ -0,0 +1,151 @@
+.TH NSObjectFileImage 3 "March 14, 2003" "Apple Computer, Inc."
+.SH NAME
+NSObjectFileImage \- programmatic interface for working with Mach-O files
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld.h>
+.sp .5
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(
+       const char *pathName,
+       NSObjectFileImage *objectFileImage);
+.sp .5
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(
+       void *address,
+       unsigned long size, 
+       NSObjectFileImage *objectFileImage);
+.sp .5
+extern NSObjectFileImageReturnCode NSCreateCoreFileImageFromFile(
+       const char *pathName,
+       NSObjectFileImage *objectFileImage);
+.sp .5
+extern enum DYLD_BOOL NSDestroyObjectFileImage(
+       NSObjectFileImage objectFileImage);
+.sp .5
+extern unsigned long NSSymbolDefinitionCountInObjectFileImage(
+       NSObjectFileImage objectFileImage);
+.sp .5
+extern const char * NSSymbolDefinitionNameInObjectFileImage(
+       NSObjectFileImage objectFileImage,
+       unsigned long ordinal);
+.sp .5
+extern unsigned long NSSymbolReferenceCountInObjectFileImage(
+       NSObjectFileImage objectFileImage);
+.sp .5
+extern const char * NSSymbolReferenceNameInObjectFileImage(
+       NSObjectFileImage objectFileImage,
+       unsigned long ordinal,
+       enum DYLD_BOOL *tentative_definition); /* can be NULL */
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolDefinedInObjectFileImage(
+       NSObjectFileImage objectFileImage,
+       const char *symbolName);
+.sp .5
+extern void * NSGetSectionDataInObjectFileImage(
+       NSObjectFileImage objectFileImage,
+       const char *segmentName,
+       const char *sectionName,
+       unsigned long* size); /* can be NULL */
+.sp .5
+extern enum DYLD_BOOL NSHasModInitObjectFileImage(
+       NSObjectFileImage objectFileImage);
+.fi
+.SH DESCRIPTION
+.PP
+These routines are the programmatic interface for working with Mach-O files.
+They bring the Mach-O file into memory and the API allows the file to
+be inspected or loaded into the program.  On creation of an object file image
+it is checked to insure it is a valid format and it is compatible with the host
+machine's cpu architecture.
+.PP
+.I NSCreateObjectFileImageFromFile
+takes the parameter
+.I pathName
+as the path name to the file name in the file system and creates and returns
+an NSObjectFileImage.  Currently only
+.SM MH_BUNDLE
+files can be used with
+.I NSCreateObjectFileImageFromFile
+which can then be loaded into the program using
+.IR NSLinkModule (3).
+If the file is valid an NSObjectFileImage is returned and the return code is
+NSObjectFileImageSuccess.
+.I NSCreateObjectFileImageFromMemory
+does the same as
+.I NSCreateObjectFileImageFromFile
+but takes two parameters
+.I address
+and
+.I size
+for the Mach-O file that is in memory.
+.PP
+.I NSCreateCoreFileImageFromFile
+takes the parameter
+.I pathName
+as the path name to a core file in the file system and creates and returns
+an NSObjectFileImage.  This NSObjectFileImage can then can be loaded into a
+task with
+.IR _dyld_debug_task_from_core (3)
+to determine what libraries were loaded and which modules were linked.
+.PP
+.I NSSymbolDefinitionCountInObjectFileImage
+returns the number of symbol definitions in the NSObjectFileImage. 
+.PP
+.I NSSymbolDefinitionNameInObjectFileImage
+returns the name of the i'th symbol definitions in the NSObjectFileImage. 
+The 'C' string returned should not be freed.  If the ordinal specified is
+outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will be
+returned. 
+.PP
+.I NSSymbolReferenceCountInObjectFileImage
+returns the number of references to undefined symbols the NSObjectFileImage. 
+.PP
+.I NSSymbolReferenceNameInObjectFileImage
+returns the name of the i'th undefined symbol in the NSObjectFileImage. 
+The 'C' string returned should not be freed.  If the ordinal specified is
+outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
+returned. 
+.PP
+.I NSIsSymbolDefinedInObjectFileImage
+returns TRUE if the specified symbol name has a definition in the
+NSObjectFileImage. 
+.PP
+.I NSGetSectionDataInObjectFileImage
+returns the address of the data for the named section in the named segment in 
+the NSObjectFileImage.  If the parameter size is not NULL, the size of the
+section is returned in size.  If the section cannot be found or a zerofill
+section, NULL is returned and the size returned is zero.
+.PP
+.I NSHasModInitObjectFileImage
+returns TRUE if the NSObjectFileImage has any module initialization routines
+and FALSE otherwise.
+
+.SH RETURN CODES
+The API's that create NSObjectFileImage's return an NSObjectFileImageReturnCode
+with the following possible values:
+.TP
+.B NSObjectFileImageSuccess
+Indicates the API was successful and it returned a valid NSObjectFileImage for
+the host machine's cpu architecture.
+.TP
+.B NSObjectFileImageFailure
+Indicates the API failed and no NSObjectFileImage was returned.  If this is
+returned an error message is printed on stderr as to the reason for the 
+failure.
+.TP
+.B NSObjectFileImageInappropriateFile
+Indicates the API failed because the file passed to it was not an appropriate
+type of object file.
+.TP
+.B NSObjectFileImageArch
+Indicates the API failed because the host machine's cpu architecture could not
+be found in the file.
+.TP
+.B NSObjectFileImageFormat
+Indicates the API failed because the Mach-O format was malformed.  If this is
+returned an error message is printed on stderr as to the format error.
+.TP
+.B NSObjectFileImageAccess
+Indicates the API failed because the file could not be accessed.
+.SH ALSO SEE
+NSModule(3), dyld(3)
diff --git a/doc/man/man3/NSObjectFileImage_priv.3 b/doc/man/man3/NSObjectFileImage_priv.3
new file mode 100644 (file)
index 0000000..aeddd1c
--- /dev/null
@@ -0,0 +1,42 @@
+.TH NSObjectFileImage 3 "July 9, 2003" "Apple Computer, Inc."
+.SH NAME
+NSObjectFileImage_priv \- programmatic interface for working with Mach-O files
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld_priv.h>
+.sp .5
+extern enum DYLD_BOOL 
+NSFindSectionAndOffsetInObjectFileImage(
+       NSObjectFileImage objectFileImage, 
+       unsigned long imageOffset,
+       const char** segmentName,       /* can be NULL */
+       const char** sectionName,       /* can be NULL */
+       unsigned long* sectionOffset)   /* can be NULL */
+.sp .5
+extern enum DYLD_BOOL 
+NSHasModInitObjectFileImage(
+       NSObjectFileImage objectFileImage);
+.fi
+.SH DESCRIPTION
+.PP
+These routines are the programmatic interface for working with Mach-O files.
+They bring the Mach-O file into memory and the API allows the file to
+be inspected or loaded into the program.  On creation of an object file image
+it is checked to insure it is a valid format and it is compatible with the host
+machine's cpu architecture.
+.PP
+.PP
+.I NSFindSectionAndOffsetInObjectFileImage
+is supplied an imageOffset into an ObjectFileImage and returns 
+via parameters the segment/section name and offset into that section of
+that imageOffset.  It returns FALSE if the imageOffset is not 
+in any section, otherwise TRUE.  You can used the resulting sectionOffset to
+index into the data returned by NSGetSectionDataInObjectFileImage.
+.PP
+.I NSHasModInitObjectFileImage
+returns TRUE if the NSObjectFileImage has any module initialization routines
+and FALSE otherwise.
+
+.SH ALSO SEE
+NSObjectFileImage(3), NSModule(3), dyld(3)
diff --git a/doc/man/man3/dladdr.3 b/doc/man/man3/dladdr.3
new file mode 100644 (file)
index 0000000..bca4462
--- /dev/null
@@ -0,0 +1,73 @@
+.Dd September 24, 2004
+.Os
+.Dt DLADDR 3
+.Sh NAME
+.Nm dladdr
+.Nd find the image containing a given address
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft int
+.Fn dladdr "const void* addr" "Dl_info* info"
+.Sh DESCRIPTION
+The
+.Fn dladdr
+function
+queries dyld (the dynamic linker) for information about the image
+containing the address
+.Fa addr .
+The information is returned in the structure specified by
+.Fa info .
+The structure contains at least the following members:
+.Bl -tag -width "XXXconst char *dli_fname"
+.It Li "const char* dli_fname"
+The pathname of the shared object containing the address.
+.It Li "void* dli_fbase"
+The base address (mach_header) at which the image is mapped into the
+address space of the calling process.
+.It Li "const char* dli_sname"
+The name of the nearest run-time symbol with a value less than or
+equal to
+.Fa addr .
+.It Li "void* dli_saddr"
+The value of the symbol returned in
+.Li dli_sname .
+.El
+.Pp
+The
+.Fn dladdr
+function
+is available only in dynamically linked programs.
+.Sh ERRORS
+If an image containing
+.Fa addr
+cannot be found,
+.Fn dladdr
+returns 0.
+On success, a non-zero value is returned.
+.Pp
+If the image containing 
+.Fa addr
+is found, but no nearest symbol was found,
+the dli_sname and dli_saddr fields are set to NULL.
+.Sh SEE ALSO
+.Xr dyld 3 ,
+.Xr dlopen 3
+.Sh HISTORY
+The
+.Fn dladdr
+function first appeared in the Solaris operating system.
+.Sh AUTHORS
+Mac OS X 10.3 incorporated the dlcompat package written by Jorge Acereda <jacereda@users.sourceforge.net>
+and Peter O'Gorman <ogorman@users.sourceforge.net>.
+.Pp
+In Mac OS X 10.4, dlopen was rewritten to be a native part of dyld.
+.Pp
+This man page was borrowed from FreeBSD and modified.
+.Sh BUGS
+This implementation is almost bug-compatible with the Solaris
+implementation.  The following bugs are present:
+.Bl -bullet
+.It
+Returning 0 as an indication of failure goes against long-standing
+Unix tradition.
+.El
diff --git a/doc/man/man3/dlclose.3 b/doc/man/man3/dlclose.3
new file mode 100644 (file)
index 0000000..c966d6a
--- /dev/null
@@ -0,0 +1,38 @@
+.Dd Sept 25, 2004
+.Dt DLCLOSE 3
+.Sh NAME
+.Nm dlclose
+.Nd close a dynamic library or bundle
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft int
+.Fn dlclose "void* handle"
+.Sh DESCRIPTION
+.Fn dlclose
+releases a reference to the dynamic library or bundle referenced by
+.Fa handle .
+If the reference count drops to 0, the bundle is removed from the
+address space, and
+.Fa handle
+is rendered invalid.
+Just before removing a dynamic library or bundle in this way, any 
+termination routines in it are called.  
+.Fa handle
+is the value returned by a previous call to dlopen.
+.Sh RETURN VALUES
+If
+.Fn dlclose
+is successful, it returns a value of 0.
+Otherwise it returns -1, and sets an error string that can be
+retrived with
+.Fn dlerror .
+.Pp
+.Sh SEE ALSO
+.Xr dlopen 3
+.Xr dlsym 3
+.Xr dlerror 3
+.Xr dyld 3
+.Xr NSModule 3
+.Xr NSObjectFileImage 3
+.Xr ld 1
+.Xr cc 1
diff --git a/doc/man/man3/dlerror.3 b/doc/man/man3/dlerror.3
new file mode 100644 (file)
index 0000000..67594b3
--- /dev/null
@@ -0,0 +1,32 @@
+.Dd Sept 25, 2004
+.Dt DLERROR 3
+.Sh NAME
+.Nm dlerror
+.Nd get diagnostic information
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft const char*
+.Fn dlerror "void"
+.Sh DESCRIPTION
+.Fn dlerror
+returns a null-terminated character string describing the last error that
+occurred on this thread during a call to
+.Fn dlopen ,
+.Fn dlsym ,
+or
+.Fn dlclose .
+If no such error has occurred,
+.Fn dlerror
+returns a null pointer.
+At each call to
+.Fn dlerror ,
+the error indication is reset.  Thus in the case of two calls
+to
+.Fn dlerror ,
+where the second call follows the first immediately, the second call
+will always return a null pointer.
+.Sh SEE ALSO
+.Xr dlopen 3
+.Xr dlclose 3
+.Xr dlsym 3
+.Xr dyld 3
diff --git a/doc/man/man3/dlopen.3 b/doc/man/man3/dlopen.3
new file mode 100644 (file)
index 0000000..e4ef8f2
--- /dev/null
@@ -0,0 +1,128 @@
+.Dd February 8, 2005
+.Os
+.Dt DLOPEN 3
+.Sh NAME
+.Nm dlopen 
+.Nd load and link a dynamic library or bundle
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft void*
+.Fn dlopen "const char* path" "int mode"
+.Sh DESCRIPTION
+.Fn dlopen
+examines the mach-o file specified by 
+.Fa path .
+If the file is compatible with the current process and has not already been 
+loaded into the current process, it is loaded and linked.  After being linked,
+if it contains any initializer functions, they are called, before
+.Fn dlopen
+returns.  
+.Fn dlopen
+can load dynamic libraries and bundles.  It returns a handle that can
+be used with 
+.Fn dlsym
+and
+.Fn dlclose .
+A second call to 
+.Fn dlopen
+with the same path will return the same handle, but the internal reference
+count for the handle will be incremented.  Therefore all 
+.Fn dlopen
+calls should be balanced with a 
+.Fn dlclose
+call.
+.Pp
+If a null pointer is passed in 
+.Fa path ,
+.Fn dlopen
+returns a handle equivalent to RTLD_DEFAULT.
+.Pp
+.Fa mode
+contains options to 
+.Fn dlopen .
+It must contain one or more of the following values, possibly ORed together:
+.Pp
+.Bl -tag -width RTLD_LAZYX
+.It Dv RTLD_LAZY
+Each external function reference is bound the first time the function is called.
+.It Dv RTLD_NOW
+All external function references are bound immediately during the call to
+.Fn dlopen .
+.El
+.Pp
+.Dv RTLD_LAZY
+is normally preferred, for reasons of efficiency.
+However,
+.Dv RTLD_NOW
+is useful to ensure that any undefined symbols are discovered during the
+call to
+.Fn dlopen .
+If neither 
+RTLD_LAZY nor RTLD_NOW is specified, the default is RTLD_LAZY.
+.Pp
+One of the following flags may be ORed into the
+.Fa mode
+argument:
+.Bl -tag -width RTLD_GLOBALX
+.It Dv RTLD_GLOBAL
+Symbols exported from this image (dynamic library or bundle) will be available to any 
+images build with -flat_namespace option to  
+.Xr ld 1
+or to calls to
+.Fn dlsym
+when using a special handle.
+.It Dv RTLD_LOCAL
+Symbols exported from this image (dynamic library or bundle) are generally hidden
+and only availble to
+.Fn dlsym
+when directly using the handle returned by this call to 
+.Fn dlopen .
+If neither 
+RTLD_GLOBAL nor RTLD_LOCAL is specified, the default is RTLD_GLOBAL.
+.El
+.Sh SEARCHING
+.Fn dlopen
+uses a series of steps to find a compatible mach-o file.  The first compatible file found is used.
+.Pp
+1) If the directory specified by 
+.Fa path 
+does not contain a slash '/' (i.e. it is a leaf name) then the environment variable LD_LIBRARY_PATH is 
+used.  LD_LIBRARY_PATH should be a colon seperated list of directories.  
+.Fn dlopen
+searches each directory, in the order specified, for the leaf name 
+.Fa path .
+.Pp
+2) If DYLD_LIBRARY_PATH is set, then those directories are searched, in order, 
+with the leaf name of 
+.Fa path .
+.Pp
+3) If DYLD_FALLBACK_LIBRARY_PATH is set, then those directories are searched, in order
+with the leaf name of 
+.Fa path .
+If DYLD_FALLBACK_LIBRARY_PATH is not set, then the following directories are searched: $HOME/lib, /usr/local/lib, /usr/lib
+.Pp
+4) Lastly, 
+.Fa path
+is tried as-is as a regular file path.  That means it might resolve relative to the current working directory. 
+.Pp
+Note: There are no configuration files to control dlopen searching.  
+.Pp
+Note: Mac OS X uses "fat" files to combine 32-bit and 64-bit libraries.  This means there are no separate 32-bit and 64-bit search paths.
+.Pp
+.Sh RETURN VALUES
+If 
+.Fn dlopen
+fails, it returns a null pointer, and sets an error condition which may be interrogated with 
+.Fn dlerror .
+.Sh AUTHORS
+Mac OS X 10.3 incorporated the dlcompat package written by Jorge Acereda <jacereda@users.sourceforge.net>
+and Peter O'Gorman <ogorman@users.sourceforge.net>.
+.Pp
+In Mac OS X 10.4, dlopen was rewritten to be a native part of dyld.
+.Pp
+.Sh SEE ALSO
+.Xr dlclose 3
+.Xr dlsym 3
+.Xr dlerror 3
+.Xr dyld 3
+.Xr ld 1
diff --git a/doc/man/man3/dlsym.3 b/doc/man/man3/dlsym.3
new file mode 100644 (file)
index 0000000..6072b92
--- /dev/null
@@ -0,0 +1,65 @@
+.Dd Sept 25, 2004
+.Dt DLSYM 3
+.Sh NAME
+.Nm dlsym
+.Nd get address of a symbol
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft void*
+.Fn dlsym "void* handle" "const char* symbol"
+.Sh DESCRIPTION
+.Fn dlsym
+returns the address of the code or data location 
+specified by the null-terminated character string
+.Fa symbol .
+Which libraries and bundles are searched depends on the  
+.Fa handle 
+parameter. 
+.Pp
+If
+.Fn dlsym
+is called with a
+.Fa handle ,
+returned by
+.Fn dlopen
+then only that image and any libraries it depends on are searched for
+.Fa symbol .
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_DEFAULT ,
+then every mach-o image in the process is searched in the order they were loaded.
+This can be a costly search and should be avoided.  
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_NEXT ,
+then the search for the symbol is limited to the images which were loaded
+after the one issuing the call to
+.Fn dlsym .
+.Pp
+.Sh RETURN VALUES
+The
+.Fn dlsym
+function
+returns a null pointer if the symbol cannot be found, and sets an error
+condition which may be queried with
+.Fn dlerror .
+.Pp
+.Sh NOTES
+Unlike other dyld API's, the symbol name passed to
+.Fn dlsym
+must NOT be prepended with an underscore.  
+.Sh SEE ALSO
+.Xr dlopen 3
+.Xr dlsym 3
+.Xr dlerror 3
+.Xr dyld 3
+.Xr NSModule 3
+.Xr NSObjectFileImage 3
+.Xr ld 1
+.Xr cc 1
diff --git a/doc/man/man3/dyld.3 b/doc/man/man3/dyld.3
new file mode 100644 (file)
index 0000000..9e10b90
--- /dev/null
@@ -0,0 +1,200 @@
+.TH DYLD 3 "January 15, 2005" "Apple Computer, Inc."
+.SH NAME
+dyld \- low level programatic interface to the dynamic link editor
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld.h>
+bool _dyld_present(void);
+.sp .5
+uint32_t _dyld_image_count(void);
+.sp .5
+const struct mach_header *_dyld_get_image_header(
+       uint32_t image_index);
+.sp .5
+intptr_t _dyld_get_image_vmaddr_slide(
+       uint32_t image_index);
+.sp .5
+const char *_dyld_get_image_name(
+       uint32_t image_index);
+.sp .5
+void _dyld_lookup_and_bind(
+       const char *symbol_name,
+       void **address,
+       NSModule *module);
+.sp .5
+void _dyld_lookup_and_bind_with_hint(
+       const char *symbol_name,
+       const char *library_name_hint,
+       void **address,
+       NSModule *module);
+.sp .5
+void _dyld_lookup_and_bind_fully(
+       const char *symbol_name,
+       void **address,
+       NSModule *module);
+.sp .5
+bool _dyld_bind_fully_image_containing_address(
+       const void *address);
+.sp .5
+bool _dyld_image_containing_address(
+       const void* address);
+.sp .5
+const struct mach_header * _dyld_get_image_header_containing_address(
+       const void* address);
+.sp .5
+bool _dyld_launched_prebound(void);
+.sp .5
+bool _dyld_all_twolevel_modules_prebound(void);
+.sp .5
+int _dyld_func_lookup(
+       const char *dyld_func_name,
+       void **address);
+.sp .5
+extern void _dyld_bind_objc_module(
+       const void *objc_module);
+.sp .5 
+extern void _dyld_get_objc_module_sect_for_module(
+       NSModule module,
+       void **objc_module,
+       size_t *size);
+.sp .5
+extern void _dyld_lookup_and_bind_objc(
+       const char *symbol_name,
+       void **address,
+       NSModule *module);
+.sp .5
+extern void _dyld_moninit(
+       void (*monaddition)(char *lowpc, char *highpc));
+.sp .5
+
+extern void _dyld_register_func_for_add_image(
+       void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+.sp .5
+extern void _dyld_register_func_for_remove_image(
+       void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+.sp .5
+extern void _dyld_register_func_for_link_module(
+       void (*func)(NSModule module));
+.fi
+.SH DESCRIPTION
+These routines are the low level programatic interface to the dynamic link
+editor.
+.PP
+.I _dyld_present returns non-zero if the dynamic linker is being used in the
+program and zero otherwise.  If this returns zero this rest of these functions
+should not be called and most likely crash the program if called.
+.PP
+.I _dyld_image_count
+returns the current number of images mapped in by the dynamic link editor.
+.PP
+.I _dyld_get_image_header
+returns the mach header of the image indexed by image_index.  If image_index is
+out of range NULL is returned.
+.PP
+.I _dyld_get_image_vmaddr_slide
+returns the virtural memory address slide amount of the image indexed by
+.I image_index.
+If image_index is out of range zero is returned.
+.PP
+.I _dyld_get_image_name
+returns the name of the image indexed by
+.I image_index.
+If image_index is out of range NULL is returned.
+.PP
+.I _dyld_lookup_and_bind
+looks up the
+.I symbol_name
+and binds it into the program.  It indirectly returns the
+.I address
+and and a pointer to the
+.I module
+that defined the symbol.
+.PP
+.I _dyld_lookup_and_bind_with_hint
+is the same as
+.I _dyld_lookup_and_bind
+but the
+.I library_name_hint
+parameter provides a hint as to where to start the lookup in a prebound
+program.  The
+.I library_name_hint
+parameter is matched up with the actual library install names with
+.IR strstr (3).
+.PP
+.I _dyld_lookup_and_bind_fully
+looks up the
+.I symbol_name
+and binds it and all of its references into the program.  It indirectly returns
+the
+.I address
+and and a pointer to the
+.I module
+that defined the symbol.
+.PP
+.I _dyld_bind_fully_image_containing_address
+fully binds the image containing the specified address.  It returns TRUE if the
+address is contained in a loaded image and FALSE otherwise.
+.PP
+.I _dyld_image_containing_address
+It returns TRUE if the address is contained in an image dyld loaded and FALSE
+otherwise.
+.PP
+.I _dyld_get_image_header_containing_address
+It returns a pointer to the mach header of the image if the address is contained
+in an image dyld loaded and NULL otherwise.
+.PP
+.I _dyld_launched_prebound
+returns TRUE if the program was launched using the prebound state and FALSE
+otherwise.
+.PP
+.I_dyld_all_twolevel_modules_prebound(void);
+returns TRUE if all the libraries currently in use by the program are being used
+as two-level namespace libraries, are prebound and have all their modules bound.
+Otherwise it returns FALSE.
+.PP
+.I _dyld_func_lookup
+is passed a name,
+.I dyld_func_name,
+of a dynamic link editor function and returns the
+.I address
+of the function indirectly.  It returns non-zero if the function is found
+and zero otherwise.
+.PP
+.I _dyld_bind_objc_module
+is passed a pointer to something in an (__OBJC,__module) section and causes the
+module that is associated with that address to be bound.
+.PP
+.I _dyld_get_objc_module_sect_for_module
+is passed a module and sets a pointer to the (__OBJC,__module) section and its
+size for the specified module.
+.PP
+.I _dyld_lookup_and_bind_objc()
+is the same as _dyld_lookup_and_bind() but does not update the symbol pointers
+if the symbol is in a bound module.  The reason for this is that an objc symbol
+like
+.I .objc_class_name_Object
+is never used by a symbol pointer.  Since this is done a lot by the objc
+runtime and updating symbol pointers is not cheep it should not be done.
+.PP
+.I _dyld_moninit
+is called from the profiling runtime routine
+.IR moninit(3)
+to cause the dyld loaded code to be profiled.  It is passed a pointer to the
+the profiling runtime routine
+.IR monaddtion(3)
+to be called after an image had been mapped in.
+.PP
+.I _dyld_register_func_for_add_image
+registers the specified function to be called when a new image is added
+(a bundle or a dynamic shared library) to the program.  When this function is
+first registered it is called for once for each image that is currently part of
+the program.
+.PP
+.I _dyld_register_func_for_remove_image
+registers the specified function to be called when an image is removed
+(a bundle or a dynamic shared library) from the program.
+.I _dyld_register_func_for_link_module
+registers the specified function to be called when a module is bound into the
+program.  When this function is first registered it is called for once for each
+module that is currently bound into the program.
diff --git a/dyld.xcode/project.pbxproj b/dyld.xcode/project.pbxproj
new file mode 100644 (file)
index 0000000..bdddd37
--- /dev/null
@@ -0,0 +1,1044 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 39;
+       objects = {
+               EF799FE7070D27BB00F78484 = {
+                       children = (
+                               EF799FE8070D27BB00F78484,
+                               EF799FEA070D27BB00F78484,
+                       );
+                       isa = PBXGroup;
+                       name = man;
+                       path = doc/man;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FE8070D27BB00F78484 = {
+                       children = (
+                               EF799FE9070D27BB00F78484,
+                       );
+                       isa = PBXGroup;
+                       name = man1;
+                       path = doc/man/man1;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FE9070D27BB00F78484 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = text.man;
+                       name = dyld.1;
+                       path = doc/man/man1/dyld.1;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FEA070D27BB00F78484 = {
+                       children = (
+                               EF799FEB070D27BB00F78484,
+                               EF799FEC070D27BB00F78484,
+                               EF799FED070D27BB00F78484,
+                               EF799FEE070D27BB00F78484,
+                               EF799FEF070D27BB00F78484,
+                               EF799FF0070D27BB00F78484,
+                               EF799FF1070D27BB00F78484,
+                               EF799FF2070D27BB00F78484,
+                               EF799FF3070D27BB00F78484,
+                       );
+                       isa = PBXGroup;
+                       name = man3;
+                       path = doc/man/man3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FEB070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = dladdr.3;
+                       path = doc/man/man3/dladdr.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FEC070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = dlclose.3;
+                       path = doc/man/man3/dlclose.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FED070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = dlerror.3;
+                       path = doc/man/man3/dlerror.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FEE070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = dlopen.3;
+                       path = doc/man/man3/dlopen.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FEF070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = dlsym.3;
+                       path = doc/man/man3/dlsym.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FF0070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = dyld.3;
+                       path = doc/man/man3/dyld.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FF1070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = NSModule.3;
+                       path = doc/man/man3/NSModule.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FF2070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = NSObjectFileImage.3;
+                       path = doc/man/man3/NSObjectFileImage.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF799FF3070D27BB00F78484 = {
+                       explicitFileType = text.man;
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       name = NSObjectFileImage_priv.3;
+                       path = doc/man/man3/NSObjectFileImage_priv.3;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               EF79A010070D293E00F78484 = {
+                       fileRef = EF799FE9070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A011070D295200F78484 = {
+                       fileRef = EF799FEB070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A012070D295200F78484 = {
+                       fileRef = EF799FEC070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A013070D295200F78484 = {
+                       fileRef = EF799FED070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A014070D295200F78484 = {
+                       fileRef = EF799FEE070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A015070D295200F78484 = {
+                       fileRef = EF799FEF070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A016070D295200F78484 = {
+                       fileRef = EF799FF0070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A017070D295200F78484 = {
+                       fileRef = EF799FF1070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A018070D295200F78484 = {
+                       fileRef = EF799FF2070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               EF79A019070D295200F78484 = {
+                       fileRef = EF799FF3070D27BB00F78484;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+//EF0
+//EF1
+//EF2
+//EF3
+//EF4
+//F90
+//F91
+//F92
+//F93
+//F94
+               F906E2230639E96400B13DB2 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = dyld_debug.c;
+                       path = src/dyld_debug.c;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F906E2240639E96400B13DB2 = {
+                       fileRef = F906E2230639E96400B13DB2;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F913FAD90630A8AE00B7AE9D = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyldAPIsInLibSystem.cpp;
+                       path = src/dyldAPIsInLibSystem.cpp;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F913FADA0630A8AE00B7AE9D = {
+                       fileRef = F913FAD90630A8AE00B7AE9D;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F921D3160703769A000D1056 = {
+                       compilerSpec = com.apple.compilers.gcc.3_5;
+                       fileType = sourcecode.c;
+                       isEditable = 1;
+                       isa = PBXBuildRule;
+                       outputFiles = (
+                       );
+               };
+               F921D317070376A6000D1056 = {
+                       compilerSpec = com.apple.compilers.gcc.3_5;
+                       fileType = sourcecode.c;
+                       isEditable = 1;
+                       isa = PBXBuildRule;
+                       outputFiles = (
+                       );
+               };
+               F921D318070376B0000D1056 = {
+                       compilerSpec = com.apple.compilers.gcc.3_5;
+                       fileType = sourcecode.asm;
+                       isEditable = 1;
+                       isa = PBXBuildRule;
+                       outputFiles = (
+                       );
+               };
+               F921D31E070376F1000D1056 = {
+                       compilerSpec = com.apple.compilers.gcc.3_5;
+                       fileType = sourcecode.cpp;
+                       isEditable = 1;
+                       isa = PBXBuildRule;
+                       outputFiles = (
+                       );
+               };
+               F939F219078F1A2100AC144F = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyld_debug.h;
+                       path = "include/mach-o/dyld_debug.h";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F939F21A078F1A2100AC144F = {
+                       fileRef = F939F219078F1A2100AC144F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F939F21B078F1A2C00AC144F = {
+                       fileRef = F939F219078F1A2100AC144F;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F93AA9A30630AE1E00301D9F = {
+                       fileRef = F9ED4CE80630A80600DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F93AA9A40630AE1E00301D9F = {
+                       fileRef = F9ED4CE90630A80600DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F93AA9A50630AE1E00301D9F = {
+                       fileRef = F9ED4CEA0630A80600DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F93AA9B30630AE8200301D9F = {
+                       buildActionMask = 8;
+                       dstPath = "/usr/include/mach-o";
+                       dstSubfolderSpec = 0;
+                       files = (
+                               F939F21B078F1A2C00AC144F,
+                               F93AA9A50630AE1E00301D9F,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+               F93AA9B60630AEB100301D9F = {
+                       buildActionMask = 8;
+                       dstPath = "/usr/local/include/mach-o";
+                       dstSubfolderSpec = 0;
+                       files = (
+                               F93AA9A30630AE1E00301D9F,
+                               F93AA9A40630AE1E00301D9F,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+               F93AA9C20630AF0700301D9F = {
+                       buildActionMask = 8;
+                       dstPath = /usr/share/man/man1;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               EF79A010070D293E00F78484,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+               F93AA9C60630AF1F00301D9F = {
+                       buildActionMask = 8;
+                       dstPath = /usr/share/man/man3;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               EF79A011070D295200F78484,
+                               EF79A012070D295200F78484,
+                               EF79A013070D295200F78484,
+                               EF79A014070D295200F78484,
+                               EF79A015070D295200F78484,
+                               EF79A016070D295200F78484,
+                               EF79A017070D295200F78484,
+                               EF79A018070D295200F78484,
+                               EF79A019070D295200F78484,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+               F9574C4906C94DA700142BFA = {
+                       compilerSpec = com.apple.compilers.gcc.3_5;
+                       fileType = sourcecode.c;
+                       isEditable = 1;
+                       isa = PBXBuildRule;
+                       outputFiles = (
+                       );
+               };
+               F9574CB206C95C0D00142BFA = {
+                       buildActionMask = 8;
+                       dstPath = /usr/include;
+                       dstSubfolderSpec = 0;
+                       files = (
+                               F9574CB306C95C1B00142BFA,
+                       );
+                       isa = PBXCopyFilesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+               F9574CB306C95C1B00142BFA = {
+                       fileRef = F99EE6AE06B48D4200BF1992;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F99EE6AE06B48D4200BF1992 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dlfcn.h;
+                       path = include/dlfcn.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F99EE6AF06B48D4200BF1992 = {
+                       fileRef = F99EE6AE06B48D4200BF1992;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9B01E3D0739ABDE00CF981B = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.exports;
+                       name = dyld.exp;
+                       path = src/dyld.exp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9B01E3E0739ABDE00CF981B = {
+                       fileRef = F9B01E3D0739ABDE00CF981B;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9CA205D06CBF578000BA084 = {
+                       buildActionMask = 8;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${DSTROOT}/usr/local/lib/system/ldyldapis.a",
+                       );
+                       isa = PBXShellScriptBuildPhase;
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+                       shellPath = /bin/sh;
+                       shellScript = "cd ${DSTROOT}/usr/local/lib/system\nln -s libdyldapis.a libdyldapis_profile.a\nln -s libdyldapis.a libdyldapis_debug.a\n";
+               };
+               F9ED4C870630A72200DF4E74 = {
+                       children = (
+                               F9ED4CBB0630A7AA00DF4E74,
+                               F9ED4CC30630A7BE00DF4E74,
+                               F9ED4CBE0630A7B100DF4E74,
+                               F9ED4C990630A76000DF4E74,
+                       );
+                       isa = PBXGroup;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F9ED4C890630A72300DF4E74 = {
+                       buildSettings = {
+                               COPY_PHASE_STRIP = NO;
+                               DEAD_CODE_STRIPPING = NO;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                       };
+                       isa = PBXBuildStyle;
+                       name = Development;
+               };
+               F9ED4C8A0630A72300DF4E74 = {
+                       buildSettings = {
+                               COPY_PHASE_STRIP = YES;
+                               GCC_ENABLE_CPP_RTTI = NO;
+                       };
+                       isa = PBXBuildStyle;
+                       name = Deployment;
+               };
+               F9ED4C8B0630A72300DF4E74 = {
+                       buildSettings = {
+                       };
+                       buildStyles = (
+                               F9ED4C890630A72300DF4E74,
+                               F9ED4C8A0630A72300DF4E74,
+                       );
+                       hasScannedForEncodings = 1;
+                       isa = PBXProject;
+                       mainGroup = F9ED4C870630A72200DF4E74;
+                       productRefGroup = F9ED4C990630A76000DF4E74;
+                       projectDirPath = "";
+                       targets = (
+                               F9ED4C920630A73900DF4E74,
+                               F9ED4C970630A76000DF4E74,
+                               F9ED4C9E0630A76B00DF4E74,
+                       );
+               };
+               F9ED4C920630A73900DF4E74 = {
+                       buildPhases = (
+                       );
+                       buildSettings = {
+                               OTHER_CFLAGS = "";
+                               OTHER_LDFLAGS = "";
+                               OTHER_REZFLAGS = "";
+                               PRODUCT_NAME = all;
+                               SECTORDER_FLAGS = "";
+                               WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                               F9ED4CA70630A78A00DF4E74,
+                               F9ED4CA90630A78A00DF4E74,
+                       );
+                       isa = PBXAggregateTarget;
+                       name = all;
+                       productName = all;
+               };
+               F9ED4C950630A76000DF4E74 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               F9ED4CDF0630A7F100DF4E74,
+                               F9ED4CD60630A7F100DF4E74,
+                               F9ED4CD70630A7F100DF4E74,
+                               F9ED4CD80630A7F100DF4E74,
+                               F9ED4CD90630A7F100DF4E74,
+                               F9ED4CDA0630A7F100DF4E74,
+                               F9ED4CDB0630A7F100DF4E74,
+                               F9ED4CDE0630A7F100DF4E74,
+                               F9ED4CE00630A7F100DF4E74,
+                               F9ED4CE10630A7F100DF4E74,
+                               F9ED4CE20630A7F100DF4E74,
+                               F9ED4CE30630A7F100DF4E74,
+                               F9ED4CE40630A7F100DF4E74,
+                               F9ED4CE50630A7F100DF4E74,
+                               F9ED4CEB0630A80600DF4E74,
+                               F9ED4CEC0630A80600DF4E74,
+                               F9ED4CED0630A80600DF4E74,
+                               F99EE6AF06B48D4200BF1992,
+                               F9B01E3E0739ABDE00CF981B,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               F9ED4C960630A76000DF4E74 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               F9ED4C970630A76000DF4E74 = {
+                       buildPhases = (
+                               F9ED4C950630A76000DF4E74,
+                               F9ED4C960630A76000DF4E74,
+                       );
+                       buildRules = (
+                               F921D318070376B0000D1056,
+                               F921D317070376A6000D1056,
+                               F921D3160703769A000D1056,
+                       );
+                       buildSettings = {
+                               ARCHS = ppc;
+                               CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
+                               DEAD_CODE_STRIPPING = YES;
+                               EXPORTED_SYMBOLS_FILE = "";
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_ENABLE_CPP_RTTI = NO;
+                               GCC_MODEL_TUNING = G4;
+                               GCC_OPTIMIZATION_LEVEL = 3;
+                               GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+                               HEADER_SEARCH_PATHS = ./include;
+                               INSTALL_PATH = /usr/lib;
+                               LIBRARY_SEARCH_PATHS = "";
+                               MACOSX_DEPLOYMENT_TARGET = 10.4;
+                               OTHER_CFLAGS = "";
+                               OTHER_LDFLAGS = "-v -seg1addr 8fe00000 -exported_symbols_list src/dyld.exp -nostdlib -lstdc++ /usr/local/lib/system/libc.a -lgcc  -Wl,-e,__dyld_start -Wl,-dylinker -Wl,-dylinker_install_name,/usr/lib/dyld";
+                               OTHER_REZFLAGS = "";
+                               PER_ARCH_CFLAGS_ppc = "";
+                               PER_ARCH_CFLAGS_ppc64 = "-msoft-float";
+                               PREBINDING = NO;
+                               PRODUCT_NAME = dyld;
+                               STRIPFLAGS = "-S";
+                               UNSTRIPPED_PRODUCT = NO;
+                               VALID_ARCHS = "ppc ppc64 i386";
+                               VERSIONING_SYSTEM = "apple-generic";
+                               WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = dyld;
+                       productName = dyld;
+                       productReference = F9ED4C980630A76000DF4E74;
+                       productType = "com.apple.product-type.tool";
+               };
+               F9ED4C980630A76000DF4E74 = {
+                       explicitFileType = "compiled.mach-o.executable";
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = dyld;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               F9ED4C990630A76000DF4E74 = {
+                       children = (
+                               F9ED4C980630A76000DF4E74,
+                               F9ED4C9F0630A76B00DF4E74,
+                       );
+                       isa = PBXGroup;
+                       name = Products;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F9ED4C9B0630A76B00DF4E74 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               F9FE429C06C82066001D8CE5,
+                               F939F21A078F1A2100AC144F,
+                       );
+                       isa = PBXHeadersBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               F9ED4C9C0630A76B00DF4E74 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                               F9F256360639DBCC00A7427D,
+                               F9F256370639DBCC00A7427D,
+                               F913FADA0630A8AE00B7AE9D,
+                               F906E2240639E96400B13DB2,
+                       );
+                       isa = PBXSourcesBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               F9ED4C9D0630A76B00DF4E74 = {
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       isa = PBXFrameworksBuildPhase;
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               F9ED4C9E0630A76B00DF4E74 = {
+                       buildPhases = (
+                               F9ED4C9C0630A76B00DF4E74,
+                               F9ED4C9B0630A76B00DF4E74,
+                               F93AA9B30630AE8200301D9F,
+                               F9574CB206C95C0D00142BFA,
+                               F93AA9B60630AEB100301D9F,
+                               F93AA9C20630AF0700301D9F,
+                               F93AA9C60630AF1F00301D9F,
+                               F9CA205D06CBF578000BA084,
+                               F9ED4C9D0630A76B00DF4E74,
+                       );
+                       buildRules = (
+                               F921D31E070376F1000D1056,
+                               F9574C4906C94DA700142BFA,
+                       );
+                       buildSettings = {
+                               ARCHS = ppc;
+                               GCC_ENABLE_CPP_EXCEPTIONS = NO;
+                               HEADER_SEARCH_PATHS = ./include;
+                               INSTALL_PATH = /usr/local/lib/system;
+                               LIBRARY_STYLE = STATIC;
+                               OTHER_CFLAGS = "";
+                               OTHER_LDFLAGS = "";
+                               OTHER_REZFLAGS = "";
+                               PRODUCT_NAME = dyldapis;
+                               SECTORDER_FLAGS = "";
+                               VALID_ARCHS = "ppc ppc64 i386";
+                               WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+                       };
+                       dependencies = (
+                       );
+                       isa = PBXNativeTarget;
+                       name = libdyld;
+                       productName = libdyld;
+                       productReference = F9ED4C9F0630A76B00DF4E74;
+                       productType = "com.apple.product-type.library.static";
+               };
+               F9ED4C9F0630A76B00DF4E74 = {
+                       explicitFileType = archive.ar;
+                       includeInIndex = 0;
+                       isa = PBXFileReference;
+                       path = libdyldapis.a;
+                       refType = 3;
+                       sourceTree = BUILT_PRODUCTS_DIR;
+               };
+               F9ED4CA60630A78A00DF4E74 = {
+                       containerPortal = F9ED4C8B0630A72300DF4E74;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = F9ED4C970630A76000DF4E74;
+                       remoteInfo = dyld;
+               };
+               F9ED4CA70630A78A00DF4E74 = {
+                       isa = PBXTargetDependency;
+                       target = F9ED4C970630A76000DF4E74;
+                       targetProxy = F9ED4CA60630A78A00DF4E74;
+               };
+               F9ED4CA80630A78A00DF4E74 = {
+                       containerPortal = F9ED4C8B0630A72300DF4E74;
+                       isa = PBXContainerItemProxy;
+                       proxyType = 1;
+                       remoteGlobalIDString = F9ED4C9E0630A76B00DF4E74;
+                       remoteInfo = libdyld;
+               };
+               F9ED4CA90630A78A00DF4E74 = {
+                       isa = PBXTargetDependency;
+                       target = F9ED4C9E0630A76B00DF4E74;
+                       targetProxy = F9ED4CA80630A78A00DF4E74;
+               };
+               F9ED4CBB0630A7AA00DF4E74 = {
+                       children = (
+                               F9ED4CC60630A7F100DF4E74,
+                               F9ED4CC70630A7F100DF4E74,
+                               F9ED4CC80630A7F100DF4E74,
+                               F9FE429B06C82066001D8CE5,
+                               F9ED4CC90630A7F100DF4E74,
+                               F9ED4CCA0630A7F100DF4E74,
+                               F913FAD90630A8AE00B7AE9D,
+                               F9ED4CCB0630A7F100DF4E74,
+                               F9ED4CCC0630A7F100DF4E74,
+                               F9ED4CCD0630A7F100DF4E74,
+                               F9ED4CCE0630A7F100DF4E74,
+                               F9ED4CCF0630A7F100DF4E74,
+                               F9ED4CD00630A7F100DF4E74,
+                               F9ED4CD10630A7F100DF4E74,
+                               F9ED4CD20630A7F100DF4E74,
+                               F9ED4CD30630A7F100DF4E74,
+                               F9ED4CD40630A7F100DF4E74,
+                               F9ED4CD50630A7F100DF4E74,
+                               F9B01E3D0739ABDE00CF981B,
+                               F906E2230639E96400B13DB2,
+                       );
+                       isa = PBXGroup;
+                       name = src;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F9ED4CBE0630A7B100DF4E74 = {
+                       children = (
+                               F9ED4CE80630A80600DF4E74,
+                               F9ED4CE90630A80600DF4E74,
+                               F939F219078F1A2100AC144F,
+                               F9ED4CEA0630A80600DF4E74,
+                               F99EE6AE06B48D4200BF1992,
+                       );
+                       isa = PBXGroup;
+                       name = include;
+                       path = "";
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F9ED4CC30630A7BE00DF4E74 = {
+                       children = (
+                               EF799FE7070D27BB00F78484,
+                       );
+                       isa = PBXGroup;
+                       name = doc;
+                       path = "";
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CC60630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyld_gdb.cpp;
+                       path = src/dyld_gdb.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CC70630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyld.cpp;
+                       path = src/dyld.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CC80630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyld.h;
+                       path = src/dyld.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CC90630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyldAPIs.cpp;
+                       path = src/dyldAPIs.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CCA0630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = dyldExceptions.c;
+                       path = src/dyldExceptions.c;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CCB0630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyldInitialization.cpp;
+                       path = src/dyldInitialization.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CCC0630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyldLock.cpp;
+                       path = src/dyldLock.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CCD0630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyldLock.h;
+                       path = src/dyldLock.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CCE0630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = dyldNew.cpp;
+                       path = src/dyldNew.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CCF0630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       indentWidth = 4;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.asm;
+                       name = dyldStartup.s;
+                       path = src/dyldStartup.s;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+                       tabWidth = 8;
+                       usesTabs = 1;
+               };
+               F9ED4CD00630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.c;
+                       name = glue.c;
+                       path = src/glue.c;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CD10630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = ImageLoader.cpp;
+                       path = src/ImageLoader.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CD20630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = ImageLoader.h;
+                       path = src/ImageLoader.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CD30630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.cpp.cpp;
+                       name = ImageLoaderMachO.cpp;
+                       path = src/ImageLoaderMachO.cpp;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CD40630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = ImageLoaderMachO.h;
+                       path = src/ImageLoaderMachO.h;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CD50630A7F100DF4E74 = {
+                       fileEncoding = 30;
+                       indentWidth = 4;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.asm;
+                       name = stub_binding_helper.s;
+                       path = src/stub_binding_helper.s;
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+                       tabWidth = 8;
+                       usesTabs = 1;
+               };
+               F9ED4CD60630A7F100DF4E74 = {
+                       fileRef = F9ED4CC60630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CD70630A7F100DF4E74 = {
+                       fileRef = F9ED4CC70630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CD80630A7F100DF4E74 = {
+                       fileRef = F9ED4CC80630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CD90630A7F100DF4E74 = {
+                       fileRef = F9ED4CC90630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CDA0630A7F100DF4E74 = {
+                       fileRef = F9ED4CCA0630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CDB0630A7F100DF4E74 = {
+                       fileRef = F9ED4CCB0630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CDE0630A7F100DF4E74 = {
+                       fileRef = F9ED4CCE0630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CDF0630A7F100DF4E74 = {
+                       fileRef = F9ED4CCF0630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE00630A7F100DF4E74 = {
+                       fileRef = F9ED4CD00630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE10630A7F100DF4E74 = {
+                       fileRef = F9ED4CD10630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE20630A7F100DF4E74 = {
+                       fileRef = F9ED4CD20630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE30630A7F100DF4E74 = {
+                       fileRef = F9ED4CD30630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE40630A7F100DF4E74 = {
+                       fileRef = F9ED4CD40630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE50630A7F100DF4E74 = {
+                       fileRef = F9ED4CD50630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CE80630A80600DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyld_gdb.h;
+                       path = "include/mach-o/dyld_gdb.h";
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CE90630A80600DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyld_priv.h;
+                       path = "include/mach-o/dyld_priv.h";
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CEA0630A80600DF4E74 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyld.h;
+                       path = "include/mach-o/dyld.h";
+                       refType = 2;
+                       sourceTree = SOURCE_ROOT;
+               };
+               F9ED4CEB0630A80600DF4E74 = {
+                       fileRef = F9ED4CE80630A80600DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CEC0630A80600DF4E74 = {
+                       fileRef = F9ED4CE90630A80600DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9ED4CED0630A80600DF4E74 = {
+                       fileRef = F9ED4CEA0630A80600DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9F256360639DBCC00A7427D = {
+                       fileRef = F9ED4CCC0630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9F256370639DBCC00A7427D = {
+                       fileRef = F9ED4CCD0630A7F100DF4E74;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               F9FE429B06C82066001D8CE5 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       name = dyldLibSystemThreadHelpers.h;
+                       path = src/dyldLibSystemThreadHelpers.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               F9FE429C06C82066001D8CE5 = {
+                       fileRef = F9FE429B06C82066001D8CE5;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+       };
+       rootObject = F9ED4C8B0630A72300DF4E74;
+}
diff --git a/include/dlfcn.h b/include/dlfcn.h
new file mode 100644 (file)
index 0000000..77d7521
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2004-2005 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@
+ */
+
+/*
+  Based on the dlcompat work done by:
+               Jorge Acereda  <jacereda@users.sourceforge.net> &
+               Peter O'Gorman <ogorman@users.sourceforge.net>
+*/
+
+#ifndef _DLFCN_H_
+#define _DLFCN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/cdefs.h>
+
+#ifndef _POSIX_C_SOURCE
+/*
+ * Structure filled in by dladdr().
+ */
+typedef struct dl_info {
+        const char      *dli_fname;     /* Pathname of shared object */
+        void            *dli_fbase;     /* Base address of shared object */
+        const char      *dli_sname;     /* Name of nearest symbol */
+        void            *dli_saddr;     /* Address of nearest symbol */
+} Dl_info;
+
+extern int dladdr(const void *, Dl_info *);
+#endif /* not POSIX */
+
+extern int dlclose(void * __handle);
+extern char * dlerror(void);
+extern void * dlopen(const char * __path, int __mode);
+extern void * dlsym(void * __handle, const char * __symbol);
+
+#define RTLD_LAZY      0x1
+#define RTLD_NOW       0x2
+#define RTLD_LOCAL     0x4
+#define RTLD_GLOBAL    0x8
+
+#ifndef _POSIX_C_SOURCE
+#define RTLD_NOLOAD    0x10
+#define RTLD_NODELETE  0x80
+
+/*
+ * Special handle arguments for dlsym().
+ */
+#define        RTLD_NEXT               ((void *) -1)   /* Search subsequent objects. */
+#define        RTLD_DEFAULT    ((void *) -2)   /* Use default search algorithm. */
+#endif /* not POSIX */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DLFCN_H_ */
diff --git a/include/mach-o/dyld.h b/include/mach-o/dyld.h
new file mode 100644 (file)
index 0000000..62cb9a7
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 1999-2005 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 _MACH_O_DYLD_H_
+#define _MACH_O_DYLD_H_
+
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stddef.h>
+#include <stdint.h>
+#if __cplusplus
+  /* C++ has bool type built in */
+#else
+ #include <stdbool.h>
+#endif
+#include <mach-o/loader.h>
+#include <AvailabilityMacros.h>
+
+#ifndef ENUM_DYLD_BOOL
+#define ENUM_DYLD_BOOL
+#undef FALSE
+#undef TRUE
+enum DYLD_BOOL {
+    FALSE,
+    TRUE
+};
+#endif /* ENUM_DYLD_BOOL */
+
+/*
+ * The high level NS... API.
+ */
+
+/* Object file image API */
+typedef enum {
+    NSObjectFileImageFailure, /* for this a message is printed on stderr */
+    NSObjectFileImageSuccess,
+    NSObjectFileImageInappropriateFile,
+    NSObjectFileImageArch,
+    NSObjectFileImageFormat, /* for this a message is printed on stderr */
+    NSObjectFileImageAccess
+} NSObjectFileImageReturnCode;
+
+typedef struct __NSObjectFileImage*  NSObjectFileImage;
+
+/* limited implementation, only MH_BUNDLE files can be used */
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(
+    const char *pathName,
+    NSObjectFileImage *objectFileImage);
+extern NSObjectFileImageReturnCode NSCreateCoreFileImageFromFile(
+    const char *pathName,
+    NSObjectFileImage *objectFileImage);
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(
+    const void *address,
+    size_t size, 
+    NSObjectFileImage *objectFileImage);
+extern bool NSDestroyObjectFileImage(
+    NSObjectFileImage objectFileImage);
+/*
+ * API on NSObjectFileImage's for:
+ *   "for Each Symbol Definition In Object File Image" (for Dynamic Bundles)
+ *   and the same thing for references
+ */
+extern uint32_t NSSymbolDefinitionCountInObjectFileImage(
+    NSObjectFileImage objectFileImage);
+extern const char * NSSymbolDefinitionNameInObjectFileImage(
+    NSObjectFileImage objectFileImage,
+    uint32_t ordinal);
+extern uint32_t NSSymbolReferenceCountInObjectFileImage(
+    NSObjectFileImage objectFileImage);
+extern const char * NSSymbolReferenceNameInObjectFileImage(
+    NSObjectFileImage objectFileImage,
+    uint32_t ordinal,
+    bool *tentative_definition); /* can be NULL */
+/*
+ * API on NSObjectFileImage:
+ *   "does Object File Image define symbol name X" (using sorted symbol table)
+ *   and a way to get the named objective-C section
+ */
+extern bool NSIsSymbolDefinedInObjectFileImage(
+    NSObjectFileImage objectFileImage,
+    const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern void * NSGetSectionDataInObjectFileImage(
+    NSObjectFileImage objectFileImage,
+    const char *segmentName,
+    const char *sectionName,
+    size_t *size); /* can be NULL */
+/* SPI first appeared in Mac OS X 10.3 */
+extern bool NSHasModInitObjectFileImage(
+    NSObjectFileImage objectFileImage)
+    AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+/* module API */
+typedef struct __NSModule* NSModule;
+extern const char * NSNameOfModule(
+    NSModule m); 
+extern const char * NSLibraryNameForModule(
+    NSModule m);
+
+/* limited implementation, only MH_BUNDLE files can be linked */
+extern NSModule NSLinkModule(
+    NSObjectFileImage objectFileImage, 
+    const char *moduleName,
+    uint32_t options);
+#define NSLINKMODULE_OPTION_NONE               0x0
+#define NSLINKMODULE_OPTION_BINDNOW            0x1
+#define NSLINKMODULE_OPTION_PRIVATE            0x2
+#define NSLINKMODULE_OPTION_RETURN_ON_ERROR    0x4
+#define NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES 0x8
+#define NSLINKMODULE_OPTION_TRAILING_PHYS_NAME 0x10
+
+/* limited implementation, only modules loaded with NSLinkModule() can be
+   unlinked */
+extern bool NSUnLinkModule(
+    NSModule module, 
+    uint32_t options);
+#define NSUNLINKMODULE_OPTION_NONE                     0x0
+#define NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED       0x1
+#define NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES    0x2
+
+/* not yet implemented */
+extern NSModule NSReplaceModule(
+    NSModule moduleToReplace,
+    NSObjectFileImage newObjectFileImage, 
+    uint32_t options);
+
+/* symbol API */
+typedef struct __NSSymbol* NSSymbol;
+extern bool NSIsSymbolNameDefined(
+    const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern bool NSIsSymbolNameDefinedWithHint(
+    const char *symbolName,
+    const char *libraryNameHint) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern bool NSIsSymbolNameDefinedInImage(
+    const struct mach_header *image,
+    const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern NSSymbol NSLookupAndBindSymbol(
+    const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern NSSymbol NSLookupAndBindSymbolWithHint(
+    const char *symbolName,
+    const char *libraryNameHint) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern NSSymbol NSLookupSymbolInModule(
+    NSModule module,
+    const char *symbolName);
+extern NSSymbol NSLookupSymbolInImage(
+    const struct mach_header *image,
+    const char *symbolName,
+    uint32_t options);
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
+extern const char * NSNameOfSymbol(
+    NSSymbol symbol);
+extern void * NSAddressOfSymbol(
+    NSSymbol symbol);
+extern NSModule NSModuleForSymbol(
+    NSSymbol symbol);
+
+/* error handling API */
+typedef enum {
+    NSLinkEditFileAccessError,
+    NSLinkEditFileFormatError,
+    NSLinkEditMachResourceError,
+    NSLinkEditUnixResourceError,
+    NSLinkEditOtherError,
+    NSLinkEditWarningError,
+    NSLinkEditMultiplyDefinedError,
+    NSLinkEditUndefinedError
+} NSLinkEditErrors;
+
+/*
+ * For the NSLinkEditErrors value NSLinkEditOtherError these are the values
+ * passed to the link edit error handler as the errorNumber (what would be an
+ * errno value for NSLinkEditUnixResourceError or a kern_return_t value for
+ * NSLinkEditMachResourceError).
+ */
+typedef enum {
+    NSOtherErrorRelocation, 
+    NSOtherErrorLazyBind,
+    NSOtherErrorIndrLoop,
+    NSOtherErrorLazyInit,
+    NSOtherErrorInvalidArgs
+} NSOtherErrorNumbers;
+
+extern void NSLinkEditError(
+    NSLinkEditErrors *c,
+    int *errorNumber, 
+    const char **fileName,
+    const char **errorString);
+
+typedef struct {
+     void     (*undefined)(const char *symbolName);
+     NSModule (*multiple)(NSSymbol s, NSModule oldModule, NSModule newModule); 
+     void     (*linkEdit)(NSLinkEditErrors errorClass, int errorNumber,
+                          const char *fileName, const char *errorString);
+} NSLinkEditErrorHandlers;
+
+extern void NSInstallLinkEditErrorHandlers(
+    const NSLinkEditErrorHandlers *handlers);
+
+/* other API */
+extern bool NSAddLibrary(
+    const char *pathName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern bool NSAddLibraryWithSearching(
+    const char *pathName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern const struct mach_header * NSAddImage(
+    const char *image_name,
+    uint32_t options);
+#define NSADDIMAGE_OPTION_NONE                         0x0
+#define NSADDIMAGE_OPTION_RETURN_ON_ERROR              0x1
+#define NSADDIMAGE_OPTION_WITH_SEARCHING               0x2
+#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED        0x4
+#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME        0x8
+extern int32_t NSVersionOfRunTimeLibrary(
+    const char *libraryName);
+extern int32_t NSVersionOfLinkTimeLibrary(
+    const char *libraryName);
+extern int _NSGetExecutablePath( /* SPI first appeared in Mac OS X 10.2 */
+    char *buf,
+    uint32_t *bufsize);
+
+/*
+ * The low level _dyld_... API.
+ * (used by the objective-C runtime primarily)
+ */
+extern bool _dyld_present(
+    void);
+
+extern uint32_t _dyld_image_count(
+    void);
+extern const struct mach_header * _dyld_get_image_header(
+    uint32_t image_index);
+extern intptr_t _dyld_get_image_vmaddr_slide(
+    uint32_t image_index);
+extern const char * _dyld_get_image_name(
+    uint32_t image_index);
+
+extern void _dyld_register_func_for_add_image(
+    void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+extern void _dyld_register_func_for_remove_image(
+    void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+extern void _dyld_register_func_for_link_module(
+    void (*func)(NSModule module));
+/* not yet implemented */
+extern void _dyld_register_func_for_unlink_module(
+    void (*func)(NSModule module));
+/* not yet implemented */
+extern void _dyld_register_func_for_replace_module(
+    void (*func)(NSModule oldmodule, NSModule newmodule));
+extern void _dyld_get_objc_module_sect_for_module(
+    NSModule module,
+    void **objc_module,
+    size_t *size);
+extern void _dyld_bind_objc_module(
+    const void *objc_module);
+extern bool _dyld_bind_fully_image_containing_address(
+    const void *address);
+extern bool _dyld_image_containing_address(
+    const void* address);
+/* SPI first appeared in Mac OS X 10.3 */
+extern const struct mach_header * _dyld_get_image_header_containing_address(
+    const void* address)
+    AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+extern void _dyld_moninit(
+    void (*monaddition)(char *lowpc, char *highpc));
+extern bool _dyld_launched_prebound(
+    void);
+/* SPI first appeared in Mac OS X 10.3 */
+extern bool _dyld_all_twolevel_modules_prebound(
+    void)
+    AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+extern void _dyld_lookup_and_bind(
+    const char *symbol_name,
+    void **address,
+    NSModule* module) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern void _dyld_lookup_and_bind_with_hint(
+    const char *symbol_name,
+    const char *library_name_hint,
+    void **address,
+    NSModule* module) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern void _dyld_lookup_and_bind_objc(
+    const char *symbol_name,
+    void **address,
+    NSModule* module);
+extern void _dyld_lookup_and_bind_fully(
+    const char *symbol_name,
+    void **address,
+    NSModule* module);
+
+extern int _dyld_func_lookup(
+    const char *dyld_func_name,
+    void **address);
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _MACH_O_DYLD_H_ */
diff --git a/include/mach-o/dyld_debug.h b/include/mach-o/dyld_debug.h
new file mode 100644 (file)
index 0000000..a0590f5
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * 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 _DYLD_DEBUG_
+#define _DYLD_DEBUG_
+
+#include <mach/mach.h>
+#ifndef DYLD_BUILD /* do not include this when building dyld itself */
+#include <mach-o/dyld.h>
+#endif /* !defined(DYLD_BUILD) */
+
+#include <AvailabilityMacros.h>
+
+/*
+ * The dyld debugging API is deprecated as of Mac OS X 10.4
+ */
+enum dyld_debug_return {
+    DYLD_SUCCESS,
+    DYLD_INCONSISTENT_DATA,
+    DYLD_INVALID_ARGUMENTS,
+    DYLD_FAILURE
+};
+
+struct dyld_debug_module {
+    struct mach_header *header;
+    unsigned long vmaddr_slide;
+    unsigned long module_index;
+};
+
+enum dyld_event_type {
+    DYLD_IMAGE_ADDED,
+    DYLD_MODULE_BOUND,
+    DYLD_MODULE_REMOVED,
+    DYLD_MODULE_REPLACED,
+    DYLD_PAST_EVENTS_END,
+    DYLD_IMAGE_REMOVED
+};
+
+struct dyld_event {
+    enum dyld_event_type type;
+    struct dyld_debug_module arg[2];
+};
+
+extern enum dyld_debug_return _dyld_debug_defining_module(
+    mach_port_t target_task,
+    unsigned long send_timeout,
+    unsigned long rcv_timeout,
+    boolean_t inconsistent_data_ok,
+    char *name,
+    struct dyld_debug_module *module) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_is_module_bound(
+    mach_port_t target_task,
+    unsigned long send_timeout,
+    unsigned long rcv_timeout,
+    boolean_t inconsistent_data_ok,
+    struct dyld_debug_module module,
+    boolean_t *bound) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_bind_module(
+    mach_port_t target_task,
+    unsigned long send_timeout,
+    unsigned long rcv_timeout,
+    boolean_t inconsistent_data_ok,
+    struct dyld_debug_module module) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_module_name(
+    mach_port_t target_task,
+    unsigned long send_timeout,
+    unsigned long rcv_timeout,
+    boolean_t inconsistent_data_ok,
+    struct dyld_debug_module module,
+    char **image_name,
+    unsigned long *image_nameCnt,
+    char **module_name,
+    unsigned long *module_nameCnt) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_subscribe_to_events(
+    mach_port_t target_task,
+    unsigned long send_timeout,
+    unsigned long rcv_timeout,
+    boolean_t inconsistent_data_ok,
+    void (*dyld_event_routine)(struct dyld_event event)) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * _dyld_debug_add_event_subscriber() uses the mig interface functions below
+ * to dispatch the dyld event messages from the subscriber port specified.
+ */
+extern enum dyld_debug_return _dyld_debug_add_event_subscriber(
+    mach_port_t target_task,
+    unsigned long send_timeout,
+    unsigned long rcv_timeout,
+    boolean_t inconsistent_data_ok,
+    mach_port_t subscriber) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * These structures should be produced by mig(1) from the mig generated files
+ * but they are not.  These are really only needed so the correct size of the
+ * request and reply messages can be allocated.
+ */
+struct _dyld_event_message_request {
+#ifdef __MACH30__
+    mach_msg_header_t head;
+    NDR_record_t NDR;
+    struct dyld_event event;
+    mach_msg_trailer_t trailer;
+#else
+    msg_header_t head;
+    msg_type_t eventType;
+    struct dyld_event event;
+#endif
+};
+struct _dyld_event_message_reply {
+#ifdef __MACH30__
+    mach_msg_header_t head;
+    NDR_record_t NDR;
+    struct dyld_event event;
+#else
+    msg_header_t head;
+    msg_type_t RetCodeType;
+    kern_return_t RetCode;
+#endif
+};
+#ifndef        mig_internal
+/*
+ * _dyld_event_server() is the mig generated routine to dispatch dyld event
+ * messages.
+ */
+extern boolean_t _dyld_event_server(
+#ifdef __MACH30__
+    mach_msg_header_t *request,
+    mach_msg_header_t *reply);
+#else
+    struct _dyld_event_message_request *request,
+    struct _dyld_event_message_reply *reply);
+#endif
+#endif /* mig_internal */
+
+#ifndef SHLIB
+/*
+ * _dyld_event_server_callback() is the routine called by _dyld_event_server()
+ * that must be written by users of _dyld_event_server().
+ */
+extern
+#ifdef __MACH30__
+kern_return_t
+#else
+void
+#endif
+_dyld_event_server_callback(
+#ifdef __MACH30__
+    mach_port_t subscriber,
+#else
+    port_t subscriber,
+#endif
+    struct dyld_event event);
+#endif /* SHLIB */
+
+/*
+ * This is the state of the target task while we are sending a message to it.
+ */
+struct _dyld_debug_task_state {
+    mach_port_t           debug_port;
+    mach_port_t    debug_thread;
+    unsigned int   debug_thread_resume_count;
+    unsigned int   task_resume_count;
+    mach_port_t   *threads;
+    unsigned int   thread_count;
+};
+
+/*
+ * _dyld_debug_make_runnable() is called before sending messages to the
+ * dynamic link editor.  Basically it assures that the debugging
+ * thread is the only runnable thread in the task to receive the
+ * message.  It also assures that the debugging thread is indeed
+ * runnable if it was suspended.  The function will make sure each 
+ * thread in the remote task is suspended and resumed the same number
+ * of times, so in the end the suspend count of each individual thread
+ * is the same.
+ */
+extern enum dyld_debug_return _dyld_debug_make_runnable(
+    mach_port_t target_task,
+    struct _dyld_debug_task_state *state) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * _dyld_debug_restore_runnable() is called after sending messages to the
+ * dynamic link editor.  It undoes what _dyld_debug_make_runnable() did to the
+ * task and put it back the way it was.
+ */
+extern enum dyld_debug_return _dyld_debug_restore_runnable(
+    mach_port_t target_task,
+    struct _dyld_debug_task_state *state) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * To provide more detailed information when the APIs of the dyld debug
+ * interfaces fail (return DYLD_FAILURE) the following structure is filled in.
+ * After it is filled in the function registered with
+ * set_dyld_debug_error_func() is called with a pointer to that struct.
+ *
+ * The local_error field is a unique number for each possible error condition
+ * in the source code in that makes up the dyld debug APIs.  The source file
+ * and line number in the cctools libdyld directory where the dyld debug APIs
+ * are implemented are set into the file_name and line_number fields.  The
+ * field dyld_debug_return is filled in with that would be returned by the
+ * API (usually DYLD_FAILURE).  The other fields will be zero or filled in by
+ * the error code from the mach system call, or UNIX system call that failed.
+ */
+struct dyld_debug_error_data {
+    enum dyld_debug_return dyld_debug_return;
+    kern_return_t mach_error;
+    int dyld_debug_errno;
+    unsigned long local_error;
+    char *file_name;
+    unsigned long line_number;
+};
+
+extern void _dyld_debug_set_error_func(
+    void (*func)(struct dyld_debug_error_data *e)) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+#ifndef DYLD_BUILD /* do not include this when building dyld itself */
+
+extern enum dyld_debug_return _dyld_debug_task_from_core(
+    NSObjectFileImage coreFileImage,
+    mach_port_t *core_task) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+#endif /* !defined(DYLD_BUILD) */
+
+#endif /* _DYLD_DEBUG_ */
diff --git a/include/mach-o/dyld_gdb.h b/include/mach-o/dyld_gdb.h
new file mode 100644 (file)
index 0000000..9910dcd
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2003 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 _DYLD_GDB_
+#define _DYLD_GDB_
+/*
+ * This file describes the interface between gdb and dyld created for
+ * MacOS X GM.  Prior to MacOS X GM gdb used the dyld_debug interfaces
+ * described in <mach-o/dyld_debug.h>.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define OLD_GDB_DYLD_INTERFACE __ppc__ || __i386__
+
+#if OLD_GDB_DYLD_INTERFACE
+/*
+ * gdb_dyld_version is the version of gdb interface that dyld is currently
+ * exporting.  For the interface described in this header file gdb_dyld_version
+ * is 2.  As the gdb/dyld interface changes this number will be incremented and
+ * comments will be added as to what are the are changes for the various
+ * versions.
+ */
+extern unsigned int gdb_dyld_version;
+
+/* 
+ * gdb_dyld_state_changed is the internal dyld routine called by dyld to notify
+ * gdb that the state of the data structures has changed.  gdb is expected to
+ * put a break point on this routine and re-read the internal dyld data
+ * structures below when this break point is hit.
+ */
+extern void gdb_dyld_state_changed(void);
+
+/*
+ * gdb looks directly at parts of two of dyld's internal data structures.  The
+ * list of object file images and the list of library images.  The parts of
+ * these structures that gdb looks at will not change unless the value of
+ * gdb_dyld_version changes.  The size of these structures and the other fields
+ * that gdb does not look at may change.
+ *
+ *  struct object_images {
+ *      struct object_image images[NOBJECT_IMAGES];
+ *      unsigned long nimages; 
+ *      struct object_images *next_images; 
+ *      ...
+ *  };
+ *
+ *  struct library_images { 
+ *      struct library_image images[NLIBRARY_IMAGES];
+ *      unsigned long nimages;
+ *      struct library_images *next_images;
+ *      ...
+ *  };
+ *
+ * Both the object_image structure and the library_image structure
+ * start with a structure containing the following fields:
+ *
+ *  struct image {   
+ *      char *physical_name;        physical image name (file name)
+ *      unsigned long vmaddr_slide; the slide from the staticly linked address
+ *      struct mach_header *mh;     address of the mach header of the image
+ *     unsigned long valid;        TRUE if this is struct is valid
+ *      char *name;                 image name for reporting errors
+ *      ...
+ *  };
+ *
+ * In gdb_dyld_version 1 the first field was "name".  In gdb_dyld_version 2 the
+ * first field was changed to "physical_name" and a new fifth field "name" was
+ * added.  These two fields are set to the same values except in the case of
+ * zero-link.  In zero-link the NSLinkModule() option
+ * NSLINKMODULE_OPTION_TRAILING_PHYS_NAME is used and then the physical_name is
+ * the file name of the module zero-link loaded that is part of the logical
+ * image "name".
+ */
+
+/* object_images is the global object_images structure */
+
+/* the number of gdb_object_image structures present per bucket */
+extern unsigned int gdb_nobject_images;
+
+/* the size of each gdb_object_image structure */
+extern unsigned int gdb_object_image_size;
+
+/* library_images is the global library_images structure */
+
+/* the number of gdb_library_image structures present per bucket */
+extern unsigned int gdb_nlibrary_images;
+
+/* the size of each gdb_library_image structure */
+extern unsigned int gdb_library_image_size;
+
+#endif /* OLD_GDB_DYLD_INTERFACE */
+
+
+/* 
+ *     Beginning in Mac OS X 10.4, there is a new mechanism for dyld to notify gdb and other about new images.
+ *
+ *
+ */
+
+enum dyld_image_mode { dyld_image_adding=0, dyld_image_removing=1 };
+
+struct dyld_image_info {
+       const struct mach_header*       imageLoadAddress;       /* base address image is mapped into */
+       const char*                                     imageFilePath;          /* path dyld used to load the image */
+       uintptr_t                                       imageFileModDate;       /* time_t of image file */
+                                                                                                       /* if stat().st_mtime of imageFilePath does not match imageFileModDate, */
+                                                                                                       /* then file has been modified since dyld loaded it */
+};
+
+
+typedef void (*dyld_image_notifier)(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
+
+/* 
+ *     gdb looks for the symbol "_dyld_all_image_infos" in dyld.  It contains the fields below.  
+ *
+ *     For a snap shot of what images are currently loaded, the infoArray fields contain a pointer
+ *     to an array of all images. If infoArray is NULL, it means it is being modified, come back later.
+ *
+ *     To be notified of changes, gdb sets a break point on the notification field.  The function
+ *     it points to is called by dyld with an array of information about what images have been added
+ *     (dyld_image_adding) or are about to be removed (dyld_image_removing). 
+ *
+ * The notification is called after infoArray is updated.  This means that if gdb attaches to a process
+ * and infoArray is NULL, gdb can set a break point on notification and let the proccess continue to
+ * run until the break point.  Then gdb can inspect the full infoArray.
+ */
+ struct dyld_all_image_infos {
+       uint32_t                                                version;                /* == 1 in Mac OS X 10.4 */
+       uint32_t                                                infoArrayCount;
+       const struct dyld_image_info*   infoArray;
+       dyld_image_notifier                             notification;           
+       bool                                                    processDetachedFromSharedRegion;
+};
+extern struct dyld_all_image_infos  dyld_all_image_infos;
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DYLD_GDB_ */
diff --git a/include/mach-o/dyld_priv.h b/include/mach-o/dyld_priv.h
new file mode 100644 (file)
index 0000000..5111ebb
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003 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 _MACH_O_DYLD_PRIV_H_
+#define _MACH_O_DYLD_PRIV_H_
+
+
+#include <mach-o/dyld.h>
+
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*
+ * Given an imageOffset into an ObjectFileImage, returns 
+ * the segment/section name and offset into that section of
+ * that imageOffset.  Returns FALSE if the imageOffset is not 
+ * in any section.  You can used the resulting sectionOffset to
+ * index into the data returned by NSGetSectionDataInObjectFileImage.
+ * 
+ * First appeared in Mac OS X 10.3 
+ *
+ * SPI: currently only used by ZeroLink to detect +load methods
+ */
+bool 
+NSFindSectionAndOffsetInObjectFileImage(
+    NSObjectFileImage objectFileImage, 
+    unsigned long imageOffset,
+    const char** segmentName,  /* can be NULL */
+    const char** sectionName,  /* can be NULL */
+    unsigned long* sectionOffset);     /* can be NULL */
+
+
+
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _MACH_O_DYLD_PRIV_H_ */
diff --git a/src/ImageLoader.cpp b/src/ImageLoader.cpp
new file mode 100644 (file)
index 0000000..663ac98
--- /dev/null
@@ -0,0 +1,1015 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mach/mach.h>
+#include <mach-o/fat.h> 
+#include <sys/types.h>
+#include <sys/stat.h> 
+#include <sys/mman.h>
+
+#include "ImageLoader.h"
+
+
+uint32_t                                                               ImageLoader::fgImagesWithUsedPrebinding = 0;
+uint32_t                                                               ImageLoader::fgTotalRebaseFixups = 0;
+uint32_t                                                               ImageLoader::fgTotalBindFixups = 0;
+uint32_t                                                               ImageLoader::fgTotalLazyBindFixups = 0;
+uint32_t                                                               ImageLoader::fgTotalPossibleLazyBindFixups = 0;
+uint64_t                                                               ImageLoader::fgTotalLoadLibrariesTime;
+uint64_t                                                               ImageLoader::fgTotalRebaseTime;
+uint64_t                                                               ImageLoader::fgTotalBindTime;
+uint64_t                                                               ImageLoader::fgTotalNotifyTime;
+uint64_t                                                               ImageLoader::fgTotalInitTime;
+uintptr_t                                                              ImageLoader::fgNextSplitSegAddress = 0x90000000;
+uintptr_t                                                              Segment::fgNextNonSplitSegAddress = 0x8FE00000;
+
+
+
+__attribute__((noreturn))
+void throwf(const char* format, ...) 
+{
+       va_list list;
+       char*   p;
+       va_start(list, format);
+       vasprintf(&p, format, list);
+       va_end(list);
+       
+       const char*     t = p;
+       throw t;
+}
+
+void ImageLoader::init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate)
+{
+       fPathHash = 0;
+       fPath = NULL;
+       if ( path != NULL )
+               this->setPath(path);
+       fLogicalPath = NULL;
+       fDevice = device;
+       fInode = inode;
+       fLastModified = modDate;
+       fOffsetInFatFile = offsetInFat;
+       //fSegments = NULL;
+       fLibraries = NULL;
+       fLibrariesCount = 0;
+       fReferenceCount = 0;
+       fAllLibraryChecksumsAndLoadAddressesMatch = false;
+       fLeaveMapped = false;
+       fHideSymbols = false;
+       fMatchByInstallName = false;
+       fLibrariesLoaded = false;
+       fBased = false;
+       fBoundAllNonLazy = false;
+       fBoundAllLazy = false;
+       fAnnounced = false;
+       fInitialized = false;
+       fNextAddImageIndex = 0;
+}
+
+
+ImageLoader::ImageLoader(const char* path, uint64_t offsetInFat, const struct stat& info)
+{
+       init(path, offsetInFat, info.st_dev, info.st_ino, info.st_mtime);
+}
+
+ImageLoader::ImageLoader(const char* moduleName)
+{
+       init(moduleName, 0, 0, 0, 0);
+}
+
+
+ImageLoader::~ImageLoader()
+{
+       // need to read up on STL and see if this is right way to destruct vector contents
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               delete seg;
+       }
+       if ( fPath != NULL ) 
+               delete [] fPath;
+       if ( fLogicalPath != NULL ) 
+               delete [] fLogicalPath;
+}
+
+                       
+void ImageLoader::setPath(const char* path)
+{
+       if ( fPath != NULL ) {
+               // if duplicate path, do nothing
+               if ( strcmp(path, fPath) == 0 )
+                       return;
+               delete [] fPath;
+       }
+       fPath = new char[strlen(path)+1];
+       strcpy((char*)fPath, path);
+       fPathHash = hash(fPath);
+}
+
+void ImageLoader::setLogicalPath(const char* path)
+{
+       if ( fPath == NULL ) {
+               // no physical path set yet, so use this path as physical
+               this->setPath(path);
+       }
+       else if ( strcmp(path, fPath) == 0 ) {
+               // do not set logical path because it is the same as the physical path
+               fLogicalPath = NULL;
+       }
+       else {
+               fLogicalPath = new char[strlen(path)+1];
+               strcpy((char*)fLogicalPath, path);
+       }
+}
+
+const char* ImageLoader::getLogicalPath() const
+{
+       if ( fLogicalPath != NULL )
+               return fLogicalPath;
+       else
+               return fPath;
+}
+
+uint32_t ImageLoader::hash(const char* path)
+{
+       // this does not need to be a great hash
+       // it is just used to reduce the number of strcmp() calls
+       // of existing images when loading a new image
+       uint32_t h = 0;
+       for (const char* s=path; *s != '\0'; ++s)
+               h = h*5 + *s;
+       return h;
+}
+
+bool ImageLoader::matchInstallPath() const
+{
+       return fMatchByInstallName;
+}
+
+void ImageLoader::setMatchInstallPath(bool match)
+{
+       fMatchByInstallName = match;
+}
+
+bool ImageLoader::statMatch(const struct stat& stat_buf) const
+{
+       return ( (this->fDevice == stat_buf.st_dev) && (this->fInode == stat_buf.st_ino) );     
+}
+
+const char* ImageLoader::getShortName() const
+{
+       // try to return leaf name
+       if ( fPath != NULL ) {
+               const char* s = strrchr(fPath, '/');
+               if ( s != NULL ) 
+                       return &s[1];
+       }
+       return fPath; 
+}
+
+uint64_t ImageLoader::getOffsetInFatFile() const
+{
+       return fOffsetInFatFile;
+}
+
+void ImageLoader::setLeaveMapped()
+{
+       fLeaveMapped = true;
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               fSegments[i]->setUnMapWhenDestructed(false);
+       }
+}
+
+void ImageLoader::setHideExports(bool hide)
+{
+       fHideSymbols = hide;
+}
+
+bool ImageLoader::hasHiddenExports() const
+{
+       return fHideSymbols;
+}
+
+bool ImageLoader::isLinked() const
+{
+       return fBoundAllNonLazy;
+}
+
+time_t ImageLoader::lastModified()
+{
+       return fLastModified;
+}
+
+bool ImageLoader::containsAddress(const void* addr) const
+{
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               const uint8_t* start = (const uint8_t*)seg->getActualLoadAddress();
+               const uint8_t* end = start + seg->getSize();
+               if ( (start <= addr) && (addr < end) && !seg->unaccessible() )
+                       return true;
+       }
+       return false;
+}
+
+void ImageLoader::addMappedRegions(RegionsVector& regions) const
+{
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               MappedRegion region;
+               region.address = seg->getActualLoadAddress();
+               region.size = seg->getSize();
+               regions.push_back(region);
+       }
+}
+
+
+void ImageLoader::incrementReferenceCount()
+{
+       ++fReferenceCount;
+}
+
+bool ImageLoader::decrementReferenceCount()
+{
+       return ( --fReferenceCount == 0 );
+}
+
+
+const ImageLoader::Symbol* ImageLoader::resolveSymbol(const char* name, bool searchSelf, ImageLoader** foundIn) const
+{
+       const ImageLoader::Symbol* sym;
+       // search self
+       if ( searchSelf ) {
+               sym = this->findExportedSymbol(name, NULL, false, foundIn);
+               if ( sym != NULL )
+                       return sym;
+       }
+
+       // search directly dependent libraries
+       for (uint32_t i=0; i < fLibrariesCount; ++i) {
+               ImageLoader* dependentImage = fLibraries[i].image;
+               if ( dependentImage != NULL ) {
+                       const ImageLoader::Symbol* sym = dependentImage->findExportedSymbol(name, NULL, false, foundIn);
+                       if ( sym != NULL )
+                               return sym;
+               }
+       }
+       
+       // search indirectly dependent libraries
+       for (uint32_t i=0; i < fLibrariesCount; ++i) {
+               ImageLoader* dependentImage = fLibraries[i].image;
+               if ( dependentImage != NULL ) {
+                       const ImageLoader::Symbol* sym = dependentImage->resolveSymbol(name, false, foundIn);
+                       if ( sym != NULL )
+                               return sym;
+               }
+       }
+
+       return NULL;
+}
+
+
+
+void ImageLoader::link(const LinkContext& context, BindingLaziness bindness, InitializerRunning inits, uint32_t notifyCount)
+{
+       uint64_t t1 = mach_absolute_time();
+       this->recursiveLoadLibraries(context);
+       
+       uint64_t t2 = mach_absolute_time();
+       this->recursiveRebase(context);
+       
+       uint64_t t3 = mach_absolute_time();
+       this->recursiveBind(context, bindness);
+       
+       uint64_t t4 = mach_absolute_time();     
+       this->recursiveImageNotification(context, notifyCount); 
+       
+       if ( (inits == kRunInitializers) || (inits == kDontRunInitializersButTellObjc) ) {
+               std::vector<ImageLoader*>       newImages;
+               this->recursiveImageAnnouncement(context, newImages);    // build bottom up list images being added
+               context.notifyAdding(newImages);        // tell gdb or anyone who cares about these
+       }
+       
+       uint64_t t5 = mach_absolute_time();
+       if ( inits == kRunInitializers ) {
+               this->recursiveInitialization(context);
+               uint64_t t6 = mach_absolute_time();
+               fgTotalInitTime += t6 - t5;
+       }
+       fgTotalLoadLibrariesTime += t2 - t1;
+       fgTotalRebaseTime += t3 - t2;
+       fgTotalBindTime += t4 - t3;
+       fgTotalNotifyTime += t5 - t4;
+}
+
+
+// only called pre-main on main executable
+// if crt.c is ever cleaned up, this could go away
+void ImageLoader::runInitializers(const LinkContext& context)
+{
+               std::vector<ImageLoader*>       newImages;
+               this->recursiveImageAnnouncement(context, newImages);    // build bottom up list images being added
+               context.notifyAdding(newImages);        // tell gdb or anyone who cares about these
+
+       this->recursiveInitialization(context);
+}
+
+// called inside _dyld_register_func_for_add_image()
+void ImageLoader::runNotification(const LinkContext& context, uint32_t notifyCount)
+{
+       this->recursiveImageNotification(context, notifyCount);
+}
+
+
+intptr_t ImageLoader::assignSegmentAddresses(const LinkContext& context)
+{
+       // preflight and calculate slide if needed
+       const unsigned int segmentCount = fSegments.size();
+       intptr_t slide = 0;
+       if ( this->segmentsCanSlide() && this->segmentsMustSlideTogether() ) {
+               bool needsToSlide = false;
+               uintptr_t lowAddr = UINTPTR_MAX;
+               uintptr_t highAddr = 0;
+               for(unsigned int i=0; i < segmentCount; ++i){
+                       Segment* seg = fSegments[i];
+                       const uintptr_t segLow = seg->getPreferredLoadAddress();
+                       const uintptr_t segHigh = segLow + seg->getSize();
+                       if ( segLow < lowAddr )
+                               lowAddr = segLow;
+                       if ( segHigh > highAddr )
+                               highAddr = segHigh;
+                               
+                       if ( context.slideAndPackDylibs || !seg->hasPreferredLoadAddress() || !Segment::reserveAddressRange(seg->getPreferredLoadAddress(), seg->getSize()) )
+                               needsToSlide = true;
+               }
+               if ( needsToSlide ) {
+                       // find a chunk of address space to hold all segments
+                       uintptr_t addr = Segment::reserveAnAddressRange(highAddr-lowAddr, context);
+                       slide = addr - lowAddr;
+               }
+       } 
+       else if ( ! this->segmentsCanSlide() ) {
+               for(unsigned int i=0; i < segmentCount; ++i){
+                       Segment* seg = fSegments[i];
+                       if ( strcmp(seg->getName(), "__PAGEZERO") == 0 )
+                               continue;
+                       if ( !Segment::reserveAddressRange(seg->getPreferredLoadAddress(), seg->getSize()) )
+                               throw "can't map";
+               }
+       }
+       else {
+               // mach-o does not support independently sliding segments
+       }
+       return slide;
+}
+
+
+void ImageLoader::mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
+{
+       if ( context.verboseMapping )
+               fprintf(stderr, "dyld: Mapping %s\n", this->getPath());
+       // find address range for image
+       intptr_t slide = this->assignSegmentAddresses(context);
+       // map in all segments
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               seg->map(fd, offsetInFat, slide, context);              
+       }
+       // update slide to reflect load location                        
+       this->setSlide(slide);
+       
+       // now that it is mapped and slide is set, mark that we should unmap it when done
+       for(unsigned int i=0; i < segmentCount; ++i){
+               fSegments[i]->setUnMapWhenDestructed(true);
+       }
+}
+
+void ImageLoader::mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context)
+{
+       if ( context.verboseMapping )
+               fprintf(stderr, "dyld: Mapping memory %p\n", memoryImage);
+       // find address range for image
+       intptr_t slide = this->assignSegmentAddresses(context);
+       // map in all segments
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               seg->map(memoryImage, slide, context);          
+       }
+       // update slide to reflect load location                        
+       this->setSlide(slide);
+       // set R/W permissions on all segments at slide location
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               seg->setPermissions();          
+       }
+}
+
+bool ImageLoader::allDependentLibrariesAsWhenPreBound() const
+{
+       return fAllLibraryChecksumsAndLoadAddressesMatch;
+}
+
+
+void ImageLoader::recursiveLoadLibraries(const LinkContext& context)
+{
+       if ( ! fLibrariesLoaded ) {
+               // break cycles
+               fLibrariesLoaded = true;
+               
+               // get list of libraries this image needs
+               fLibrariesCount = this->doGetDependentLibraryCount();
+               fLibraries = new DependentLibrary[fLibrariesCount];
+               this->doGetDependentLibraries(fLibraries);
+               
+               // try to load each
+               bool canUsePrelinkingInfo = true; 
+               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                       DependentLibrary& requiredLib = fLibraries[i];
+                       try {
+                               requiredLib.image = context.loadLibrary(requiredLib.name, true, this->getPath(), NULL);
+                               if ( requiredLib.image == this ) {
+                                       // found circular reference, perhaps DYLD_LIBARY_PATH is causing this rdar://problem/3684168 
+                                       requiredLib.image = context.loadLibrary(requiredLib.name, false, NULL, NULL);
+                                       if ( requiredLib.image != this )
+                                               fprintf(stderr, "dyld: warning DYLD_ setting caused circular dependency in %s\n", this->getPath());
+                               }
+                               LibraryInfo actualInfo = requiredLib.image->doGetLibraryInfo();
+                               requiredLib.checksumMatches = ( actualInfo.checksum == requiredLib.info.checksum );
+                               // check found library version is compatible
+                               if ( actualInfo.minVersion < requiredLib.info.minVersion ) {
+                                       throwf("Incompatible library version: %s requires version %d.%d.%d or later, but %s provides version %d.%d.%d",
+                                                       this->getShortName(), requiredLib.info.minVersion >> 16, (requiredLib.info.minVersion >> 8) & 0xff, requiredLib.info.minVersion & 0xff,
+                                                       requiredLib.image->getShortName(), actualInfo.minVersion >> 16, (actualInfo.minVersion >> 8) & 0xff, actualInfo.minVersion & 0xff);
+                               }
+                               // prebinding for this image disabled if any dependent library changed or slid
+                               if ( !requiredLib.checksumMatches || (requiredLib.image->getSlide() != 0) )
+                                       canUsePrelinkingInfo = false;
+                               //if ( context.verbosePrebinding ) {
+                               //      if ( !requiredLib.checksumMatches )
+                               //              fprintf(stderr, "dyld: checksum mismatch, (%lld v %lld) for %s referencing %s\n", requiredLib.info.checksum, actualInfo.checksum, this->getPath(),      requiredLib.image->getPath());          
+                               //      if ( requiredLib.image->getSlide() != 0 )
+                               //              fprintf(stderr, "dyld: dependent library slid for %s referencing %s\n", this->getPath(), requiredLib.image->getPath());         
+                               //}
+                       }
+                       catch (const char* msg) {
+                               //if ( context.verbosePrebinding )
+                               //      fprintf(stderr, "dyld: exception during processing for %s referencing %s\n", this->getPath(), requiredLib.image->getPath());            
+                               if ( requiredLib.required ) {
+                                       const char* formatString = "Library not loaded: %s\n  Referenced from: %s\n  Reason: %s";
+                                       const char* referencedFrom = this->getPath();
+                                       char buf[strlen(requiredLib.name)+strlen(referencedFrom)+strlen(formatString)+strlen(msg)+2];
+                                       sprintf(buf, formatString, requiredLib.name, referencedFrom, msg);
+                                       throw strdup(buf);  // this is a leak if exception doesn't halt program
+                               }
+                               // ok if weak library not found
+                               requiredLib.image = NULL;
+                               canUsePrelinkingInfo = false;  // this disables all prebinding, we may want to just slam import vectors for this lib to zero
+                       }
+               }
+               fAllLibraryChecksumsAndLoadAddressesMatch = canUsePrelinkingInfo;
+
+               // tell each to load its dependents
+               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                       DependentLibrary& libInfo = fLibraries[i];
+                       if ( libInfo.image != NULL ) {  
+                               libInfo.isSubFramework = libInfo.image->isSubframeworkOf(context, this);
+                               libInfo.isReExported = libInfo.isSubFramework || this->hasSubLibrary(context, libInfo.image);
+                               //if ( libInfo.isReExported  )
+                               //      fprintf(stderr, "%s re-exports %s\n", strrchr(this->getPath(), '/'), strrchr(libInfo.image->getPath(),'/'));
+                               libInfo.image->recursiveLoadLibraries(context);
+                       }
+               }
+               
+               // do deep prebind check
+               if ( fAllLibraryChecksumsAndLoadAddressesMatch ) {
+                       for(unsigned int i=0; i < fLibrariesCount; ++i){
+                               const DependentLibrary& libInfo = fLibraries[i];
+                               if ( libInfo.image != NULL ) {
+                                       if ( !libInfo.image->allDependentLibrariesAsWhenPreBound() )
+                                               fAllLibraryChecksumsAndLoadAddressesMatch = false;
+                               }
+                       }
+               }
+               
+       }
+}
+
+void ImageLoader::recursiveRebase(const LinkContext& context)
+{ 
+       if ( ! fBased ) {
+               // break cycles
+               fBased = true;
+               
+               try {
+                       // rebase lower level libraries first
+                       for(unsigned int i=0; i < fLibrariesCount; ++i){
+                               DependentLibrary& libInfo = fLibraries[i];
+                               if ( libInfo.image != NULL )
+                                       libInfo.image->recursiveRebase(context);
+                       }
+                               
+                       // rebase this image
+                       doRebase(context);
+               }
+               catch (const char* msg) {
+                       // this image is not rebased
+                       fBased = false;
+                       throw msg;
+               }
+       }
+}
+
+
+
+
+void ImageLoader::recursiveBind(const LinkContext& context, BindingLaziness bindness)
+{
+       // normally just non-lazy pointers are bound up front,
+       // but DYLD_BIND_AT_LAUNCH will cause lazy pointers to be bound up from
+       // and some dyld API's bind all lazys at runtime
+       bool nonLazy = false;
+       bool lazy = false;
+       switch( bindness ) {
+               case kNonLazyOnly:
+                       nonLazy = true;
+                       break;
+               case kLazyAndNonLazy:
+                       nonLazy = true;
+                       lazy = true;
+                       break;
+               case kLazyOnly:
+               case kLazyOnlyNoDependents:
+                       lazy = true;
+                       break;
+       }
+       const bool doNonLazy = nonLazy && !fBoundAllNonLazy;
+       const bool doLazy = lazy && !fBoundAllLazy;
+       if ( doNonLazy || doLazy ) {
+               // break cycles
+               bool oldBoundAllNonLazy = fBoundAllNonLazy;
+               bool oldBoundAllLazy = fBoundAllLazy;
+               fBoundAllNonLazy = fBoundAllNonLazy || nonLazy;
+               fBoundAllLazy = fBoundAllLazy || lazy;
+               
+               try {
+                       // bind lower level libraries first
+                       if ( bindness != kLazyOnlyNoDependents ) {
+                               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                                       DependentLibrary& libInfo = fLibraries[i];
+                                       if ( libInfo.image != NULL )
+                                               libInfo.image->recursiveBind(context, bindness);
+                               }
+                       }
+                       // bind this image
+                       if ( doLazy && !doNonLazy )
+                               doBind(context, kLazyOnly);     
+                       else if ( !doLazy && doNonLazy )
+                               doBind(context, kNonLazyOnly);
+                       else 
+                               doBind(context, kLazyAndNonLazy);
+               }
+               catch (const char* msg) {
+                       // restore state
+                       fBoundAllNonLazy = oldBoundAllNonLazy;
+                       fBoundAllLazy = oldBoundAllLazy;
+                       throw msg;
+               }
+       }
+}
+
+//
+// This is complex because _dyld_register_func_for_add_image() is defined to not only
+// notify you of future image loads, but also of all currently loaded images.  Therefore
+// each image needs to track that all add-image-funcs have been notified about it.
+// Since add-image-funcs cannot be removed, each has a unique index and each image
+// records the thru which index notificiation has already been done.
+//
+void ImageLoader::recursiveImageNotification(const LinkContext& context, uint32_t addImageCount)
+{
+       if ( fNextAddImageIndex < addImageCount ) {
+               // break cycles
+               const uint32_t initIndex = fNextAddImageIndex;
+               fNextAddImageIndex = addImageCount;
+       
+               // notify all requestors about this image
+               context.imageNotification(this, initIndex);
+       
+               // notify about lower level libraries first
+               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                       DependentLibrary& libInfo = fLibraries[i];
+                       if ( libInfo.image != NULL )
+                               libInfo.image->recursiveImageNotification(context, addImageCount);
+               }
+       }
+}
+
+
+void ImageLoader::recursiveImageAnnouncement(const LinkContext& context, std::vector<ImageLoader*>& newImages)
+{
+       if ( ! fAnnounced ) {
+               // break cycles
+               fAnnounced = true;
+               
+               // announce lower level libraries first
+               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                       DependentLibrary& libInfo = fLibraries[i];
+                       if ( libInfo.image != NULL )
+                               libInfo.image->recursiveImageAnnouncement(context, newImages);
+               }
+               
+               // add to list of images to notify gdb about
+               newImages.push_back(this);
+               //fprintf(stderr, "next size = %d\n", newImages.size());
+               
+               // remember that this image wants to be notified about other images
+                if ( this->hasImageNotification() )
+                       context.addImageNeedingNotification(this);
+       }
+}
+
+
+
+void ImageLoader::recursiveInitialization(const LinkContext& context)
+{
+       if ( ! fInitialized ) {
+               // break cycles
+               fInitialized = true;
+
+               try {
+                       // initialize lower level libraries first
+                       for(unsigned int i=0; i < fLibrariesCount; ++i){
+                               DependentLibrary& libInfo = fLibraries[i];
+                               if ( libInfo.image != NULL )
+                                       libInfo.image->recursiveInitialization(context);
+                       }
+                       
+                       // record termination order
+                       if ( this->needsTermination() )
+                               context.terminationRecorder(this);
+                       
+                       // initialize this image
+                       this->doInitialization(context);
+               }
+               catch (const char* msg) {
+                       // this image is not initialized
+                       fInitialized = false;
+                       throw msg;
+               }
+       }
+}
+
+void ImageLoader::reprebindCommit(const LinkContext& context, bool commit)
+{
+       // do nothing on unprebound images
+       if ( ! this->isPrebindable() )
+               return;
+
+       // do nothing if prebinding is up to date
+       if ( this->usablePrebinding(context) )
+               return;
+               
+       // make sure we are not replacing a symlink with a file
+       char realFilePath[PATH_MAX];
+       if ( realpath(this->getPath(), realFilePath) == NULL ) {
+               throwf("realpath() failed on %s, errno=%d", this->getPath(), errno);
+       }
+       // recreate temp file name
+       char tempFilePath[PATH_MAX];
+       ImageLoader::addSuffix(realFilePath, "_redoprebinding", tempFilePath);
+
+       if ( commit ) {
+               // all files successfully reprebound, so do swap
+               int result = rename(tempFilePath, realFilePath);
+               if ( result != 0 ) {
+                       // if there are two dylibs with the same install path, the second will fail to prebind
+                       // because the _redoprebinding temp file is gone.  In that case, log and go on.
+                       if ( errno == ENOENT )
+                               fprintf(stderr, "update_prebinding: temp file missing: %s\n", tempFilePath);
+                       else
+                               throwf("can't swap temporary re-prebound file: rename(%s,%s) returned errno=%d", tempFilePath, realFilePath, errno);
+               }
+       }
+       else {
+               // something went wrong during prebinding, delete the temp files
+               unlink(tempFilePath);
+       }
+}
+
+void ImageLoader::reprebind(const LinkContext& context, time_t timestamp)
+{
+       // do nothing on unprebound images
+       if ( ! this->isPrebindable() )
+               return;
+
+       // do nothing if prebinding is up to date
+       if ( this->usablePrebinding(context) ) {
+               if ( context.verbosePrebinding )
+                       fprintf(stderr, "dyld: no need to re-prebind: %s\n", this->getPath());
+               return;
+       }
+       // make copy of file and map it in
+       char tempFilePath[PATH_MAX];
+       realpath(this->getPath(), tempFilePath);
+       ImageLoader::addSuffix(this->getPath(), "_redoprebinding", tempFilePath);
+       uint8_t* fileToPrebind;
+       uint64_t fileToPrebindSize;
+       this->copyAndMap(tempFilePath, &fileToPrebind, &fileToPrebindSize);
+
+       // do format specific prebinding
+       this->doPrebinding(context, timestamp, fileToPrebind);
+       
+       // flush and swap files
+       int result = msync(fileToPrebind, fileToPrebindSize, MS_ASYNC);
+       if ( result != 0 )
+               throw "error syncing re-prebound file";
+       result = munmap(fileToPrebind, fileToPrebindSize);
+       if ( result != 0 )
+               throw "error unmapping re-prebound file";
+
+       // log
+       if ( context.verbosePrebinding )
+               fprintf(stderr, "dyld: re-prebound: %s\n", this->getPath());
+}
+
+void ImageLoader::copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize)
+{
+       // reopen dylib 
+       int src = open(this->getPath(), O_RDONLY);      
+       if ( src == -1 )
+               throw "can't open image";
+       struct stat stat_buf;
+       if ( fstat(src, &stat_buf) == -1)
+               throw "can't stat image";
+       if ( stat_buf.st_mtime != fLastModified )
+               throw "image file changed since it was loaded";
+               
+       // create new file with all same permissions to hold copy of dylib 
+       unlink(tempFile);
+       int dst = open(tempFile, O_CREAT | O_RDWR | O_TRUNC, stat_buf.st_mode); 
+       if ( dst == -1 )
+               throw "can't create temp image";
+       
+       // mark source as "don't cache"
+       (void)fcntl(src, F_NOCACHE, 1);
+       // we want to cache the dst because we are about to map it in and modify it
+       
+       // copy permission bits
+       if ( chmod(tempFile, stat_buf.st_mode & 07777) == -1 )
+               throw "can't chmod temp image";
+       if ( chown(tempFile, stat_buf.st_uid, stat_buf.st_gid) == -1)
+               throw "can't chown temp image";
+                 
+       // copy contents
+       ssize_t len;
+       const uint32_t kBufferSize = 128*1024;
+       static uint8_t* buffer = NULL;
+       if ( buffer == NULL ) {
+               vm_address_t addr = 0;
+               if ( vm_allocate(mach_task_self(), &addr, kBufferSize, true /*find range*/) == KERN_SUCCESS )
+                       buffer = (uint8_t*)addr;
+               else
+                       throw "can't allcoate copy buffer";
+       }
+       while ( (len = read(src, buffer, kBufferSize)) > 0 ) {
+               write(dst, buffer, len);
+       }
+       
+       // map in dst file
+       *fileToPrebindSize = stat_buf.st_size - fOffsetInFatFile; // this may map in too much, but it does not matter
+       *fileToPrebind = (uint8_t*)mmap(NULL, *fileToPrebindSize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, dst, fOffsetInFatFile);
+       if ( *fileToPrebind == (uint8_t*)(-1) )
+               throw "can't mmap temp image";
+               
+       // closing notes:  
+       //              ok to close file after mapped in
+       //              ok to throw above without closing file because the throw will terminate update_prebinding
+       int result1 = close(dst);
+       int result2 = close(src);
+       if ( (result1 != 0) || (result2 != 0) )
+               throw "can't close file";
+}
+
+
+static void printTime(const char* msg, uint64_t partTime, uint64_t totalTime)
+{
+       static uint64_t sUnitsPerSecond = 0;
+       if ( sUnitsPerSecond == 0 ) {
+               struct mach_timebase_info timeBaseInfo;
+               if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
+                       sUnitsPerSecond = timeBaseInfo.denom;
+               }
+       }
+       if ( partTime < sUnitsPerSecond ) {
+               uint32_t milliSecondsTimeTen = (partTime*10000)/sUnitsPerSecond;
+               uint32_t milliSeconds = milliSecondsTimeTen/10;
+               uint32_t percentTimesTen = (partTime*1000)/totalTime;
+               uint32_t percent = percentTimesTen/10;
+               fprintf(stderr, "%s: %u.%u milliseconds (%u.%u%%)\n", msg, milliSeconds, milliSecondsTimeTen-milliSeconds*10, percent, percentTimesTen-percent*10);
+       }
+       else {
+               uint32_t secondsTimeTen = (partTime*10)/sUnitsPerSecond;
+               uint32_t seconds = secondsTimeTen/100;
+               uint32_t percentTimesTen = (partTime*1000)/totalTime;
+               uint32_t percent = percentTimesTen/10;
+               fprintf(stderr, "%s: %u.%u seconds (%u.%u%%)\n", msg, seconds, secondsTimeTen-seconds*10, percent, percentTimesTen-percent*10);
+       }
+}
+
+static char* commatize(uint64_t in, char* out)
+{
+       char* result = out;
+       char rawNum[30];
+       sprintf(rawNum, "%llu", in);
+       const int rawNumLen = strlen(rawNum);
+       for(int i=0; i < rawNumLen-1; ++i) {
+               *out++ = rawNum[i];
+               if ( ((rawNumLen-i) % 3) == 1 )
+                       *out++ = ',';
+       }
+       *out++ = rawNum[rawNumLen-1];
+       *out = '\0';
+       return result;
+} 
+
+
+void ImageLoader::printStatistics(unsigned int imageCount)
+{
+       uint64_t totalTime = fgTotalLoadLibrariesTime + fgTotalRebaseTime + fgTotalBindTime + fgTotalNotifyTime + fgTotalInitTime;
+       char commaNum1[40];
+       char commaNum2[40];
+
+       printTime("total time", totalTime, totalTime);
+       fprintf(stderr, "total images loaded:  %d (%d used prebinding)\n", imageCount, fgImagesWithUsedPrebinding);
+       printTime("total images loading time", fgTotalLoadLibrariesTime, totalTime);
+       fprintf(stderr, "total rebase fixups:  %s\n", commatize(fgTotalRebaseFixups, commaNum1));
+       printTime("total rebase fixups time", fgTotalRebaseFixups, totalTime);
+       fprintf(stderr, "total binding fixups: %s\n", commatize(fgTotalBindFixups, commaNum1));
+       printTime("total binding fixups time", fgTotalBindTime, totalTime);
+       fprintf(stderr, "total bindings lazily fixed up: %s of %s\n", commatize(fgTotalLazyBindFixups, commaNum1), commatize(fgTotalPossibleLazyBindFixups, commaNum2));
+       printTime("total notify time time", fgTotalNotifyTime, totalTime);
+       printTime("total init time time", fgTotalInitTime, totalTime);
+}
+
+
+//
+// copy path and add suffix to result
+//
+//  /path/foo.dylib            _debug   =>   /path/foo_debug.dylib     
+//  foo.dylib                  _debug   =>   foo_debug.dylib
+//  foo                        _debug   =>   foo_debug
+//  /path/bar                  _debug   =>   /path/bar_debug  
+//  /path/bar.A.dylib   _debug   =>   /path/bar.A_debug.dylib
+//
+void ImageLoader::addSuffix(const char* path, const char* suffix, char* result)
+{
+       strcpy(result, path);
+       
+       char* start = strrchr(result, '/');
+       if ( start != NULL )
+               start++;
+       else
+               start = result;
+               
+       char* dot = strrchr(start, '.');
+       if ( dot != NULL ) {
+               strcpy(dot, suffix);
+               strcat(&dot[strlen(suffix)], &path[dot-result]);
+       }
+       else {
+               strcat(result, suffix);
+       }
+}
+
+
+void Segment::map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader::LinkContext& context)
+{
+       vm_offset_t fileOffset = this->getFileOffset() + offsetInFatWrapper;
+       vm_size_t size = this->getFileSize();
+       void* requestedLoadAddress = (void*)(this->getPreferredLoadAddress() + slide);
+       int protection = 0;
+       if ( !this->unaccessible() ) {
+               if ( this->executable() )
+                       protection   |= PROT_EXEC;
+               if ( this->readable() )
+                       protection   |= PROT_READ;
+               if ( this->writeable() )
+                       protection   |= PROT_WRITE;
+       }
+       void* loadAddress = mmap(requestedLoadAddress, size, protection, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd, fileOffset);
+       if ( loadAddress == ((void*)(-1)) )
+               throwf("mmap() error %d at address=0x%08lX, size=0x%08lX in Segment::map() mapping %s", errno, (uintptr_t)requestedLoadAddress, (uintptr_t)size, this->getImage()->getPath());
+       
+       if ( context.verboseMapping )
+               fprintf(stderr, "%18s at %p->%p\n", this->getName(), loadAddress, (char*)loadAddress+this->getFileSize()-1);
+}
+
+void Segment::map(const void* memoryImage, intptr_t slide, const ImageLoader::LinkContext& context)
+{
+       vm_address_t loadAddress = this->getPreferredLoadAddress() + slide;
+       vm_address_t srcAddr = (uintptr_t)memoryImage + this->getFileOffset();
+       vm_size_t size = this->getFileSize();
+       kern_return_t r = vm_copy(mach_task_self(), srcAddr, size, loadAddress);
+       if ( r != KERN_SUCCESS ) 
+               throw "can't map segment";
+               
+       if ( context.verboseMapping )
+               fprintf(stderr, "%18s at %p->%p\n", this->getName(), (char*)loadAddress, (char*)loadAddress+this->getFileSize()-1);
+}
+
+void Segment::setPermissions()
+{
+       vm_prot_t protection = 0;
+       if ( !this->unaccessible() ) {
+               if ( this->executable() )
+                       protection   |= VM_PROT_EXECUTE;
+               if ( this->readable() )
+                       protection   |= VM_PROT_READ;
+               if ( this->writeable() )
+                       protection   |= VM_PROT_WRITE;
+       }
+       vm_address_t addr = this->getActualLoadAddress();
+       vm_size_t size = this->getSize();
+       const bool setCurrentPermissions = false;
+       kern_return_t r = vm_protect(mach_task_self(), addr, size, setCurrentPermissions, protection);
+       if ( r != KERN_SUCCESS ) 
+               throw "can't set vm permissions for mapped segment";
+}      
+
+void Segment::tempWritable()
+{
+       vm_address_t addr = this->getActualLoadAddress();
+       vm_size_t size = this->getSize();
+       const bool setCurrentPermissions = false;
+       kern_return_t r = vm_protect(mach_task_self(), addr, size, setCurrentPermissions, VM_PROT_WRITE | VM_PROT_READ);
+       if ( r != KERN_SUCCESS ) 
+               throw "can't set vm permissions for mapped segment";
+}
+
+
+bool Segment::hasTrailingZeroFill()
+{
+       return ( this->writeable() && (this->getSize() > this->getFileSize()) );
+}
+
+
+uintptr_t Segment::reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context)
+{
+       vm_address_t addr = 0;
+       vm_size_t size = length;
+       if ( context.slideAndPackDylibs ) {
+               addr = (fgNextNonSplitSegAddress - length) & (-4096); // page align
+               kern_return_t r = vm_allocate(mach_task_self(), &addr, size, false /*use this range*/);
+               if ( r != KERN_SUCCESS ) 
+                       throw "out of address space";
+               fgNextNonSplitSegAddress = addr;
+       }
+       else {
+               kern_return_t r = vm_allocate(mach_task_self(), &addr, size, true /*find range*/);
+               if ( r != KERN_SUCCESS ) 
+                       throw "out of address space";
+       }
+       return addr;
+}
+
+bool Segment::reserveAddressRange(uintptr_t start, size_t length)
+{
+       vm_address_t addr = start;
+       vm_size_t size = length;
+       kern_return_t r = vm_allocate(mach_task_self(), &addr, size, false /*only this range*/);
+       if ( r != KERN_SUCCESS ) 
+               return false;
+       return true;
+}
+
+
+
diff --git a/src/ImageLoader.h b/src/ImageLoader.h
new file mode 100644 (file)
index 0000000..609c222
--- /dev/null
@@ -0,0 +1,460 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 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 __IMAGELOADER__
+#define __IMAGELOADER__
+
+#include <sys/types.h>
+#include <mach/mach_time.h> // struct mach_timebase_info
+#include <stdint.h>
+#include <vector>
+
+#include "mach-o/dyld_gdb.h"
+
+
+// utility
+__attribute__((noreturn)) void throwf(const char* format, ...);
+
+//
+// ImageLoader is an abstract base class.  To support loading a particular executable
+// file format, you make a concrete subclass of ImageLoader.
+//
+// For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
+//
+// The ImageLoader base class does the work of linking together images, but it knows nothing
+// about any particular file format.
+//
+//
+class ImageLoader {
+public:
+
+       typedef uint32_t DefinitionFlags;
+       static const DefinitionFlags kNoDefinitionOptions = 0;
+       static const DefinitionFlags kWeakDefinition = 1;
+       
+       typedef uint32_t ReferenceFlags;
+       static const ReferenceFlags kNoReferenceOptions = 0;
+       static const ReferenceFlags kWeakReference = 1;
+       static const ReferenceFlags kTentativeDefinition = 2;
+       
+
+       enum BindingLaziness { kNonLazyOnly, kLazyAndNonLazy, kLazyOnly, kLazyOnlyNoDependents };
+       enum InitializerRunning { kDontRunInitializers, kRunInitializers, kDontRunInitializersButTellObjc };
+       enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding };
+       enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers };
+       enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion };
+       
+       struct Symbol;  // abstact symbol
+
+       struct MappedRegion {
+               uintptr_t       address;
+               size_t          size;
+       };
+       typedef std::vector<MappedRegion> RegionsVector;
+
+       struct LinkContext {
+               ImageLoader*    (*loadLibrary)(const char* libraryName, bool search, const char* origin, const char* rpath[]);
+               uint32_t                (*imageNotification)(ImageLoader* image, uint32_t startIndex);
+               void                    (*terminationRecorder)(ImageLoader* image);
+               bool                    (*flatExportFinder)(const char* name, const Symbol** sym, ImageLoader** image);
+               bool                    (*coalescedExportFinder)(const char* name, const Symbol** sym, ImageLoader** image);
+               void                    (*undefinedHandler)(const char* name);
+               void                    (*addImageNeedingNotification)(ImageLoader* image);
+               void                    (*notifyAdding)(std::vector<ImageLoader*>& images);
+               void                    (*getAllMappedRegions)(RegionsVector&);
+               void *                  (*bindingHandler)(const char *, const char *, void *);
+               BindingOptions  bindingOptions;
+               int                             argc;
+               const char**    argv;
+               const char**    envp;
+               const char**    apple;
+               ImageLoader*    mainExecutable;
+               const char*             imageSuffix;
+               PrebindMode             prebindUsage;
+               SharedRegionMode sharedRegionMode;
+               bool                    bindFlat;
+               bool                    slideAndPackDylibs;
+               bool                    verboseOpts;
+               bool                    verboseEnv;
+               bool                    verboseMapping;
+               bool                    verboseRebase;
+               bool                    verboseBind;
+               bool                    verboseInit;
+               bool                    verbosePrebinding;
+               bool                    verboseWarnings;
+       };
+       
+                                                                               // constructor is protected, but anyone can delete an image
+       virtual                                                         ~ImageLoader();
+       
+                                                                               // link() takes a newly instantiated ImageLoader and does all 
+                                                                               // fixups needed to make it usable by the process
+       void                                                            link(const LinkContext& context, BindingLaziness mode, InitializerRunning inits, uint32_t notifyCount);
+       
+                                                                               // runInitializers() is normally called in link() but the main executable must 
+                                                                               // run crt code before initializers
+       void                                                            runInitializers(const LinkContext& context);
+       
+                                                                               // runNotification() is normally called in link() but the main executable must 
+                                                                               // run crt code before initializers
+       void                                                            runNotification(const LinkContext& context, uint32_t notifyCount);
+               
+                                                                               // used by dyld to see if a requested library is already loaded (might be symlink)
+       bool                                                            statMatch(const struct stat& stat_buf) const;
+
+                                                                               // get short name of this image
+       const char*                                                     getShortName() const;
+
+                                                                               // get path used to load this image, not necessarily the "real" path
+       const char*                                                     getPath() const { return fPath; }
+
+       uint32_t                                                        getPathHash() const { return fPathHash; }
+
+                                                                               // get path used to load this image represents (ZeroLink only) which image this .o is part of
+       const char*                                                     getLogicalPath() const;
+
+                                                                               // get path this image is intended to be placed on disk or NULL if no preferred install location
+       virtual const char*                                     getInstallPath() const = 0;
+
+                                                                               // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path 
+       bool                                                            matchInstallPath() const;
+       void                                                            setMatchInstallPath(bool);
+       
+                                                                               // if path was a fat file, offset of image loaded in that fat file
+       uint64_t                                                        getOffsetInFatFile() const;
+
+                                                                               // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
+       void                                                            setHideExports(bool hide = true);
+       
+                                                                               // check if this image's exported symbols should be ignored when linking other images 
+       bool                                                            hasHiddenExports() const;
+       
+                                                                               // checks if this image is already linked into the process
+       bool                                                            isLinked() const;
+       
+                                                                               // even if image is deleted, leave segments mapped in
+       void                                                            setLeaveMapped();
+       
+                                                                               // checks if the specifed address is within one of this image's segments
+       virtual bool                                            containsAddress(const void* addr) const;
+
+                                                                               // adds to list of ranges of memory mapped in
+       void                                                            addMappedRegions(RegionsVector& regions) const;
+
+                                                                               // st_mtime from stat() on file
+       time_t                                                          lastModified();
+
+                                                                               // image should create prebound version of itself
+       void                                                            reprebind(const LinkContext& context, time_t timestamp);
+       
+                                                                               // if 'commit', the prebound version should be swapped in, otherwise deleted
+       void                                                            reprebindCommit(const LinkContext& context, bool commit);
+       
+                                                                               // only valid for main executables, returns a pointer its entry point
+       virtual void*                                           getMain() const = 0;
+       
+                                                                               // dyld API's require each image to have an associated mach_header
+       virtual const struct mach_header*   machHeader() const = 0;
+       
+                                                                               // dyld API's require each image to have a slide (actual load address minus preferred load address)
+       virtual uintptr_t                                       getSlide() const = 0;
+       
+                                                                               // dyld API's require each image to have a slide (actual load address minus preferred load address)
+       virtual const void*                                     getBaseAddress() const = 0;
+       
+                                                                               // image has exports that participate in runtime coalescing
+       virtual bool                                            hasCoalescedExports() const = 0;
+       
+                                                                               // search symbol table of definitions in this image for requested name
+       virtual const Symbol*                           findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const = 0;
+       
+                                                                               // gets address of implementation (code) of the specified exported symbol
+       virtual uintptr_t                                       getExportedSymbolAddress(const Symbol* sym) const = 0;
+       
+                                                                               // gets attributes of the specified exported symbol
+       virtual DefinitionFlags                         getExportedSymbolInfo(const Symbol* sym) const = 0;
+       
+                                                                               // gets name of the specified exported symbol
+       virtual const char*                                     getExportedSymbolName(const Symbol* sym) const = 0;
+       
+                                                                               // gets how many symbols are exported by this image
+       virtual uint32_t                                        getExportedSymbolCount() const = 0;
+                       
+                                                                               // gets the i'th exported symbol
+       virtual const Symbol*                           getIndexedExportedSymbol(uint32_t index) const = 0;
+                       
+                                                                               // find exported symbol as if imported by this image
+                                                                               // used by RTLD_NEXT and RTLD_SELF
+       virtual const Symbol*                           resolveSymbol(const char* name, bool searchSelf, ImageLoader** foundIn) const;
+       
+                                                                               // gets how many symbols are imported by this image
+       virtual uint32_t                                        getImportedSymbolCount() const = 0;
+       
+                                                                               // gets the i'th imported symbol
+       virtual const Symbol*                           getIndexedImportedSymbol(uint32_t index) const = 0;
+                       
+                                                                               // gets attributes of the specified imported symbol
+       virtual ReferenceFlags                          geImportedSymbolInfo(const Symbol* sym) const = 0;
+                       
+                                                                               // gets name of the specified imported symbol
+       virtual const char*                                     getImportedSymbolName(const Symbol* sym) const = 0;
+                       
+                                                                               // checks if this image is a bundle and can be loaded but not linked
+       virtual bool                                            isBundle() const = 0;
+       
+                                                                               // checks if this image is a dylib 
+       virtual bool                                            isDylib() const = 0;
+       
+                                                                               // only for main executable
+       virtual bool                                            forceFlat() const = 0;
+       
+                                                                               // called at runtime when a lazily bound function is first called
+       virtual uintptr_t                                       doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
+       
+                                                                               // calls termination routines (e.g. C++ static destructors for image)
+       virtual void                                            doTermination(const LinkContext& context) = 0;
+                                       
+                                                                               // tell this image about other images
+       virtual void                                            doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]) = 0;
+                                       
+                                                                               // return if this image has initialization routines
+       virtual bool                                            needsInitialization() = 0;
+                       
+                                                                               // return if this image has a routine to be called when any image is loaded or unloaded
+       virtual bool                                            hasImageNotification() = 0;
+       
+                                                                               // return if this image has specified section and set start and length
+       virtual bool                                            getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
+                       
+                                                                               // given a pointer into an image, find which segment and section it is in
+       virtual bool                                            findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
+       
+                                                                               // the image supports being prebound
+       virtual bool                                            isPrebindable() const = 0;
+       
+                                                                               // the image is prebindable and its prebinding is valid
+       virtual bool                                            usablePrebinding(const LinkContext& context) const = 0;
+       
+                                                                               // used to implement refernce counting of images
+       void                                                            incrementReferenceCount();
+       bool                                                            decrementReferenceCount();
+
+                                                                               // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
+       static void                                                     printStatistics(unsigned int imageCount);
+                               
+                                                                               // used with DYLD_IMAGE_SUFFIX
+       static void                                                     addSuffix(const char* path, const char* suffix, char* result);
+       
+       static uint32_t                                         hash(const char*);
+       
+       
+                       void                                            setPath(const char* path);      // only called for images created from memory
+                       void                                            setLogicalPath(const char* path);
+                       
+               
+protected:
+       // abstract base class so all constructors protected
+                                       ImageLoader(const char* path, uint64_t offsetInFat, const struct stat& info); 
+                                       ImageLoader(const char* moduleName); 
+                                       ImageLoader(const ImageLoader&);
+       void                    operator=(const ImageLoader&);
+       
+
+       struct LibraryInfo {
+               uint64_t                checksum;
+               uint32_t                minVersion;
+               uint32_t                maxVersion;
+       };
+
+       struct DependentLibrary {
+               const char*             name;
+               ImageLoader*    image;
+               LibraryInfo             info;
+               bool                    required;
+               bool                    checksumMatches;
+               bool                    isReExported;
+               bool                    isSubFramework;
+       };
+       
+       typedef void (*Initializer)(int argc, const char* argv[], const char* envp[],const char* apple[]);
+       typedef void (*Terminator)(void);
+       
+                                               // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
+                                               // These methods do the above, exactly once, and it the right order
+       void                            recursiveLoadLibraries(const LinkContext& context);
+       void                            recursiveRebase(const LinkContext& context);
+       void                            recursiveBind(const LinkContext& context, BindingLaziness bindness);
+       void                            recursiveImageAnnouncement(const LinkContext& context, std::vector<ImageLoader*>& newImages);
+       void                            recursiveImageNotification(const LinkContext& context, uint32_t addImageCount);
+       void                            recursiveInitialization(const LinkContext& context);
+
+                                                               // map any segments this image has into memory and build fSegments
+                                                               // this is called before doGetDependentLibraryCount so if metadata is in segments it is mapped in
+       virtual void                            instantiateSegments(const uint8_t* fileData) = 0;
+       
+                                                               // return how many libraries this image depends on
+       virtual uint32_t                        doGetDependentLibraryCount() = 0;
+       
+                                                               // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
+       virtual void                            doGetDependentLibraries(DependentLibrary libs[]) = 0;
+       
+                                                               // called on images that are libraries, returns info about itself
+       virtual LibraryInfo                     doGetLibraryInfo() = 0;
+       
+                                                               // do any fix ups in this image that depend only on the load address of the image
+       virtual void                            doRebase(const LinkContext& context) = 0;
+       
+                                                               // do any symbolic fix ups in this image
+       virtual void                            doBind(const LinkContext& context, BindingLaziness bindness) = 0;
+       
+                                                               // run any initialization routines in this image
+       virtual void                            doInitialization(const LinkContext& context) = 0;
+       
+                                                               // write prebinding updates to mapped file fileToPrebind
+       virtual void                            doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind) = 0;
+
+                                                               // return if this image has termination routines
+       virtual bool                            needsTermination() = 0;
+       
+                                                               // support for runtimes in which segments don't have to maintain their relative positions
+       virtual bool                            segmentsMustSlideTogether() const = 0;  
+       
+                                                               // built with PIC code and can load at any address
+       virtual bool                            segmentsCanSlide() const = 0;           
+       
+                                                               // set how much all segments slide
+       virtual void                            setSlide(intptr_t slide) = 0;           
+       
+                                                               // utility routine to map in all segements in fSegments from a file
+       virtual void                            mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+       
+                                                               // utility routine to map in all segements in fSegments from a memory image
+       virtual void                            mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context);
+
+                                                               // returns if all dependent libraries checksum's were as expected and none slide
+                       bool                            allDependentLibrariesAsWhenPreBound() const;
+
+                                                               // in mach-o a child tells it parent to re-export, instead of the other way around...
+       virtual bool                            isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
+
+                                                               // in mach-o a parent library knows name of sub libraries it re-exports..
+       virtual bool                            hasSubLibrary(const LinkContext& context, const ImageLoader* child) const  = 0;
+       
+       static uint32_t                         fgImagesWithUsedPrebinding;
+       static uint32_t                         fgTotalRebaseFixups;
+       static uint32_t                         fgTotalBindFixups;
+       static uint32_t                         fgTotalLazyBindFixups;
+       static uint32_t                         fgTotalPossibleLazyBindFixups;
+       static uint64_t                         fgTotalLoadLibrariesTime;
+       static uint64_t                         fgTotalRebaseTime;
+       static uint64_t                         fgTotalBindTime;
+       static uint64_t                         fgTotalNotifyTime;
+       static uint64_t                         fgTotalInitTime;
+       static uintptr_t                        fgNextSplitSegAddress;
+       const char*                                     fPath;
+       const char*                                     fLogicalPath; // for ZeroLink - the image which this bundle is part of
+       dev_t                                           fDevice;
+       ino_t                                           fInode;
+       time_t                                          fLastModified;
+       uint64_t                                        fOffsetInFatFile;
+       std::vector<class Segment*> fSegments;
+       DependentLibrary*                       fLibraries;
+       uint32_t                                        fLibrariesCount;
+       uint32_t                                        fPathHash;
+       uint32_t                                        fReferenceCount;
+       bool                                            fAllLibraryChecksumsAndLoadAddressesMatch;
+       bool                                            fLeaveMapped;           // when unloaded, leave image mapped in cause some other code may have pointers into it
+
+
+private:
+       void                                            init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate);
+       intptr_t                                        assignSegmentAddresses(const LinkContext& context);
+       void                                            copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize);
+
+
+       bool                                            fHideSymbols;           // ignore this image's exported symbols when linking other images
+       bool                                            fMatchByInstallName;// look at image's install-path not its load path
+       bool                                            fLibrariesLoaded;
+       bool                                            fBased;
+       bool                                            fBoundAllNonLazy;
+       bool                                            fBoundAllLazy;
+       bool                                            fAnnounced;
+       bool                                            fInitialized;
+       uint16_t                                        fNextAddImageIndex;
+};
+
+
+//
+// Segment is an abstract base class.  A segment is a chunk of an executable
+// file that is mapped into memory.  Each subclass of ImageLoader typically
+// implements its own concrete subclass of Segment.
+//
+//  
+class Segment {
+public:
+       virtual                                         ~Segment() {}
+
+       virtual const ImageLoader*      getImage() = 0;
+       virtual const char*                     getName() = 0;
+       virtual uintptr_t                       getSize() = 0;
+       virtual uintptr_t                       getFileSize() = 0;
+       virtual bool                            hasTrailingZeroFill();
+       virtual uintptr_t                       getFileOffset() = 0;
+       virtual bool                            readable() = 0;
+       virtual bool                            writeable() = 0;
+       virtual bool                            executable() = 0;
+       virtual bool                            unaccessible() = 0;
+       virtual bool                            hasFixUps() = 0;
+       virtual uintptr_t                       getActualLoadAddress() = 0;
+       virtual uintptr_t                       getPreferredLoadAddress() = 0;
+       virtual void                            setUnMapWhenDestructed(bool unmap) = 0;
+       
+protected:
+       // abstract base class so all constructors protected
+                                                               Segment() {}
+                                                               Segment(const Segment&);
+       void                                            operator=(const Segment&);
+
+       virtual bool                            hasPreferredLoadAddress() = 0;
+       //virtual void                          setActualLoadAddress(uint64_t addr) = 0;
+       
+       static bool                                     reserveAddressRange(uintptr_t start, size_t length);
+       static uintptr_t                        reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context);
+       static uintptr_t                        fgNextNonSplitSegAddress;
+
+private:
+       void                                            map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader::LinkContext& context);
+       void                                            map(const void* memoryImage, intptr_t slide, const ImageLoader::LinkContext& context);
+       void                                            setPermissions();
+       void                                            tempWritable();
+       
+       friend class ImageLoader;
+       friend class ImageLoaderMachO;
+};
+
+
+
+#endif
+
diff --git a/src/ImageLoaderMachO.cpp b/src/ImageLoaderMachO.cpp
new file mode 100644 (file)
index 0000000..84a3da6
--- /dev/null
@@ -0,0 +1,2463 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h> 
+#include <sys/mman.h>
+#include <mach/shared_memory_server.h>
+#include <mach/mach.h>
+#include <mach/thread_status.h>
+#include <mach-o/loader.h> 
+#include <mach-o/reloc.h> 
+#include <mach-o/nlist.h> 
+#include <sys/sysctl.h>
+#if __ppc__ || __ppc64__
+       #include <mach-o/ppc/reloc.h>
+#endif
+
+#include "ImageLoaderMachO.h"
+#include "mach-o/dyld_gdb.h"
+
+// no header for this yet, rdar://problem/3850825
+extern "C" void sys_icache_invalidate(void *, size_t);
+
+// optimize strcmp for ppc
+#if __ppc__
+       #include <ppc_intrinsics.h>
+#else
+       #define astrcmp(a,b) strcmp(a,b)
+#endif
+
+// relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables
+#if __LP64__
+       #define RELOC_SIZE 3
+       #define LC_SEGMENT_COMMAND              LC_SEGMENT_64
+       #define LC_ROUTINES_COMMAND             LC_ROUTINES_64
+       struct macho_header                             : public mach_header_64  {};
+       struct macho_segment_command    : public segment_command_64  {};
+       struct macho_section                    : public section_64  {};        
+       struct macho_nlist                              : public nlist_64  {};  
+       struct macho_routines_command   : public routines_command_64  {};       
+#else
+       #define RELOC_SIZE 2
+       #define LC_SEGMENT_COMMAND              LC_SEGMENT
+       #define LC_ROUTINES_COMMAND             LC_ROUTINES
+       struct macho_header                             : public mach_header  {};
+       struct macho_segment_command    : public segment_command {};
+       struct macho_section                    : public section  {};   
+       struct macho_nlist                              : public nlist  {};     
+       struct macho_routines_command   : public routines_command  {};  
+#endif
+
+
+uint32_t ImageLoaderMachO::fgHintedBinaryTreeSearchs = 0;
+uint32_t ImageLoaderMachO::fgUnhintedBinaryTreeSearchs = 0;
+
+
+//#define LINKEDIT_USAGE_DEBUG 1
+
+#if LINKEDIT_USAGE_DEBUG
+       #include <set>
+       static std::set<uintptr_t> sLinkEditPageBuckets;
+
+       namespace dyld {
+               extern ImageLoader*     findImageContainingAddress(const void* addr);
+       };
+
+       static void noteAccessedLinkEditAddress(const void* addr)
+       {
+               uintptr_t page = ((uintptr_t)addr) & (-4096);
+               sLinkEditPageBuckets.insert(page);
+               fprintf(stderr, "dyld: accessing page 0x%08lX in __LINKEDIT of %s\n", page, dyld::findImageContainingAddress(addr)->getPath());
+       }
+#endif
+
+// only way to share initialization in C++
+void ImageLoaderMachO::init()
+{
+       fMachOData              = NULL;
+       fLinkEditBase   = NULL;
+       fSymbolTable    = NULL;
+       fStrings                = NULL;
+       fDynamicInfo    = NULL;
+       fSlide                  = 0;
+       fIsSplitSeg             = false;
+       fHasSubLibraries= false;
+       fHasSubUmbrella = false;
+       fDashInit               = NULL;
+       fModInitSection = NULL;
+       fModTermSection = NULL;
+       fDATAdyld               = NULL;
+       fImageNotifySection     = NULL;
+       fTwoLevelHints  = NULL;
+       fDylibID                = NULL;
+       fReExportThruFramework  = NULL;
+       fTextSegmentWithFixups = NULL;
+}
+
+// create image by copying an in-memory mach-o file
+ImageLoaderMachO::ImageLoaderMachO(const char* moduleName, const struct mach_header* mh, uint64_t len, const LinkContext& context)
+ : ImageLoader(moduleName)
+{
+       // clean slate
+       this->init();
+
+       // temporary use this buffer until TEXT is mapped in
+       fMachOData = (const uint8_t*)mh;
+
+       // create segments
+       this->instantiateSegments((const uint8_t*)mh);
+       
+       // map segments
+       if ( mh->filetype != MH_EXECUTE )
+               ImageLoader::mapSegments((const void*)mh, len, context);
+       
+       // get pointers to interesting things 
+       this->parseLoadCmds();
+}
+
+
+// create image by mapping in a mach-o file
+ImageLoaderMachO::ImageLoaderMachO(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offsetInFat, 
+                                                                       uint64_t lenInFat, const struct stat& info, const LinkContext& context)
+ : ImageLoader(path, offsetInFat, info)
+{      
+       // clean slate
+       this->init();
+
+       // read load commands
+       const unsigned int dataSize = sizeof(macho_header) + ((macho_header*)firstPage)->sizeofcmds;
+       uint8_t buffer[dataSize];
+       const uint8_t* fileData = firstPage;
+       if ( dataSize > 4096 ) {
+               // only read more if cmds take up more space than first page
+               fileData = buffer;
+               memcpy(buffer, firstPage, 4096);
+               pread(fd, &buffer[4096], dataSize-4096, offsetInFat+4096);
+       }
+       
+       // temporary use this buffer until TEXT is mapped in
+       fMachOData = fileData;
+       
+       // the meaning of many fields changes in split seg mach-o files
+       fIsSplitSeg = ((((macho_header*)fileData)->flags & MH_SPLIT_SEGS) != 0) && (((macho_header*)fileData)->filetype == MH_DYLIB);   
+       
+       // create segments
+       this->instantiateSegments(fileData);
+       
+       // map segments, except for main executable which is already mapped in by kernel
+       if ( ((macho_header*)fileData)->filetype != MH_EXECUTE )
+               this->mapSegments(fd, offsetInFat, lenInFat, info.st_size, context);
+                       
+       // get pointers to interesting things 
+       this->parseLoadCmds();
+}
+
+
+
+
+void ImageLoaderMachO::instantiateSegments(const uint8_t* fileData)
+{
+       const uint32_t cmd_count = ((macho_header*)fileData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fileData[sizeof(macho_header)];
+
+       // construct Segment object for each LC_SEGMENT cmd and add to list
+       const struct load_command* cmd = cmds;
+       for (unsigned long i = 0; i < cmd_count; ++i) {
+               if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
+                       fSegments.push_back(new SegmentMachO((struct macho_segment_command*)cmd, this, fileData));
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+}
+
+
+
+bool ImageLoaderMachO::segmentsMustSlideTogether() const 
+{
+       return true;
+}
+
+bool ImageLoaderMachO::segmentsCanSlide() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( (mh->filetype == MH_DYLIB) || (mh->filetype == MH_BUNDLE) );
+}
+
+bool ImageLoaderMachO::isBundle() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( mh->filetype == MH_BUNDLE );
+}
+
+bool ImageLoaderMachO::isDylib() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( mh->filetype == MH_DYLIB );
+}
+
+bool ImageLoaderMachO::forceFlat() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( (mh->flags & MH_FORCE_FLAT) != 0 );
+}
+
+bool ImageLoaderMachO::usesTwoLevelNameSpace() const
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( (mh->flags & MH_TWOLEVEL) != 0 );
+}
+
+bool ImageLoaderMachO::isPrebindable() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( (mh->flags & MH_PREBOUND) != 0 );
+}
+
+bool ImageLoaderMachO::hasCoalescedExports() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( (mh->flags & MH_WEAK_DEFINES) != 0 );
+}
+
+bool ImageLoaderMachO::needsCoalescing() const 
+{
+       const macho_header* mh = (macho_header*)fMachOData;
+       return ( (mh->flags & MH_BINDS_TO_WEAK) != 0 );
+}
+
+#if !__LP64__   // split segs not supported for 64-bits
+
+#if 1 // hack until kernel headers and glue are in system
+struct _shared_region_mapping_np {
+    mach_vm_address_t   address;
+    mach_vm_size_t      size;
+    mach_vm_offset_t    file_offset;
+       vm_prot_t               max_prot;   /* read/write/execute/COW/ZF */
+       vm_prot_t               init_prot;  /* read/write/execute/COW/ZF */
+};
+struct _shared_region_range_np {
+    mach_vm_address_t   address;
+    mach_vm_size_t      size;
+};
+               
+// Called by dyld.  
+// Requests the kernel to map a number of regions from the fd into the
+// shared sections address range (0x90000000-0xAFFFFFFF).
+// If shared_region_make_private_np() has not been called by this process, 
+// the file mapped in is seen in the address space of all processes that
+// participate in using the shared region. 
+// If shared_region_make_private_np() _has_ been called by this process, 
+// the file mapped in is only seen by this process.
+// If the slide parameter is not NULL and then regions cannot be mapped
+// as requested, the kernel will try to map the file in at a different
+// address in the shared region and return the distance slid. 
+// If the mapping requesting cannot be fulfilled, returns non-zero.
+static int 
+_shared_region_map_file_np(
+       int fd,                                                 // file descriptor to map into shared region
+       unsigned int regionCount,               // number of entres in array of regions
+       const _shared_region_mapping_np regions[],      // the array of regions to map
+       uint64_t* slide)                                        // the amount all regions were slid,  NULL means don't attempt to slide
+{
+       //fprintf(stderr, "%s(%i, %u, %8p, %8p)\n", __func__, fd, regionCount, regions, slide);
+       //for ( unsigned int i=0; i < regionCount; ++i) {
+       //      fprintf(stderr, "\taddress=0x%08llX, size=0x%08llX\n", regions[i].address, regions[i].size);
+       //}
+       int r = syscall(299, fd, regionCount, regions, slide);
+//     if(0 != r)
+//             fprintf(stderr, "%s(%i, %u, %8p, %8p) errno=%i (%s)\n", __func__, fd, regionCount, regions, slide, errno, strerror(errno));
+    return r;
+}
+// Called by dyld if shared_region_map_file() fails.
+// Requests the kernel to take this process out of using the shared region.
+// The specified ranges are created as private copies from the shared region for this process.
+static int 
+_shared_region_make_private_np(
+       unsigned int rangeCount,                                // number of entres in array of msrp_range
+       const _shared_region_range_np ranges[]) // the array of shared regions to make private
+{
+       //fprintf(stderr, "%s(%u, %8p)\n", __func__, rangeCount, ranges);
+       int r = syscall(300, rangeCount, ranges);
+//     if(0 != r)
+//             fprintf(stderr, "%s(%u, %8p) errno=%i (%s)\n", __func__, rangeCount, ranges, errno, strerror(errno));
+    return r;
+}
+#define KERN_SHREG_PRIVATIZABLE        54
+#endif // hack until kernel headers and glue are in system
+
+static uintptr_t sNextAltLoadAddress 
+#if __ppc_
+       = 0xC0000000;
+#else
+       = 0;
+#endif
+
+
+static
+bool
+hasSharedRegionMapFile(void)
+{
+       int     mib[CTL_MAXNAME];
+       int     value = 0;
+       size_t  size;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_SHREG_PRIVATIZABLE;
+       size = sizeof (int);
+       if (sysctl(mib, 2, &value, &size, NULL, 0) != 0) {
+               value = 0;
+       }
+
+       return 0 != value;
+}
+
+int
+ImageLoaderMachO::sharedRegionMapFilePrivateOutside(int fd,
+                                                                                                       uint64_t offsetInFat,
+                                                                                                       uint64_t lenInFat,
+                                                                                                       uint64_t fileLen,
+                                                                                                       const LinkContext& context)
+{
+       const unsigned int segmentCount = fSegments.size();
+       const unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+       const unsigned int regionCount = segmentCount+extraZeroFillEntries;
+       _shared_region_mapping_np regions[regionCount];
+       initMappingTable(offsetInFat, regions);
+       int r = -1;
+               // find space somewhere to allocate split seg
+               bool foundRoom = false;
+               vm_size_t biggestDiff = 0;
+               while ( ! foundRoom ) {
+                       foundRoom = true;
+                       for(unsigned int i=0; i < regionCount; ++i) {
+                               vm_address_t addr = sNextAltLoadAddress + regions[i].address - regions[0].address;
+                               vm_size_t size = regions[i].size ;
+                               r = vm_allocate(mach_task_self(), &addr, size, false /*only this range*/);
+                               if ( 0 != r ) {
+                                       // no room here, deallocate what has succeeded so far
+                                       for(unsigned int j=0; j < i; ++j) {
+                                               vm_address_t addr = sNextAltLoadAddress + regions[j].address - regions[0].address;
+                                               vm_size_t size = regions[j].size ;
+                                               (void)vm_deallocate(mach_task_self(), addr, size);
+                                       }
+                                       sNextAltLoadAddress += 0x00100000;  // skip ahead 1MB and try again
+                                       if ( (sNextAltLoadAddress & 0xF0000000) == 0x90000000 )
+                                               throw "can't map split seg anywhere";
+                                       foundRoom = false;
+                                       break;
+                               }
+                               vm_size_t high = (regions[i].address + size - regions[0].address) & 0x0FFFFFFF;
+                               if ( high > biggestDiff )
+                                       biggestDiff = high;
+                       }
+               }
+               
+               // map in each region
+               uintptr_t slide = sNextAltLoadAddress - regions[0].address;
+               this->setSlide(slide);
+               for(unsigned int i=0; i < regionCount; ++i) {
+                       if ( (regions[i].init_prot & VM_PROT_ZF) != 0 ) {
+                               // do nothing vm_allocate() zero-fills by default
+                       }
+                       else {
+                               void* mmapAddress = (void*)(uintptr_t)(regions[i].address + slide);
+                               size_t size = regions[i].size;
+                               int protection = 0;
+                               if ( regions[i].init_prot & VM_PROT_EXECUTE )
+                                       protection   |= PROT_EXEC;
+                               if ( regions[i].init_prot & VM_PROT_READ )
+                                       protection   |= PROT_READ;
+                               if ( regions[i].init_prot & VM_PROT_WRITE )
+                                       protection   |= PROT_WRITE;
+                               off_t offset = regions[i].file_offset;
+                               //fprintf(stderr, "mmap(%p, 0x%08lX, block=0x%08X, %s\n", mmapAddress, size, biggestDiff, fPath);
+                               mmapAddress = mmap(mmapAddress, size, protection, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd, offset);
+                               if ( mmapAddress == ((void*)(-1)) )
+                                       throw "mmap error";
+                       }
+               }
+               // set so next maps right after this one
+               sNextAltLoadAddress += biggestDiff; 
+               sNextAltLoadAddress = (sNextAltLoadAddress + 4095) & (-4096);
+               
+               // logging
+               if ( context.verboseMapping ) {
+                       fprintf(stderr, "dyld: Mapping split-seg outside shared region, slid by 0x%08lX %s\n", this->fSlide, this->getPath());
+                       for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+                               Segment* seg = fSegments[segIndex];
+                               const _shared_region_mapping_np* entry = &regions[entryIndex];
+                               if ( (entry->init_prot & VM_PROT_ZF) == 0 ) 
+                                       fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+                                                       seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+                               if ( entryIndex < (regionCount-1) ) {
+                                       const _shared_region_mapping_np* nextEntry = &regions[entryIndex+1];
+                                       if ( (nextEntry->init_prot & VM_PROT_ZF) != 0 ) {
+                                               uint64_t segOffset = nextEntry->address - entry->address;
+                                               fprintf(stderr, "%18s at 0x%08lX->0x%08lX (zerofill)\n",
+                                                               seg->getName(), (uintptr_t)(seg->getActualLoadAddress() + segOffset), (uintptr_t)(seg->getActualLoadAddress() + segOffset + nextEntry->size - 1));
+                                               ++entryIndex;
+                                       }
+                               }
+                       }
+               }
+               
+               return r;
+}
+
+
+void ImageLoaderMachO::mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
+{
+       enum SharedRegionState
+       {
+               kSharedRegionStartState = 0,
+               kSharedRegionLoadFileState,
+               kSharedRegionMapFileState,
+               kSharedRegionMapFilePrivateState,
+               kSharedRegionMapFilePrivateOutsideState,
+       };
+       static SharedRegionState sSharedRegionState = kSharedRegionStartState;
+
+       // non-split segment libraries handled by super class
+       if ( !fIsSplitSeg )
+               return ImageLoader::mapSegments(fd, offsetInFat, lenInFat, fileLen, context);
+       
+       if ( kSharedRegionStartState == sSharedRegionState ) {
+               if ( hasSharedRegionMapFile() ) {
+                       if ( (context.sharedRegionMode == kUsePrivateSharedRegion) || context.slideAndPackDylibs ) { 
+                               sharedRegionMakePrivate(context);
+                               sSharedRegionState = kSharedRegionMapFilePrivateState;
+                       }
+                       else if ( context.sharedRegionMode == kDontUseSharedRegion ) {
+                               sSharedRegionState = kSharedRegionMapFilePrivateOutsideState;
+                       }
+                       else {
+                               sSharedRegionState = kSharedRegionMapFileState;
+                       }
+               }
+               else {
+                       sSharedRegionState = kSharedRegionLoadFileState;
+               }
+       }
+       
+       if ( kSharedRegionLoadFileState == sSharedRegionState ) {
+               if ( 0 != sharedRegionLoadFile(fd, offsetInFat, lenInFat, fileLen, context) ) {
+                       sSharedRegionState = kSharedRegionMapFilePrivateOutsideState;
+               }
+       }
+       else
+       if ( kSharedRegionMapFileState == sSharedRegionState ) {
+               if ( 0 != sharedRegionMapFile(fd, offsetInFat, lenInFat, fileLen, context) ) {
+                       sharedRegionMakePrivate(context);
+                       sSharedRegionState = kSharedRegionMapFilePrivateState;
+               }
+       }
+       
+       if ( kSharedRegionMapFilePrivateState == sSharedRegionState ) {
+               if ( 0 != sharedRegionMapFilePrivate(fd, offsetInFat, lenInFat, fileLen, context) ) {
+                       sSharedRegionState = kSharedRegionMapFilePrivateOutsideState;
+               }
+       }
+       
+       if ( kSharedRegionMapFilePrivateOutsideState == sSharedRegionState ) {
+               if ( 0 != sharedRegionMapFilePrivateOutside(fd, offsetInFat, lenInFat, fileLen, context) ) {
+                       throw "mapping error";
+               }
+       }
+}
+
+unsigned int
+ImageLoaderMachO::getExtraZeroFillEntriesCount()
+{
+       // calculate mapping entries
+       const unsigned int segmentCount = fSegments.size();
+       unsigned int extraZeroFillEntries = 0;
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               if ( seg->hasTrailingZeroFill() )
+                       ++extraZeroFillEntries;
+       }
+       
+       return extraZeroFillEntries;
+}
+
+void
+ImageLoaderMachO::initMappingTable(uint64_t offsetInFat,
+                                                                  _shared_region_mapping_np *mappingTable)
+{
+       unsigned int segmentCount = fSegments.size();
+       for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+               Segment* seg = fSegments[segIndex];
+               _shared_region_mapping_np* entry = &mappingTable[entryIndex];
+               entry->address                  = seg->getActualLoadAddress();
+               entry->size                             = seg->getFileSize();
+               entry->file_offset              = seg->getFileOffset() + offsetInFat;
+               entry->init_prot                = VM_PROT_NONE;
+               if ( !seg->unaccessible() ) {
+                       if ( seg->executable() )
+                               entry->init_prot   |= VM_PROT_EXECUTE;
+                       if ( seg->readable() )
+                               entry->init_prot   |= VM_PROT_READ;
+                       if ( seg->writeable() )
+                               entry->init_prot   |= VM_PROT_WRITE | VM_PROT_COW;
+               }
+               entry->max_prot                 = entry->init_prot;
+               if ( seg->hasTrailingZeroFill() ) {
+                       _shared_region_mapping_np* zfentry = &mappingTable[++entryIndex];
+                       zfentry->address                = entry->address + seg->getFileSize();
+                       zfentry->size                   = seg->getSize() - seg->getFileSize();
+                       zfentry->file_offset    = 0;
+                       zfentry->init_prot              = entry->init_prot | VM_PROT_COW | VM_PROT_ZF;
+                       zfentry->max_prot               = zfentry->init_prot;
+               }
+       }
+}
+       
+int
+ImageLoaderMachO::sharedRegionMakePrivate(const LinkContext& context)
+{
+       if ( context.verboseMapping )
+               fprintf(stderr, "dyld: making shared regions private\n");
+
+       // shared mapping failed, so make private copy of shared region and try mapping private
+       RegionsVector allRegions;
+       context.getAllMappedRegions(allRegions);
+       std::vector<_shared_region_range_np> splitSegRegions;
+       const unsigned int allRegiontCount = allRegions.size();
+       for(unsigned int i=0; i < allRegiontCount; ++i){
+               MappedRegion region = allRegions[i];
+               uint8_t highByte = region.address >> 28;
+               if ( (highByte == 9) || (highByte == 0xA) ) {
+                       _shared_region_range_np splitRegion;
+                       splitRegion.address = region.address;
+                       splitRegion.size = region.size;
+                       splitSegRegions.push_back(splitRegion);
+               }
+       }
+       int result = _shared_region_make_private_np(splitSegRegions.size(), &splitSegRegions[0]);
+       // notify gdb or other lurkers that this process is no longer using the shared region
+       dyld_all_image_infos.processDetachedFromSharedRegion = true;
+       return result;
+}
+
+int
+ImageLoaderMachO::sharedRegionMapFile(int fd,
+                                         uint64_t offsetInFat,
+                                         uint64_t lenInFat,
+                                         uint64_t fileLen,
+                                         const LinkContext& context)
+{
+       // build table of segments to map
+       const unsigned int segmentCount = fSegments.size();
+       const unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+       const unsigned int mappingTableCount = segmentCount+extraZeroFillEntries;
+       _shared_region_mapping_np mappingTable[mappingTableCount];
+       initMappingTable(offsetInFat, mappingTable);
+//     uint64_t slide;
+       uint64_t *slidep = NULL;
+
+       // try to map it in shared
+       int r = _shared_region_map_file_np(fd, mappingTableCount, mappingTable, slidep);
+       if ( 0 == r ) {
+               if(NULL != slidep && 0 != *slidep) {
+                       // update with actual load addresses
+               }
+               if ( context.verboseMapping ) {
+                       fprintf(stderr, "dyld: Mapping split-seg shared %s\n", this->getPath());
+                       for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+                               Segment* seg = fSegments[segIndex];
+                               const _shared_region_mapping_np* entry = &mappingTable[entryIndex];
+                               if ( (entry->init_prot & VM_PROT_ZF) == 0 ) 
+                                       fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+                                                       seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+                               if ( entryIndex < (mappingTableCount-1) ) {
+                                       const _shared_region_mapping_np* nextEntry = &mappingTable[entryIndex+1];
+                                       if ( (nextEntry->init_prot & VM_PROT_ZF) != 0 ) {
+                                               uint64_t segOffset = nextEntry->address - entry->address;
+                                               fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+                                                               seg->getName(), (uintptr_t)(seg->getActualLoadAddress() + segOffset), (uintptr_t)(seg->getActualLoadAddress() + segOffset + nextEntry->size - 1));
+                                               ++entryIndex;
+                                       }
+                               }
+                       }
+               }
+       }
+       return r;
+}
+
+int
+ImageLoaderMachO::sharedRegionMapFilePrivate(int fd,
+                                                                                        uint64_t offsetInFat,
+                                                                                        uint64_t lenInFat,
+                                                                                        uint64_t fileLen,
+                                                                                        const LinkContext& context)
+{
+       const unsigned int segmentCount = fSegments.size();
+
+       // adjust base address of segments to pack next to last dylib
+       if ( context.slideAndPackDylibs ) {
+               uintptr_t lowestReadOnly = (uintptr_t)(-1);
+               uintptr_t lowestWritable = (uintptr_t)(-1);
+               for(unsigned int segIndex=0; segIndex < segmentCount; ++segIndex){
+                       Segment* seg = fSegments[segIndex];
+                       uintptr_t segEnd = seg->getActualLoadAddress();
+                       if ( seg->writeable() ) {
+                               if ( segEnd < lowestWritable )
+                                       lowestWritable = segEnd;
+                       }
+                       else {
+                               if ( segEnd < lowestReadOnly )
+                                       lowestReadOnly = segEnd;
+                       }
+               }
+               uintptr_t baseAddress;
+               if ( lowestWritable - 256*1024*1024 < lowestReadOnly )
+                       baseAddress = lowestWritable - 256*1024*1024;
+               else
+                       baseAddress = lowestReadOnly;
+               // record that we want dylb slid to fgNextSplitSegAddress
+               this->setSlide(fgNextSplitSegAddress - baseAddress);
+       }
+       
+       // build table of segments to map
+       const unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+       const unsigned int mappingTableCount = segmentCount+extraZeroFillEntries;
+       _shared_region_mapping_np mappingTable[mappingTableCount];
+       initMappingTable(offsetInFat, mappingTable);
+       uint64_t slide = 0;
+
+       // try map it in privately (don't allow sliding if we pre-calculated the load address to pack dylibs)
+       int r = _shared_region_map_file_np(fd, mappingTableCount, mappingTable, context.slideAndPackDylibs ? NULL : &slide);
+       if ( 0 == r ) {
+               if ( 0 != slide ) {
+                       slide = (slide) & (-4096); // round down to page boundary
+                       this->setSlide(slide);
+               }
+               if ( context.verboseMapping ) {
+                       if ( slide == 0 )
+                               fprintf(stderr, "dyld: Mapping split-seg un-shared %s\n", this->getPath());
+                       else
+                               fprintf(stderr, "dyld: Mapping split-seg un-shared slid by 0x%08llX %s\n", slide, this->getPath());
+                       for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+                               Segment* seg = fSegments[segIndex];
+                               const _shared_region_mapping_np* entry = &mappingTable[entryIndex];
+                               if ( (entry->init_prot & VM_PROT_ZF) == 0 ) 
+                                       fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+                                                       seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+                               if ( entryIndex < (mappingTableCount-1) ) {
+                                       const _shared_region_mapping_np* nextEntry = &mappingTable[entryIndex+1];
+                                       if ( (nextEntry->init_prot & VM_PROT_ZF) != 0 ) {
+                                               uint64_t segOffset = nextEntry->address - entry->address;
+                                               fprintf(stderr, "%18s at 0x%08lX->0x%08lX (zerofill)\n",
+                                                               seg->getName(), (uintptr_t)(seg->getActualLoadAddress() + segOffset), (uintptr_t)(seg->getActualLoadAddress() + segOffset + nextEntry->size - 1));
+                                               ++entryIndex;
+                                       }
+                               }
+                       }
+               }
+               if ( context.slideAndPackDylibs ) {
+                       // calculate where next split-seg dylib can load
+                       uintptr_t largestReadOnly = 0;
+                       uintptr_t largestWritable = 0;
+                       for (unsigned int segIndex=0; segIndex < segmentCount; ++segIndex) {
+                               Segment* seg = fSegments[segIndex];
+                               uintptr_t segEnd = seg->getActualLoadAddress()+seg->getSize();
+                               segEnd = (segEnd+4095) & (-4096); // page align
+                               if ( seg->writeable() ) {
+                                       if ( segEnd > largestWritable )
+                                               largestWritable = segEnd;
+                               }
+                               else {
+                                       if ( segEnd > largestReadOnly )
+                                               largestReadOnly = segEnd;
+                               }
+                       }
+                       if ( largestWritable - 256*1024*1024 > largestReadOnly )
+                               fgNextSplitSegAddress = largestWritable - 256*1024*1024;
+                       else
+                               fgNextSplitSegAddress = largestReadOnly;
+               }
+       }
+       if ( context.slideAndPackDylibs && (r != 0) )
+               throw "can't rebase split-seg dylib";
+       
+       return r;
+}
+
+
+int
+ImageLoaderMachO::sharedRegionLoadFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
+{
+       
+       // map in split segment file at random address, then tell kernel to share it
+       void* loadAddress = 0;
+       loadAddress = mmap(NULL, fileLen, PROT_READ, MAP_FILE, fd, 0);
+       if ( loadAddress == ((void*)(-1)) )
+               throw "mmap error";
+
+       // calculate mapping entries
+       const unsigned int segmentCount = fSegments.size();
+       unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+       
+       // build table of segments to map
+       const unsigned int mappingTableCount = segmentCount+extraZeroFillEntries;
+       const uintptr_t baseAddress = fSegments[0]->getPreferredLoadAddress();
+       sf_mapping mappingTable[mappingTableCount];
+       initMappingTable(offsetInFat, mappingTable, baseAddress);
+       
+       
+       // use load_shared_file() to map all segments at once
+       int flags = 0; // might need to set NEW_LOCAL_SHARED_REGIONS on first use
+       static bool firstTime = true;
+       if ( firstTime ) {
+               // when NEW_LOCAL_SHARED_REGIONS bit is set, this process will get is own shared region
+               // this is used by Xcode to prevent development libraries from polluting the global shared segment
+               if ( context.sharedRegionMode == kUsePrivateSharedRegion )
+                       flags |= NEW_LOCAL_SHARED_REGIONS;
+               firstTime = false;
+       }
+       
+       caddr_t base_address = (caddr_t)baseAddress;
+       kern_return_t r;
+       r = load_shared_file(   (char*)fPath,           // path of file to map shared
+                                                       (char*)loadAddress, // beginning of local copy of sharable pages in file
+                                                       fileLen,                        // end of shareable pages in file
+                                                       &base_address,          // beginning of address range to map
+                                                       mappingTableCount,  // number of entres in array of sf_mapping
+                                                       mappingTable,           // the array of sf_mapping
+                                                       &flags);                        // in/out flags
+       if ( 0 != r ) {
+               // try again but tell kernel it is ok to slide
+               flags |= ALTERNATE_LOAD_SITE;
+               r = load_shared_file((char*)fPath,(char*)loadAddress, fileLen, &base_address,   
+                                                       mappingTableCount, mappingTable, &flags);
+       }
+       
+       // unmap file from random address now that they are (hopefully) mapped into the shared region
+       munmap(loadAddress, fileLen);
+
+       if ( 0 == r ) {
+               if ( base_address != (caddr_t)baseAddress )
+                       this->setSlide((uintptr_t)base_address - baseAddress);
+               if ( context.verboseMapping ) {
+                       if ( base_address != (caddr_t)baseAddress )
+                               fprintf(stderr, "dyld: Mapping split-seg load_shared_alt_region %s\n", this->getPath());
+                       else
+                               fprintf(stderr, "dyld: Mapping split-seg load_shared %s\n", this->getPath());
+                       for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+                               Segment* seg = fSegments[segIndex];
+                               const sf_mapping* entry = &mappingTable[entryIndex];
+                               if ( (entry->protection & VM_PROT_ZF) == 0 )
+                                       fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+                                                       seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+                               if ( entryIndex < (mappingTableCount-1) ) {
+                                       const sf_mapping* nextEntry = &mappingTable[entryIndex+1];
+                                       if ( (nextEntry->protection & VM_PROT_ZF) != 0 ) {
+                                               fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+                                                       seg->getName(), (uintptr_t)(nextEntry->mapping_offset + base_address), (uintptr_t)(nextEntry->mapping_offset + base_address + nextEntry->size - 1));
+                                               ++entryIndex;
+                                       }
+                               }
+                       }
+               }
+       }
+       return r;
+}
+void
+ImageLoaderMachO::initMappingTable(uint64_t offsetInFat,
+                                                                  sf_mapping *mappingTable,
+                                                                  uintptr_t baseAddress)
+{
+       unsigned int segmentCount = fSegments.size();
+       for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+               Segment* seg = fSegments[segIndex];
+               sf_mapping* entry = &mappingTable[entryIndex];
+               entry->mapping_offset   = seg->getPreferredLoadAddress() - baseAddress;
+               entry->size                             = seg->getFileSize();
+               entry->file_offset              = seg->getFileOffset() + offsetInFat;
+               entry->protection               = VM_PROT_NONE;
+               if ( !seg->unaccessible() ) {
+                       if ( seg->executable() )
+                               entry->protection   |= VM_PROT_EXECUTE;
+                       if ( seg->readable() )
+                               entry->protection   |= VM_PROT_READ;
+                       if ( seg->writeable() )
+                               entry->protection   |= VM_PROT_WRITE | VM_PROT_COW;
+               }
+               
+               entry->cksum                    = 0;
+               if ( seg->hasTrailingZeroFill() ) {
+                       sf_mapping* zfentry = &mappingTable[++entryIndex];
+                       zfentry->mapping_offset = entry->mapping_offset + seg->getFileSize();
+                       zfentry->size                   = seg->getSize() - seg->getFileSize();
+                       zfentry->file_offset    = 0;
+                       zfentry->protection             = entry->protection | VM_PROT_COW | VM_PROT_ZF;
+                       zfentry->cksum                  = 0;
+               }
+       }
+}
+
+#endif //  !__LP64__  split segs not supported for 64-bits
+
+
+void ImageLoaderMachO::setSlide(intptr_t slide)
+{
+       fSlide = slide;
+}
+
+void ImageLoaderMachO::parseLoadCmds()
+{
+       // now that segments are mapped in, get real fMachOData, fLinkEditBase, and fSlide
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i){
+               Segment* seg = fSegments[i];
+               // set up pointer to __LINKEDIT segment
+               if ( strcmp(seg->getName(),"__LINKEDIT") == 0 ) 
+                       fLinkEditBase = (uint8_t*)(seg->getActualLoadAddress() - seg->getFileOffset());
+               // __TEXT segment always starts at beginning of file and contains mach_header and load commands
+               if ( strcmp(seg->getName(),"__TEXT") == 0 ) {
+                       if ( seg->hasFixUps() )
+                               fTextSegmentWithFixups = (SegmentMachO*)seg;
+               }
+               // some segment always starts at beginning of file and contains mach_header and load commands
+               if ( (seg->getFileOffset() == 0) && (seg->getFileSize() != 0) ) {
+                       fMachOData = (uint8_t*)(seg->getActualLoadAddress());
+               }
+       }
+
+       // walk load commands (mapped in at start of __TEXT segment)
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SYMTAB:
+                               {
+                                       const struct symtab_command* symtab = (struct symtab_command*)cmd;
+                                       fStrings = (const char*)&fLinkEditBase[symtab->stroff];
+                                       fSymbolTable = (struct macho_nlist*)(&fLinkEditBase[symtab->symoff]);
+                               }
+                               break;
+                       case LC_DYSYMTAB:
+                               fDynamicInfo = (struct dysymtab_command*)cmd;
+                               break;
+                       case LC_SUB_UMBRELLA:
+                               fHasSubUmbrella = true;
+                               break;
+                       case LC_SUB_FRAMEWORK:
+                               {
+                                       const struct sub_framework_command* subf = (struct sub_framework_command*)cmd;
+                                       fReExportThruFramework = (char*)cmd + subf->umbrella.offset;
+                               }
+                               break;
+                       case LC_SUB_LIBRARY:
+                               fHasSubLibraries = true;
+                               break;
+                       case LC_ROUTINES_COMMAND:
+                               fDashInit = (struct macho_routines_command*)cmd;
+                               break;
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       const bool isDataSeg = (strcmp(seg->segname, "__DATA") == 0);
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               const uint8_t type = sect->flags & SECTION_TYPE;
+                                               if ( type == S_MOD_INIT_FUNC_POINTERS )
+                                                       fModInitSection = sect;
+                                               else if ( type == S_MOD_TERM_FUNC_POINTERS )
+                                                       fModTermSection = sect;
+                                               else if ( isDataSeg && (strcmp(sect->sectname, "__dyld") == 0) )
+                                                       fDATAdyld = sect;
+                                               else if ( isDataSeg && (strcmp(sect->sectname, "__image_notify") == 0) )
+                                                       fImageNotifySection = sect;
+                                       }
+                               }
+                               break;
+                       case LC_TWOLEVEL_HINTS:
+                               fTwoLevelHints = (struct twolevel_hints_command*)cmd;
+                               break;
+                       case LC_ID_DYLIB:
+                               {
+                                       fDylibID = (struct dylib_command*)cmd;
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+}
+
+
+
+
+const char* ImageLoaderMachO::getInstallPath() const
+{
+       if ( fDylibID != NULL ) {
+               return (char*)fDylibID + fDylibID->dylib.name.offset;
+       }
+       return NULL;
+}
+
+// test if this image is re-exported through parent (the image that loaded this one)
+bool ImageLoaderMachO::isSubframeworkOf(const LinkContext& context, const ImageLoader* parent) const
+{
+       if ( fReExportThruFramework != NULL ) {
+               // need to match LC_SUB_FRAMEWORK string against the leaf name of the install location of parent...
+               const char* parentInstallPath = parent->getInstallPath();
+               if ( parentInstallPath != NULL ) {
+                       const char* lastSlash = strrchr(parentInstallPath, '/');
+                       if ( lastSlash != NULL ) {
+                               if ( strcmp(&lastSlash[1], fReExportThruFramework) == 0 )
+                                       return true;
+                               if ( context.imageSuffix != NULL ) {
+                                       // when DYLD_IMAGE_SUFFIX is used, lastSlash string needs imageSuffix removed from end
+                                       char reexportAndSuffix[strlen(context.imageSuffix)+strlen(fReExportThruFramework)+1];
+                                       strcpy(reexportAndSuffix, fReExportThruFramework);
+                                       strcat(reexportAndSuffix, context.imageSuffix);
+                                       if ( strcmp(&lastSlash[1], reexportAndSuffix) == 0 )
+                                               return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
+// test if child is re-exported 
+bool ImageLoaderMachO::hasSubLibrary(const LinkContext& context, const ImageLoader* child) const
+{
+       if ( fHasSubLibraries ) {
+               // need to match LC_SUB_LIBRARY string against the leaf name (without extension) of the install location of child...
+               const char* childInstallPath = child->getInstallPath();
+               if ( childInstallPath != NULL ) {
+                       const char* lastSlash = strrchr(childInstallPath, '/');
+                       if ( lastSlash != NULL ) {
+                               const char* firstDot = strchr(lastSlash, '.');
+                               int len;
+                               if ( firstDot == NULL )
+                                       len = strlen(lastSlash);
+                               else
+                                       len = firstDot-lastSlash-1;
+                               char childLeafName[len+1];
+                               strncpy(childLeafName, &lastSlash[1], len);
+                               childLeafName[len] = '\0';
+                               const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+                               const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+                               const struct load_command* cmd = cmds;
+                               for (uint32_t i = 0; i < cmd_count; ++i) {
+                                       switch (cmd->cmd) {
+                                               case LC_SUB_LIBRARY:
+                                                       {
+                                                               const struct sub_library_command* lib = (struct sub_library_command*)cmd;
+                                                               const char* aSubLibName = (char*)cmd + lib->sub_library.offset;
+                                                               if ( strcmp(aSubLibName, childLeafName) == 0 )
+                                                                       return true;
+                                                               if ( context.imageSuffix != NULL ) {
+                                                                       // when DYLD_IMAGE_SUFFIX is used, childLeafName string needs imageSuffix removed from end
+                                                                       char aSubLibNameAndSuffix[strlen(context.imageSuffix)+strlen(aSubLibName)+1];
+                                                                       strcpy(aSubLibNameAndSuffix, aSubLibName);
+                                                                       strcat(aSubLibNameAndSuffix, context.imageSuffix);
+                                                                       if ( strcmp(aSubLibNameAndSuffix, childLeafName) == 0 )
+                                                                               return true;
+                                                               }
+                                                       }
+                                                       break;
+                                       }
+                                       cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+                               }
+                       }
+               }
+       }
+       if ( fHasSubUmbrella ) {
+               // need to match LC_SUB_UMBRELLA string against the leaf name of install location of child...
+               const char* childInstallPath = child->getInstallPath();
+               if ( childInstallPath != NULL ) {
+                       const char* lastSlash = strrchr(childInstallPath, '/');
+                       if ( lastSlash != NULL ) {
+                               const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+                               const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+                               const struct load_command* cmd = cmds;
+                               for (uint32_t i = 0; i < cmd_count; ++i) {
+                                       switch (cmd->cmd) {
+                                               case LC_SUB_UMBRELLA:
+                                                       {
+                                                               const struct sub_umbrella_command* um = (struct sub_umbrella_command*)cmd;
+                                                               const char* aSubUmbrellaName = (char*)cmd + um->sub_umbrella.offset;
+                                                               if ( strcmp(aSubUmbrellaName, &lastSlash[1]) == 0 )
+                                                                       return true;
+                                                               if ( context.imageSuffix != NULL ) {
+                                                                       // when DYLD_IMAGE_SUFFIX is used, lastSlash string needs imageSuffix removed from end
+                                                                       char umbrellaAndSuffix[strlen(context.imageSuffix)+strlen(aSubUmbrellaName)+1];
+                                                                       strcpy(umbrellaAndSuffix, aSubUmbrellaName);
+                                                                       strcat(umbrellaAndSuffix, context.imageSuffix);
+                                                                       if ( strcmp(umbrellaAndSuffix, &lastSlash[1]) == 0 )
+                                                                               return true;
+                                                               }
+                                                       }
+                                                       break;
+                                       }
+                                       cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
+       
+void* ImageLoaderMachO::getMain() const
+{
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       for (unsigned long i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_UNIXTHREAD:
+                       {
+                       #if __ppc__
+                               const ppc_thread_state_t* registers = (ppc_thread_state_t*)(((char*)cmd) + 16);
+                               return (void*)registers->srr0;
+                       #elif __ppc64__
+                               const ppc_thread_state64_t* registers = (ppc_thread_state64_t*)(((char*)cmd) + 16);
+                               return (void*)registers->srr0;
+                       #elif __i386__
+                               const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
+                               return (void*)registers->eip;
+                       #else
+                               #warning need processor specific code
+                       #endif
+                       }
+                       break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       return NULL;
+}
+
+
+uint32_t ImageLoaderMachO::doGetDependentLibraryCount()
+{
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       uint32_t count = 0;
+       const struct load_command* cmd = cmds;
+       for (unsigned long i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_LOAD_DYLIB:
+                       case LC_LOAD_WEAK_DYLIB:
+                               ++count;
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       return count;
+}
+
+void ImageLoaderMachO::doGetDependentLibraries(DependentLibrary libs[])
+{
+       uint32_t index = 0;
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       for (unsigned long i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_LOAD_DYLIB:
+                       case LC_LOAD_WEAK_DYLIB:
+                       {
+                               const struct dylib_command* dylib = (struct dylib_command*)cmd;
+                               DependentLibrary* lib = &libs[index++];
+                               lib->name = (char*)cmd + dylib->dylib.name.offset;
+                               //lib->name = strdup((char*)cmd + dylib->dylib.name.offset);
+                               lib->image = NULL;
+                               lib->info.checksum = dylib->dylib.timestamp;
+                               lib->info.minVersion = dylib->dylib.compatibility_version;
+                               lib->info.maxVersion = dylib->dylib.current_version;
+                               lib->required = (cmd->cmd == LC_LOAD_DYLIB);
+                               lib->checksumMatches = false;
+                               lib->isReExported = false;
+                       }
+                       break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+}
+
+ImageLoader::LibraryInfo ImageLoaderMachO::doGetLibraryInfo()
+{
+       LibraryInfo info;
+       if ( fDylibID != NULL ) {
+               info.minVersion = fDylibID->dylib.compatibility_version;
+               info.maxVersion = fDylibID->dylib.current_version;
+               info.checksum = fDylibID->dylib.timestamp;
+       }
+       else {
+               info.minVersion = 0;
+               info.maxVersion = 0;            
+               info.checksum = 0;
+       }
+       return info;
+}
+
+
+uintptr_t ImageLoaderMachO::getRelocBase()
+{
+       if ( fIsSplitSeg ) {
+               // in split segment libraries r_address is offset from first writable segment
+               const unsigned int segmentCount = fSegments.size();
+               for(unsigned int i=0; i < segmentCount; ++i){
+                       Segment* seg = fSegments[i];
+                       if ( seg->writeable() ) {
+                               return seg->getActualLoadAddress();
+                       }
+               }
+       }
+       
+       // in non-split segment libraries r_address is offset from first segment
+       return fSegments[0]->getActualLoadAddress();
+}
+
+#if __ppc__
+static inline void otherRelocsPPC(uintptr_t* locationToFix, uint8_t relocationType, uint16_t otherHalf, uintptr_t slide)
+{
+       // low 16 bits of 32-bit ppc instructions need fixing
+       struct ppcInstruction { uint16_t opcode; int16_t immediateValue; };
+       ppcInstruction* instruction = (ppcInstruction*)locationToFix;
+       //uint32_t before = *((uint32_t*)locationToFix);
+       switch ( relocationType )
+       {
+               case PPC_RELOC_LO16: 
+                       instruction->immediateValue = ((otherHalf << 16) | instruction->immediateValue) + slide;
+                       break;
+               case PPC_RELOC_HI16: 
+                       instruction->immediateValue = ((((instruction->immediateValue << 16) | otherHalf) + slide) >> 16);
+                       break;
+               case PPC_RELOC_HA16: 
+                       int16_t signedOtherHalf = (int16_t)(otherHalf & 0xffff);
+                       uint32_t temp = (instruction->immediateValue << 16) + signedOtherHalf + slide;
+                       if ( (temp & 0x00008000) != 0 )
+                               temp += 0x00008000;
+                       instruction->immediateValue = temp >> 16;
+       }
+       //uint32_t after = *((uint32_t*)locationToFix);
+       //fprintf(stderr, "dyld: ppc fixup %0p type %d from 0x%08X to 0x%08X\n", locationToFix, relocationType, before, after);
+}
+#endif
+
+void ImageLoaderMachO::doRebase(const LinkContext& context)
+{
+       // if prebound and loaded at prebound address, then no need to rebase
+       // Note: you might think that the check for allDependentLibrariesAsWhenPreBound() is not needed
+       // but it is.  If a dependent library changed, this image's lazy pointers into that library
+       // need to be updated (reset back to lazy binding handler).  That work is done most easily
+       // here because there is a PPC_RELOC_PB_LA_PTR reloc record for each lazy pointer.
+       if ( this->usablePrebinding(context) && this->usesTwoLevelNameSpace() ) {
+               // skip rebasing cause prebound and prebinding not disabled
+               ++fgImagesWithUsedPrebinding; // bump totals for statistics
+               return;
+       }
+               
+       // print why prebinding was not used
+       if ( context.verbosePrebinding ) {
+               if ( !this->isPrebindable() ) {
+                       fprintf(stderr, "dyld: image not prebound, so could not use prebinding in %s\n", this->getPath());
+               }
+               else if ( fSlide != 0 ) {
+                       fprintf(stderr, "dyld: image slid, so could not use prebinding in %s\n", this->getPath());
+               }
+               else if ( !this->allDependentLibrariesAsWhenPreBound() ) {
+                       fprintf(stderr, "dyld: dependent libraries changed, so could not use prebinding in %s\n", this->getPath());
+               }
+               else if ( !this->usesTwoLevelNameSpace() ){
+                       fprintf(stderr, "dyld: image uses flat-namespace so, parts of prebinding ignored %s\n", this->getPath());
+               }
+               else {
+                       fprintf(stderr, "dyld: environment variable disabled use of prebinding in %s\n", this->getPath());
+               }
+       }
+
+       // if there are __TEXT fixups, temporarily make __TEXT writable
+       if ( fTextSegmentWithFixups != NULL ) 
+               fTextSegmentWithFixups->tempWritable();
+
+       // cache this value that is used in the following loop
+       register const uintptr_t slide = this->fSlide;
+       
+       // loop through all local (internal) relocation records
+       const uintptr_t relocBase = this->getRelocBase();
+       const relocation_info* const relocsStart = (struct relocation_info*)(&fLinkEditBase[fDynamicInfo->locreloff]);
+       const relocation_info* const relocsEnd = &relocsStart[fDynamicInfo->nlocrel];
+       for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+               if ( (reloc->r_address & R_SCATTERED) == 0 ) {
+                       if ( reloc->r_symbolnum == R_ABS ) {
+                               // ignore absolute relocations
+                       }
+                       else if (reloc->r_length == RELOC_SIZE) {
+                               switch(reloc->r_type) {
+                                       case GENERIC_RELOC_VANILLA:
+                                               *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
+                                               break;
+               #if __ppc__
+                                       case PPC_RELOC_HI16: 
+                                       case PPC_RELOC_LO16: 
+                                       case PPC_RELOC_HA16: 
+                                               // some tools leave object file relocations in linked images
+                                               otherRelocsPPC((uintptr_t*)(reloc->r_address + relocBase), reloc->r_type, reloc[1].r_address, slide);
+                                               ++reloc; // these relocations come in pairs, skip next
+                                               break;
+               #endif
+                                       default:
+                                               throw "unknown local relocation type";
+                               }
+                       }
+                       else {
+                               throw "bad local relocation length";
+                       }
+               }
+               else {
+                       const struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
+                       if (sreloc->r_length == RELOC_SIZE) {
+                               uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
+                               switch(sreloc->r_type) {
+                                       case GENERIC_RELOC_VANILLA:
+                                               *locationToFix += slide;
+                                               break;
+               #if __ppc__ || __ppc64__
+                                       case PPC_RELOC_PB_LA_PTR:
+                                               // should only see these in prebound images, and we got here so prebinding is being ignored
+                                               *locationToFix = sreloc->r_value + slide;
+                                               break;
+               #endif
+               #if __ppc__
+                                       case PPC_RELOC_HI16: 
+                                       case PPC_RELOC_LO16: 
+                                       case PPC_RELOC_HA16: 
+                                               // Metrowerks compiler sometimes leaves object file relocations in linked images???
+                                               ++reloc; // these relocations come in pairs, get next one
+                                               otherRelocsPPC(locationToFix, sreloc->r_type, reloc->r_address, slide);
+                                               break;
+               #endif
+               #if __i386__
+                                       case GENERIC_RELOC_PB_LA_PTR:
+                                               // should only see these in prebound images, and we got here so prebinding is being ignored
+                                               *locationToFix = sreloc->r_value + slide;
+                                               break;
+               #endif
+                                       default:
+                                               throw "unknown local scattered relocation type";
+                               }
+                       }
+                       else {
+                               throw "bad local scattered relocation length";
+                       }
+               }
+       }
+       
+       // if there were __TEXT fixups, restore write protection
+       if ( fTextSegmentWithFixups != NULL ) {
+               fTextSegmentWithFixups->setPermissions();
+               sys_icache_invalidate((void*)fTextSegmentWithFixups->getActualLoadAddress(), fTextSegmentWithFixups->getSize());
+       }
+       
+       // update stats
+       fgTotalRebaseFixups += fDynamicInfo->nlocrel;
+}
+
+
+const struct macho_nlist* ImageLoaderMachO::binarySearchWithToc(const char* key, const char stringPool[], const struct macho_nlist symbols[], 
+                                                                                               const struct dylib_table_of_contents toc[], uint32_t symbolCount, uint32_t hintIndex)
+{
+       int32_t high = symbolCount-1;
+       int32_t mid = hintIndex;
+       
+       // handle out of range hint
+       if ( mid >= (int32_t)symbolCount ) {
+               mid = symbolCount/2;
+               ++ImageLoaderMachO::fgUnhintedBinaryTreeSearchs;
+       }
+       else {
+               ++ImageLoaderMachO::fgHintedBinaryTreeSearchs;
+       }
+
+       for (int32_t low = 0; low <= high; mid = (low+high)/2) {
+               const uint32_t index = toc[mid].symbol_index;
+               const struct macho_nlist* pivot = &symbols[index];
+               const char* pivotStr = &stringPool[pivot->n_un.n_strx];
+#if LINKEDIT_USAGE_DEBUG
+               noteAccessedLinkEditAddress(&toc[mid]);
+               noteAccessedLinkEditAddress(pivot);
+               noteAccessedLinkEditAddress(pivotStr);
+#endif
+               int cmp = astrcmp(key, pivotStr);
+               if ( cmp == 0 )
+                       return pivot;
+               if ( cmp > 0 ) {
+                       // key > pivot 
+                       low = mid + 1;
+               }
+               else {
+                       // key < pivot 
+                       high = mid - 1;
+               }
+       }
+       return NULL;
+}
+
+const struct macho_nlist* ImageLoaderMachO::binarySearch(const char* key, const char stringPool[], const struct macho_nlist symbols[], uint32_t symbolCount)
+{
+       ++ImageLoaderMachO::fgUnhintedBinaryTreeSearchs;
+       const struct macho_nlist* base = symbols;
+       for (uint32_t n = symbolCount; n > 0; n /= 2) {
+               const struct macho_nlist* pivot = &base[n/2];
+               const char* pivotStr = &stringPool[pivot->n_un.n_strx];
+#if LINKEDIT_USAGE_DEBUG
+               noteAccessedLinkEditAddress(pivot);
+               noteAccessedLinkEditAddress(pivotStr);
+#endif
+               int cmp = astrcmp(key, pivotStr);
+               if ( cmp == 0 )
+                       return pivot;
+               if ( cmp > 0 ) {
+                       // key > pivot 
+                       // move base to symbol after pivot
+                       base = &pivot[1];
+                       --n; 
+               }
+               else {
+                       // key < pivot 
+                       // keep same base
+               }
+       }
+       return NULL;
+}
+
+const ImageLoader::Symbol* ImageLoaderMachO::findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const
+{
+       const struct macho_nlist* sym = NULL;
+       const struct twolevel_hint* theHint = (struct twolevel_hint*)hint;
+       if ( fDynamicInfo->tocoff == 0 )
+               sym = binarySearch(name, fStrings, &fSymbolTable[fDynamicInfo->iextdefsym], fDynamicInfo->nextdefsym);
+       else {
+               uint32_t start = fDynamicInfo->nextdefsym;
+               if ( theHint != NULL )
+                        start = theHint->itoc;
+               if ( (theHint == NULL) || (theHint->isub_image == 0) ) {
+                       sym = binarySearchWithToc(name, fStrings, fSymbolTable, (dylib_table_of_contents*)&fLinkEditBase[fDynamicInfo->tocoff], 
+                                                                               fDynamicInfo->ntoc, start);
+               }
+       }
+       if ( sym != NULL ) {
+               if ( foundIn != NULL )
+                       *foundIn = (ImageLoader*)this;          
+                       
+               return (const Symbol*)sym;
+       }
+       
+       if ( searchReExports ) {
+               // hint might tell us to try a particular subimage
+               if ( (theHint != NULL) && (theHint->isub_image > 0) && (theHint->isub_image <= fLibrariesCount) ) {
+                       // isub_image is an index into a list that is sorted non-rexported images first
+                       uint32_t index = 0;
+                       ImageLoader* target = NULL;
+                       // pass one, only look at sub-frameworks
+                       for (uint32_t i=0; i < fLibrariesCount; ++i) {
+                               DependentLibrary& libInfo =  fLibraries[i];
+                               if ( libInfo.isSubFramework && (libInfo.image != NULL)) {
+                                       if ( ++index == theHint->isub_image ) {
+                                               target = libInfo.image;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (target != NULL) {
+                               // pass two, only look at non-sub-framework-reexports
+                               for (uint32_t i=0; i < fLibrariesCount; ++i) {
+                                       DependentLibrary& libInfo =  fLibraries[i];
+                                       if ( libInfo.isReExported && !libInfo.isSubFramework && (libInfo.image != NULL) ) {
+                                               if ( ++index == theHint->isub_image ) {
+                                                       target = libInfo.image;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       if (target != NULL) {
+                               const Symbol* result = target->findExportedSymbol(name, NULL, searchReExports, foundIn);
+                               if ( result != NULL )
+                                       return result;
+                       }
+               }
+               
+               // hint failed, try all sub images
+               // pass one, only look at sub-frameworks
+               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                       DependentLibrary& libInfo =  fLibraries[i];
+                       if ( (libInfo.image != NULL) && libInfo.isSubFramework ) {
+                               const Symbol* result = libInfo.image->findExportedSymbol(name, NULL, searchReExports, foundIn);
+                               if ( result != NULL )
+                                       return result;
+                       }
+               }
+               // pass two, only look at non-sub-framework-reexports
+               for(unsigned int i=0; i < fLibrariesCount; ++i){
+                       DependentLibrary& libInfo =  fLibraries[i];
+                       if ( (libInfo.image != NULL) && libInfo.isReExported && !libInfo.isSubFramework ) {
+                               const Symbol* result = libInfo.image->findExportedSymbol(name, NULL, searchReExports, foundIn);
+                               if ( result != NULL )
+                                       return result;
+                       }
+               }
+       }
+       
+       // last change: the hint is wrong (non-zero but actually in this image)
+       if ( (theHint != NULL) && (theHint->isub_image != 0) ) {
+               sym = binarySearchWithToc(name, fStrings, fSymbolTable, (dylib_table_of_contents*)&fLinkEditBase[fDynamicInfo->tocoff], 
+                                                                               fDynamicInfo->ntoc, fDynamicInfo->nextdefsym);
+               if ( sym != NULL ) {
+                       if ( foundIn != NULL ) 
+                               *foundIn = (ImageLoader*)this;
+                       return (const Symbol*)sym;
+               }
+       }
+
+       return NULL;
+}
+
+
+uintptr_t ImageLoaderMachO::getExportedSymbolAddress(const Symbol* sym) const
+{
+       const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+       return nlistSym->n_value + fSlide;
+}
+
+ImageLoader::DefinitionFlags ImageLoaderMachO::getExportedSymbolInfo(const Symbol* sym) const
+{
+       const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+       if ( (nlistSym->n_desc & N_WEAK_DEF) != 0 )
+               return kWeakDefinition;
+       return kNoDefinitionOptions;
+}
+
+const char* ImageLoaderMachO::getExportedSymbolName(const Symbol* sym) const
+{
+       const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+       return &fStrings[nlistSym->n_un.n_strx];
+}
+
+uint32_t ImageLoaderMachO::getExportedSymbolCount() const
+{
+       return fDynamicInfo->nextdefsym;
+}
+
+
+const ImageLoader::Symbol* ImageLoaderMachO::getIndexedExportedSymbol(uint32_t index) const
+{
+       if ( index < fDynamicInfo->nextdefsym ) {
+               const struct macho_nlist* sym = &fSymbolTable[fDynamicInfo->iextdefsym + index];
+               return (const ImageLoader::Symbol*)sym;
+       }
+       return NULL;
+}
+
+
+uint32_t ImageLoaderMachO::getImportedSymbolCount() const
+{
+       return fDynamicInfo->nundefsym;
+}
+
+
+const ImageLoader::Symbol* ImageLoaderMachO::getIndexedImportedSymbol(uint32_t index) const
+{
+       if ( index < fDynamicInfo->nundefsym ) {
+               const struct macho_nlist* sym = &fSymbolTable[fDynamicInfo->iundefsym + index];
+               return (const ImageLoader::Symbol*)sym;
+       }
+       return NULL;
+}
+
+
+ImageLoader::ReferenceFlags ImageLoaderMachO::geImportedSymbolInfo(const ImageLoader::Symbol* sym) const
+{
+       const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+       ImageLoader::ReferenceFlags flags = kNoReferenceOptions;
+       if ( ((nlistSym->n_type & N_TYPE) == N_UNDF) && (nlistSym->n_value != 0) )
+               flags |= ImageLoader::kTentativeDefinition;
+       if ( (nlistSym->n_desc & N_WEAK_REF) != 0 )
+               flags |= ImageLoader::kWeakReference;
+       return flags;
+}
+
+
+const char* ImageLoaderMachO::getImportedSymbolName(const ImageLoader::Symbol* sym) const
+{
+       const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+       return &fStrings[nlistSym->n_un.n_strx];
+}
+
+
+bool ImageLoaderMachO::getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length)
+{
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               if ( (strcmp(sect->segname, segmentName) == 0) && (strcmp(sect->sectname, sectionName) == 0) ) {
+                                                       *start = (uintptr_t*)(sect->addr + fSlide);
+                                                       *length = sect->size;
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       return false;
+}
+
+
+bool ImageLoaderMachO::findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset)
+{
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       const uintptr_t unslidInteriorAddress = (uintptr_t)imageInterior - this->getSlide();
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       if ( (unslidInteriorAddress >= seg->vmaddr) && (unslidInteriorAddress < (seg->vmaddr+seg->vmsize)) ) {
+                                               const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                               const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                               for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                                       if ((sect->addr <= unslidInteriorAddress) && (unslidInteriorAddress < (sect->addr+sect->size))) {
+                                                               if ( segmentName != NULL )
+                                                                       *segmentName = sect->segname;
+                                                               if ( sectionName != NULL )
+                                                                       *sectionName = sect->sectname;
+                                                               if ( sectionOffset != NULL )
+                                                                       *sectionOffset = unslidInteriorAddress - sect->addr;
+                                                               return true;
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       return false;
+}
+
+
+bool ImageLoaderMachO::symbolRequiresCoalescing(const struct macho_nlist* symbol)
+{
+       // if a define and weak ==> coalesced 
+       if ( ((symbol->n_type & N_TYPE) == N_SECT) && ((symbol->n_desc & N_WEAK_DEF) != 0) ) 
+               return true;
+       // if an undefine and not referencing a weak symbol ==> coalesced
+       if ( ((symbol->n_type & N_TYPE) != N_SECT) && ((symbol->n_desc & N_REF_TO_WEAK) != 0) )
+               return true;
+       
+       // regular symbol
+       return false;
+}
+
+
+static void __attribute__((noreturn)) throwSymbolNotFound(const char* symbol, const char* referencedFrom, const char* expectedIn)
+{
+       const char* formatString = "Symbol not found: %s\n  Referenced from: %s\n  Expected in: %s\n";
+       char buf[strlen(symbol)+strlen(referencedFrom)+strlen(expectedIn)+strlen(formatString)];
+       sprintf(buf, formatString, symbol, referencedFrom, expectedIn);
+       throw strdup(buf);  // this is a leak if exception doesn't halt program
+}
+
+uintptr_t ImageLoaderMachO::resolveUndefined(const LinkContext& context, const struct macho_nlist* undefinedSymbol, bool twoLevel, ImageLoader** foundIn)
+{
+       const char* symbolName = &fStrings[undefinedSymbol->n_un.n_strx];
+
+       if ( context.bindFlat || !twoLevel ) {
+               // flat lookup
+               const Symbol* sym;
+               if ( context.flatExportFinder(symbolName, &sym, foundIn) )
+                       return (*foundIn)->getExportedSymbolAddress(sym);
+               // if a bundle is loaded privately the above will not find its exports
+               if ( this->isBundle() && this->hasHiddenExports() ) {
+                       // look in self for needed symbol
+                       sym = this->findExportedSymbol(symbolName, NULL, false, foundIn);
+                       if ( sym != NULL )
+                               return (*foundIn)->getExportedSymbolAddress(sym);
+               }
+               if ( ((undefinedSymbol->n_type & N_PEXT) != 0) || ((undefinedSymbol->n_type & N_TYPE) == N_SECT) ) {
+                       // could be a multi-module private_extern internal reference
+                       // the static linker squirrels away the target address in n_value
+                       uintptr_t addr = undefinedSymbol->n_value + this->fSlide;
+                       *foundIn = this;
+                       return addr;
+               }
+               if ( (undefinedSymbol->n_desc & N_WEAK_REF) != 0 ) {
+                       // definition can't be found anywhere
+                       // if reference is weak_import, then it is ok, just return 0
+                       return 0;
+               }
+               throwSymbolNotFound(symbolName, this->getPath(), "flat namespace");
+       }
+       else {
+               // symbol requires searching images with coalesced symbols
+               if ( this->needsCoalescing() && symbolRequiresCoalescing(undefinedSymbol) ) {
+                       const Symbol* sym;
+                       if ( context.coalescedExportFinder(symbolName, &sym, foundIn) )
+                               return (*foundIn)->getExportedSymbolAddress(sym);
+                       //throwSymbolNotFound(symbolName, this->getPath(), "coalesced namespace");
+                       //fprintf(stderr, "dyld: coalesced symbol %s not found in any coalesced image, falling back to two-level lookup", symbolName);
+               }
+               
+               // two level lookup
+               void* hint = NULL;
+               ImageLoader* target = NULL;
+               uint8_t ord = GET_LIBRARY_ORDINAL(undefinedSymbol->n_desc);
+               if ( ord == EXECUTABLE_ORDINAL ) {
+                       target = context.mainExecutable;
+               }
+               else if ( ord == SELF_LIBRARY_ORDINAL ) {
+                       target = this;
+               }
+               else if ( ord == DYNAMIC_LOOKUP_ORDINAL ) {
+                       // rnielsen: HACKHACK
+                       // flat lookup
+                       const Symbol* sym;
+                       if ( context.flatExportFinder(symbolName, &sym, foundIn) )
+                               return (*foundIn)->getExportedSymbolAddress(sym);
+                       // no image has exports this symbol
+                       // either report error or hope ZeroLink can just-in-time load an image
+                       context.undefinedHandler(symbolName);
+                       // try looking again
+                       if ( context.flatExportFinder(symbolName, &sym, foundIn) )
+                               return (*foundIn)->getExportedSymbolAddress(sym);
+                       
+                       throwSymbolNotFound(symbolName, this->getPath(), "dynamic lookup");
+               }
+               else if ( ord <= fLibrariesCount ) {
+                       DependentLibrary& libInfo = fLibraries[ord-1];
+                       target = libInfo.image;
+                       if ( (target == NULL) && (((undefinedSymbol->n_desc & N_WEAK_REF) != 0) || !libInfo.required) ) {
+                               // if target library not loaded and reference is weak or library is weak return 0
+                               return 0;
+                       }
+               }
+               else {
+                       throw "corrupt binary, library ordinal too big";
+               }
+               
+               if ( target == NULL ) {
+                       fprintf(stderr, "resolveUndefined(%s) in %s\n", symbolName, this->getPath());
+                       throw "symbol not found";
+               }
+               
+               // interpret hint
+               if ( fTwoLevelHints != NULL ) {
+                       uint32_t symIndex = undefinedSymbol - fSymbolTable;
+                       int32_t undefinedIndex = symIndex - fDynamicInfo->iundefsym;
+                       if ( (undefinedIndex >= 0) && ((uint32_t)undefinedIndex < fDynamicInfo->nundefsym) ) {
+                               const struct twolevel_hint* hints = (struct twolevel_hint*)(&fLinkEditBase[fTwoLevelHints->offset]);
+                               const struct twolevel_hint* theHint = &hints[undefinedIndex];
+                               hint = (void*)theHint;
+                       }
+               }
+               
+               const Symbol* sym = target->findExportedSymbol(symbolName, hint, true, foundIn);
+               if ( sym!= NULL ) {
+                       return (*foundIn)->getExportedSymbolAddress(sym);
+               }
+               else if ( (undefinedSymbol->n_type & N_PEXT) != 0 ) {
+                       // don't know why the static linker did not eliminate the internal reference to a private extern definition
+                       *foundIn = this;
+                       return undefinedSymbol->n_value + fSlide;
+               }
+               else if ( (undefinedSymbol->n_desc & N_WEAK_REF) != 0 ) {
+                       // if definition not found and reference is weak return 0
+                       return 0;
+               }
+               
+               // nowhere to be found
+               throwSymbolNotFound(symbolName, this->getPath(), target->getPath());
+       }
+}
+
+void ImageLoaderMachO::doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols)
+{
+       const uintptr_t relocBase = this->getRelocBase();
+       const bool twoLevel = this->usesTwoLevelNameSpace();
+       const bool prebound = this->isPrebindable();
+       
+       // if there are __TEXT fixups, temporarily make __TEXT writable
+       if ( fTextSegmentWithFixups != NULL ) 
+               fTextSegmentWithFixups->tempWritable();
+
+       // cache last lookup
+       const struct macho_nlist*       lastUndefinedSymbol = 0;
+       uintptr_t                                       symbolAddr = 0;
+       ImageLoader*                            image = NULL;
+       
+       // loop through all external relocation records and bind each
+       const relocation_info* const relocsStart = (struct relocation_info*)(&fLinkEditBase[fDynamicInfo->extreloff]);
+       const relocation_info* const relocsEnd = &relocsStart[fDynamicInfo->nextrel];
+       for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+               if (reloc->r_length == RELOC_SIZE) {
+                       switch(reloc->r_type) {
+                               case GENERIC_RELOC_VANILLA:
+                                       {
+                                               const struct macho_nlist* undefinedSymbol = &fSymbolTable[reloc->r_symbolnum];
+                                               // if only processing coalesced symbols and this one does not require coalesceing, skip to next
+                                               if ( onlyCoalescedSymbols && !symbolRequiresCoalescing(undefinedSymbol) )
+                                                       continue;
+                                               uintptr_t* location = ((uintptr_t*)(reloc->r_address + relocBase));
+                                               uintptr_t value = *location;
+                                               if ( prebound ) {
+                                                       // we are doing relocations, so prebinding was not usable
+                                                       // in a prebound executable, the n_value field is set to the address where the symbol was found when prebound
+                                                       // so, subtracting that gives the initial displacement which we need to add to the newly found symbol address
+                                                       // if mach-o relocation structs had an "addend" field this would not be necessary.
+                                                       value -= undefinedSymbol->n_value;
+                                               }
+                                               // if undefinedSymbol is same as last time, then symbolAddr and image will resolve to the same too
+                                               if ( undefinedSymbol != lastUndefinedSymbol ) {
+                                                       symbolAddr = this->resolveUndefined(context, undefinedSymbol, twoLevel, &image);
+                                                       lastUndefinedSymbol = undefinedSymbol;
+                                               }
+                                               if ( context.verboseBind ) {
+                                                       const char *path = NULL;
+                                                       if(NULL != image) {
+                                                               path = image->getShortName();
+                                                       }
+                                                       if(0 == value) {
+                                                               fprintf(stderr, "dyld: bind: %s:0x%08lx = %s:%s, *0x%08lx = 0x%08lx\n",
+                                                                               this->getShortName(), (uintptr_t)location,
+                                                                               path, &fStrings[undefinedSymbol->n_un.n_strx], (uintptr_t)location, symbolAddr);
+                                                       }
+                                                       else {
+                                                               fprintf(stderr, "dyld: bind: %s:0x%08lx = %s:%s, *0x%08lx = 0x%08lx + %ld\n",
+                                                                               this->getShortName(), (uintptr_t)location,
+                                                                               path, &fStrings[undefinedSymbol->n_un.n_strx], (uintptr_t)location, symbolAddr, value);
+                                                       }
+                                               }
+                                               value += symbolAddr;
+                                               *location = value; 
+                                       }
+                                       break;
+                               default:
+                                       throw "unknown external relocation type";
+                       }
+               }
+               else {
+                       throw "bad external relocation length";
+               }
+       }
+       
+       // if there were __TEXT fixups, restore write protection
+       if ( fTextSegmentWithFixups != NULL ) {
+               fTextSegmentWithFixups->setPermissions();
+               sys_icache_invalidate((void*)fTextSegmentWithFixups->getActualLoadAddress(), fTextSegmentWithFixups->getSize());
+       }
+       
+       // update stats
+       fgTotalBindFixups += fDynamicInfo->nextrel;
+}
+
+const mach_header* ImageLoaderMachO::machHeader() const
+{
+       return (mach_header*)fMachOData;
+}
+
+uintptr_t ImageLoaderMachO::getSlide() const
+{
+       return fSlide;
+}
+
+// hmm. maybe this should be up in ImageLoader??
+const void* ImageLoaderMachO::getBaseAddress() const
+{
+       Segment* seg = fSegments[0];
+       return (const void*)seg->getActualLoadAddress();
+}
+
+
+uintptr_t ImageLoaderMachO::doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context)
+{
+       // scan for all non-lazy-pointer sections
+       const bool twoLevel = this->usesTwoLevelNameSpace();
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       const uint32_t* const indirectTable = (uint32_t*)&fLinkEditBase[fDynamicInfo->indirectsymoff];
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               const uint8_t type = sect->flags & SECTION_TYPE;
+                                               if ( type == S_LAZY_SYMBOL_POINTERS ) {
+                                                       const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
+                                                       uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
+                                                       if ( (lazyPointer >= symbolPointers) && (lazyPointer < &symbolPointers[pointerCount]) ) {
+                                                               const uint32_t indirectTableOffset = sect->reserved1;
+                                                               const uint32_t lazyIndex = lazyPointer - symbolPointers;
+                                                               uint32_t symbolIndex = indirectTable[indirectTableOffset + lazyIndex];
+                                                               if ( symbolIndex != INDIRECT_SYMBOL_ABS && symbolIndex != INDIRECT_SYMBOL_LOCAL ) {
+                                                                       ImageLoader *image = NULL;
+                                                                       const char *path = NULL;
+                                                                       uintptr_t symbolAddr = this->resolveUndefined(context,  &fSymbolTable[symbolIndex], twoLevel, &image);
+                                                                       if ( context.verboseBind ) {
+                                                                               if(NULL == path && NULL != image) {
+                                                                                       path = image->getShortName();
+                                                                               }
+                                                                               fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
+                                                                                               this->getShortName(), &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], "lazy_ptr",
+                                                                                               path, &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], (uintptr_t)&symbolPointers[lazyIndex], symbolAddr);
+                                                                       }
+                                                                       if ( NULL != context.bindingHandler ) {
+                                                                               if(NULL == path && NULL != image) {
+                                                                                       path = image->getPath();
+                                                                               }
+                                                                               symbolAddr = (uintptr_t)context.bindingHandler(path, &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], (void *)symbolAddr);
+                                                                       }
+                                                                       symbolPointers[lazyIndex] = symbolAddr;
+                                                                       // update stats
+                                                                       fgTotalLazyBindFixups++;
+                                                                       return symbolPointers[lazyIndex];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       throw "lazy pointer not found";
+}
+
+
+
+void ImageLoaderMachO::doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols)
+{
+       // scan for all non-lazy-pointer sections 
+       const bool twoLevel = this->usesTwoLevelNameSpace();
+       const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       const uint32_t* const indirectTable = (uint32_t*)&fLinkEditBase[fDynamicInfo->indirectsymoff];
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               const uint8_t type = sect->flags & SECTION_TYPE;
+                                               const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
+                                               if ( type == S_NON_LAZY_SYMBOL_POINTERS ) {
+                                                       if ( (bindness == kLazyOnly) || (bindness == kLazyOnlyNoDependents) )
+                                                               continue;
+                                               }
+                                               else if ( type == S_LAZY_SYMBOL_POINTERS ) {
+                                                       // process each symbol pointer in this section
+                                                       fgTotalPossibleLazyBindFixups += pointerCount;
+                                                       if ( bindness == kNonLazyOnly )
+                                                               continue;
+                                               }
+                                               else {
+                                                       continue;
+                                               }
+                                               const uint32_t indirectTableOffset = sect->reserved1;
+                                               uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
+                                               for (uint32_t j=0; j < pointerCount; ++j) {
+                                                       uint32_t symbolIndex = indirectTable[indirectTableOffset + j];
+                                                       if ( symbolIndex == INDIRECT_SYMBOL_LOCAL) {
+                                                               symbolPointers[j] += this->fSlide;
+                                                       }
+                                                       else if ( symbolIndex == INDIRECT_SYMBOL_ABS) {
+                                                               // do nothing since already has absolute address
+                                                       }
+                                                       else {
+                                                               const struct macho_nlist* sym = &fSymbolTable[symbolIndex];
+                                                               if ( symbolIndex == 0 ) {
+                                                                       // This could be rdar://problem/3534709 
+                                                                       if ( ((const macho_header*)fMachOData)->filetype == MH_EXECUTE ) {
+                                                                               static bool alreadyWarned = false;
+                                                                               if ( (sym->n_type & N_TYPE) != N_UNDF ) {
+                                                                                       // The indirect table parallels the (non)lazy pointer sections.  For
+                                                                                       // instance, to find info about the fifth lazy pointer you look at the
+                                                                                       // fifth entry in the indirect table.  (try otool -Iv on a file).
+                                                                                       // The entry in the indirect table contains an index into the symbol table.
+
+                                                                                       // The bug in ld caused the entry in the indirect table to be zero
+                                                                                       // (instead of a magic value that means a local symbol).  So, if the
+                                                                                       // symbolIndex == 0, we may be encountering the bug, or 0 may be a valid
+                                                                                       // symbol table index. The check I put in place is to see if the zero'th
+                                                                                       // symbol table entry is an import entry (usually it is a local symbol
+                                                                                       // definition).
+                                                                                       if ( context.verboseWarnings && !alreadyWarned ) {
+                                                                                               fprintf(stderr, "dyld: malformed executable '%s', skipping indirect symbol to %s\n",
+                                                                                                               this->getPath(), &fStrings[sym->n_un.n_strx]);
+                                                                                               alreadyWarned = true;
+                                                                                       }
+                                                                                       continue;
+                                                                               }
+                                                                       }
+                                                               }
+                                                               ImageLoader *image = NULL;
+                                                               // if only processing coalesced symbols and this one does not require coalesceing, skip to next
+                                                               if ( onlyCoalescedSymbols && !symbolRequiresCoalescing(sym) )
+                                                                       continue;
+                                                               uintptr_t symbolAddr;
+                                                                       symbolAddr = resolveUndefined(context, sym, twoLevel, &image);
+                                                               if ( context.verboseBind ) {
+                                                                       const char *path = NULL;
+                                                                       if(NULL != image) {
+                                                                               path = image->getShortName();
+                                                                       }
+                                                                       const char *typeName;
+                                                                       if ( type == S_LAZY_SYMBOL_POINTERS ) {
+                                                                               typeName = "lazy_ptr";
+                                                                       }
+                                                                       else {
+                                                                               typeName = "non_lazy_ptr";
+                                                                       }
+                                                                       fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
+                                                                                       this->getShortName(), &fStrings[sym->n_un.n_strx], typeName,
+                                                                                       path, &fStrings[sym->n_un.n_strx], (uintptr_t)&symbolPointers[j], symbolAddr);
+                                                               }
+                                                               symbolPointers[j] = symbolAddr;
+                                                       }
+                                               }
+                                               // update stats
+                                               fgTotalBindFixups += pointerCount;
+                                       }
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+}
+
+/*
+ * The address of these symbols are written in to the (__DATA,__dyld) section
+ * at the following offsets:
+ *     at offset 0     stub_binding_helper_interface
+ *     at offset 4     _dyld_func_lookup
+ *     at offset 8     start_debug_thread
+ * The 'C' types (if any) for these symbols are ignored here and all are
+ * declared as longs so the assignment of their address in to the section will
+ * not require a cast.  stub_binding_helper_interface is really a label in the
+ * assembly code interface for the stub binding.  It does not have a meaningful 
+ * 'C' type.  _dyld_func_lookup is the routine in dyld_libfuncs.c.
+ * start_debug_thread is the routine in debug.c.
+ *
+ * For ppc the image's stub_binding_binding_helper is read from:
+ *     at offset 20    the image's stub_binding_binding_helper address
+ * and saved into to the image structure.
+ */
+struct DATAdyld {
+       void*   dyldLazyBinder;         // filled in at launch by dyld to point into dyld to &stub_binding_helper_interface
+       void*   dyldFuncLookup;         // filled in at launch by dyld to point into dyld to &_dyld_func_lookup
+       void*   startDebugThread;   // debugger interface ???
+       void*   debugPort;                      // debugger interface ???
+       void*   debugThread;            // debugger interface ???
+       void*   stubBindHelper;         // filled in at static link time to point to stub helper in image
+       void*   coreDebug;                      // ???
+};
+
+// These are defined in dyldStartup.s
+extern "C" void stub_binding_helper();
+extern "C" bool dyld_func_lookup(const char* name, uintptr_t* address);
+
+
+void ImageLoaderMachO::setupLazyPointerHandler()
+{
+       if ( fDATAdyld != NULL ) {
+               struct DATAdyld* dd = (struct DATAdyld*)(fDATAdyld->addr + fSlide);
+               if ( fDATAdyld->size > offsetof(DATAdyld, dyldLazyBinder) ) {
+                       if ( dd->dyldLazyBinder != (void*)&stub_binding_helper )
+                               dd->dyldLazyBinder = (void*)&stub_binding_helper;
+               }
+               if ( fDATAdyld->size > offsetof(DATAdyld, dyldFuncLookup) ) {
+                       if ( dd->dyldFuncLookup != (void*)&dyld_func_lookup )
+                               dd->dyldFuncLookup = (void*)&dyld_func_lookup;
+               }
+               //if ( fDATAdyld->size > offsetof(DATAdyld, startDebugThread) ) 
+               //      dd->startDebugThread = &start_debug_thread;
+#ifdef __ppc__
+               //if ( fDATAdyld->size > offsetof(DATAdyld, stubBindHelper) )
+               //      save = dd->stubBindHelper;      
+#endif
+       }
+}
+
+bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const
+{
+       // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
+       if ( this->isPrebindable() && this->allDependentLibrariesAsWhenPreBound() && (this->getSlide() == 0) ) {
+               // allow environment variables to disable prebinding
+               if ( context.bindFlat )
+                       return false;
+               switch ( context.prebindUsage ) {
+                       case kUseAllPrebinding:
+                               return true;
+                       case kUseSplitSegPrebinding:
+                               return this->fIsSplitSeg;
+                       case kUseAllButAppPredbinding:
+                               return (this != context.mainExecutable);
+                       case kUseNoPrebinding:
+                               return false;
+               }
+       }
+       return false;
+}
+
+void ImageLoaderMachO::doBind(const LinkContext& context, BindingLaziness bindness)
+{
+       // set dyld entry points in image
+       this->setupLazyPointerHandler();
+
+       // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
+       // note: flat-namespace binaries need to be imports rebound (even if correctly prebound)
+       if ( this->usablePrebinding(context) && this->usesTwoLevelNameSpace() ) {
+               // if image has coalesced symbols, then these need to be rebound
+               if ( this->needsCoalescing() ) {
+                       this->doBindExternalRelocations(context, true);
+                       this->doBindIndirectSymbolPointers(context, kLazyAndNonLazy, true);
+               }
+               // skip binding because prebound and prebinding not disabled
+               return;
+       }
+       
+       // values bound by name are stored two different ways in mach-o
+       switch (bindness) {
+               case kNonLazyOnly:
+               case kLazyAndNonLazy:
+                       // external relocations are used for data initialized to external symbols
+                       this->doBindExternalRelocations(context, false);
+                       break;
+               case kLazyOnly:
+               case kLazyOnlyNoDependents:
+                       break;
+       }
+       // "indirect symbols" are used for code references to external symbols
+       this->doBindIndirectSymbolPointers(context, bindness, false);
+}
+
+
+
+void ImageLoaderMachO::doImageInit(const LinkContext& context)
+{
+       if ( fDashInit != NULL ) {
+               Initializer func = (Initializer)(fDashInit->init_address + fSlide);
+               if ( context.verboseInit )
+                       fprintf(stderr, "dyld: calling -init function 0x%p in %s\n", func, this->getPath());
+               func(context.argc, context.argv, context.envp, context.apple);
+       }
+}
+
+void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)
+{
+       if ( fModInitSection != NULL ) {
+               Initializer* inits = (Initializer*)(fModInitSection->addr + fSlide);
+               const uint32_t count = fModInitSection->size / sizeof(uintptr_t);
+               for (uint32_t i=0; i < count; ++i) {
+                       Initializer func = inits[i];
+                       if ( context.verboseInit )
+                               fprintf(stderr, "dyld: calling initializer function %p in %s\n", func, this->getPath());
+                       func(context.argc, context.argv, context.envp, context.apple);
+               }
+       }
+}
+
+
+void ImageLoaderMachO::doInitialization(const LinkContext& context)
+{
+       // mach-o has -init and static initializers
+       doImageInit(context);
+       doModInitFunctions(context);
+}
+
+bool ImageLoaderMachO::needsInitialization()
+{
+       return ( (fDashInit != NULL) || (fModInitSection != NULL) );
+}
+
+
+bool ImageLoaderMachO::needsTermination()
+{
+       return ( fModTermSection != NULL );
+}
+
+bool ImageLoaderMachO::hasImageNotification()
+{
+       return ( fImageNotifySection != NULL );
+}
+
+
+void ImageLoaderMachO::doTermination(const LinkContext& context)
+{
+       if ( fModTermSection != NULL ) {
+               Terminator* terms = (Terminator*)(fModTermSection->addr + fSlide);
+               const uint32_t count = fModTermSection->size / sizeof(uintptr_t);
+               for (uint32_t i=count; i > 0; --i) {
+                       Terminator func = terms[i-1];
+                       if ( context.verboseInit )
+                               fprintf(stderr, "dyld: calling terminaton function %p in %s\n", func, this->getPath());
+                       func();
+               }
+       }
+}
+
+void ImageLoaderMachO::doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[])
+{
+       if ( fImageNotifySection != NULL ) {
+               dyld_image_notifier* notes = (dyld_image_notifier*)(fImageNotifySection->addr + fSlide);
+               const uint32_t count = fImageNotifySection->size / sizeof(uintptr_t);
+               for (uint32_t i=count; i > 0; --i) {
+                       dyld_image_notifier func = notes[i-1];
+                       func(mode, infoCount, info);
+               }
+       }
+}
+
+void ImageLoaderMachO::printStatistics(unsigned int imageCount)
+{
+       ImageLoader::printStatistics(imageCount);
+       fprintf(stderr, "total hinted binary tree searches:    %d\n", fgHintedBinaryTreeSearchs);
+       fprintf(stderr, "total unhinted binary tree searches:  %d\n", fgUnhintedBinaryTreeSearchs);
+       
+#if LINKEDIT_USAGE_DEBUG
+       fprintf(stderr, "linkedit pages accessed (%lu):\n", sLinkEditPageBuckets.size());
+#endif 
+}
+
+void ImageLoaderMachO::doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind)
+{
+       // update __DATA segment
+       this->applyPrebindingToDATA(fileToPrebind);
+       
+       // update load commands 
+       this->applyPrebindingToLoadCommands(context, fileToPrebind, timestamp);
+       
+       // update symbol table  
+       this->applyPrebindingToLinkEdit(context, fileToPrebind);
+}
+
+void ImageLoaderMachO::applyPrebindingToDATA(uint8_t* fileToPrebind)
+{
+       const unsigned int segmentCount = fSegments.size();
+       for(unsigned int i=0; i < segmentCount; ++i) {
+               SegmentMachO* seg = (SegmentMachO*)fSegments[i];
+               if ( seg->writeable() ) {
+                       memcpy(&fileToPrebind[seg->fFileOffset], (void*)seg->getActualLoadAddress(), seg->fFileSize);
+               }
+       }
+}
+
+void ImageLoaderMachO::applyPrebindingToLoadCommands(const LinkContext& context, uint8_t* fileToPrebind, time_t timestamp)
+{
+       macho_header* mh = (macho_header*)fileToPrebind;
+       const uint32_t cmd_count = mh->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fileToPrebind[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_LOAD_DYLIB:
+                       case LC_LOAD_WEAK_DYLIB:
+                               {
+                                       // update each dylib load command with the timestamp of the target dylib
+                                       struct dylib_command* dylib  = (struct dylib_command*)cmd;
+                                       const char* name = (char*)cmd + dylib->dylib.name.offset;
+                                       for (const DependentLibrary* dl=fLibraries; dl < &fLibraries[fLibrariesCount]; dl++) {
+                                               if (strcmp(dl->name, name) == 0 ) {
+                                                       // found matching DependentLibrary for this load command
+                                                       ImageLoaderMachO* targetImage = (ImageLoaderMachO*)(dl->image); // !!! assume only mach-o images are prebound
+                                                       if ( ! targetImage->isPrebindable() )
+                                                               throw "dependent dylib is not prebound";
+                                                       // if the target is currently being re-prebound then its timestamp will be the same as this one
+                                                       if ( ! targetImage->usablePrebinding(context) ) {
+                                                               dylib->dylib.timestamp = timestamp;
+                                                       }
+                                                       else {
+                                                               // otherwise dependent library is already correctly prebound, so use its checksum
+                                                               dylib->dylib.timestamp = targetImage->doGetLibraryInfo().checksum;
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                               }
+                               break;
+                       case LC_ID_DYLIB:
+                               {
+                                       // update the ID of this library with the new timestamp
+                                       struct dylib_command* dylib  = (struct dylib_command*)cmd;
+                                       dylib->dylib.timestamp = timestamp;
+                               }
+                               break;
+                       case LC_SEGMENT_COMMAND:
+                               // if dylib was rebased, update segment commands
+                               if ( fSlide != 0 ) {
+                                       struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       seg->vmaddr += fSlide;
+                                       struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               sect->addr += fSlide;
+                                       }
+                               }
+                               break;
+                       case LC_ROUTINES_COMMAND:
+                               // if dylib was rebased, update -init command
+                               if ( fSlide != 0 ) {
+                                       struct macho_routines_command* routines = (struct macho_routines_command*)cmd;
+                                       routines->init_address += fSlide;
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }       
+}
+
+void ImageLoaderMachO::applyPrebindingToLinkEdit(const LinkContext& context, uint8_t* fileToPrebind)
+{
+       // In prebound images, the n_value of the symbol table entry for is the prebound address
+       // This is needed when prebinding can't be used, to back solve for any possible addend in non-lazy pointers
+       const char* stringPool = NULL;
+       struct macho_nlist* symbolTable = NULL;
+       const struct dysymtab_command* dysymtab = NULL;
+       
+       // get symbol table info
+       macho_header* mh = (macho_header*)fileToPrebind;
+       const uint32_t cmd_count = mh->ncmds;
+       const struct load_command* const cmds = (struct load_command*)&fileToPrebind[sizeof(macho_header)];
+       const struct load_command* cmd = cmds;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SYMTAB:
+                               {
+                                       const struct symtab_command* symtab = (struct symtab_command*)cmd;
+                                       stringPool = (const char*)&fileToPrebind[symtab->stroff];
+                                       symbolTable = (struct macho_nlist*)(&fileToPrebind[symtab->symoff]);
+                               }
+                               break;
+                       case LC_DYSYMTAB:
+                               dysymtab = (struct dysymtab_command*)cmd;
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }       
+
+       // walk all imports and re-resolve their n_value (needed incase prebinding is invalid)
+       struct macho_nlist* lastImport = &symbolTable[dysymtab->iundefsym+dysymtab->nundefsym];
+       for (struct macho_nlist* entry = &symbolTable[dysymtab->iundefsym]; entry < lastImport; ++entry) {
+               ImageLoader* dummy;
+               entry->n_value = this->resolveUndefined(context, entry, this->usesTwoLevelNameSpace(), &dummy);
+       }
+       
+       // walk all exports and slide their n_value
+       struct macho_nlist* lastExport = &symbolTable[dysymtab->iextdefsym+dysymtab->nextdefsym];
+       for (struct macho_nlist* entry = &symbolTable[dysymtab->iextdefsym]; entry < lastExport; ++entry) {
+               entry->n_value += fSlide;
+       }
+
+       // walk all local symbols and slide their n_value
+       struct macho_nlist* lastLocal = &symbolTable[dysymtab->ilocalsym+dysymtab->nlocalsym];
+       for (struct macho_nlist* entry = &symbolTable[dysymtab->ilocalsym]; entry < lastLocal; ++entry) {
+               if ( (entry->n_type & N_TYPE) == N_SECT )
+                       entry->n_value += fSlide;
+       }
+       
+       // walk all local relocations and reset every PPC_RELOC_PB_LA_PTR r_value
+       relocation_info* const relocsStart = (struct relocation_info*)(&fileToPrebind[dysymtab->locreloff]);
+       relocation_info* const relocsEnd = &relocsStart[dysymtab->nlocrel];
+       for (relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+               if ( (reloc->r_address & R_SCATTERED) != 0 ) {
+                       struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
+                       if (sreloc->r_length == RELOC_SIZE) {
+                               switch(sreloc->r_type) {
+               #if __ppc__ || __ppc64__
+                                       case PPC_RELOC_PB_LA_PTR:
+               #elif __i386__
+                                       case GENERIC_RELOC_PB_LA_PTR:
+               #else
+                       #error unknown architecture
+               #endif
+                                               sreloc->r_value += fSlide;
+                                               break;
+                               }
+                       }
+               }
+       }
+
+}
+
+
+SegmentMachO::SegmentMachO(const struct macho_segment_command* cmd, ImageLoaderMachO* image, const uint8_t* fileData)
+ : fImage(image), fSize(cmd->vmsize), fFileSize(cmd->filesize), fFileOffset(cmd->fileoff), fPreferredLoadAddress(cmd->vmaddr), 
+       fVMProtection(cmd->initprot), fHasFixUps(false), fUnMapOnDestruction(false)
+{
+       strncpy(fName, cmd->segname, 16);
+       fName[16] = '\0';
+       // scan sections for fix-up bit
+       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)cmd + sizeof(struct macho_segment_command));
+       const struct macho_section* const sectionsEnd = &sectionsStart[cmd->nsects];
+       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+               if ( (sect->flags & (S_ATTR_EXT_RELOC | S_ATTR_LOC_RELOC)) != 0 )
+                       fHasFixUps = true;
+       }
+}
+
+SegmentMachO::~SegmentMachO()
+{
+       if ( fUnMapOnDestruction ) {
+               //fprintf(stderr, "unmapping segment %s at 0x%08lX\n", getName(), getActualLoadAddress());
+               munmap((void*)(this->getActualLoadAddress()), this->getSize());
+       }
+}
+
+const ImageLoader* SegmentMachO::getImage()
+{
+       return fImage;
+}
+
+const char* SegmentMachO::getName()
+{
+       return fName;
+}
+
+uintptr_t SegmentMachO::getSize()
+{
+       return fSize;
+}
+
+uintptr_t SegmentMachO::getFileSize()
+{
+       return fFileSize;
+}
+
+uintptr_t SegmentMachO::getFileOffset()
+{
+       return fFileOffset;
+}
+
+bool SegmentMachO::readable()
+{
+       return ( (fVMProtection & VM_PROT_READ) != 0);
+}
+
+bool SegmentMachO::writeable()
+{
+       return ((fVMProtection & VM_PROT_WRITE) != 0);
+}
+
+bool SegmentMachO::executable()
+{
+       return ((fVMProtection & VM_PROT_EXECUTE) != 0);
+}
+
+bool SegmentMachO::unaccessible()
+{
+       return (fVMProtection == 0);
+}
+
+bool SegmentMachO::hasFixUps()
+{
+       return fHasFixUps;
+}
+
+uintptr_t SegmentMachO::getActualLoadAddress()
+{
+       return fPreferredLoadAddress + fImage->fSlide;
+}
+
+uintptr_t SegmentMachO::getPreferredLoadAddress()
+{
+       return fPreferredLoadAddress;
+}
+
+bool SegmentMachO::hasPreferredLoadAddress()
+{
+       return (fPreferredLoadAddress != 0);
+}
+
+void SegmentMachO::setUnMapWhenDestructed(bool unmap)
+{
+       fUnMapOnDestruction = unmap;
+}
+
+static uint32_t *buildCRCTable(void)
+{
+       uint32_t *table = new uint32_t[256];
+       uint32_t p = 0xedb88320UL;  // standard CRC-32 polynomial
+
+       for (unsigned int i = 0; i < 256; i++) {
+               uint32_t c = i;
+               for (unsigned int j = 0; j < 8; j++) {
+                       if ( c & 1 ) c = p ^ (c >> 1);
+                       else c = c >> 1;
+               }
+               table[i] = c;
+       }
+
+       return table;
+}
+
+uint32_t SegmentMachO::crc32()
+{
+       if ( !readable() ) return 0;
+
+       static uint32_t *crcTable = NULL;
+       if ( !crcTable ) crcTable = buildCRCTable();
+       
+       uint32_t crc = ~(uint32_t)0;
+       uint8_t *p = (uint8_t *)getActualLoadAddress(); 
+       uint8_t *end = p + getSize();
+       while ( p < end ) {
+               crc = crcTable[(crc & 0xff) ^ (*p++)] ^ (crc >> 8);
+       }
+       return crc ^ ~(uint32_t)0;
+}
+
+
+
+
+
diff --git a/src/ImageLoaderMachO.h b/src/ImageLoaderMachO.h
new file mode 100644 (file)
index 0000000..acafd58
--- /dev/null
@@ -0,0 +1,209 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __IMAGELOADERMACHO__
+#define __IMAGELOADERMACHO__
+
+#include <stdint.h> 
+
+#include "ImageLoader.h"
+
+struct sf_mapping;
+struct _shared_region_mapping_np;
+
+//
+// ImageLoaderMachO is the concrete subclass of ImageLoader which loads mach-o format files.
+// The class is written to be 64-bit clean and support both 32-bit and 64-bit executables in
+// mach-o.
+//
+//
+class ImageLoaderMachO : public ImageLoader {
+public:
+                                                                               ImageLoaderMachO(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offset, uint64_t len, const struct stat& info, const LinkContext& context);
+                                                                               ImageLoaderMachO(const char* moduleName, const struct mach_header* mh, uint64_t len, const LinkContext& context);
+       virtual                                                         ~ImageLoaderMachO()  {}
+
+       const char*                                                     getInstallPath() const;
+       virtual void*                                           getMain() const;
+       virtual const struct mach_header*   machHeader() const;
+       virtual uintptr_t                                       getSlide() const;
+       virtual const void*                                     getBaseAddress() const;
+       virtual bool                                            hasCoalescedExports() const;
+       virtual const Symbol*                           findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const;
+       virtual uintptr_t                                       getExportedSymbolAddress(const Symbol* sym) const;
+       virtual DefinitionFlags                         getExportedSymbolInfo(const Symbol* sym) const;
+       virtual const char*                                     getExportedSymbolName(const Symbol* sym) const;
+       virtual uint32_t                                        getExportedSymbolCount() const;
+       virtual const Symbol*                           getIndexedExportedSymbol(uint32_t index) const;
+       virtual uint32_t                                        getImportedSymbolCount() const;
+       virtual const Symbol*                           getIndexedImportedSymbol(uint32_t index) const;
+       virtual ReferenceFlags                          geImportedSymbolInfo(const Symbol* sym) const;
+       virtual const char*                                     getImportedSymbolName(const Symbol* sym) const;
+       virtual bool                                            isBundle() const;
+       virtual bool                                            isDylib() const;
+       virtual bool                                            forceFlat() const;
+       virtual uintptr_t                                       doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context);
+       virtual void                                            doTermination(const LinkContext& context);
+       virtual void                                            doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
+       virtual bool                                            needsInitialization();
+       virtual bool                                            hasImageNotification();
+       virtual bool                                            getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length);
+       virtual bool                                            findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset);
+       virtual bool                                            usablePrebinding(const LinkContext& context) const;
+                       
+       
+       static void                                                     printStatistics(unsigned int imageCount);
+       
+protected:
+                                               ImageLoaderMachO(const ImageLoaderMachO&);
+       void                            operator=(const ImageLoaderMachO&);
+
+       virtual uint32_t        doGetDependentLibraryCount();
+       virtual void            doGetDependentLibraries(DependentLibrary libs[]);
+       virtual LibraryInfo doGetLibraryInfo();
+       virtual void            doRebase(const LinkContext& context);
+       virtual void            doBind(const LinkContext& context, BindingLaziness bindness);
+       virtual void            doInitialization(const LinkContext& context);
+       virtual void            doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind);
+       virtual bool            needsTermination();
+       virtual void            instantiateSegments(const uint8_t* fileData);
+       virtual bool            segmentsMustSlideTogether() const;      
+       virtual bool            segmentsCanSlide() const;                       
+       virtual void            setSlide(intptr_t slide);               
+       virtual bool            usesTwoLevelNameSpace() const;
+       virtual bool            isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const;
+       virtual bool            hasSubLibrary(const LinkContext& context, const ImageLoader* child) const;
+       virtual bool            isPrebindable() const;
+
+#if !__LP64__   // split segs not supported for 64-bits
+       virtual void            mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+#endif 
+               
+private:
+       friend class SegmentMachO;
+
+                       void            init();
+                       void            parseLoadCmds();
+                       void            doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols);
+                       void            doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols);
+                       uintptr_t       resolveUndefined(const LinkContext& context, const struct macho_nlist* symbol, bool twoLevel, ImageLoader **foundIn);
+                       uintptr_t       getRelocBase();
+                       void            doImageInit(const LinkContext& context);
+                       void            doModInitFunctions(const LinkContext& context);
+                       void            setupLazyPointerHandler();
+                       void            applyPrebindingToDATA(uint8_t* fileToPrebind);
+                       void            applyPrebindingToLoadCommands(const LinkContext& context, uint8_t* fileToPrebind, time_t timestamp);
+                       void            applyPrebindingToLinkEdit(const LinkContext& context, uint8_t* fileToPrebind);
+#if !__LP64__   // split segs not supported for 64-bits
+                       unsigned int getExtraZeroFillEntriesCount();
+                       int                     sharedRegionLoadFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+                       int                     sharedRegionMapFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+                       int                     sharedRegionMakePrivate(const LinkContext& context);
+                       int                     sharedRegionMapFilePrivate(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+                       int                     sharedRegionMapFilePrivateOutside(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+                       void            initMappingTable(uint64_t offsetInFat, sf_mapping *mappingTable, uintptr_t baseAddress);
+                       void            initMappingTable(uint64_t offsetInFat, _shared_region_mapping_np *mappingTable);
+#endif
+                       bool            needsCoalescing() const;
+                       
+       static  bool                            symbolRequiresCoalescing(const struct macho_nlist* symbol); 
+       static uintptr_t                        bindLazySymbol(const mach_header*, uintptr_t* lazyPointer);
+       static const struct macho_nlist*  binarySearch(const char* key, const char stringPool[], const struct macho_nlist symbols[], uint32_t symbolCount);
+       static const struct macho_nlist*  binarySearchWithToc(const char* key, const char stringPool[], const struct macho_nlist symbols[], 
+                                                                                               const struct dylib_table_of_contents toc[], uint32_t symbolCount, uint32_t hintIndex);
+                       
+       const uint8_t*                                                  fMachOData;
+       const uint8_t*                                                  fLinkEditBase; // add any internal "offset" to this to get actual address
+       const struct macho_nlist*                               fSymbolTable;
+       const char*                                                             fStrings;
+       const struct dysymtab_command*                  fDynamicInfo;
+       uintptr_t                                                               fSlide;
+       bool                                                                    fIsSplitSeg;
+       bool                                                                    fHasSubLibraries;
+       bool                                                                    fHasSubUmbrella;
+       bool                                                                    fTextSegmentHasFixups;
+       const struct macho_routines_command*    fDashInit;
+       const struct macho_section*                             fModInitSection;
+       const struct macho_section*                             fModTermSection;
+       const struct macho_section*                             fDATAdyld;
+       const struct macho_section*                             fImageNotifySection;
+       const struct twolevel_hints_command*    fTwoLevelHints;
+       const struct dylib_command*                             fDylibID;
+       const char*                                                             fReExportThruFramework;
+       SegmentMachO*                                                   fTextSegmentWithFixups; // NULL unless __TEXT segment has fixups
+
+       static uint32_t                                 fgHintedBinaryTreeSearchs;
+       static uint32_t                                 fgUnhintedBinaryTreeSearchs;
+};
+
+
+class SegmentMachO : public Segment
+{
+public:        
+                                                               SegmentMachO(const struct macho_segment_command* cmd, ImageLoaderMachO*, const uint8_t* fileData);
+       virtual                                         ~SegmentMachO();
+                                                               
+       virtual const ImageLoader*      getImage();
+       virtual const char*                     getName();
+       virtual uintptr_t                       getSize();
+       virtual uintptr_t                       getFileSize();
+       virtual uintptr_t                       getFileOffset();
+       virtual bool                            readable();
+       virtual bool                            writeable();
+       virtual bool                            executable();
+       virtual bool                            unaccessible();
+       virtual bool                            hasFixUps();
+       virtual uintptr_t                       getActualLoadAddress();
+       virtual uintptr_t                       getPreferredLoadAddress();
+       virtual void                            setUnMapWhenDestructed(bool unmap);
+       virtual uint32_t                        crc32();
+
+protected:
+       virtual bool                            hasPreferredLoadAddress();
+       
+private:
+                                               SegmentMachO(const SegmentMachO&);
+       void                            operator=(const SegmentMachO&);
+
+       friend class ImageLoaderMachO;
+       
+
+       ImageLoaderMachO* const fImage;
+       char                                    fName[18];
+       const uintptr_t                 fSize;
+       const uintptr_t                 fFileSize;
+       const uintptr_t                 fFileOffset;
+       const uintptr_t                 fPreferredLoadAddress;
+       const uint16_t                  fVMProtection;
+       bool                                    fHasFixUps;
+       bool                                    fUnMapOnDestruction;
+};
+
+
+#endif // __IMAGELOADERMACHO__
+
+
+
+
diff --git a/src/dyld.cpp b/src/dyld.cpp
new file mode 100644 (file)
index 0000000..1be0973
--- /dev/null
@@ -0,0 +1,1965 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/param.h>
+#include <mach/mach_time.h> // mach_absolute_time()
+#include <sys/types.h>
+#include <sys/stat.h> 
+#include <mach-o/fat.h> 
+#include <mach-o/loader.h> 
+#include <libkern/OSByteOrder.h> 
+#include <mach/mach.h>
+#include <sys/sysctl.h>
+
+#include <vector>
+
+#include "mach-o/dyld_gdb.h"
+
+#include "dyld.h"
+#include "ImageLoader.h"
+#include "ImageLoaderMachO.h"
+#include "dyldLibSystemThreadHelpers.h"
+
+
+#define CPU_TYPE_MASK 0x00FFFFFF       /* complement of CPU_ARCH_MASK */
+
+
+/* implemented in dyld_gdb.cpp */
+void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]);
+void removeImageFromAllImages(const mach_header* mh);
+#if OLD_GDB_DYLD_INTERFACE
+void addImageForgdb(const mach_header* mh, uintptr_t slide, const char* physicalPath, const char* logicalPath);
+void removeImageForgdb(const struct mach_header* mh);
+#endif
+
+// magic so CrashReporter logs message
+extern "C" {
+       char error_string[1024];
+}
+
+
+//
+// The file contains the core of dyld used to get a process to main().  
+// The API's that dyld supports are implemented in dyldAPIs.cpp.
+//
+//
+//
+//
+//
+
+
+namespace dyld {
+
+
+// 
+// state of all environment variables dyld uses
+//
+struct EnvironmentVariables {
+       const char* const *                     DYLD_FRAMEWORK_PATH;
+       const char* const *                     DYLD_FALLBACK_FRAMEWORK_PATH;
+       const char* const *                     DYLD_LIBRARY_PATH;
+       const char* const *                     DYLD_FALLBACK_LIBRARY_PATH;
+       const char*     const *                 DYLD_ROOT_PATH;
+       const char* const *                     DYLD_INSERT_LIBRARIES;
+       const char* const *                     LD_LIBRARY_PATH;                        // for unix conformance
+       bool                                            DYLD_PRINT_LIBRARIES;
+       bool                                            DYLD_PRINT_LIBRARIES_POST_LAUNCH;
+       bool                                            DYLD_BIND_AT_LAUNCH;
+       bool                                            DYLD_PRINT_STATISTICS;
+       bool                                            DYLD_PRINT_OPTS;
+       bool                                            DYLD_PRINT_ENV;
+                                                       //      DYLD_IMAGE_SUFFIX                               ==> gLinkContext.imageSuffix
+                                                       //      DYLD_PRINT_OPTS                                 ==> gLinkContext.verboseOpts
+                                                       //      DYLD_PRINT_ENV                                  ==> gLinkContext.verboseEnv
+                                                       //      DYLD_FORCE_FLAT_NAMESPACE               ==> gLinkContext.bindFlat
+                                                       //      DYLD_PRINT_INITIALIZERS                 ==> gLinkContext.verboseInit
+                                                       //      DYLD_PRINT_SEGMENTS                             ==> gLinkContext.verboseMapping
+                                                       //      DYLD_PRINT_BINDINGS                             ==> gLinkContext.verboseBind
+                                                       //      DYLD_PRINT_REBASINGS                    ==> gLinkContext.verboseRebase
+                                                       //      DYLD_PRINT_APIS                                 ==> gLogAPIs
+                                                       //      DYLD_IGNORE_PREBINDING                  ==> gLinkContext.prebindUsage
+                                                       //      DYLD_PREBIND_DEBUG                              ==> gLinkContext.verbosePrebinding
+                                                       //      DYLD_NEW_LOCAL_SHARED_REGIONS   ==> gLinkContext.sharedRegionMode
+                                                       //      DYLD_SHARED_REGION                              ==> gLinkContext.sharedRegionMode
+                                                       //      DYLD_SLIDE_AND_PACK_DYLIBS              ==> gLinkContext.slideAndPackDylibs
+                                                       //      DYLD_PRINT_WARNINGS                             ==> gLinkContext.verboseWarnings
+};
+
+// all global state
+static const char*                                     sExecPath = NULL;
+static const struct mach_header*       sMainExecutableMachHeader = NULL;
+static cpu_type_t                                      sHostCPU;
+static cpu_subtype_t                           sHostCPUsubtype;
+static ImageLoader*                                    sMainExecutable = NULL;
+static std::vector<ImageLoader*>       sAllImages;
+static std::vector<ImageLoader*>       sImageRoots;
+static std::vector<ImageLoader*>       sImageFilesNeedingTermination;
+static std::vector<ImageLoader*>       sImagesToNotifyAboutOtherImages;
+static std::vector<ImageCallback>   sAddImageCallbacks;
+static std::vector<ImageCallback>   sRemoveImageCallbacks;
+static ImageLoader*                                    sLastImageByAddressCache;
+static EnvironmentVariables                    sEnv;
+static const char*                                     sFrameworkFallbackPaths[] = { "$HOME/Library/Frameworks", "/Library/Frameworks", "/Network/Library/Frameworks", "/System/Library/Frameworks", NULL };
+static const char*                                     sLibraryFallbackPaths[] = { "$HOME/lib", "/usr/local/lib", "/usr/lib", NULL };
+static BundleNotificationCallBack   sBundleNotifier = NULL;
+static BundleLocatorCallBack           sBundleLocation = NULL;
+static UndefinedHandler                                sUndefinedHandler = NULL;
+ImageLoader::LinkContext                       gLinkContext;
+bool                                                           gLogAPIs = false;
+const struct ThreadingHelpers*         gThreadHelpers = NULL;
+
+
+
+// utility class to assure files are closed when an exception is thrown
+class FileOpener {
+public:
+       FileOpener(const char* path);
+       ~FileOpener();
+       int getFileDescriptor() { return fd; }
+private:
+       int fd;
+};
+
+FileOpener::FileOpener(const char* path)
+{
+       fd = open(path, O_RDONLY, 0);
+}
+
+FileOpener::~FileOpener()
+{
+       close(fd);
+}
+
+
+
+// Objective-C installs an addImage hook to dyld to get notified about new images
+// The callback needs to be run after the image is rebased and bound, but before its initializers are called
+static uint32_t imageNotification(ImageLoader* image, uint32_t startIndex)
+{
+       // tell all register add image handlers about this
+       const uint32_t callbackCount = sAddImageCallbacks.size();
+       for (uint32_t i=startIndex; i < callbackCount; ++i) {
+               ImageCallback cb = sAddImageCallbacks[i];
+               //fprintf(stderr, "dyld: calling add-image-callback[%d]=%p for %s\n", i, cb, image->getPath());
+               (cb)(image->machHeader(), image->getSlide());
+       }
+       return callbackCount;
+}
+
+
+
+// notify gdb et al about these new images
+static void notifyAdding(std::vector<ImageLoader*>& images)
+{
+       // build array
+       unsigned int len = images.size();
+       if ( len != 0 ) {
+               dyld_image_info infos[len];
+               for (unsigned int i=0; i < len; ++i) {
+                       dyld_image_info* p = &infos[i];
+                       ImageLoader* image = images[i];
+                       p->imageLoadAddress = image->machHeader();
+                       p->imageFilePath = image->getPath();
+                       p->imageFileModDate = image->lastModified();
+                       //fprintf(stderr, "notifying objc about %s\n", image->getPath());
+               }
+               
+               // tell gdb
+               addImagesToAllImages(len, infos);
+                               
+               // tell all interested images (after gdb, so you can debug anything the notification does)
+               for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
+                       (*it)->doNotification(dyld_image_adding, len, infos);
+               }
+       }
+}
+
+
+
+// In order for register_func_for_add_image() callbacks to to be called bottom up,
+// we need to maintain a list of root images. The main executable is usally the
+// first root. Any images dynamically added are also roots (unless already loaded).
+// If DYLD_INSERT_LIBRARIES is used, those libraries are first.
+static void addRootImage(ImageLoader* image)
+{
+       //fprintf(stderr, "addRootImage(%p, %s)\n", image, image->getPath());
+       // add to list of roots
+       sImageRoots.push_back(image);
+}
+
+// Objective-C will contain a __DATA/__image_notify section which contains pointers to a function to call
+// whenever any new image is loaded.
+static void addImageNeedingNotification(ImageLoader* image)
+{
+       sImagesToNotifyAboutOtherImages.push_back(image);
+}
+
+static void addImage(ImageLoader* image)
+{
+       // add to master list
+       sAllImages.push_back(image);
+       
+       if ( sEnv.DYLD_PRINT_LIBRARIES || (sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH && (sMainExecutable!=NULL) && sMainExecutable->isLinked()) ) {
+               uint64_t offset = image->getOffsetInFatFile();
+               if ( offset == 0 )
+                       fprintf(stderr, "dyld: loaded: %s\n", image->getPath());
+               else
+                       fprintf(stderr, "dyld: loaded: %s, cpu-sub-type: %d\n", image->getPath(), image->machHeader()->cpusubtype);
+       }
+       
+#if OLD_GDB_DYLD_INTERFACE
+       // let gdb find out about this
+       addImageForgdb(image->machHeader(), image->getSlide(), image->getPath(), image->getLogicalPath());
+#endif
+}
+
+void removeImage(ImageLoader* image)
+{
+       // flush find-by-address cache
+       if ( sLastImageByAddressCache == image )
+               sLastImageByAddressCache = NULL;
+
+       // if in termination list, pull it out and run terminator
+       for (std::vector<ImageLoader*>::iterator it=sImageFilesNeedingTermination.begin(); it != sImageFilesNeedingTermination.end(); it++) {
+               if ( *it == image ) {
+                       sImageFilesNeedingTermination.erase(it);
+                       image->doTermination(gLinkContext);
+                       break;
+               }
+       }
+       
+       // tell all register add image handlers about this
+       // do this before removing image from internal data structures so that the callback can querey dyld about the image
+       for (std::vector<ImageCallback>::iterator it=sRemoveImageCallbacks.begin(); it != sRemoveImageCallbacks.end(); it++) {
+               (*it)(image->machHeader(), image->getSlide());
+       }
+       
+       // remove from master list
+       for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+               if ( *it == image ) {
+                       sAllImages.erase(it);
+                       break;
+               }
+       }
+       
+       // if in announcement list, pull it out 
+       for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
+               if ( *it == image ) {
+                       sImagesToNotifyAboutOtherImages.erase(it);
+                       break;
+               }
+       }
+
+       // if in root list, pull it out 
+       for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
+               if ( *it == image ) {
+                       sImageRoots.erase(it);
+                       break;
+               }
+       }
+
+       // tell gdb, new way
+       removeImageFromAllImages(image->machHeader());
+
+#if OLD_GDB_DYLD_INTERFACE
+       // tell gdb, old way
+       removeImageForgdb(image->machHeader());
+       gdb_dyld_state_changed();
+#endif
+}
+
+
+static void terminationRecorder(ImageLoader* image)
+{
+       sImageFilesNeedingTermination.push_back(image);
+}
+
+const char* getExecutablePath()
+{
+       return sExecPath;
+}
+
+
+void initializeMainExecutable()
+{
+       const int rootCount = sImageRoots.size();
+       for(int i=0; i < rootCount; ++i) {
+               ImageLoader* image = sImageRoots[i];
+               //fprintf(stderr, "initializeMainExecutable: image = %p\n", image);
+               image->runInitializers(gLinkContext);
+       }
+/*
+       // this does not work???
+       for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
+               ImageLoader* image = *it;
+               fprintf(stderr, "initializeMainExecutable: image = %p\n", image);
+               // don't know why vector sometimes starts with NULL element???
+               if ( image != NULL ) 
+                       image->runInitializers(gLinkContext);
+       }
+*/
+       if ( sEnv.DYLD_PRINT_STATISTICS )
+               ImageLoaderMachO::printStatistics(sAllImages.size());
+}
+
+bool mainExecutablePrebound()
+{
+       return sMainExecutable->usablePrebinding(gLinkContext);
+}
+
+ImageLoader* mainExecutable()
+{
+       return sMainExecutable;
+}
+
+
+void runTerminators()
+{
+       const unsigned int imageCount = sImageFilesNeedingTermination.size();
+       for(unsigned int i=imageCount; i > 0; --i){
+               ImageLoader* image = sImageFilesNeedingTermination[i-1];
+               image->doTermination(gLinkContext);
+       }
+       sImageFilesNeedingTermination.clear();
+}
+
+
+//
+// Turns a colon separated list of strings
+// into a NULL terminated array of string 
+// pointers.
+//
+static const char** parseColonList(const char* list)
+{
+       if ( list[0] == '\0' )
+               return NULL;
+
+       int colonCount = 0;
+       for(const char* s=list; *s != '\0'; ++s) {
+               if (*s == ':') 
+                       ++colonCount;
+       }
+       
+       int index = 0;
+       const char* start = list;
+       char** result = new char*[colonCount+2];
+       for(const char* s=list; *s != '\0'; ++s) {
+               if (*s == ':') {
+                       int len = s-start;
+                       char* str = new char[len+1];
+                       strncpy(str, start, len);
+                       str[len] = '\0';
+                       start = &s[1];
+                       result[index++] = str;
+               }
+       }
+       int len = strlen(start);
+       char* str = new char[len+1];
+       strcpy(str, start);
+       result[index++] = str;
+       result[index] = NULL;
+       
+       return (const char**)result;
+}
+
+/*
+ * Library path searching is not done for setuid programs
+ * which are not run by the real user.  Futher the
+ * evironment varaible for the library path is cleared so
+ * that if this program executes a non-set uid program this
+ * part of the evironment will not be passed along so that
+ * that program also will not have it's libraries searched
+ * for.
+ */
+ static bool riskyUser()
+ {
+       static bool checked = false;
+       static bool risky = false;
+       if ( !checked ) {
+               risky = ( getuid() != 0 && (getuid() != geteuid() || getgid() != getegid()) );
+               checked = true;
+       }
+       return risky;
+ }
+static bool disableIfBadUser(char* rhs)
+{
+       bool didDisable = false;
+       if ( riskyUser() ) {
+               *rhs ='\0';
+               didDisable = true;
+       }
+       return didDisable;
+}
+
+static void paths_expand_roots(const char **paths, const char *key, const char *val)
+{
+//     assert(val != NULL);
+//     assert(paths != NULL);
+       if(NULL != key) {
+               size_t keyLen = strlen(key);
+               for(int i=0; paths[i] != NULL; ++i) {
+                       if ( strncmp(paths[i], key, keyLen) == 0 ) {
+                               char* newPath = new char[strlen(val) + (strlen(paths[i]) - keyLen) + 1];
+                               strcpy(newPath, val);
+                               strcat(newPath, &paths[i][keyLen]);
+                               paths[i] = newPath;
+                       }
+               }
+       }
+       return;
+}
+
+static void removePathWithPrefix(const char* paths[], const char* prefix)
+{
+       size_t prefixLen = strlen(prefix);
+       for(int s=0,d=0; (paths[d] != NULL) && (paths[s] != NULL); ++s, ++d) {
+               if ( strncmp(paths[s], prefix, prefixLen) == 0 )
+                       ++s;
+               paths[d] = paths[s];
+       }
+}
+
+#if 0
+static void paths_dump(const char **paths)
+{
+//   assert(paths != NULL);
+  const char **strs = paths;
+  while(*strs != NULL)
+  {
+    fprintf(stderr, "\"%s\"\n", *strs);
+    strs++;
+  }
+  return;
+}
+#endif
+
+static void printOptions(const char* argv[])
+{
+       uint32_t i = 0;
+       while ( NULL != argv[i] ) {
+               fprintf(stderr, "opt[%i] = \"%s\"\n", i, argv[i]);
+               i++;
+       }
+}
+
+static void printEnvironmentVariables(const char* envp[])
+{
+       while ( NULL != *envp ) {
+               fprintf(stderr, "%s\n", *envp);
+               envp++;
+       }
+}
+
+
+
+void processDyldEnvironmentVarible(const char* key, const char* value)
+{
+       if ( strcmp(key, "DYLD_FRAMEWORK_PATH") == 0 ) {
+               if ( !disableIfBadUser((char*)value) )
+                       sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
+       }
+       else if ( strcmp(key, "DYLD_FALLBACK_FRAMEWORK_PATH") == 0 ) {
+               if ( !disableIfBadUser((char*)value) )
+                       sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
+       }
+       else if ( strcmp(key, "DYLD_LIBRARY_PATH") == 0 ) {
+               if ( !disableIfBadUser((char*)value) )
+                       sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
+       }
+       else if ( strcmp(key, "DYLD_FALLBACK_LIBRARY_PATH") == 0 ) {
+               if ( !disableIfBadUser((char*)value) )
+                       sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
+       }
+       else if ( (strcmp(key, "DYLD_ROOT_PATH") == 0) || (strcmp(key, "DYLD_PATHS_ROOT") == 0) ) {
+               if ( !disableIfBadUser((char*)value) ) {
+                       if ( strcmp(value, "/") != 0 ) {
+                               sEnv.DYLD_ROOT_PATH = parseColonList(value);
+                               for (int i=0; sEnv.DYLD_ROOT_PATH[i] != NULL; ++i) {
+                                       if ( sEnv.DYLD_ROOT_PATH[i][0] != '/' ) {
+                                               fprintf(stderr, "dyld: warning DYLD_ROOT_PATH not used because it contains a non-absolute path");
+                                               sEnv.DYLD_ROOT_PATH = NULL;
+                                       }
+                               }
+                       }
+               }
+       } 
+       else if ( strcmp(key, "DYLD_IMAGE_SUFFIX") == 0 ) {
+               if ( !disableIfBadUser((char*)value) )
+                       gLinkContext.imageSuffix = value;
+       }
+       else if ( strcmp(key, "DYLD_INSERT_LIBRARIES") == 0 ) {
+               if ( !disableIfBadUser((char*)value) )
+                       sEnv.DYLD_INSERT_LIBRARIES = parseColonList(value);
+       }
+       else if ( strcmp(key, "DYLD_DEBUG_TRACE") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_DEBUG_TRACE not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_ERROR_PRINT") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_ERROR_PRINT not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_PRINT_OPTS") == 0 ) {
+               sEnv.DYLD_PRINT_OPTS = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_ENV") == 0 ) {
+               sEnv.DYLD_PRINT_ENV = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_LIBRARIES") == 0 ) {
+               sEnv.DYLD_PRINT_LIBRARIES = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_LIBRARIES_POST_LAUNCH") == 0 ) {
+               sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH = true;
+       }
+       else if ( strcmp(key, "DYLD_TRACE") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_TRACE not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_EBADEXEC_ONLY") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_EBADEXEC_ONLY not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_BIND_AT_LAUNCH") == 0 ) {
+               sEnv.DYLD_BIND_AT_LAUNCH = true;
+       }
+       else if ( strcmp(key, "DYLD_FORCE_FLAT_NAMESPACE") == 0 ) {
+               gLinkContext.bindFlat = true;
+       }
+       else if ( strcmp(key, "DYLD_DEAD_LOCK_HANG") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_DEAD_LOCK_HANG not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_ABORT_MULTIPLE_INITS") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_ABORT_MULTIPLE_INITS not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_NEW_LOCAL_SHARED_REGIONS") == 0 ) {
+               gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
+       }
+       else if ( strcmp(key, "DYLD_SLIDE_AND_PACK_DYLIBS") == 0 ) {
+               gLinkContext.slideAndPackDylibs = true;
+       }
+       else if ( strcmp(key, "DYLD_NO_FIX_PREBINDING") == 0 ) {
+               // since the new dyld never runs fix_prebinding, no need to warn if someone does not want it run
+               //fprintf(stderr, "dyld: warning DYLD_NO_FIX_PREBINDING not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_PREBIND_DEBUG") == 0 ) {
+               gLinkContext.verbosePrebinding = true;
+       }
+       else if ( strcmp(key, "DYLD_HINTS_DEBUG") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_HINTS_DEBUG not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_SAMPLE_DEBUG") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_SAMPLE_DEBUG not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_EXECUTABLE_PATH_DEBUG") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_EXECUTABLE_PATH_DEBUG not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_TWO_LEVEL_DEBUG") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_TWO_LEVEL_DEBUG not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_LAZY_INITIALIZERS") == 0 ) {
+               fprintf(stderr, "dyld: warning DYLD_LAZY_INITIALIZERS not supported\n");
+       }
+       else if ( strcmp(key, "DYLD_PRINT_INITIALIZERS") == 0 ) {
+               gLinkContext.verboseInit = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_STATISTICS") == 0 ) {
+               sEnv.DYLD_PRINT_STATISTICS = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_SEGMENTS") == 0 ) {
+               gLinkContext.verboseMapping = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_BINDINGS") == 0 ) {
+               gLinkContext.verboseBind = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_REBASINGS") == 0 ) {
+               gLinkContext.verboseRebase = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_APIS") == 0 ) {
+               gLogAPIs = true;
+       }
+       else if ( strcmp(key, "DYLD_PRINT_WARNINGS") == 0 ) {
+               gLinkContext.verboseWarnings = true;
+       }
+       else if ( strcmp(key, "DYLD_SHARED_REGION") == 0 ) {
+               if ( strcmp(value, "private") == 0 ) {
+                       gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
+               }
+               else if ( strcmp(value, "avoid") == 0 ) {
+                       gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
+               }
+               else if ( strcmp(value, "use") == 0 ) {
+                       gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
+               }
+               else if ( value[0] == '\0' ) {
+                       gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
+               }
+               else {
+                       fprintf(stderr, "dyld: warning unknown option to DYLD_SHARED_REGION.  Valid options are: use, private, avoid\n");
+               }
+       }
+       else if ( strcmp(key, "DYLD_IGNORE_PREBINDING") == 0 ) {
+               if ( strcmp(value, "all") == 0 ) {
+                       gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
+               }
+               else if ( strcmp(value, "app") == 0 ) {
+                       gLinkContext.prebindUsage = ImageLoader::kUseAllButAppPredbinding;
+               }
+               else if ( strcmp(value, "nonsplit") == 0 ) {
+                       gLinkContext.prebindUsage = ImageLoader::kUseSplitSegPrebinding;
+               }
+               else if ( value[0] == '\0' ) {
+                       gLinkContext.prebindUsage = ImageLoader::kUseSplitSegPrebinding;
+               }
+               else {
+                       fprintf(stderr, "dyld: warning unknown option to DYLD_IGNORE_PREBINDING.  Valid options are: all, app, nonsplit\n");
+               }
+       }
+       else {
+               fprintf(stderr, "dyld: warning, unknown environment variable: %s\n", key);
+       }
+}
+
+static void checkEnvironmentVariables(const char* envp[])
+{
+       const char* home = NULL;
+       const char** p;
+       for(p = envp; *p != NULL; p++) {
+               const char* keyEqualsValue = *p;
+           if ( strncmp(keyEqualsValue, "DYLD_", 5) == 0 ) {
+                       const char* equals = strchr(keyEqualsValue, '=');
+                       if ( equals != NULL ) {
+                               const char* value = &equals[1];
+                               const int keyLen = equals-keyEqualsValue;
+                               char key[keyLen];
+                               strncpy(key, keyEqualsValue, keyLen);
+                               key[keyLen] = '\0';
+                               processDyldEnvironmentVarible(key, value);
+                       }
+               }
+           else if ( strncmp(keyEqualsValue, "HOME=", 5) == 0 ) {
+                       home = &keyEqualsValue[5];
+               }
+               else if ( strncmp(keyEqualsValue, "LD_LIBRARY_PATH=", 16) == 0 ) {
+                       const char* path = &keyEqualsValue[16];
+                       if ( !disableIfBadUser((char*)path) )
+                               sEnv.LD_LIBRARY_PATH = parseColonList(path);
+               }
+       }
+       
+       // default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
+       if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
+               const char** paths = sFrameworkFallbackPaths;
+               if ( home != NULL ) {
+                       if ( riskyUser() )
+                               removePathWithPrefix(paths, "$HOME");
+                       else
+                               paths_expand_roots(paths, "$HOME", home);
+               }
+               sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
+       }
+
+       // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
+       if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
+               const char** paths = sLibraryFallbackPaths;
+               if ( home != NULL ) {
+                       if ( riskyUser() )
+                               removePathWithPrefix(paths, "$HOME");
+                       else
+                               paths_expand_roots(paths, "$HOME", home);
+               }
+               sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
+       }
+}
+
+
+static void getHostInfo()
+{
+#if 0
+       struct host_basic_info info;
+       mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
+       mach_port_t hostPort = mach_host_self();
+       kern_return_t result = host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&info, &count);
+       mach_port_deallocate(mach_task_self(), hostPort);
+       if ( result != KERN_SUCCESS )
+               throw "host_info() failed";
+       
+       sHostCPU                = info.cpu_type;
+       sHostCPUsubtype = info.cpu_subtype;
+#endif
+
+       size_t valSize = sizeof(sHostCPU);
+       if (sysctlbyname ("hw.cputype", &sHostCPU, &valSize, NULL, 0) != 0) 
+               throw "sysctlbyname(hw.cputype) failed";
+       valSize = sizeof(sHostCPUsubtype);
+       if (sysctlbyname ("hw.cpusubtype", &sHostCPUsubtype, &valSize, NULL, 0) != 0) 
+               throw "sysctlbyname(hw.cpusubtype) failed";
+}
+
+bool validImage(ImageLoader* possibleImage)
+{
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i) {
+               if ( possibleImage == sAllImages[i] ) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+uint32_t getImageCount()
+{
+       return sAllImages.size();
+}
+
+ImageLoader* getIndexedImage(unsigned int index)
+{
+       if ( index < sAllImages.size() )
+               return sAllImages[index];
+       else
+               return NULL;
+}
+
+ImageLoader* findImageByMachHeader(const struct mach_header* target)
+{
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i) {
+               ImageLoader* anImage = sAllImages[i];
+               if ( anImage->machHeader() == target )
+                       return anImage;
+       }
+       return NULL;
+}
+
+
+ImageLoader* findImageContainingAddress(const void* addr)
+{
+#if FIND_STATS 
+       static int cacheHit = 0; 
+       static int cacheMiss = 0; 
+       static int cacheNotMacho = 0; 
+       if ( ((cacheHit+cacheMiss+cacheNotMacho) % 100) == 0 )
+               fprintf(stderr, "findImageContainingAddress(): cache hit = %d, miss = %d, unknown = %d\n", cacheHit, cacheMiss, cacheNotMacho);
+#endif
+       // first look in image where last address was found rdar://problem/3685517
+       if ( (sLastImageByAddressCache != NULL) && sLastImageByAddressCache->containsAddress(addr) ) {
+#if FIND_STATS 
+               ++cacheHit;
+#endif
+               return sLastImageByAddressCache;
+       }
+       // do exhastive search 
+       // todo: consider maintaining a list sorted by address ranges and do a binary search on that
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i) {
+               ImageLoader* anImage = sAllImages[i];
+               if ( anImage->containsAddress(addr) ) {
+                       sLastImageByAddressCache = anImage;
+#if FIND_STATS 
+               ++cacheMiss;
+#endif
+                       return anImage;
+               }
+       }
+#if FIND_STATS 
+               ++cacheNotMacho;
+#endif
+       return NULL;
+}
+
+
+void forEachImageDo( void (*callback)(ImageLoader*, void* userData), void* userData)
+{
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i) {
+               ImageLoader* anImage = sAllImages[i];
+               (*callback)(anImage, userData);
+       }
+}
+
+ImageLoader* findLoadedImage(const struct stat& stat_buf)
+{
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i){
+               ImageLoader* anImage = sAllImages[i];
+               if ( anImage->statMatch(stat_buf) )
+                       return anImage;
+       }
+       return NULL;
+}
+
+// based on ANSI-C strstr()
+static const char* strrstr(const char* str, const char* sub) 
+{
+       const int sublen = strlen(sub);
+       for(const char* p = &str[strlen(str)]; p != str; --p) {
+               if ( strncmp(p, sub, sublen) == 0 )
+                       return p;
+       }
+       return NULL;
+}
+
+
+//
+// Find framework path
+//
+//  /path/foo.framework/foo                                                            =>   foo.framework/foo  
+//  /path/foo.framework/Versions/A/foo                                 =>   foo.framework/Versions/A/foo
+//  /path/foo.framework/Frameworks/bar.framework/bar   =>   bar.framework/bar
+//  /path/foo.framework/Libraries/bar.dylb                             =>   NULL
+//  /path/foo.framework/bar                                                            =>   NULL
+//
+// Returns NULL if not a framework path
+//
+static const char* getFrameworkPartialPath(const char* path)
+{
+       const char* dirDot = strrstr(path, ".framework/");
+       if ( dirDot != NULL ) {
+               const char* dirStart = dirDot;
+               for ( ; dirStart >= path; --dirStart) {
+                       if ( (*dirStart == '/') || (dirStart == path) ) {
+                               const char* frameworkStart = &dirStart[1];
+                               if ( dirStart == path )
+                                       --frameworkStart;
+                               int len = dirDot - frameworkStart;
+                               char framework[len+1];
+                               strncpy(framework, frameworkStart, len);
+                               framework[len] = '\0';
+                               const char* leaf = strrchr(path, '/');
+                               if ( leaf != NULL ) {
+                                       if ( strcmp(framework, &leaf[1]) == 0 ) {
+                                               return frameworkStart;
+                                       }
+                                       if (  gLinkContext.imageSuffix != NULL ) {
+                                               // some debug frameworks have install names that end in _debug
+                                               if ( strncmp(framework, &leaf[1], len) == 0 ) {
+                                                       if ( strcmp( gLinkContext.imageSuffix, &leaf[len+1]) == 0 )
+                                                               return frameworkStart;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
+
+
+static const char* getLibraryLeafName(const char* path)
+{
+       const char* start = strrchr(path, '/');
+       if ( start != NULL )
+               return &start[1];
+       else
+               return path;
+}
+
+
+
+const cpu_subtype_t CPU_SUBTYPE_END_OF_LIST = -1;
+
+
+//
+//     A fat file may contain multiple sub-images for the same CPU type.
+//     In that case, dyld picks which sub-image to use by scanning a table
+//     of preferred cpu-sub-types for the running cpu.  
+//     
+//     There is one row in the table for each cpu-sub-type on which dyld might run.
+//  The first entry in a row is that cpu-sub-type.  It is followed by all
+//     cpu-sub-types that can run on that cpu, if preferred order.  Each row ends with 
+//     a "SUBTYPE_ALL" (to denote that images written to run on any cpu-sub-type are usable), 
+//  followed by one or more CPU_SUBTYPE_END_OF_LIST to pad out this row.
+//
+
+
+//      
+//     32-bit PowerPC sub-type lists
+//
+const int kPPC_RowCount = 4;
+static const cpu_subtype_t kPPC32[kPPC_RowCount][6] = { 
+       // G5 can run any code
+       {  CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_7450,  CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST },
+       
+       // G4 can run all but G5 code
+       {  CPU_SUBTYPE_POWERPC_7450,  CPU_SUBTYPE_POWERPC_7400,  CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
+       {  CPU_SUBTYPE_POWERPC_7400,  CPU_SUBTYPE_POWERPC_7450,  CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
+
+       // G3 cannot run G4 or G5 code
+       { CPU_SUBTYPE_POWERPC_750,  CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST,  CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST }
+};
+
+
+//      
+//     64-bit PowerPC sub-type lists
+//
+const int kPPC64_RowCount = 1;
+static const cpu_subtype_t kPPC64[kPPC64_RowCount][3] = { 
+       // G5 can run any 64-bit code
+       {  CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST },
+};
+
+
+
+//      
+//     32-bit x86 sub-type lists
+//
+//     TO-DO
+
+
+
+// scan the tables above to find the cpu-sub-type-list for this machine
+static const cpu_subtype_t* findCPUSubtypeList(cpu_type_t cpu, cpu_subtype_t subtype)
+{
+       switch (cpu) {
+               case CPU_TYPE_POWERPC:
+                       for (int i=0; i < kPPC_RowCount ; ++i) {
+                               if ( kPPC32[i][0] == subtype )
+                                       return kPPC32[i];
+                       }
+                       break;
+               case CPU_TYPE_POWERPC64:
+                       for (int i=0; i < kPPC64_RowCount ; ++i) {
+                               if ( kPPC64[i][0] == subtype )
+                                       return kPPC64[i];
+                       }
+                       break;
+               case CPU_TYPE_I386:
+                       // To do 
+                       break;
+       }
+       return NULL;
+}
+
+
+
+
+// scan fat table-of-contents for best most preferred subtype
+static bool fatFindBestFromOrderedList(cpu_type_t cpu, const cpu_subtype_t list[], const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+       const fat_arch* const archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
+       for (uint32_t subTypeIndex=0; list[subTypeIndex] != CPU_SUBTYPE_END_OF_LIST; ++subTypeIndex) {
+               for(uint32_t fatIndex=0; fatIndex < OSSwapBigToHostInt32(fh->nfat_arch); ++fatIndex) {
+                       if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[fatIndex].cputype) == cpu) 
+                               && (list[subTypeIndex] == archs[fatIndex].cpusubtype) ) {
+                               *offset = OSSwapBigToHostInt32(archs[fatIndex].offset);
+                               *len = OSSwapBigToHostInt32(archs[fatIndex].size);
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+// scan fat table-of-contents for exact match of cpu and cpu-sub-type
+static bool fatFindExactMatch(cpu_type_t cpu, cpu_subtype_t subtype, const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+       const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
+       for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
+               if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu)
+                       && ((cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == subtype) ) {
+                       *offset = OSSwapBigToHostInt32(archs[i].offset);
+                       *len = OSSwapBigToHostInt32(archs[i].size);
+                       return true;
+               }
+       }
+       return false;
+}
+
+// scan fat table-of-contents for image with matching cpu-type and runs-on-all-sub-types
+static bool fatFindRunsOnAllCPUs(cpu_type_t cpu, const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+       const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
+       for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
+               if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu) {
+                       switch (cpu) {
+                               case CPU_TYPE_POWERPC:
+                               case CPU_TYPE_POWERPC64:
+                                       if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_POWERPC_ALL ) {
+                                               *offset = OSSwapBigToHostInt32(archs[i].offset);
+                                               *len = OSSwapBigToHostInt32(archs[i].size);
+                                               return true;
+                                       }
+                                       break;
+                               case CPU_TYPE_I386:
+                                       if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_I386_ALL ) {
+                                               *offset = OSSwapBigToHostInt32(archs[i].offset);
+                                               *len = OSSwapBigToHostInt32(archs[i].size);
+                                               return true;
+                                       }
+                                       break;
+                       }
+               }
+       }
+       return false;
+}
+
+
+//
+// A fat file may contain multiple sub-images for the same cpu-type,
+// each optimized for a different cpu-sub-type (e.g G3 or G5).
+// This routine picks the optimal sub-image.
+//
+static bool fatFindBest(const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+       // assume all dylibs loaded must have same cpu type as main executable
+       const cpu_type_t cpu = sMainExecutableMachHeader->cputype;
+
+       // We only know the subtype to use if the main executable cpu type matches the host
+       if ( (cpu & CPU_TYPE_MASK) == sHostCPU ) {
+               // get preference ordered list of subtypes
+               const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(cpu, sHostCPUsubtype);
+       
+               // use ordered list to find best sub-image in fat file
+               if ( subTypePreferenceList != NULL ) 
+                       return fatFindBestFromOrderedList(cpu, subTypePreferenceList, fh, offset, len);
+               
+               // if running cpu is not in list, try for an exact match
+               if ( fatFindExactMatch(cpu, sHostCPUsubtype, fh, offset, len) )
+                       return true;
+       }
+       
+       // running on an uknown cpu, can only load generic code
+       return fatFindRunsOnAllCPUs(cpu, fh, offset, len);
+}
+
+
+
+//
+// This is used to validate if a non-fat (aka thin or raw) mach-o file can be used
+// on the current processor.  It is deemed compatible if any of the following are true:
+//  1) mach_header subtype is in list of compatible subtypes for running processor
+//  2) mach_header subtype is same as running processor subtype
+//  3) mach_header subtype runs on all processor variants
+//
+//
+bool isCompatibleMachO(const uint8_t* firstPage)
+{
+       const mach_header* mh = (mach_header*)firstPage;
+       if ( mh->magic == sMainExecutableMachHeader->magic ) {
+               if ( mh->cputype == sMainExecutableMachHeader->cputype ) {
+                       if ( (mh->cputype & CPU_TYPE_MASK) == sHostCPU ) {
+                               // get preference ordered list of subtypes that this machine can use
+                               const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(mh->cputype, sHostCPUsubtype);
+                               if ( subTypePreferenceList != NULL ) {
+                                       // if image's subtype is in the list, it is compatible
+                                       for (const cpu_subtype_t* p = subTypePreferenceList; *p != CPU_SUBTYPE_END_OF_LIST; ++p) {
+                                               if ( *p == mh->cpusubtype )
+                                                       return true;
+                                       }
+                                       // have list and not in list, so not compatible
+                                       throw "incompatible cpu-subtype";
+                               }
+                               // unknown cpu sub-type, but if exact match for current subtype then ok to use
+                               if ( mh->cpusubtype == sHostCPUsubtype ) 
+                                       return true;
+                       }
+                       
+                       // cpu unknown, so don't know if subtype is compatible
+                       // only load _ALL variant
+                       switch (mh->cputype) {
+                               case CPU_TYPE_POWERPC:
+                               case CPU_TYPE_POWERPC64:
+                                       if ( mh->cpusubtype == CPU_SUBTYPE_POWERPC_ALL ) 
+                                               return true;
+                                       break;
+                               case CPU_TYPE_I386:
+                                       if ( mh->cpusubtype == CPU_SUBTYPE_I386_ALL ) 
+                                               return true;
+                                       break;                                  
+                       }
+               }
+       }
+       return false;
+}
+
+
+// The kernel maps in main executable before dyld gets control.  We need to 
+// make an ImageLoader* for the already mapped in main executable.
+static ImageLoader* instantiateFromLoadedImage(const struct mach_header* mh, const char* path)
+{
+       // try mach-o loader
+       if ( isCompatibleMachO((const uint8_t*)mh) ) {
+               ImageLoader* image = new ImageLoaderMachO(path, mh, 0, gLinkContext);
+               addImage(image);
+               return image;
+       }
+       
+       return NULL;
+}
+
+
+
+
+// map in file and instantiate an ImageLoader
+static ImageLoader* loadPhase6(int fd, struct stat& stat_buf, const char* path, const LoadContext& context)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       uint64_t fileOffset = 0;
+       uint64_t fileLength = stat_buf.st_size;
+#if __ppc64__
+       if ( *((uint32_t*)((char*)(&stat_buf)+0x60)) == 0xFEFEFEFE )
+               fileLength = *((uint64_t*)((char*)(&stat_buf)+0x30));   // HACK work around for kernel stat bug rdar://problem/3845883
+#endif
+
+       // validate it is a file (not directory)
+       if ( (stat_buf.st_mode & S_IFMT) != S_IFREG ) 
+               throw "not a file";
+
+       // min file is 4K
+       if ( fileLength < 4096 ) {
+               throw "file to short";
+       }
+       
+       uint8_t firstPage[4096];
+       pread(fd, firstPage, 4096,0);
+       
+       // if fat wrapper, find usable sub-file
+       const fat_header* fileStartAsFat = (fat_header*)firstPage;
+       if ( fileStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
+               if ( fatFindBest(fileStartAsFat, &fileOffset, &fileLength) ) {
+                       pread(fd, firstPage, 4096, fileOffset);
+               }
+               else {
+                       throw "no matching architecture in fat wrapper";
+               }
+       }
+       
+       // try mach-o loader
+       if ( isCompatibleMachO(firstPage) ) {
+               char realFilePath[PATH_MAX];
+               if ( gLinkContext.slideAndPackDylibs ) {
+                       // when prebinding, we always want to track the real path of images
+                       if ( realpath(path, realFilePath) != NULL )
+                               path = realFilePath;
+               }
+
+               // instantiate an image
+               ImageLoader* image = new ImageLoaderMachO(path, fd, firstPage, fileOffset, fileLength, stat_buf, gLinkContext);
+               
+               // now sanity check that this loaded image does not have the same install path as any existing image
+               const char* loadedImageInstallPath = image->getInstallPath();
+               if ( image->isDylib() && (loadedImageInstallPath != NULL) && (loadedImageInstallPath[0] == '/') ) {
+                       for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+                               ImageLoader* anImage = *it;
+                               const char* installPath = anImage->getInstallPath();
+                               if ( installPath != NULL) {
+                                       if ( strcmp(loadedImageInstallPath, installPath) == 0 ) {
+                                               //fprintf(stderr, "duplicate(%s) => %p\n", installPath, anImage);
+                                               delete image;
+                                               return anImage;
+                                       }
+                               }
+                       }
+               }
+
+               // some API's restrict what they can load
+               if ( context.mustBeBundle && !image->isBundle() )
+                       throw "not a bundle";
+               if ( context.mustBeDylib && !image->isDylib() )
+                       throw "not a dylib";
+
+               // don't add bundles to global list, they can be loaded but not linked.  When linked it will be added to list
+               if ( ! image->isBundle() ) 
+                       addImage(image);
+
+               return image;
+       }
+       
+       // try other file formats...
+       
+       throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", 
+               firstPage[0], firstPage[1], firstPage[2], firstPage[3], firstPage[4], firstPage[5], firstPage[6],firstPage[7]);
+}
+
+
+// try to open file
+static ImageLoader* loadPhase5open(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+       //fprintf(stdout, "%s(%s)\n", __func__, path);
+       ImageLoader* image = NULL;
+
+       // open file (automagically closed when this function exits)
+       FileOpener file(path);
+       
+       //fprintf(stderr, "open(%s) => %d\n", path, file.getFileDescriptor() );
+       
+       if ( file.getFileDescriptor() == -1 )
+               return NULL;
+               
+       struct stat stat_buf;
+#if __ppc64__
+       memset(&stat_buf, 254, sizeof(struct stat));     // hack until rdar://problem/3845883 is fixed
+#endif
+       if ( fstat(file.getFileDescriptor(), &stat_buf) == -1)
+               throw "stat error";
+       
+       // in case image was renamed or found via symlinks, check for inode match
+       image = findLoadedImage(stat_buf);
+       if ( image != NULL )
+               return image;
+       
+       // needed to implement NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+       if ( context.dontLoad )
+               return NULL;
+       
+       try {
+               return loadPhase6(file.getFileDescriptor(), stat_buf, path, context);
+       }
+       catch (const char* msg) {
+               char* newMsg = new char[strlen(msg) + strlen(path) + 8];
+               sprintf(newMsg, "%s: %s", path, msg);
+               exceptions->push_back(newMsg);
+               return NULL;
+       }
+}
+
+// look for path match with existing loaded images
+static ImageLoader* loadPhase5check(const char* path, const LoadContext& context)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       // search path against load-path and install-path of all already loaded images
+       uint32_t hash = ImageLoader::hash(path);
+       for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+               ImageLoader* anImage = *it;
+               // check has first to cut down on strcmp calls
+               if ( anImage->getPathHash() == hash )
+                       if ( strcmp(path, anImage->getPath()) == 0 ) {
+                               // if we are looking for a dylib don't return something else
+                               if ( !context.mustBeDylib || anImage->isDylib() )
+                                       return anImage;
+                       }
+               if ( context.matchByInstallName || anImage->matchInstallPath() ) {
+                       const char* installPath = anImage->getInstallPath();
+                       if ( installPath != NULL) {
+                               if ( strcmp(path, installPath) == 0 ) {
+                                       // if we are looking for a dylib don't return something else
+                                       if ( !context.mustBeDylib || anImage->isDylib() )
+                                               return anImage;
+                               }
+                       }
+               }
+       }
+       
+       //fprintf(stderr, "check(%s) => NULL\n", path);
+       return NULL;
+}
+
+
+// open or check existing
+static ImageLoader* loadPhase5(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       if ( exceptions != NULL ) 
+               return loadPhase5open(path, context, exceptions);
+       else
+               return loadPhase5check(path, context);
+}
+
+// try with and without image suffix
+static ImageLoader* loadPhase4(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       ImageLoader* image = NULL;
+       if (  gLinkContext.imageSuffix != NULL ) {
+               char pathWithSuffix[strlen(path)+strlen( gLinkContext.imageSuffix)+2];
+               ImageLoader::addSuffix(path,  gLinkContext.imageSuffix, pathWithSuffix);
+               image = loadPhase5(pathWithSuffix, context, exceptions);
+       }
+       if ( image == NULL )
+               image = loadPhase5(path, context, exceptions);
+       return image;
+}
+
+
+// expand @ variables
+static ImageLoader* loadPhase3(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       ImageLoader* image = NULL;
+       if ( strncmp(path, "@executable_path/", 17) == 0 ) {
+               // handle @executable_path path prefix
+               const char* executablePath = sExecPath;
+               char newPath[strlen(executablePath) + strlen(path)];
+               strcpy(newPath, executablePath);
+               char* addPoint = strrchr(newPath,'/');
+               if ( addPoint != NULL )
+                       strcpy(&addPoint[1], &path[17]);
+               else
+                       strcpy(newPath, &path[17]);
+               image = loadPhase4(newPath, context, exceptions);
+               if ( image != NULL ) 
+                       return image;
+
+               // perhaps main executable path is a sym link, find realpath and retry
+               char resolvedPath[PATH_MAX];
+               if ( realpath(sExecPath, resolvedPath) != NULL ) {
+                       char newRealPath[strlen(resolvedPath) + strlen(path)];
+                       strcpy(newRealPath, resolvedPath);
+                       char* addPoint = strrchr(newRealPath,'/');
+                       if ( addPoint != NULL )
+                               strcpy(&addPoint[1], &path[17]);
+                       else
+                               strcpy(newRealPath, &path[17]);
+                       image = loadPhase4(newRealPath, context, exceptions);
+                       if ( image != NULL ) 
+                               return image;
+               }
+       }
+       else if ( (strncmp(path, "@loader_path/", 13) == 0) && (context.origin != NULL) ) {
+               // handle @loader_path path prefix
+               char newPath[strlen(context.origin) + strlen(path)];
+               strcpy(newPath, context.origin);
+               char* addPoint = strrchr(newPath,'/');
+               if ( addPoint != NULL )
+                       strcpy(&addPoint[1], &path[13]);
+               else
+                       strcpy(newPath, &path[13]);
+               image = loadPhase4(newPath, context, exceptions);
+               if ( image != NULL ) 
+                       return image;
+               
+               // perhaps loader path is a sym link, find realpath and retry
+               char resolvedPath[PATH_MAX];
+               if ( realpath(context.origin, resolvedPath) != NULL ) {
+                       char newRealPath[strlen(resolvedPath) + strlen(path)];
+                       strcpy(newRealPath, resolvedPath);
+                       char* addPoint = strrchr(newRealPath,'/');
+                       if ( addPoint != NULL )
+                               strcpy(&addPoint[1], &path[13]);
+                       else
+                               strcpy(newRealPath, &path[13]);
+                       image = loadPhase4(newRealPath, context, exceptions);
+                       if ( image != NULL ) 
+                               return image;
+               }
+       }
+       
+       return loadPhase4(path, context, exceptions);
+}
+
+
+// try search paths
+static ImageLoader* loadPhase2(const char* path, const LoadContext& context, 
+                                                          const char* const frameworkPaths[], const char* const libraryPaths[], 
+                                                          std::vector<const char*>* exceptions)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       ImageLoader* image = NULL;
+       const char* frameworkPartialPath = getFrameworkPartialPath(path);
+       if ( frameworkPaths != NULL ) {
+               if ( frameworkPartialPath != NULL ) {
+                       const int frameworkPartialPathLen = strlen(frameworkPartialPath);
+                       for(const char* const* fp = frameworkPaths; *fp != NULL; ++fp) {
+                               char npath[strlen(*fp)+frameworkPartialPathLen+8];
+                               strcpy(npath, *fp);
+                               strcat(npath, "/");
+                               strcat(npath, frameworkPartialPath);
+                               //fprintf(stderr, "dyld: fallback framework path used: %s() -> loadPhase4(\"%s\", ...)\n", __func__, npath);
+                               image = loadPhase4(npath, context, exceptions);
+                               if ( image != NULL )
+                                       return image;
+                       }
+               }
+       }
+       if ( libraryPaths != NULL ) {
+               const char* libraryLeafName = getLibraryLeafName(path);
+               const int libraryLeafNameLen = strlen(libraryLeafName);
+               for(const char* const* lp = libraryPaths; *lp != NULL; ++lp) {
+                       char libpath[strlen(*lp)+libraryLeafNameLen+8];
+                       strcpy(libpath, *lp);
+                       strcat(libpath, "/");
+                       strcat(libpath, libraryLeafName);
+                       //fprintf(stderr, "dyld: fallback library path used: %s() -> loadPhase4(\"%s\", ...)\n", __func__, libpath);
+                       image = loadPhase4(libpath, context, exceptions);
+                       if ( image != NULL )
+                               return image;
+               }
+       }
+       return NULL;
+}
+
+// try search overrides and fallbacks
+static ImageLoader* loadPhase1(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       ImageLoader* image = NULL;
+
+       // handle LD_LIBRARY_PATH environment variables that force searching
+       if ( context.useLdLibraryPath && (sEnv.LD_LIBRARY_PATH != NULL) ) {
+               image = loadPhase2(path, context, NULL, sEnv.LD_LIBRARY_PATH, exceptions);
+               if ( image != NULL )
+                       return image;
+       }
+
+       // handle DYLD_ environment variables that force searching
+       if ( context.useSearchPaths && ((sEnv.DYLD_FRAMEWORK_PATH != NULL) || (sEnv.DYLD_LIBRARY_PATH != NULL)) ) {
+               image = loadPhase2(path, context, sEnv.DYLD_FRAMEWORK_PATH, sEnv.DYLD_LIBRARY_PATH, exceptions);
+               if ( image != NULL )
+                       return image;
+       }
+       
+       // try raw path
+       image = loadPhase3(path, context, exceptions);
+       if ( image != NULL )
+               return image;
+       
+       // try fallback paths
+       if ( (sEnv.DYLD_FALLBACK_FRAMEWORK_PATH != NULL) || (sEnv.DYLD_FALLBACK_LIBRARY_PATH != NULL) ) {
+               image = loadPhase2(path, context, sEnv.DYLD_FALLBACK_FRAMEWORK_PATH, sEnv.DYLD_FALLBACK_LIBRARY_PATH, exceptions);
+               if ( image != NULL )
+                       return image;
+       }
+               
+       return NULL;
+}
+
+// try root substitutions
+static ImageLoader* loadPhase0(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       
+       // handle DYLD_ROOT_PATH which forces absolute paths to use a new root
+       if ( (sEnv.DYLD_ROOT_PATH != NULL) && (path[0] == '/') ) {
+               for(const char* const* rootPath = sEnv.DYLD_ROOT_PATH ; *rootPath != NULL; ++rootPath) {
+                       char newPath[strlen(*rootPath) + strlen(path)+2];
+                       strcpy(newPath, *rootPath);
+                       strcat(newPath, path);
+                       ImageLoader* image = loadPhase1(newPath, context, exceptions);
+                       if ( image != NULL )
+                               return image;
+               }
+       }
+
+       // try raw path
+       return loadPhase1(path, context, exceptions);
+}
+
+//
+// Given all the DYLD_ environment variables, the general case for loading libraries
+// is that any given path expands into a list of possible locations to load.  We
+// also must take care to ensure two copies of the "same" library are never loaded.
+//
+// The algorithm used here is that there is a separate function for each "phase" of the
+// path expansion.  Each phase function calls the next phase with each possible expansion
+// of that phase.  The result is the last phase is called with all possible paths.  
+//
+// To catch duplicates the algorithm is run twice.  The first time, the last phase checks
+// the path against all loaded images.  The second time, the last phase calls open() on 
+// the path.  Either time, if an image is found, the phases all unwind without checking
+// for other paths.
+//
+ImageLoader* load(const char* path, const LoadContext& context)
+{
+       //fprintf(stderr, "%s(%s)\n", __func__ , path);
+       char realPath[PATH_MAX];
+       // when DYLD_IMAGE_SUFFIX is in used, do a realpath(), otherwise a load of "Foo.framework/Foo" will not match
+       if ( context.useSearchPaths && ( gLinkContext.imageSuffix != NULL) ) {
+               if ( realpath(path, realPath) != NULL )
+                       path = realPath;
+       }
+       
+       // try all path permutations and check against existing loaded images
+       ImageLoader* image = loadPhase0(path, context, NULL);
+       if ( image != NULL )
+               return image;
+       
+       // try all path permutations and try open() until first sucesss
+       std::vector<const char*> exceptions;
+       image = loadPhase0(path, context, &exceptions);
+       if ( image != NULL )
+               return image;
+       else if ( context.dontLoad )
+               return NULL;
+       else if ( exceptions.size() == 0 )
+               throw "image not found";
+       else {
+               const char* msgStart = "no suitable image found.  Did find:";
+               const char* delim = "\n\t";
+               size_t allsizes = strlen(msgStart)+8;
+               for (unsigned int i=0; i < exceptions.size(); ++i) 
+                       allsizes += (strlen(exceptions[i]) + strlen(delim));
+               char* fullMsg = new char[allsizes];
+               strcpy(fullMsg, msgStart);
+               for (unsigned int i=0; i < exceptions.size(); ++i) {
+                       strcat(fullMsg, delim);
+                       strcat(fullMsg, exceptions[i]);
+               }
+               throw (const char*)fullMsg;
+       }
+}
+
+
+
+
+// create when NSLinkModule is called for a second time on a bundle
+ImageLoader* cloneImage(ImageLoader* image)
+{
+       const uint64_t offsetInFat = image->getOffsetInFatFile();
+
+       // open file (automagically closed when this function exits)
+       FileOpener file(image->getPath());
+       
+       struct stat stat_buf;
+#if __ppc64__
+       memset(&stat_buf, 254, sizeof(struct stat));     // hack until rdar://problem/3845883 is fixed
+#endif
+       if ( fstat(file.getFileDescriptor(), &stat_buf) == -1)
+               throw "stat error";
+       
+       // read first page of file
+       uint8_t firstPage[4096];
+       pread(file.getFileDescriptor(), firstPage, 4096, offsetInFat);
+       
+       // fat length is only used for sanity checking, since this image was already loaded once, just use upper bound
+       uint64_t lenInFat = stat_buf.st_size - offsetInFat;
+       
+       // try mach-o loader
+       if ( isCompatibleMachO(firstPage) ) {
+               ImageLoader* clone = new ImageLoaderMachO(image->getPath(), file.getFileDescriptor(), firstPage, offsetInFat, lenInFat, stat_buf, gLinkContext);
+               // don't add bundles to global list, they can be loaded but not linked.  When linked it will be added to list
+               if ( ! image->isBundle() ) 
+                       addImage(clone);
+               return clone;
+       }
+       
+       // try other file formats...
+       throw "can't clone image";
+}
+
+
+ImageLoader* loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName)
+{
+       // try mach-o each loader
+       if ( isCompatibleMachO(mem) ) {
+               ImageLoader* image = new ImageLoaderMachO(moduleName, (mach_header*)mem, len, gLinkContext);
+               // don't add bundles to global list, they can be loaded but not linked.  When linked it will be added to list
+               if ( ! image->isBundle() ) 
+                       addImage(image);
+               return image;
+       }
+       
+       // try other file formats...
+       
+       throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", 
+               mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]);
+}
+
+
+void registerAddCallback(ImageCallback func)
+{
+       // now add to list to get notified when any more images are added
+       sAddImageCallbacks.push_back(func);
+       
+       // call callback with all existing images, starting at roots
+       const int rootCount = sImageRoots.size();
+       for(int i=0; i < rootCount; ++i) {
+               ImageLoader* image = sImageRoots[i];
+               image->runNotification(gLinkContext, sAddImageCallbacks.size());
+       }
+       
+//     for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
+//             ImageLoader* image = *it;
+//             image->runNotification(gLinkContext, sAddImageCallbacks.size());
+//     }
+}
+
+void registerRemoveCallback(ImageCallback func)
+{
+       sRemoveImageCallbacks.push_back(func);
+}
+
+void clearErrorMessage()
+{
+       error_string[0] = '\0';
+}
+
+void setErrorMessage(const char* message)
+{
+       // save off error message in global buffer for CrashReporter to find
+       strncpy(error_string, message, sizeof(error_string)-1);
+       error_string[sizeof(error_string)-1] = '\0';
+}
+
+const char* getErrorMessage()
+{
+       return error_string;
+}
+
+void  halt(const char* message)
+{
+       fprintf(stderr, "dyld: %s\n", message);
+       setErrorMessage(message);
+       strncpy(error_string, message, sizeof(error_string)-1);
+       error_string[sizeof(error_string)-1] = '\0';
+       
+#if __ppc__ || __ppc64__
+       __asm__  ("trap");
+#elif __i386__
+       __asm__  ("int3");
+#else
+       #error unknown architecture
+#endif
+       abort();        // needed to suppress warning that noreturn function returns
+}
+
+
+uintptr_t bindLazySymbol(const mach_header* mh, uintptr_t* lazyPointer)
+{
+       uintptr_t result = 0;
+       // acquire read-lock on dyld's data structures
+#if 0 // rdar://problem/3811777 turn off locking until deadlock is resolved
+       if ( gThreadHelpers != NULL ) 
+               (*gThreadHelpers->lockForReading)();
+#endif
+       // lookup and bind lazy pointer and get target address
+       try {
+               // note, target should always be mach-o, because only mach-o lazy handler wired up to this
+               ImageLoader* target = dyld::findImageByMachHeader(mh);
+               if ( target == NULL )
+                       throw "image not found for lazy pointer";
+               result = target->doBindLazySymbol(lazyPointer, gLinkContext);
+       }
+       catch (const char* message) {
+               fprintf(stderr, "dyld: lazy symbol binding failed: %s\n", message);
+               halt(message);
+       }
+       // release read-lock on dyld's data structures
+#if 0
+       if ( gThreadHelpers != NULL ) 
+               (*gThreadHelpers->unlockForReading)();
+#endif
+       // return target address to glue which jumps to it with real parameters restored
+       return result;
+}
+
+
+// SPI used by ZeroLink to lazy load bundles
+void registerZeroLinkHandlers(BundleNotificationCallBack notify, BundleLocatorCallBack locate)
+{
+       sBundleNotifier = notify;
+       sBundleLocation = locate;
+}
+
+void registerUndefinedHandler(UndefinedHandler handler)
+{
+       sUndefinedHandler = handler;
+}
+
+static void undefinedHandler(const char* symboName)
+{
+       if ( sUndefinedHandler != NULL ) {
+               (*sUndefinedHandler)(symboName);
+       }
+}
+
+static bool findExportedSymbol(const char* name, bool onlyInCoalesced, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+       // try ZeroLink short cut to finding bundle which exports this symbol
+       if ( sBundleLocation != NULL ) {
+               ImageLoader* zlImage = (*sBundleLocation)(name);
+               if ( zlImage == ((ImageLoader*)(-1)) ) {
+                       // -1 is magic value that request symbol is in a bundle not yet linked into process
+                       // try calling handler to link in that symbol
+                       undefinedHandler(name);
+                       // call locator again
+                       zlImage = (*sBundleLocation)(name);
+               }
+               // if still not found, then ZeroLink has no idea where to find it
+               if ( zlImage == ((ImageLoader*)(-1)) ) 
+                       return false;
+               if ( zlImage != NULL ) {
+                       // ZeroLink cache knows where the symbol is
+                       *sym = zlImage->findExportedSymbol(name, NULL, false, image);
+                       if ( *sym != NULL ) {
+                               *image = zlImage;
+                               return true;
+                       }
+               }
+               else {
+                       // ZeroLink says it is in some bundle already loaded, but not linked, walk them all
+                       const unsigned int imageCount = sAllImages.size();
+                       for(unsigned int i=0; i < imageCount; ++i){
+                               ImageLoader* anImage = sAllImages[i];
+                               if ( anImage->isBundle() && !anImage->hasHiddenExports() ) {
+                                       //fprintf(stderr, "dyld: search for %s in %s\n", name, anImage->getPath());
+                                       *sym = anImage->findExportedSymbol(name, NULL, false, image);
+                                       if ( *sym != NULL ) {
+                                               return true;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // search all images in order
+       ImageLoader* firstWeakImage = NULL;
+       const ImageLoader::Symbol* firstWeakSym = NULL;
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i){
+               ImageLoader* anImage = sAllImages[i];
+               if ( ! anImage->hasHiddenExports() && (!onlyInCoalesced || anImage->hasCoalescedExports()) ) {
+                       *sym = anImage->findExportedSymbol(name, NULL, false, image);
+                       if ( *sym != NULL ) {
+                               // if weak definition found, record first one found
+                               if ( ((*image)->getExportedSymbolInfo(*sym) & ImageLoader::kWeakDefinition) != 0 ) {
+                                       if ( firstWeakImage == NULL ) {
+                                               firstWeakImage = *image;
+                                               firstWeakSym = *sym;
+                                       }
+                               }
+                               else {
+                                       // found non-weak, so immediately return with it
+                                       return true;
+                               }
+                       }
+               }
+       }
+       if ( firstWeakSym != NULL ) {
+               // found a weak definition, but no non-weak, so return first weak found
+               *sym = firstWeakSym;
+               *image = firstWeakImage;
+               return true;
+       }
+       
+       return false;
+}
+
+bool flatFindExportedSymbol(const char* name, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+       return findExportedSymbol(name, false, sym, image);
+}
+
+bool findCoalescedExportedSymbol(const char* name, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+       return findExportedSymbol(name, true, sym, image);
+}
+
+
+bool flatFindExportedSymbolWithHint(const char* name, const char* librarySubstring, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+       // search all images in order
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i){
+               ImageLoader* anImage = sAllImages[i];
+               // only look at images whose paths contain the hint string (NULL hint string is wildcard)
+               if ( ! anImage->isBundle() && ((librarySubstring==NULL) || (strstr(anImage->getPath(), librarySubstring) != NULL)) ) {
+                       *sym = anImage->findExportedSymbol(name, NULL, false, image);
+                       if ( *sym != NULL ) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+static void getMappedRegions(ImageLoader::RegionsVector& regions)
+{
+       const unsigned int imageCount = sAllImages.size();
+       for(unsigned int i=0; i < imageCount; ++i){
+               ImageLoader* anImage = sAllImages[i];
+               anImage->addMappedRegions(regions);
+       }
+}
+
+
+static ImageLoader* libraryLocator(const char* libraryName, bool search, const char* origin, const char* rpath[])
+{
+       dyld::LoadContext context;
+       context.useSearchPaths          = search;
+       context.useLdLibraryPath        = false;
+       context.dontLoad                        = false;
+       context.mustBeBundle            = false;
+       context.mustBeDylib                     = true;
+       context.matchByInstallName      = false;
+       context.origin                          = origin;
+       context.rpath                           = rpath;
+       return load(libraryName, context);
+}
+
+       
+static void setContext(int argc, const char* argv[], const char* envp[], const char* apple[])
+{
+       gLinkContext.loadLibrary                        = &libraryLocator;
+       gLinkContext.imageNotification          = &imageNotification;
+       gLinkContext.terminationRecorder        = &terminationRecorder;
+       gLinkContext.flatExportFinder           = &flatFindExportedSymbol;
+       gLinkContext.coalescedExportFinder      = &findCoalescedExportedSymbol;
+       gLinkContext.undefinedHandler           = &undefinedHandler;
+       gLinkContext.addImageNeedingNotification = &addImageNeedingNotification;
+       gLinkContext.notifyAdding                       = &notifyAdding;
+       gLinkContext.getAllMappedRegions        = &getMappedRegions;
+       gLinkContext.bindingHandler                     = NULL;
+       gLinkContext.bindingOptions                     = ImageLoader::kBindingNone;
+       gLinkContext.mainExecutable                     = sMainExecutable;
+       gLinkContext.argc                                       = argc;
+       gLinkContext.argv                                       = argv;
+       gLinkContext.envp                                       = envp;
+       gLinkContext.apple                                      = apple;
+}
+
+
+
+void link(ImageLoader* image, ImageLoader::BindingLaziness bindness, ImageLoader::InitializerRunning runInitializers)
+{
+       // add to list of known images.  This did not happen at creation time for bundles
+       if ( image->isBundle() )
+               addImage(image);
+
+       // we detect root images as those not linked in yet 
+       if ( !image->isLinked() )
+               addRootImage(image);
+       
+       // notify ZeroLink of new image with concat of logical and physical name
+       if ( sBundleNotifier != NULL && image->isBundle() ) {
+               const int logicalLen = strlen(image->getLogicalPath());
+               char logAndPhys[strlen(image->getPath())+logicalLen+2];
+               strcpy(logAndPhys, image->getLogicalPath());
+               strcpy(&logAndPhys[logicalLen+1], image->getPath());
+               (*sBundleNotifier)(logAndPhys, image);
+       }
+
+       // process images
+       image->link(gLinkContext, bindness, runInitializers, sAddImageCallbacks.size());
+       
+#if OLD_GDB_DYLD_INTERFACE
+       // notify gdb that loaded libraries have changed
+       gdb_dyld_state_changed();
+#endif
+}
+
+
+//
+// Entry point for dyld.  The kernel loads dyld and jumps to __dyld_start which
+// sets up some registers and call this function.
+//
+// Returns address of main() in target program which __dyld_start jumps to
+//
+uintptr_t
+_main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[])
+{      
+       // Pickup the pointer to the exec path.
+       const char* executable = apple[0];
+       if ( executable[0] == '/' ) {
+               // have full path, use it
+               sExecPath = executable;
+       }
+       else {
+               // have relative path, use cwd to make absolute
+               char cwdbuff[MAXPATHLEN];
+           if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
+                       // maybe use static buffer to avoid calling malloc so early...
+                       char* s = new char[strlen(cwdbuff) + strlen(executable) + 2];
+                       strcpy(s, cwdbuff);
+                       strcat(s, "/");
+                       strcat(s, executable);
+                       sExecPath = s;
+               }
+       }
+       uintptr_t result = 0;
+       sMainExecutableMachHeader = mainExecutableMH;
+       checkEnvironmentVariables(envp);
+       if ( sEnv.DYLD_PRINT_OPTS ) 
+               printOptions(argv);
+       if ( sEnv.DYLD_PRINT_ENV ) 
+               printEnvironmentVariables(envp);
+       getHostInfo();
+       setContext(argc, argv, envp, apple);
+       ImageLoader::BindingLaziness bindness = sEnv.DYLD_BIND_AT_LAUNCH ? ImageLoader::kLazyAndNonLazy : ImageLoader::kNonLazyOnly;
+       
+       // load any inserted libraries before loading the main executable so that they are first in flat namespace
+       int insertLibrariesCount = 0;
+       if ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {
+               for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib) {
+                       insertLibrariesCount++;
+               }
+       }
+       ImageLoader* insertedImages[insertLibrariesCount];
+       if ( insertLibrariesCount > 0 ) {
+               for (int i=0; i < insertLibrariesCount; ++i) {
+                       try {
+                               LoadContext context;
+                               context.useSearchPaths          = false;
+                               context.useLdLibraryPath        = false;
+                               context.dontLoad                        = false;
+                               context.mustBeBundle            = false;
+                               context.mustBeDylib                     = true;
+                               context.matchByInstallName      = false;
+                               context.origin                          = NULL; // can't use @loader_path with DYLD_INSERT_LIBRARIES
+                               context.rpath                           = NULL;
+                               insertedImages[i] = load(sEnv.DYLD_INSERT_LIBRARIES[i], context);
+                       }
+                       catch (...) {
+                               char buf[strlen(sEnv.DYLD_INSERT_LIBRARIES[i])+50];
+                               sprintf(buf, "could not load inserted library: %s\n", sEnv.DYLD_INSERT_LIBRARIES[i]);
+                               insertedImages[i]  = NULL;
+                               halt(buf);
+                       }
+               }
+       }
+       
+       // load and link main executable
+       try {
+               sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, sExecPath);
+               gLinkContext.mainExecutable = sMainExecutable;
+               if ( sMainExecutable->forceFlat() ) {
+                       gLinkContext.bindFlat = true;
+                       gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
+               }
+               link(sMainExecutable, bindness, ImageLoader::kDontRunInitializers);
+               result = (uintptr_t)sMainExecutable->getMain();
+       }
+       catch(const char* message) {
+               halt(message);
+       }
+       catch(...) {
+               fprintf(stderr, "dyld: launch failed\n");
+       }
+       
+       // Link in any inserted libraries.  
+       // Do this after link main executable so any extra libraries pulled in by inserted libraries are at end of flat namespace
+       if ( insertLibrariesCount > 0 ) {
+               for (int i=0; i < insertLibrariesCount; ++i) {
+                       try {
+                               if ( insertedImages[i] != NULL )
+                                       link(insertedImages[i], bindness, ImageLoader::kDontRunInitializers);
+                       }
+                       catch (const char* message) {
+                               char buf[strlen(sEnv.DYLD_INSERT_LIBRARIES[i])+50+strlen(message)];
+                               sprintf(buf, "could not link inserted library: %s\n%s\n", sEnv.DYLD_INSERT_LIBRARIES[i], message);
+                               halt(buf);
+                       }
+               }
+       }
+       
+       return result;
+}
+
+
+
+
+}; // namespace
+
+
+
diff --git a/src/dyld.exp b/src/dyld.exp
new file mode 100644 (file)
index 0000000..ee6ad95
--- /dev/null
@@ -0,0 +1,52 @@
+#
+#  Copyright (c) 2004-2005 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@
+#
+
+#
+#  Only the following symbols should be "global". 
+#  gdb and vmutils lookup these symbols in dyld in order to determine what images the process is using 
+#
+
+# Mac OS X 10.4 way to discover a process's images
+_dyld_all_image_infos
+
+# CrashReporter uses this to get message as to why dyld terminated the process
+_error_string
+
+# Used by various tools to see build number of dyld
+_dyldVersionString
+_dyldVersionNumber
+
+# Entry points into dyld needed by loaded every image
+_stub_binding_helper
+_dyld_func_lookup
+
+# Old symbols left for compatibility
+_gdb_dyld_version
+_gdb_dyld_state_changed
+_gdb_nobject_images
+_gdb_object_image_size
+_gdb_nlibrary_images
+_gdb_library_image_size
+_object_images
+_library_images
+_send_event
diff --git a/src/dyld.h b/src/dyld.h
new file mode 100644 (file)
index 0000000..72e0e2a
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stdint.h>
+
+#include "ImageLoader.h"
+
+
+
+//
+// dyld functions available when implementing dyld API's
+//
+//
+namespace dyld {
+
+       struct LoadContext
+       {
+               bool                    useSearchPaths;
+               bool                    useLdLibraryPath;
+               bool                    matchByInstallName;
+               bool                    dontLoad;
+               bool                    mustBeBundle;
+               bool                    mustBeDylib;
+               const char*             origin;                 // path for expanding @loader_path
+               const char**    rpath;                  // future support of -rpath
+       };
+
+
+
+       typedef void             (*ImageCallback)(const struct mach_header* mh, intptr_t slide);
+       typedef void             (*BundleNotificationCallBack)(const char* imageName, ImageLoader* image);
+       typedef ImageLoader* (*BundleLocatorCallBack)(const char* symbolName);
+       typedef void             (*UndefinedHandler)(const char* symbolName);
+
+
+       extern ImageLoader::LinkContext                 gLinkContext;
+       extern bool                                                             gLogAPIs;
+       extern const struct ThreadingHelpers*   gThreadHelpers;
+
+       
+       extern void                                     registerAddCallback(ImageCallback func);
+       extern void                                     registerRemoveCallback(ImageCallback func);
+       extern void                                     registerZeroLinkHandlers(BundleNotificationCallBack, BundleLocatorCallBack);
+       extern void                                     registerUndefinedHandler(UndefinedHandler);
+       extern void                                     initializeMainExecutable();
+       extern void                                     link(ImageLoader* image, ImageLoader::BindingLaziness bindness, ImageLoader::InitializerRunning runInitializers);
+       extern void                                     runTerminators();
+       extern const char*                      getExecutablePath();
+       extern bool                                     validImage(ImageLoader*);
+       extern ImageLoader*                     getIndexedImage(uint32_t index);
+       extern uint32_t                         getImageCount();
+       extern ImageLoader*                     findImageByMachHeader(const struct mach_header* target);
+       extern ImageLoader*                     findImageContainingAddress(const void* addr);
+       extern ImageLoader*                     findImageByName(const char* path);
+       extern ImageLoader*                     findLoadedImageByInstallPath(const char* path);
+       extern bool                                     flatFindExportedSymbol(const char* name, const ImageLoader::Symbol** sym, ImageLoader** image);
+       extern bool                                     flatFindExportedSymbolWithHint(const char* name, const char* librarySubstring, const ImageLoader::Symbol** sym, ImageLoader** image);
+       extern ImageLoader*                     load(const char* path, const LoadContext& context);
+       extern ImageLoader*                     loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName);
+       extern void                                     removeImage(ImageLoader* image);
+       extern ImageLoader*                     cloneImage(ImageLoader* image);
+       extern void                                     forEachImageDo( void (*)(ImageLoader*, void*), void*);
+       extern uintptr_t                        _main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[]);
+       extern void                                     halt(const char* message)  __attribute__((noreturn));
+       extern void                                     setErrorMessage(const char* msg);
+       extern const char*                      getErrorMessage();
+       extern void                                     clearErrorMessage();
+       extern bool                                     mainExecutablePrebound();
+       extern ImageLoader*                     mainExecutable();
+       extern void                                     processDyldEnvironmentVarible(const char* key, const char* value);
+
+};
+
diff --git a/src/dyldAPIs.cpp b/src/dyldAPIs.cpp
new file mode 100644 (file)
index 0000000..fb9f89c
--- /dev/null
@@ -0,0 +1,1608 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+//
+// This file implements that API's in <mach-o/dyld.h>
+//
+//
+
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <mach/mach.h>
+#include <sys/time.h>
+
+extern "C" mach_port_name_t    task_self_trap(void);  // can't include <System/mach/mach_traps.h> because it is missing extern C
+
+#include "mach-o/dyld_gdb.h"
+#include "mach-o/dyld.h"
+#include "mach-o/dyld_priv.h"
+#include "dlfcn.h"
+
+#include "ImageLoader.h"
+#include "dyld.h"
+#include "dyldLibSystemThreadHelpers.h"
+
+static char sLastErrorFilePath[1024];
+static NSLinkEditErrors sLastErrorFileCode;
+static int sLastErrorNo;
+
+
+// In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
+// Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
+// This conditional keeps support for old libSystem's which needed some help implementing the API's
+#define OLD_LIBSYSTEM_SUPPORT 1
+
+
+// The following functions have no prototype in any header.  They are special cases
+// where _dyld_func_lookup() is used directly.
+static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit);
+static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options);
+static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions);
+static void _dyld_fork_prepare();
+static void _dyld_fork_parent();
+static void _dyld_fork_child();
+static void _dyld_fork_child_final();
+static void _dyld_make_delayed_module_initializer_calls();
+static void _dyld_mod_term_funcs();
+static bool NSMakePrivateModulePublic(NSModule module);
+static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header);
+static void registerThreadHelpers(const dyld::ThreadingHelpers*);
+static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t flags);
+static const struct dyld_all_image_infos* _dyld_get_all_image_infos();
+
+// The following functions are dyld API's, but since dyld links with a static copy of libc.a
+// the public name cannot be used.
+static void            client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module);
+static bool            client_NSIsSymbolNameDefined(const char* symbolName);
+
+
+static void unimplemented()
+{
+       dyld::halt("unimplemented dyld function\n");
+}
+
+struct dyld_func {
+    const char* name;
+    void*              implementation;
+};
+
+static struct dyld_func dyld_funcs[] = {
+    {"__dyld_image_count",                                                     (void*)_dyld_image_count },
+    {"__dyld_get_image_header",                                                (void*)_dyld_get_image_header },
+    {"__dyld_get_image_vmaddr_slide",                          (void*)_dyld_get_image_vmaddr_slide },
+    {"__dyld_get_image_name",                                          (void*)_dyld_get_image_name },
+    {"__dyld_lookup_and_bind",                                         (void*)client_dyld_lookup_and_bind },
+    {"__dyld_lookup_and_bind_with_hint",                       (void*)_dyld_lookup_and_bind_with_hint },
+    {"__dyld_lookup_and_bind_objc",                                    (void*)unimplemented },
+    {"__dyld_lookup_and_bind_fully",                           (void*)_dyld_lookup_and_bind_fully },
+    {"__dyld_install_handlers",                                                (void*)_dyld_install_handlers },
+    {"__dyld_link_edit_error",                                         (void*)NSLinkEditError },
+#if OLD_LIBSYSTEM_SUPPORT
+    {"__dyld_link_module",                                                     (void*)_dyld_link_module },
+#endif
+    {"__dyld_unlink_module",                                           (void*)NSUnLinkModule },
+    {"__dyld_register_func_for_add_image",                     (void*)_dyld_register_func_for_add_image },
+    {"__dyld_register_func_for_remove_image",          (void*)_dyld_register_func_for_remove_image },
+    {"__dyld_register_func_for_link_module",           (void*)unimplemented },
+    {"__dyld_register_func_for_unlink_module",         (void*)unimplemented },
+    {"__dyld_register_func_for_replace_module",                (void*)unimplemented },
+    {"__dyld_get_objc_module_sect_for_module",         (void*)unimplemented },
+    {"__dyld_bind_objc_module",                                                (void*)_dyld_bind_objc_module },
+    {"__dyld_bind_fully_image_containing_address",  (void*)_dyld_bind_fully_image_containing_address },
+    {"__dyld_image_containing_address",                                (void*)_dyld_image_containing_address },
+    {"__dyld_get_image_header_containing_address",  (void*)_dyld_get_image_header_containing_address },
+    {"__dyld_moninit",                                                         (void*)_dyld_moninit },
+    {"__dyld_register_binding_handler",                                                (void*)_dyld_register_binding_handler },
+    {"__dyld_fork_prepare",                                                    (void*)_dyld_fork_prepare },
+    {"__dyld_fork_parent",                                                     (void*)_dyld_fork_parent },
+    {"__dyld_fork_child",                                                      (void*)_dyld_fork_child },
+    {"__dyld_fork_child_final",                                                (void*)_dyld_fork_child_final },
+    {"__dyld_fork_mach_init",                                          (void*)unimplemented },
+    {"__dyld_make_delayed_module_initializer_calls",(void*)_dyld_make_delayed_module_initializer_calls },
+    {"__dyld_NSNameOfSymbol",                                          (void*)NSNameOfSymbol },
+    {"__dyld_NSAddressOfSymbol",                                       (void*)NSAddressOfSymbol },
+    {"__dyld_NSModuleForSymbol",                                       (void*)NSModuleForSymbol },
+    {"__dyld_NSLookupAndBindSymbol",                           (void*)NSLookupAndBindSymbol },
+    {"__dyld_NSLookupAndBindSymbolWithHint",           (void*)NSLookupAndBindSymbolWithHint },
+    {"__dyld_NSLookupSymbolInModule",                          (void*)NSLookupSymbolInModule},
+    {"__dyld_NSLookupSymbolInImage",                           (void*)NSLookupSymbolInImage},
+    {"__dyld_NSMakePrivateModulePublic",                       (void*)NSMakePrivateModulePublic},
+    {"__dyld_NSIsSymbolNameDefined",                           (void*)client_NSIsSymbolNameDefined},
+    {"__dyld_NSIsSymbolNameDefinedWithHint",           (void*)NSIsSymbolNameDefinedWithHint },
+    {"__dyld_NSIsSymbolNameDefinedInImage",                    (void*)NSIsSymbolNameDefinedInImage},
+    {"__dyld_NSNameOfModule",                                          (void*)NSNameOfModule },
+    {"__dyld_NSLibraryNameForModule",                          (void*)NSLibraryNameForModule },
+    {"__dyld_NSAddLibrary",                                                    (void*)NSAddLibrary },
+    {"__dyld_NSAddLibraryWithSearching",                       (void*)NSAddLibraryWithSearching },
+    {"__dyld_NSAddImage",                                                      (void*)NSAddImage },
+    {"__dyld__NSGetExecutablePath",                                    (void*)_NSGetExecutablePath },
+    {"__dyld_launched_prebound",                                       (void*)_dyld_launched_prebound },
+    {"__dyld_all_twolevel_modules_prebound",           (void*)_dyld_all_twolevel_modules_prebound },
+    {"__dyld_call_module_initializers_for_dylib",   (void*)_dyld_call_module_initializers_for_dylib },
+    {"__dyld_mod_term_funcs",                                          (void*)_dyld_mod_term_funcs },
+    {"__dyld_install_link_edit_symbol_handlers",       (void*)dyld::registerZeroLinkHandlers },
+    {"__dyld_NSCreateObjectFileImageFromFile",                 (void*)NSCreateObjectFileImageFromFile },
+    {"__dyld_NSCreateObjectFileImageFromMemory",               (void*)NSCreateObjectFileImageFromMemory },
+    {"__dyld_NSCreateCoreFileImageFromFile",                   (void*)unimplemented },
+    {"__dyld_NSDestroyObjectFileImage",                                        (void*)NSDestroyObjectFileImage },
+    {"__dyld_NSLinkModule",                                                            (void*)NSLinkModule },
+    {"__dyld_NSHasModInitObjectFileImage",                             (void*)NSHasModInitObjectFileImage },
+    {"__dyld_NSSymbolDefinitionCountInObjectFileImage",        (void*)NSSymbolDefinitionCountInObjectFileImage },
+    {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage },
+    {"__dyld_NSIsSymbolDefinedInObjectFileImage",              (void*)NSIsSymbolDefinedInObjectFileImage },
+    {"__dyld_NSSymbolReferenceNameInObjectFileImage",  (void*)NSSymbolReferenceNameInObjectFileImage },
+    {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage },
+    {"__dyld_NSGetSectionDataInObjectFileImage",               (void*)NSGetSectionDataInObjectFileImage },
+    {"__dyld_NSFindSectionAndOffsetInObjectFileImage",  (void*)NSFindSectionAndOffsetInObjectFileImage },
+       {"__dyld_register_thread_helpers",                                      (void*)registerThreadHelpers },
+    {"__dyld_dladdr",                                                                  (void*)dladdr },
+    {"__dyld_dlclose",                                                                 (void*)dlclose },
+    {"__dyld_dlerror",                                                                 (void*)dlerror },
+    {"__dyld_dlopen",                                                                  (void*)dlopen },
+    {"__dyld_dlsym",                                                                   (void*)dlsym },
+       {"__dyld_update_prebinding",                                            (void*)_dyld_update_prebinding },
+       {"__dyld_get_all_image_infos",                                          (void*)_dyld_get_all_image_infos },
+    {NULL, 0}
+};
+
+
+
+// dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
+inline NSSymbol SymbolToNSSymbol(const ImageLoader::Symbol* sym)
+{
+       return (NSSymbol)sym;
+}      
+inline const ImageLoader::Symbol* NSSymbolToSymbol(NSSymbol sym)
+{
+       return (const ImageLoader::Symbol*)sym;
+}      
+
+// dyld's abstract type NSModule is implemented as ImageLoader*
+inline NSModule ImageLoaderToNSModule(ImageLoader* image)
+{
+       return (NSModule)image;
+}      
+inline ImageLoader* NSModuleToImageLoader(NSModule module)
+{
+       ImageLoader* image = (ImageLoader*)module;
+       if ( dyld::validImage(image) )
+               return image;
+       return NULL;
+}
+
+// actual definition for opaque type
+struct __NSObjectFileImage
+{
+       ImageLoader*    image;  
+       const void*             imageBaseAddress;       // not used with OFI created from files
+       size_t                  imageLength;            // not used with OFI created from files
+};
+static std::vector<NSObjectFileImage> sObjectFileImages;
+
+
+
+//
+// __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
+// The contained image is delete in one of two places:
+//     NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
+//     NSDestroyObjectFileImage deletes the image if image is not in list of valid images
+//
+
+
+static void dyldAPIhalt(const char* apiName, const char* errorMsg)
+{
+       fprintf(stderr, "dyld: %s() error\n", apiName);
+       dyld::halt(errorMsg);
+}
+
+
+
+static void setLastError(NSLinkEditErrors code, int errnum, const char* file, const char* message)
+{
+       dyld::setErrorMessage(message);
+       strncpy(sLastErrorFilePath, file, 1024);
+       sLastErrorFilePath[1023] = '\0';
+       sLastErrorFileCode = code;
+       sLastErrorNo = errnum;
+}
+
+
+/*
+ *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
+ * copies the path of the executable into the buffer and returns 0 if the path
+ * was successfully copied in the provided buffer. If the buffer is not large
+ * enough, -1 is returned and the expected buffer size is copied in *bufsize.
+ * Note that _NSGetExecutablePath will return "a path" to the executable not a
+ * "real path" to the executable. That is the path may be a symbolic link and
+ * not the real file. And with deep directories the total bufsize needed could
+ * be more than MAXPATHLEN.
+ */
+int _NSGetExecutablePath(char* buf, uint32_t *bufsize)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(...)\n", __func__);
+       const char* exePath = dyld::getExecutablePath();
+       if(*bufsize < strlen(exePath) + 1){
+           *bufsize = strlen(exePath) + 1;
+           return -1;
+       }
+       strcpy(buf, exePath);
+       return 0;
+}
+
+
+//
+// _dyld_call_module_initializers_for_dylib() is the dyld side of
+// __initialize_Cplusplus() which is in dylib1.o.
+// It is intended to only be called inside -init rouintes.
+// -init routines are called before module initializers (what C++
+// initializers use).  Calling __initialize_Cplusplus() in a -init
+// routine causes the module initializers for an image to be called
+// which then allows C++ to be used inside a -init routine
+//
+static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "__initialize_Cplusplus()\n");
+       
+       // for now, do nothing...
+}
+
+
+void _dyld_lookup_and_bind_fully(const char* symbolName, void** address, NSModule* module)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", %p, %p)\n", __func__, symbolName, address, module);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       dyld::clearErrorMessage();
+       if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) { 
+               try {
+                       dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
+                       if ( address != NULL)
+                               *address = (void*)image->getExportedSymbolAddress(sym);
+                       if ( module != NULL)
+                               *module = ImageLoaderToNSModule(image);
+               }
+               catch (const char* msg) {
+                       dyldAPIhalt(__func__, msg);
+               }
+       }
+       else {
+               // on failure to find symbol return NULLs
+               if ( address != NULL)
+                       *address = NULL;
+               if ( module != NULL)
+                       *module = NULL;
+       }
+}
+
+// Note: This cannot have public name because dyld is built with a static copy of libc.a
+// which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
+static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName, address, module);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+               if ( address != NULL)
+                       *address = (void*)image->getExportedSymbolAddress(sym);
+               if ( module != NULL)
+                       *module = ImageLoaderToNSModule(image);
+       }
+       else {
+               // on failure to find symbol return NULLs
+               if ( address != NULL)
+                       *address = NULL;
+               if ( module != NULL)
+                       *module = NULL;
+       }
+}
+
+void _dyld_lookup_and_bind_with_hint(const char* symbolName, const char* library_name_hint, void** address, NSModule* module)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", \"%s\", %p, %p)\n", __func__, symbolName, library_name_hint, address, module);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       // Look for library whose path contains the hint.  If that fails search everywhere
+       if (  dyld::flatFindExportedSymbolWithHint(symbolName, library_name_hint, &sym, &image) 
+         ||  dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+               if ( address != NULL)
+                       *address = (void*)image->getExportedSymbolAddress(sym);
+               if ( module != NULL)
+                       *module = ImageLoaderToNSModule(image);
+       }
+       else {
+               // on failure to find symbol return NULLs
+               if ( address != NULL)
+                       *address = NULL;
+               if ( module != NULL)
+                       *module = NULL;
+       }
+}
+
+
+NSSymbol NSLookupAndBindSymbol(const char *symbolName)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\")\n", __func__, symbolName);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+               return SymbolToNSSymbol(sym);
+       }
+       // return NULL on failure
+       return NULL;
+}
+
+NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
+       if ( ! found ) {
+               // hint failed, do slow search of all images
+                found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
+       }
+       if ( found )
+               return SymbolToNSSymbol(sym);
+               
+       // return NULL on failure and log
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", \"%s\") => NULL \n", __func__, symbolName, libraryNameHint);
+       return NULL;
+}
+
+uint32_t _dyld_image_count(void)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       return dyld::getImageCount();
+}
+
+const struct mach_header* _dyld_get_image_header(uint32_t image_index)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%u)\n", __func__, image_index);
+       ImageLoader* image = dyld::getIndexedImage(image_index);
+       if ( image != NULL )
+               return (struct mach_header*)image->machHeader();
+       else
+               return NULL;
+}
+
+
+static __attribute__((noinline)) 
+const struct mach_header* addImage(const char* path, bool search, bool dontLoad, bool matchInstallName, bool abortOnError)
+{
+       ImageLoader*    image = NULL;
+       try {
+               dyld::clearErrorMessage();
+               void* callerAddress = __builtin_return_address(2); // note layers: 2: real client, 1: libSystem glue, 0: dyld API
+               ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+               dyld::LoadContext context;
+               context.useSearchPaths          = search;
+               context.useLdLibraryPath        = false;
+               context.matchByInstallName      = matchInstallName;
+               context.dontLoad                        = dontLoad;
+               context.mustBeBundle            = false;
+               context.mustBeDylib                     = true;
+               context.origin                          = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
+               context.rpath                           = NULL; // support not yet implemented
+                               
+               image = load(path, context);
+               if ( image != NULL ) {
+                       if ( context.matchByInstallName )
+                               image->setMatchInstallPath(true);
+                       dyld::link(image, ImageLoader::kNonLazyOnly, ImageLoader::kRunInitializers);
+                       return image->machHeader();
+               }
+       }
+       catch (const char* msg) {
+               if ( abortOnError) {
+                       char pathMsg[strlen(msg)+strlen(path)+4];
+                       strcpy(pathMsg, msg);
+                       strcat(pathMsg, " ");
+                       strcat(pathMsg, path);
+                       dyldAPIhalt("NSAddImage", pathMsg);
+               }
+               // not halting, so set error state for NSLinkEditError to find
+               setLastError(NSLinkEditOtherError, 0, path, msg);
+       }
+       return NULL;
+}
+
+const struct mach_header* NSAddImage(const char* path, uint32_t options)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", 0x%08X)\n", __func__, path, options);
+       const bool dontLoad = ( (options & NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) != 0 );
+       const bool search = ( (options & NSADDIMAGE_OPTION_WITH_SEARCHING) != 0 );
+       const bool matchInstallName = ( (options & NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME) != 0 );
+       const bool abortOnError = ( (options & NSADDIMAGE_OPTION_RETURN_ON_ERROR) == 0 );
+       return addImage(path, search, dontLoad, matchInstallName, abortOnError);
+}
+
+bool NSAddLibrary(const char* path)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\")\n", __func__, path);
+       return (addImage(path, false, false, false, false) != NULL);
+}
+
+bool NSAddLibraryWithSearching(const char* path)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\")\n", __func__, path);
+       return (addImage(path, true, false, false, false) != NULL);
+}
+
+
+
+//#define NSADDIMAGE_OPTION_NONE                       0x0
+//#define NSADDIMAGE_OPTION_RETURN_ON_ERROR            0x1
+//#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME      0x8
+
+bool NSIsSymbolNameDefinedInImage(const struct mach_header* mh, const char* symbolName)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, \"%s\")\n", __func__, (void *)mh, symbolName);
+       ImageLoader* image = dyld::findImageByMachHeader(mh);
+       if ( image != NULL ) {
+               if ( image->findExportedSymbol(symbolName, NULL, true, NULL) != NULL)
+                       return true;
+       }
+       return false;
+}
+
+NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolName, uint32_t options)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", __func__, mh, symbolName, options);
+       const ImageLoader::Symbol* symbol = NULL;
+       dyld::clearErrorMessage();
+       ImageLoader* image = dyld::findImageByMachHeader(mh);
+       if ( image != NULL ) {
+               try {
+                       if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY ) {
+                               dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
+                       }
+                       else if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW ) {
+                               dyld::link(image, ImageLoader::kLazyOnlyNoDependents, ImageLoader::kDontRunInitializers);
+                       }
+               }
+               catch (const char* msg) {
+                       if ( (options & NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) == 0 ) {
+                               dyldAPIhalt(__func__, msg);
+                       }
+               }
+               symbol = image->findExportedSymbol(symbolName, NULL, true, NULL);
+       }
+       if ( dyld::gLogAPIs && (symbol == NULL) )
+               fprintf(stderr, "%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__, mh, symbolName, options);
+       return SymbolToNSSymbol(symbol);
+}
+
+
+// Note: This cannot have public name because dyld is built with a static copy of libc.a
+// which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
+static bool client_NSIsSymbolNameDefined(const char* symbolName)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "NSIsSymbolNameDefined(\"%s\")\n", symbolName);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       return dyld::flatFindExportedSymbol(symbolName, &sym, &image);
+}
+
+bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+       bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
+       if ( ! found ) {
+               // hint failed, do slow search of all images
+                found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
+       }
+       if ( !found && dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", \"%s\") => false \n", __func__, symbolName, libraryNameHint);
+       return found;
+}
+
+const char* NSNameOfSymbol(NSSymbol symbol)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
+       const char* result = NULL;
+       ImageLoader* image = dyld::findImageContainingAddress(symbol);
+       if ( image != NULL ) 
+               result = image->getExportedSymbolName(NSSymbolToSymbol(symbol));
+       return result;
+}
+
+void* NSAddressOfSymbol(NSSymbol symbol)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
+       void* result = NULL;
+       ImageLoader* image = dyld::findImageContainingAddress(symbol);
+       if ( image != NULL ) 
+               result = (void*)image->getExportedSymbolAddress(NSSymbolToSymbol(symbol));
+       return result;
+}
+
+NSModule NSModuleForSymbol(NSSymbol symbol)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
+       NSModule result = NULL;
+       ImageLoader* image = dyld::findImageContainingAddress(symbol);
+       if ( image != NULL ) 
+               result = ImageLoaderToNSModule(image);
+       return result;
+}
+
+
+intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%u)\n", __func__, image_index);
+       ImageLoader* image = dyld::getIndexedImage(image_index);
+       if ( image != NULL )
+               return image->getSlide();
+       else
+               return 0;
+}
+
+const char* _dyld_get_image_name(uint32_t image_index)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%u)\n", __func__, image_index);
+       ImageLoader* image = dyld::getIndexedImage(image_index);
+       if ( image != NULL )
+               return image->getLogicalPath();
+       else
+               return NULL;
+}
+
+
+
+bool _dyld_all_twolevel_modules_prebound(void)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       return FALSE; // fixme
+}
+
+void _dyld_bind_objc_module(const void *objc_module)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, objc_module);
+       // do nothing, with new dyld everything already bound
+}
+
+
+bool _dyld_bind_fully_image_containing_address(const void* address)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, address);
+       dyld::clearErrorMessage();
+       ImageLoader* image = dyld::findImageContainingAddress(address);
+       if ( image != NULL ) {
+               try {
+                       dyld::link(image, ImageLoader::kLazyAndNonLazy, ImageLoader::kDontRunInitializers);
+                       return true;
+               }
+               catch (const char* msg) {
+                       dyldAPIhalt(__func__, msg);
+               }
+       }
+       return false;
+}
+
+bool _dyld_image_containing_address(const void* address)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, address);
+       ImageLoader *imageLoader = dyld::findImageContainingAddress(address);
+       return (NULL != imageLoader);
+}
+
+static NSObjectFileImage createObjectImageFile(ImageLoader* image, const void* address = NULL, size_t len=0)
+{
+       NSObjectFileImage result = new __NSObjectFileImage();
+       result->image = image;
+       result->imageBaseAddress = address;
+       result->imageLength = len;
+       sObjectFileImages.push_back(result);
+       return result;
+}
+
+NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage *objectFileImage)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(\"%s\", ...)\n", __func__, pathName);
+       try {
+               void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+               ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+
+               dyld::LoadContext context;
+               context.useSearchPaths          = false;
+               context.useLdLibraryPath        = false;
+               context.matchByInstallName      = false;
+               context.dontLoad                        = false;
+               context.mustBeBundle            = true;
+               context.mustBeDylib                     = false;
+               context.origin                          = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
+               context.rpath                           = NULL; // support not yet implemented
+
+               ImageLoader* image = dyld::load(pathName, context);
+               // Note:  We DO NOT link the image!  NSLinkModule will do that
+               if ( image != NULL ) {
+                       if ( !image->isBundle() ) {
+                               // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
+                               return NSObjectFileImageInappropriateFile;
+                       }
+                       *objectFileImage = createObjectImageFile(image);
+                       return NSObjectFileImageSuccess;
+               }
+       }
+       catch (const char* msg) {
+               //fprintf(stderr, "dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
+               return NSObjectFileImageInappropriateFile;
+       }
+       return NSObjectFileImageFailure;
+}
+
+
+NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* address, size_t size, NSObjectFileImage *objectFileImage)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, %lu, %p)\n", __func__, address, size, objectFileImage);
+       
+       try {
+               ImageLoader* image = dyld::loadFromMemory((const uint8_t*)address, size, NULL); 
+               if ( ! image->isBundle() ) {
+                       // this API can only be used with bundles...
+                       delete image; 
+                       return NSObjectFileImageInappropriateFile;
+               }
+               // Note:  We DO NOT link the image!  NSLinkModule will do that
+               if ( image != NULL ) {
+                       *objectFileImage = createObjectImageFile(image, address, size);
+                       return NSObjectFileImageSuccess;
+               }
+       }
+       catch (const char* msg) {
+               fprintf(stderr, "dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg);
+       }
+       return NSObjectFileImageFailure;
+}
+
+static bool validOFI(NSObjectFileImage objectFileImage)
+{
+       const int ofiCount = sObjectFileImages.size();
+       for (int i=0; i < ofiCount; ++i) {
+               if ( sObjectFileImages[i] == objectFileImage )
+                       return true;
+       }
+       return false;
+}
+
+bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+       
+       if ( validOFI(objectFileImage) ) {
+               // if the image has never been linked or has been unlinked, the image is not in the list of valid images
+               // and we should delete it
+               bool linkedImage = dyld::validImage(objectFileImage->image);
+               if ( ! linkedImage ) 
+                       delete objectFileImage->image;
+               
+               // remove from list of ofi's
+               for (std::vector<NSObjectFileImage>::iterator it=sObjectFileImages.begin(); it != sObjectFileImages.end(); it++) {
+                       if ( *it == objectFileImage ) {
+                               sObjectFileImages.erase(it);
+                               break;
+                       }
+               }
+               
+               // if object was created from a memory, release that memory
+               // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
+               if ( objectFileImage->imageBaseAddress != NULL ) {
+                       vm_deallocate(mach_task_self(), (vm_address_t)objectFileImage->imageBaseAddress, objectFileImage->imageLength);
+               }
+               
+               // free ofi object
+               delete objectFileImage;
+               
+               return true;
+       }
+       return false;
+}
+
+bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+       return objectFileImage->image->needsInitialization();
+}
+
+uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+       return objectFileImage->image->getExportedSymbolCount();
+}
+
+const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p,%d)\n", __func__, objectFileImage, ordinal);
+       const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedExportedSymbol(ordinal);
+       return objectFileImage->image->getExportedSymbolName(sym);      
+}
+
+uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+       return objectFileImage->image->getImportedSymbolCount();
+}
+
+const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal, 
+                                                                                                       bool* tentative_definition)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p,%d)\n", __func__, objectFileImage, ordinal);
+       const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedImportedSymbol(ordinal);
+       if ( tentative_definition != NULL ) {
+               ImageLoader::ReferenceFlags flags = objectFileImage->image->geImportedSymbolInfo(sym);
+               if ( (flags & ImageLoader::kTentativeDefinition) != 0 )
+                       *tentative_definition = true;
+               else
+                       *tentative_definition = false;
+       }
+       return objectFileImage->image->getImportedSymbolName(sym);      
+}
+
+void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage,
+                                                                               const char* segmentName, const char* sectionName, unsigned long* size)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p,%s, %s)\n", __func__, objectFileImage, segmentName, sectionName);
+
+       void* start;
+       size_t length;
+       if ( objectFileImage->image->getSectionContent(segmentName, sectionName, &start, &length) ) {
+               if ( size != NULL )
+                       *size = length;
+               return start;
+       }
+       return NULL;
+}
+
+
+
+bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p,%s)\n", __func__, objectFileImage, symbolName);
+       const ImageLoader::Symbol* sym = objectFileImage->image->findExportedSymbol(symbolName, NULL, true, NULL);
+       return ( sym != NULL );
+}
+
+/*
+ * Given an imageOffset into an ObjectFileImage, returns 
+ * the segment/section name and offset into that section of
+ * that imageOffset.  Returns FALSE if the imageOffset is not 
+ * in any section.  You can used the resulting sectionOffset to
+ * index into the data returned by NSGetSectionDataInObjectFileImage.
+ * 
+ * First appeared in Mac OS X 10.3 
+ *
+ * SPI: currently only used by ZeroLink to detect +load methods
+ */
+bool 
+NSFindSectionAndOffsetInObjectFileImage(NSObjectFileImage objectFileImage, 
+                                                                               unsigned long imageOffset,
+                                                                               const char** segmentName,       /* can be NULL */
+                                                                               const char** sectionName,       /* can be NULL */
+                                                                               unsigned long* sectionOffset)   /* can be NULL */
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+       
+       return objectFileImage->image->findSection((char*)(objectFileImage->image->getBaseAddress())+imageOffset, segmentName, sectionName, sectionOffset);
+}
+
+
+
+NSModule NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", __func__, objectFileImage, moduleName, options); 
+       
+       dyld::clearErrorMessage();
+       try {
+               // NSLinkModule allows a bundle to be link multpile times
+               // each link causes the bundle to be copied to a new address
+               if ( objectFileImage->image->isLinked() ) {
+                       // already linked, so clone a new one and link it
+#if 0
+                       fprintf(stderr, "dyld: warning: %s(0x%08X, \"%s\", 0x%08X) called more than once for 0x%08X\n",
+                                       __func__, objectFileImage, moduleName, options, objectFileImage); 
+#endif
+                       objectFileImage->image = dyld::cloneImage(objectFileImage->image);
+               }
+               
+               // if this ofi was made with NSCreateObjectFileImageFromFile() then physical path is already set
+               // if this ofi was create with NSCreateObjectFileImageFromMemory() then the phyiscal path should be set if supplied 
+               if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 ) {
+                       if ( objectFileImage->imageBaseAddress != NULL ) {
+                               const char* physEnd = &moduleName[strlen(moduleName)+1];
+                               objectFileImage->image->setPath(physEnd);
+                       }
+               }
+       
+               // set moduleName as the name anyone calling _dyld_get_image_name() will see
+               objectFileImage->image->setLogicalPath(moduleName);
+
+               // support private bundles
+               if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
+                       objectFileImage->image->setHideExports();
+       
+               // set up linking options
+               ImageLoader::BindingLaziness bindness = ImageLoader::kNonLazyOnly;
+               if ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 )
+                       bindness = ImageLoader::kLazyAndNonLazy;
+               ImageLoader::InitializerRunning runInitializers = ImageLoader::kRunInitializers;
+               if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) != 0 )
+                       runInitializers = ImageLoader::kDontRunInitializersButTellObjc;
+               
+               // load libraries, rebase, bind, to make this image usable
+               dyld::link(objectFileImage->image, bindness, runInitializers);
+               
+               return ImageLoaderToNSModule(objectFileImage->image);
+       }
+       catch (const char* msg) {
+               if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
+                       dyldAPIhalt(__func__, msg);
+               // not halting, so set error state for NSLinkEditError to find
+               dyld::removeImage(objectFileImage->image);
+               setLastError(NSLinkEditOtherError, 0, moduleName, msg);
+               return NULL;
+       }
+}
+
+#if OLD_LIBSYSTEM_SUPPORT
+// This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
+static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr,  moduleName, options); // note name/args translation
+       ImageLoader* image = NULL;
+       dyld::clearErrorMessage();
+       try {
+               const char* imageName = moduleName;
+               if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 )
+                       imageName = &moduleName[strlen(moduleName)+1];
+                       
+               image = dyld::loadFromMemory((const uint8_t*)object_addr, object_size, imageName); 
+               
+               if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 )
+                       image->setLogicalPath(moduleName);
+                       
+               if ( image != NULL ) {          
+                       // support private bundles
+                       if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
+                               image->setHideExports();
+               
+                       // set up linking options
+                       ImageLoader::BindingLaziness bindness = ImageLoader::kNonLazyOnly;
+                       if ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 )
+                               bindness = ImageLoader::kLazyAndNonLazy;
+                       ImageLoader::InitializerRunning runInitializers = ImageLoader::kRunInitializers;
+                       if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) != 0 )
+                               runInitializers = ImageLoader::kDontRunInitializersButTellObjc;
+                       
+                       // load libraries, rebase, bind, to make this image usable
+                       dyld::link(image, bindness, runInitializers);
+               }
+       }
+       catch (const char* msg) {
+               if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
+                       dyldAPIhalt("NSLinkModule", msg);
+               // not halting, so set error state for NSLinkEditError to find
+               setLastError(NSLinkEditOtherError, 0, moduleName, msg);
+               // if image was created for this bundle, destroy it
+               if ( image != NULL ) {
+                       dyld::removeImage(image);
+                       delete image;
+               }
+               image = NULL;
+       }
+       return ImageLoaderToNSModule(image);
+}
+#endif
+
+NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, \"%s\")\n", __func__, (void *)module, symbolName);
+       ImageLoader* image = NSModuleToImageLoader(module);
+       if ( image == NULL ) 
+               return NULL;
+       return SymbolToNSSymbol(image->findExportedSymbol(symbolName, NULL, false, NULL));
+}
+
+const char* NSNameOfModule(NSModule module)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, module);
+       ImageLoader* image = NSModuleToImageLoader(module);
+       if ( image == NULL ) 
+               return NULL;
+       return image->getPath();
+}
+
+const char* NSLibraryNameForModule(NSModule module)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, module);
+       ImageLoader* image = NSModuleToImageLoader(module);
+       if ( image == NULL ) 
+               return NULL;
+       return image->getPath();
+}
+
+bool NSUnLinkModule(NSModule module, uint32_t options)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, 0x%08X)\n", __func__, module, options); 
+       if ( module == NULL )
+               return false;
+       ImageLoader* image = NSModuleToImageLoader(module);
+       if ( image == NULL ) 
+               return false;
+       dyld::removeImage(image);
+       
+       if ( (options & NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) != 0 )
+               image->setLeaveMapped();
+               
+       // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
+
+       // Only delete image if there is no ofi referencing it
+       // That means the ofi was destroyed after linking, so no one is left to delete this image       
+       const int ofiCount = sObjectFileImages.size();
+       bool found = false;
+       for (int i=0; i < ofiCount; ++i) {
+               NSObjectFileImage ofi = sObjectFileImages[i];
+               if ( ofi->image == image )
+                       found = true;
+       }
+       if ( !found )
+               delete image;
+       
+       return true;
+}
+
+// internal name and parameters do not match public name and parameters...
+static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "NSLinkEditErrorHandlers()\n");
+
+       dyld::registerUndefinedHandler((dyld::UndefinedHandler)undefined);
+       // no support for multiple or linkedit handlers
+}
+
+const struct mach_header * _dyld_get_image_header_containing_address(const void* address)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, address);
+       ImageLoader* image = dyld::findImageContainingAddress(address);
+       if ( image != NULL ) 
+               return image->machHeader();
+       return NULL;
+}
+
+
+void _dyld_register_func_for_add_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, (void *)func);
+       dyld::registerAddCallback(func);
+}
+
+void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, (void *)func);
+       dyld::registerRemoveCallback(func);
+}
+
+// called by atexit() function installed by crt
+static void _dyld_mod_term_funcs()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       dyld::runTerminators();
+}
+
+// called by crt before main
+static void _dyld_make_delayed_module_initializer_calls()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       dyld::initializeMainExecutable();
+}
+
+
+void NSLinkEditError(NSLinkEditErrors* c, int* errorNumber, const char** fileName, const char** errorString)
+{
+       // FIXME FIXME
+       *c = sLastErrorFileCode;
+       *errorNumber = sLastErrorNo;
+       *fileName = sLastErrorFilePath;
+       *errorString = dyld::getErrorMessage();
+}
+
+static void _dyld_register_binding_handler(void * (*bindingHandler)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       dyld::gLinkContext.bindingHandler = bindingHandler;
+       dyld::gLinkContext.bindingOptions = bindingOptions;
+}
+
+// Call by fork() in libSystem before the kernel trap is done
+static void _dyld_fork_prepare()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+}
+
+// Call by fork() in libSystem after the kernel trap is done on the parent side
+static void _dyld_fork_parent()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+}
+
+// Call by fork() in libSystem after the kernel trap is done on the child side
+static void _dyld_fork_child()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
+       // in libSystem for the child of a fork.  But dyld is built with a static copy
+       // of libc.a and has its own copy of mach_task_self_ which we reset here.
+       //
+       // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
+       // in mach_init() mach_task_self_ is initialized to task_self_trap().
+       //
+       extern mach_port_t      mach_task_self_;
+       mach_task_self_ = task_self_trap();
+}
+
+// Call by fork() in libSystem after the kernel trap is done on the child side after
+// other libSystem child side fixups are done
+static void _dyld_fork_child_final()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+}
+
+
+typedef void (*MonitorProc)(char *lowpc, char *highpc);
+
+static void monInitCallback(ImageLoader* image, void* userData)
+{
+       MonitorProc proc = (MonitorProc)userData;
+       void* start;
+       size_t length;
+       if ( image->getSectionContent("__TEXT", "__text", &start, &length) ) {
+               proc((char*)start, (char*)start+length);
+       }
+}
+
+//
+// _dyld_moninit is called from profiling runtime routine moninit().
+// dyld calls back with the range of each __TEXT/__text section in every
+// linked image.
+//
+void _dyld_moninit(MonitorProc proc)
+{
+       dyld::forEachImageDo(&monInitCallback, (void*)proc);
+}
+
+// returns true if prebinding was used in main executable
+bool _dyld_launched_prebound()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+               
+       // Â¥Â¥Â¥ÃŠif we deprecate prebinding, we may want to consider always returning true or false here
+       return dyld::mainExecutablePrebound();
+}
+
+
+//
+// _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
+// NSMakePrivateModulePublic() needed for the dlopen() to turn it's
+// RTLD_LOCAL handles into RTLD_GLOBAL.  It just simply turns off the private
+// flag on the image for this module.  If the module was found and it was
+// private then everything worked and TRUE is returned else FALSE is returned.
+//
+static bool NSMakePrivateModulePublic(NSModule module)
+{
+       ImageLoader* image = NSModuleToImageLoader(module);
+       if ( image != NULL ) {
+               if ( image->hasHiddenExports() ) {
+                       image->setHideExports(false);
+                       return true;
+               }
+       }
+       return false;
+}
+
+
+
+bool lookupDyldFunction(const char* name, uintptr_t* address)
+{
+       for (const dyld_func* p = dyld_funcs; p->name != NULL; ++p) {
+           if ( strcmp(p->name, name) == 0 ) {
+                       if( p->implementation == unimplemented )
+                               fprintf(stderr, "unimplemented dyld function: %s\n", p->name);
+                       *address = (uintptr_t)p->implementation;
+                       return true;
+           }
+       }
+       *address = 0;
+       return false;
+}
+
+
+static void registerThreadHelpers(const dyld::ThreadingHelpers* helpers)
+{
+       // We need to make sure libSystem's lazy pointer's are bound
+       // before installing thred helpers.
+       // The reason for this is that if accessing the lock requires
+       // a lazy pointer to be bound (and it does when multi-module
+       // libSystem) is not prebound, the lazy handler will be
+       // invoked which tries to acquire the lock again...an infinite 
+       // loop.
+       ImageLoader* image = dyld::findImageContainingAddress(helpers);
+       dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
+
+       dyld::gThreadHelpers = helpers;
+}
+
+
+static void dlerrorClear()
+{
+       if ( dyld::gThreadHelpers != NULL ) {
+               char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(1);
+               buffer[0] = '\0';
+       }
+}
+
+static void dlerrorSet(const char* msg)
+{
+       if ( dyld::gThreadHelpers != NULL ) {
+               char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(strlen(msg)+1);
+               strcpy(buffer, msg);
+       }
+}
+
+
+
+void* dlopen(const char* path, int mode)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%s, 0x%08X)\n", __func__, path, mode);
+
+       dlerrorClear();
+       
+       // passing NULL for path means return magic object
+       if ( path == NULL ) {
+               return RTLD_DEFAULT;
+       }
+       
+       try {
+               void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+               ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+
+               ImageLoader*    image = NULL;
+               dyld::LoadContext context;
+               context.useSearchPaths  = true;
+               context.useLdLibraryPath= (strchr(path, '/') == NULL);  // a leafname implies should search 
+               context.matchByInstallName = true;
+               context.dontLoad = ( (mode & RTLD_NOLOAD) != 0 );
+               context.mustBeBundle    = false;
+               context.mustBeDylib             = false;
+               context.origin                  = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
+               context.rpath                   = NULL; // support not yet implemented
+               
+               image = load(path, context);
+               if ( image != NULL ) {
+                       image->incrementReferenceCount();
+                       if ( ! image->isLinked() ) {
+                               ImageLoader::BindingLaziness bindiness = ImageLoader::kNonLazyOnly;
+                               if ( (mode & RTLD_NOW) != 0 )
+                                       bindiness = ImageLoader::kLazyAndNonLazy;
+                               dyld::link(image, bindiness, ImageLoader::kRunInitializers);
+                               // only hide exports if image is not already in use
+                               if ( (mode & RTLD_LOCAL) != 0 )
+                                       image->setHideExports(true);
+                       }
+                       // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
+                       // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated. 
+                       // The subtle differences are: 
+                       //  1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
+                       //  2) If someone does a supsequent dlopen() on the same image, whether the same address should be used. 
+                       if ( (mode & RTLD_NODELETE) != 0 )
+                               image->setLeaveMapped();
+                       return image;
+               }
+       }
+       catch (const char* msg) {
+               const char* format = "dlopen(%s, %d): %s";
+               char temp[strlen(format)+strlen(path)+strlen(msg)+10];
+               sprintf(temp, format, path, mode, msg);
+               dlerrorSet(temp);
+       }
+       return NULL;
+}
+
+int dlclose(void* handle)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p)\n", __func__, handle);
+
+       ImageLoader* image = (ImageLoader*)handle;
+       if ( dyld::validImage(image) ) {
+               if ( image->decrementReferenceCount() ) {
+                       // for now, only bundles can be unloaded
+                       // to unload dylibs we would need to track all direct and indirect uses
+                       if ( image->isBundle() ) {
+                               dyld::removeImage(image);
+                               delete image;
+                       }
+               }
+               dlerrorClear();
+               return 0;
+       }
+       else {
+               dlerrorSet("invalid handle passed to dlclose()");
+               return -1;
+       }
+}
+
+
+
+int dladdr(const void* address, Dl_info* info)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, %p)\n", __func__, address, info);
+
+       ImageLoader* image = dyld::findImageContainingAddress(address);
+       if ( image != NULL ) {
+               info->dli_fname = image->getLogicalPath();
+               info->dli_fbase = (void*)image->machHeader();   
+               // find closest exported symbol in the image
+               const uint32_t exportCount = image->getExportedSymbolCount();
+               const ImageLoader::Symbol* bestSym = NULL;
+               const void* bestAddr = 0;
+               for(uint32_t i=0; i < exportCount; ++i) {
+                       const ImageLoader::Symbol* sym = image->getIndexedExportedSymbol(i);
+                       const void* symAddr = (void*)image->getExportedSymbolAddress(sym);
+                       if ( (symAddr <= address) && (bestAddr < symAddr) ) {
+                               bestSym = sym;
+                               bestAddr = symAddr;
+                       }
+               }
+               if ( bestSym != NULL ) {
+                       info->dli_sname = image->getExportedSymbolName(bestSym) + 1; // strip off leading underscore
+                       info->dli_saddr = (void*)bestAddr;
+               }
+               else {
+                       info->dli_sname = NULL;
+                       info->dli_saddr = NULL;
+               }
+               return 1; // success
+       }
+       return 0;  // failure
+}
+
+
+char* dlerror()
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+
+       if ( dyld::gThreadHelpers != NULL ) {
+               char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(1);
+               // if no error set, return NULL
+               if ( buffer[0] != '\0' )
+                       return buffer;
+       }
+       return NULL;
+}
+
+void* dlsym(void* handle, const char* symbolName)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s(%p, %s)\n", __func__, handle, symbolName);
+
+       dlerrorClear();
+
+       ImageLoader* image;
+       const ImageLoader::Symbol* sym;
+
+       // dlsym() assumes symbolName passed in is same as in C source code
+       // dyld assumes all symbol names have an underscore prefix
+       char underscoredName[strlen(symbolName)+2];
+       underscoredName[0] = '_';
+       strcpy(&underscoredName[1], symbolName);
+       
+       // magic "search all" handle
+       if ( handle == RTLD_DEFAULT ) {
+               if ( dyld::flatFindExportedSymbol(underscoredName, &sym, &image) ) {
+                       return (void*)image->getExportedSymbolAddress(sym);
+               }
+               const char* format = "dlsym(RTLD_DEFAULT, %s): symbol not found";
+               char temp[strlen(format)+strlen(symbolName)+2];
+               sprintf(temp, format, symbolName);
+               dlerrorSet(temp);
+               return NULL;
+       }
+       
+       // magic "search what I would see" handle
+       if ( handle == RTLD_NEXT ) {
+               void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+               ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+               sym = callerImage->resolveSymbol(underscoredName, false, &image);
+               if ( sym != NULL ) {
+                       return (void*)image->getExportedSymbolAddress(sym);
+               }
+               const char* format = "dlsym(RTLD_NEXT, %s): symbol not found";
+               char temp[strlen(format)+strlen(symbolName)+2];
+               sprintf(temp, format, symbolName);
+               dlerrorSet(temp);
+               return NULL;
+       }
+#ifdef RTLD_SELF
+       // magic "search me, then what I would see" handle
+       if ( handle == RTLD_SELF ) {
+               void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+               ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+               sym = callerImage->findExportedSymbol(underscoredName, NULL, false, &image);  // search first in calling image
+               if ( sym != NULL ) {
+                       return (void*)image->getExportedSymbolAddress(sym);
+               }
+               sym = callerImage->resolveSymbol(underscoredName, false, &image);                       // search what calling image links against
+               if ( sym != NULL ) {
+                       return (void*)image->getExportedSymbolAddress(sym);
+               }
+               const char* format = "dlsym(RTLD_SELF, %s): symbol not found";
+               char temp[strlen(format)+strlen(symbolName)+2];
+               sprintf(temp, format, symbolName);
+               dlerrorSet(temp);
+               return NULL;
+       }
+#endif
+       // real handle
+       image = (ImageLoader*)handle;
+       if ( dyld::validImage(image) ) {
+               ImageLoader* foundIn;
+               sym = image->findExportedSymbol(underscoredName, NULL, true, &foundIn);
+               if ( sym != NULL ) {
+                       return (void*)(foundIn->getExportedSymbolAddress(sym));
+               }
+               sym = image->resolveSymbol(underscoredName, false, &image);// search what image links against
+               if ( sym != NULL ) {
+                       return (void*)image->getExportedSymbolAddress(sym);
+               }
+               const char* format = "dlsym(%p, %s): symbol not found";
+               char temp[strlen(format)+strlen(symbolName)+20];
+               sprintf(temp, format, handle, symbolName);
+               dlerrorSet(temp);
+       }
+       else {
+               dlerrorSet("invalid handle passed to dlsym()");
+       }
+       return NULL;
+}
+
+
+#define UPDATE_PREBINDING_DRY_RUN  0x00000001
+#define UPDATE_PREBINDING_PROGRESS 0x00000002
+
+//
+// SPI called only by update_prebinding tool to redo prebinding in all prebound files specified
+// There must be no dylibs loaded when this fnction is called.
+//
+__attribute__((noreturn))
+static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t flags)
+{
+       if ( dyld::gLogAPIs )
+               fprintf(stderr, "%s()\n", __func__);
+       
+       // list of requested dylibs actually loaded
+       std::vector<ImageLoader*> preboundImages;
+       
+       try {
+               // verify no dylibs loaded
+               if ( dyld::getImageCount() != 1 )
+                       throw "_dyld_update_prebinding cannot be called with dylib already loaded";
+                       
+               const uint32_t max_allowed_link_errors = 10;
+               uint32_t link_error_count = 0;
+               
+               // load and link each dylib
+               for (int i=0; i < pathCount; ++i) {
+                       dyld::LoadContext context;
+                       context.useSearchPaths          = false;
+                       context.matchByInstallName      = true;
+                       context.dontLoad                        = false;
+                       context.mustBeBundle            = false;
+                       context.mustBeDylib                     = true;
+                       context.origin                          = NULL;         // @loader_path not allowed in prebinding list
+                       context.rpath                           = NULL;         // support not yet implemented
+                       
+                       ImageLoader* image = NULL;
+                       try {
+                               image = dyld::load(paths[i], context);
+                               // bind lazy and non-lazy symbols, but don't run initializers
+                               // this may bring in other dylibs later in the list or missing from list, but that is ok
+                               dyld::link(image, ImageLoader::kLazyAndNonLazy, ImageLoader::kDontRunInitializers);
+                               // recored images we successfully loaded
+                               preboundImages.push_back(image);
+                       }
+                       catch (const char* msg) {
+                               if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) ) {
+                                       const char *stage;
+                                       if ( image == NULL ) // load exception
+                                               stage = "load";
+                                       else // link exception
+                                               stage = "link";
+                                       fprintf(stderr, "update_prebinding: warning: could not %s %s: %s\n", stage, paths[i], msg);
+                               }
+                               if ( image != NULL )
+                                       link_error_count++;
+                               if ( link_error_count > max_allowed_link_errors )
+                                       throw;
+                       }
+               }
+               
+               // find missing images
+               uint32_t loadedImageCount =     dyld::getImageCount();
+               if ( loadedImageCount > (preboundImages.size()+1) ) {
+                       if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+                               fprintf(stderr, "update_prebinding: warning: the following dylibs were loaded but will not have their prebinding updated because they are not in the list of paths to reprebind\n");
+                       for (uint32_t i=1; i < loadedImageCount; ++i) {
+                               ImageLoader* target = dyld::getIndexedImage(i);
+                               bool found = false;
+                               for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+                                       if ( *it == target ) {
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                               if ( !found ) 
+                                       if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+                                               fprintf(stderr, "  %s\n", target->getPath());
+                       }
+               }
+
+               // warn about unprebound files in the list
+               bool unpreboundWarned = false;
+               for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+                       if ( ! (*it)->isPrebindable() && (*it != dyld::mainExecutable()) ) {
+                               if ( ! unpreboundWarned ) {
+                                       if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+                                               fprintf(stderr, "update_prebinding: warning: the following dylibs were specified but were not built prebound\n");
+                                       unpreboundWarned = true;
+                               }
+                               if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+                                       fprintf(stderr, "  %s\n", (*it)->getPath());
+                       }
+               }
+               
+               if(UPDATE_PREBINDING_DRY_RUN & flags) {
+                       fprintf(stderr, "update_prebinding: dry-run: no changes were made to the filesystem.\n");
+               }
+               else {
+                       uint32_t imageCount = preboundImages.size();
+                       uint32_t imageNumber = 1;
+                       // tell each image to write itself out re-prebound
+                       struct timeval currentTime = { 0 , 0 };
+                       gettimeofday(&currentTime, NULL);
+                       time_t timestamp = currentTime.tv_sec;
+                       for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+                               (*it)->reprebind(dyld::gLinkContext, timestamp);
+                               if(UPDATE_PREBINDING_PROGRESS & flags) {
+                                       fprintf(stdout, "update_prebinding: progress: %3u/%u\n", imageNumber, imageCount);
+                                       fflush(stdout);
+                                       imageNumber++;
+                               }
+                       }
+               
+                       // tell file system to flush all dirty buffers to disk
+                       // after this sync, all the _redoprebinding files will be on disk
+                       sync();
+               
+                       // now commit (swap file) for each re-prebound image
+                       // this only updates directories, since the files have already been flushed by previous sync()
+                       for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+                               (*it)->reprebindCommit(dyld::gLinkContext, true);
+                       }
+               
+                       // tell file system to flush all dirty buffers to disk
+                       // this should flush out all directory changes caused by the file swapping
+                       sync();
+               }
+       }
+       catch (const char* msg) {
+               // delete temp files
+               try {
+                       for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+                               (*it)->reprebindCommit(dyld::gLinkContext, false);
+                       }
+               }
+               catch (const char* commitMsg) {
+                       fprintf(stderr, "update_prebinding: error: %s\n", commitMsg);
+               }
+               fprintf(stderr, "update_prebinding: error: %s\n", msg);
+               exit(1);
+       }
+       exit(0);
+}
+
+
+
+static const struct dyld_all_image_infos* _dyld_get_all_image_infos()
+{
+       return &dyld_all_image_infos;
+}
+
+
+
+
+
+
+
+
diff --git a/src/dyldAPIsInLibSystem.cpp b/src/dyldAPIsInLibSystem.cpp
new file mode 100644 (file)
index 0000000..67f4eb7
--- /dev/null
@@ -0,0 +1,1133 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <crt_externs.h>
+
+#include "mach-o/dyld.h"
+#include "mach-o/dyld_priv.h"
+
+#include "dyldLock.h"
+
+/*
+ * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
+ * libraryName (which is -lx or -framework Foo argument passed to the static
+ * link editor for the same library) and determines if they match.  This depends
+ * on conventional use of names including major versioning.
+ */
+static
+bool
+names_match(
+char *install_name,
+const char* libraryName)
+{
+    char *basename;
+    unsigned long n;
+
+       /*
+        * Conventional install names have these forms:
+        *      /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
+        *      /Local/Library/Frameworks/AppKit.framework/Appkit
+        *      /lib/libsys_s.A.dylib
+        *      /usr/lib/libsys_s.dylib
+        */
+       basename = strrchr(install_name, '/');
+       if(basename == NULL)
+           basename = install_name;
+       else
+           basename++;
+
+       /*
+        * By checking the base name matching the library name we take care
+        * of the -framework cases.
+        */
+       if(strcmp(basename, libraryName) == 0)
+           return(TRUE);
+
+       /*
+        * Now check the base name for "lib" if so proceed to check for the
+        * -lx case dealing with a possible .X.dylib and a .dylib extension.
+        */
+       if(strncmp(basename, "lib", 3) ==0){
+           n = strlen(libraryName);
+           if(strncmp(basename+3, libraryName, n) == 0){
+               if(strncmp(basename+3+n, ".dylib", 6) == 0)
+                   return(TRUE);
+               if(basename[3+n] == '.' &&
+                  basename[3+n+1] != '\0' &&
+                  strncmp(basename+3+n+2, ".dylib", 6) == 0)
+                   return(TRUE);
+           }
+       }
+       return(FALSE);
+}
+
+void NSInstallLinkEditErrorHandlers(
+const NSLinkEditErrorHandlers* handlers)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(
+       void     (*undefined)(const char* symbol_name),
+       NSModule (*multiple)(NSSymbol s, NSModule old, NSModule newhandler),
+       void     (*linkEdit)(NSLinkEditErrors c, int errorNumber,
+                    const char* fileName, const char* errorString)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_install_handlers", (void**)&p);
+       p(handlers->undefined, handlers->multiple, handlers->linkEdit);
+}
+
+const char* 
+NSNameOfModule(
+NSModule module)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static const char*  (*p)(NSModule module) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p);
+       return(p(module));
+} 
+
+const char* 
+NSLibraryNameForModule(
+NSModule module)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static const char*  (*p)(NSModule module) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p);
+       return(p(module));
+}
+
+bool
+NSIsSymbolNameDefined(
+const char* symbolName)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(const char* symbolName) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p);
+       return(p(symbolName));
+}
+
+bool
+NSIsSymbolNameDefinedWithHint(
+const char* symbolName,
+const char* libraryNameHint)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(const char* symbolName,
+                         const char* libraryNameHint) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p);
+       return(p(symbolName, libraryNameHint));
+}
+
+bool
+NSIsSymbolNameDefinedInImage(
+const struct mach_header *image,
+const char* symbolName)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(const struct mach_header *image,
+                         const char* symbolName) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p);
+       return(p(image, symbolName));
+}
+
+NSSymbol
+NSLookupAndBindSymbol(
+const char* symbolName)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static NSSymbol (*p)(const char* symbolName) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p);
+       return(p(symbolName));
+}
+
+NSSymbol
+NSLookupAndBindSymbolWithHint(
+const char* symbolName,
+const char* libraryNameHint)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static NSSymbol (*p)(const char* symbolName,
+                        const char* libraryNameHint) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p);
+       return(p(symbolName, libraryNameHint));
+}
+
+NSSymbol
+NSLookupSymbolInModule(
+NSModule module,
+const char* symbolName)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static NSSymbol (*p)(NSModule module, const char* symbolName) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p);
+       return(p(module, symbolName));
+}
+
+NSSymbol
+NSLookupSymbolInImage(
+const struct mach_header *image,
+const char* symbolName,
+uint32_t options)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+   static NSSymbol (*p)(const struct mach_header *image,
+                        const char* symbolName,
+                        uint32_t options) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p);
+       return(p(image, symbolName, options));
+}
+
+const char* 
+NSNameOfSymbol(
+NSSymbol symbol)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static char * (*p)(NSSymbol symbol) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p);
+       return(p(symbol));
+}
+
+void *
+NSAddressOfSymbol(
+NSSymbol symbol)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static void * (*p)(NSSymbol symbol) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p);
+       return(p(symbol));
+}
+
+NSModule
+NSModuleForSymbol(
+NSSymbol symbol)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static NSModule (*p)(NSSymbol symbol) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p);
+       return(p(symbol));
+}
+
+bool
+NSAddLibrary(
+const char* pathName)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static bool (*p)(const char* pathName) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p);
+       return(p(pathName));
+}
+
+bool
+NSAddLibraryWithSearching(
+const char* pathName)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static bool (*p)(const char* pathName) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p);
+       return(p(pathName));
+}
+
+const struct mach_header *
+NSAddImage(
+const char* image_name,
+uint32_t options)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static const struct mach_header * (*p)(const char* image_name,
+                                          uint32_t options) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSAddImage", (void**)&p);
+       return(p(image_name, options));
+}
+
+/*
+ * This routine returns the current version of the named shared library the
+ * executable it was built with.  The libraryName parameter is the same as the
+ * -lx or -framework Foo argument passed to the static link editor when building
+ * the executable (with -lx it would be "x" and with -framework Foo it would be
+ * "Foo").  If this the executable was not built against the specified library
+ * it returns -1.  It should be noted that if this only returns the value the
+ * current version of the named shared library the executable was built with
+ * and not a list of current versions that dependent libraries and bundles the
+ * program is using were built with.
+ */
+int32_t
+NSVersionOfLinkTimeLibrary(
+const char* libraryName)
+{
+    unsigned long i;
+    struct load_command *load_commands, *lc;
+    struct dylib_command *dl;
+    char *install_name;
+#ifndef __OPENSTEP__
+    static struct mach_header *mh = NULL;
+       if(mh == NULL)
+           mh = _NSGetMachExecuteHeader();
+#else /* defined(__OPENSTEP__) */
+#ifdef __DYNAMIC__
+    static struct mach_header *mh = NULL;
+       if(mh == NULL)
+           _dyld_lookup_and_bind("__mh_execute_header", &mh, NULL);
+#else
+    struct mach_header *mh;
+       mh = (struct mach_header *)&_mh_execute_header;
+#endif
+#endif /* __OPENSTEP__ */
+       load_commands = (struct load_command *)
+                       ((char *)mh + sizeof(struct mach_header));
+       lc = load_commands;
+       for(i = 0; i < mh->ncmds; i++){
+           if(lc->cmd == LC_LOAD_DYLIB){
+               dl = (struct dylib_command *)lc;
+               install_name = (char *)dl + dl->dylib.name.offset;
+               if(names_match(install_name, libraryName) == TRUE)
+                   return(dl->dylib.current_version);
+           }
+           lc = (struct load_command *)((char *)lc + lc->cmdsize);
+       }
+       return(-1);
+}
+
+/*
+ * This routine returns the current version of the named shared library the
+ * program it is running against.  The libraryName parameter is the same as
+ * would be static link editor using the -lx or -framework Foo flags (with -lx
+ * it would be "x" and with -framework Foo it would be "Foo").  If the program
+ * is not using the specified library it returns -1.
+ */
+int32_t
+NSVersionOfRunTimeLibrary(
+const char* libraryName)
+{
+    unsigned long i, j, n;
+    char *install_name;
+    struct load_command *load_commands, *lc;
+    struct dylib_command *dl;
+    const struct mach_header *mh;
+
+       n = _dyld_image_count();
+       for(i = 0; i < n; i++){
+           mh = _dyld_get_image_header(i);
+           if(mh->filetype != MH_DYLIB)
+               continue;
+           load_commands = (struct load_command *)
+                           ((char *)mh + sizeof(struct mach_header));
+           lc = load_commands;
+           for(j = 0; j < mh->ncmds; j++){
+               if(lc->cmd == LC_ID_DYLIB){
+                   dl = (struct dylib_command *)lc;
+                   install_name = (char *)dl + dl->dylib.name.offset;
+                   if(names_match(install_name, libraryName) == TRUE)
+                       return(dl->dylib.current_version);
+               }
+               lc = (struct load_command *)((char *)lc + lc->cmdsize);
+           }
+       }
+       return(-1);
+}
+
+/*
+ * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
+ * specified file name if the file is a correct Mach-O file that can be loaded
+ * with NSloadModule().  For return codes of NSObjectFileImageFailure and
+ * NSObjectFileImageFormat an error message is printed to stderr.  All
+ * other codes cause no printing. 
+ */
+NSObjectFileImageReturnCode
+NSCreateObjectFileImageFromFile(
+const char* pathName,
+NSObjectFileImage *objectFileImage)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p);
+       return p(pathName, objectFileImage);
+}
+
+
+/*
+ * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
+ * object file mapped into memory at address of size length if the object file
+ * is a correct Mach-O file that can be loaded with NSloadModule().  For return
+ * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
+ * message is printed to stderr.  All other codes cause no printing. 
+ */
+NSObjectFileImageReturnCode
+NSCreateObjectFileImageFromMemory(
+const void* address,
+size_t size, 
+NSObjectFileImage *objectFileImage)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p);
+       return p(address, size, objectFileImage);
+}
+
+/*
+ * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the 
+ * specified core file name if the file is a correct Mach-O core file.
+ * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
+ * an error message is printed to stderr.  All other codes cause no printing. 
+ */
+NSObjectFileImageReturnCode
+NSCreateCoreFileImageFromFile(
+const char* pathName,
+NSObjectFileImage *objectFileImage)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p);
+       return p(pathName, objectFileImage);
+}
+
+bool
+NSDestroyObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static bool (*p)(NSObjectFileImage) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p);
+       return p(objectFileImage);
+}
+
+
+NSModule
+NSLinkModule(
+NSObjectFileImage objectFileImage, 
+const char* moduleName,
+uint32_t options)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p);
+               
+       return p(objectFileImage, moduleName, options);
+}
+
+
+/*
+ * NSFindSectionAndOffsetInObjectFileImage() takes the specified imageOffset
+ * into the specified ObjectFileImage and returns the segment/section name and
+ * offset into that section of that imageOffset.  Returns FALSE if the
+ * imageOffset is not in any section.  You can used the resulting sectionOffset
+ * to index into the data returned by NSGetSectionDataInObjectFileImage.
+ * 
+ * SPI: currently only used by ZeroLink to detect +load methods
+ */
+bool 
+NSFindSectionAndOffsetInObjectFileImage(
+NSObjectFileImage objectFileImage, 
+unsigned long imageOffset,
+const char** segmentName,      /* can be NULL */
+const char** sectionName,      /* can be NULL */
+unsigned long* sectionOffset)  /* can be NULL */
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(NSObjectFileImage, unsigned long, const char**, const char**, unsigned long*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSFindSectionAndOffsetInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage, imageOffset, segmentName, sectionName, sectionOffset);
+}
+
+
+/*
+ * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
+ * definitions in the NSObjectFileImage.
+ */
+uint32_t
+NSSymbolDefinitionCountInObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static unsigned long (*p)(NSObjectFileImage) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage);
+}
+
+/*
+ * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
+ * symbol definitions in the NSObjectFileImage.  If the ordinal specified is
+ * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
+ * be returned.
+ */
+const char* 
+NSSymbolDefinitionNameInObjectFileImage(
+NSObjectFileImage objectFileImage,
+uint32_t ordinal)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static const char*  (*p)(NSObjectFileImage, uint32_t) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage, ordinal);
+}
+
+/*
+ * NSSymbolReferenceCountInObjectFileImage() returns the number of references
+ * to undefined symbols the NSObjectFileImage.
+ */
+uint32_t
+NSSymbolReferenceCountInObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static unsigned long (*p)(NSObjectFileImage) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage);
+}
+
+/*
+ * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
+ * undefined symbol in the NSObjectFileImage. If the ordinal specified is
+ * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
+ * returned.
+ */
+const char* 
+NSSymbolReferenceNameInObjectFileImage(
+NSObjectFileImage objectFileImage,
+uint32_t ordinal,
+bool *tentative_definition) /* can be NULL */
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static const char*  (*p)(NSObjectFileImage, uint32_t, bool*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage, ordinal, tentative_definition);
+}
+
+/*
+ * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
+ * name has a definition in the NSObjectFileImage and FALSE otherwise.
+ */
+bool
+NSIsSymbolDefinedInObjectFileImage(
+NSObjectFileImage objectFileImage,
+const char* symbolName)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(NSObjectFileImage, const char*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage, symbolName);
+}
+
+/*
+ * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
+ * in the NSObjectFileImage for the specified segmentName and sectionName if
+ * it exists and it is not a zerofill section.  If not it returns NULL.  If
+ * the parameter size is not NULL the size of the section is also returned
+ * indirectly through that pointer.
+ */
+void *
+NSGetSectionDataInObjectFileImage(
+NSObjectFileImage objectFileImage,
+const char* segmentName,
+const char* sectionName,
+unsigned long *size) /* can be NULL */
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage, segmentName, sectionName, size);
+}
+
+/*
+ * NSHasModInitObjectFileImage() returns TRUE if the NSObjectFileImage has any
+ * module initialization sections and FALSE it it does not.
+ *
+ * SPI: currently only used by ZeroLink to detect C++ initializers
+ */
+bool
+NSHasModInitObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(NSObjectFileImage) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_NSHasModInitObjectFileImage", (void**)&p);
+               
+       return p(objectFileImage);
+}
+
+void
+NSLinkEditError(
+NSLinkEditErrors *c,
+int *errorNumber, 
+const char* *fileName,
+const char* *errorString)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(NSLinkEditErrors *c,
+                    int *errorNumber, 
+                    const char* *fileName,
+                    const char* *errorString) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_link_edit_error", (void**)&p);
+       if(p != NULL)
+           p(c, errorNumber, fileName, errorString);
+}
+
+bool
+NSUnLinkModule(
+NSModule module, 
+uint32_t options)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static bool (*p)(NSModule module, uint32_t options) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_unlink_module", (void**)&p);
+
+       return p(module, options);
+}
+
+NSModule
+NSReplaceModule(
+NSModule moduleToReplace,
+NSObjectFileImage newObjectFileImage, 
+uint32_t options)
+{
+       return(NULL);
+}
+
+/*
+ *_NSGetExecutablePath copies the path of the executable into the buffer and
+ * returns 0 if the path was successfully copied in the provided buffer. If the
+ * buffer is not large enough, -1 is returned and the expected buffer size is
+ * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
+ * the executable not a "real path" to the executable. That is the path may be
+ * a symbolic link and not the real file. And with deep directories the total
+ * bufsize needed could be more than MAXPATHLEN.
+ */
+int
+_NSGetExecutablePath(
+char *buf,
+uint32_t *bufsize)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static int (*p)(char *buf, uint32_t *bufsize) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p);
+       return(p(buf, bufsize));
+}
+
+void
+_dyld_lookup_and_bind(
+const char* symbol_name,
+void** address,
+NSModule* module)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(const char*, void** , NSModule*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p);
+       p(symbol_name, address, module);
+}
+
+void
+_dyld_lookup_and_bind_with_hint(
+const char* symbol_name,
+const char* library_name_hint,
+void** address,
+NSModule* module)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(const char*, const char*, void**, NSModule*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p);
+       p(symbol_name, library_name_hint, address, module);
+}
+
+void
+_dyld_lookup_and_bind_objc(
+const char* symbol_name,
+void** address,
+NSModule* module)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(const char* , void**, NSModule*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p);
+       p(symbol_name, address, module);
+}
+
+void
+_dyld_lookup_and_bind_fully(
+const char* symbol_name,
+void** address,
+NSModule* module)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(const char*, void**, NSModule*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p);
+       p(symbol_name, address, module);
+}
+
+bool
+_dyld_bind_fully_image_containing_address(
+const void* address)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static bool (*p)(const void*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p);
+       return p(address);
+}
+
+
+/*
+ * _dyld_register_func_for_add_image registers the specified function to be
+ * called when a new image is added (a bundle or a dynamic shared library) to
+ * the program.  When this function is first registered it is called for once
+ * for each image that is currently part of the program.
+ */
+void
+_dyld_register_func_for_add_image(
+void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p);
+       p(func);
+}
+
+/*
+ * _dyld_register_func_for_remove_image registers the specified function to be
+ * called when an image is removed (a bundle or a dynamic shared library) from
+ * the program.
+ */
+void
+_dyld_register_func_for_remove_image(
+void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p);
+       p(func);
+}
+
+/*
+ * _dyld_register_func_for_link_module registers the specified function to be
+ * called when a module is bound into the program.  When this function is first
+ * registered it is called for once for each module that is currently bound into
+ * the program.
+ */
+void
+_dyld_register_func_for_link_module(
+void (*func)(NSModule module))
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(void (*func)(NSModule module)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p);
+       p(func);
+}
+
+/*
+ * _dyld_register_func_for_unlink_module registers the specified function to be
+ * called when a module is unbound from the program.
+ */
+void
+_dyld_register_func_for_unlink_module(
+void (*func)(NSModule module))
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(void (*func)(NSModule module)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p);
+       p(func);
+}
+
+/*
+ * _dyld_register_func_for_replace_module registers the specified function to be
+ * called when a module is to be replace with another module in the program.
+ */
+void
+_dyld_register_func_for_replace_module(
+void (*func)(NSModule oldmodule, NSModule newmodule))
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void (*p)(void (*func)(NSModule oldmodule,
+                                 NSModule newmodule)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p);
+       p(func);
+}
+
+
+/*
+ * _dyld_get_objc_module_sect_for_module is passed a module and sets a 
+ * pointer to the (__OBJC,__module) section and its size for the specified
+ * module.
+ */
+void
+_dyld_get_objc_module_sect_for_module(
+NSModule module,
+void **objc_module,
+unsigned long *size)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static void (*p)(NSModule module,
+                    void **objc_module,
+                    unsigned long *size) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p);
+       p(module, objc_module, size);
+}
+
+/*
+ * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
+ * __module) section and causes the module that is associated with that address
+ * to be bound.
+ */
+void
+_dyld_bind_objc_module(
+const void* objc_module)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static void (*p)(const void *objc_module) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p);
+       p(objc_module);
+}
+
+
+#if __DYNAMIC__
+bool
+_dyld_present(
+void)
+{
+       // hmmm, this code is in libSystem.dylib, which is loaded by dyld...
+       return true;
+}
+#endif
+
+uint32_t
+_dyld_image_count(
+void)
+{
+       DYLD_NO_LOCK_THIS_BLOCK;
+    static unsigned long (*p)(void) = NULL;
+
+       if(_dyld_present() == 0)
+           return(0);
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_image_count", (void**)&p);
+       return(p());
+}
+
+const struct mach_header *
+_dyld_get_image_header(
+uint32_t image_index)
+{
+       DYLD_NO_LOCK_THIS_BLOCK;
+    static struct mach_header * (*p)(uint32_t image_index) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_get_image_header", (void**)&p);
+       return(p(image_index));
+}
+
+intptr_t
+_dyld_get_image_vmaddr_slide(
+uint32_t image_index)
+{
+       DYLD_NO_LOCK_THIS_BLOCK;
+    static unsigned long (*p)(uint32_t image_index) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p);
+       return(p(image_index));
+}
+
+const char* 
+_dyld_get_image_name(
+uint32_t image_index)
+{
+       DYLD_NO_LOCK_THIS_BLOCK;
+    static const char*  (*p)(uint32_t image_index) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_get_image_name", (void**)&p);
+       return(p(image_index));
+}
+
+bool
+_dyld_image_containing_address(
+const void* address)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(const void*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_image_containing_address", (void**)&p);
+       return(p(address));
+}
+
+const struct mach_header *
+_dyld_get_image_header_containing_address(
+const void* address)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static const struct mach_header * (*p)(const void*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
+       return p(address);
+}
+
+void _dyld_moninit(
+void (*monaddition)(char *lowpc, char *highpc))
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static void (*p)(void (*monaddition)(char *lowpc, char *highpc)) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_moninit", (void**)&p);
+       p(monaddition);
+}
+
+bool _dyld_launched_prebound(
+void)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(void) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_launched_prebound", (void**)&p);
+       return(p());
+}
+
+bool _dyld_all_twolevel_modules_prebound(
+void)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static bool (*p)(void) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p);
+       return(p());
+}
+
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+#include "dyldLock.h"
+#include "dyldLibSystemThreadHelpers.h"
+
+// pthread key used to access per-thread dlerror message
+static pthread_key_t dlerrorPerThreadKey;
+
+// data kept per-thread
+struct dlerrorPerThreadData
+{
+       uint32_t        sizeAllocated;
+       char            message[1];
+};
+
+// function called by dyld to get buffer to store dlerror message
+static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired)
+{
+       const int size = (sizeRequired < 256) ? 256 : sizeRequired;
+       dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey);
+       if ( data == NULL ) {
+               //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
+               const int mallocSize = sizeof(dlerrorPerThreadData)+size;
+               data = (dlerrorPerThreadData*)malloc(mallocSize);
+               data->sizeAllocated = size;
+               pthread_setspecific(dlerrorPerThreadKey, data);
+       }
+       else if ( data->sizeAllocated < sizeRequired ) {
+               free(data);
+               //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
+               const int mallocSize = sizeof(dlerrorPerThreadData)+size;
+               data = (dlerrorPerThreadData*)malloc(mallocSize);
+               data->sizeAllocated = size;
+               pthread_setspecific(dlerrorPerThreadKey, data);
+       }
+       return data->message;
+}
+
+// that table passed to dyld containing thread helpers
+static dyld::ThreadingHelpers sThreadHelpers = { 1, &lockForLazyBinding, &unlockForLazyBinding, &getPerThreadBufferFor_dlerror };
+
+//
+// during initialization of libSystem this routine will run
+// and call dyld, registering the threading helpers.
+//
+//
+static int registerWithDyld()
+{
+    static void (*p)(dyld::ThreadingHelpers*) = NULL;
+
+       // create key and tell pthread package to call free() on any data associated with key if thread dies
+       pthread_key_create(&dlerrorPerThreadKey, &free);
+       
+       if(p == NULL) 
+           _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p);
+       if(p != NULL)
+               p(&sThreadHelpers);
+       
+       return 0;
+}
+
+// should be able to use __attribute__((constructor)) on registerWithDyld, but compiler has bug (3679135)
+// instead use initialization of global to force it to run.
+static int hack = registerWithDyld();
+
+
+char* dlerror()
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static char* (*p)() = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_dlerror", (void**)&p);
+       return(p());
+}
+
+int dladdr(const void* addr, Dl_info* info)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static int (*p)(const void* , Dl_info*) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_dladdr", (void**)&p);
+       return(p(addr, info));
+}
+
+int dlclose(void* handle)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static int (*p)(void* handle) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_dlclose", (void**)&p);
+       return(p(handle));
+}
+
+void* dlopen(const char* path, int mode)
+{
+       DYLD_WRITER_LOCK_THIS_BLOCK;
+    static void* (*p)(const char* path, int) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_dlopen", (void**)&p);
+       return(p(path, mode));
+}
+
+void* dlsym(void* handle, const char* symbol)
+{
+       DYLD_READER_LOCK_THIS_BLOCK;
+    static void* (*p)(void* handle, const char* symbol) = NULL;
+
+       if(p == NULL)
+           _dyld_func_lookup("__dyld_dlsym", (void**)&p);
+       return(p(handle, symbol));
+}
+
+
+
+
+
diff --git a/src/dyldExceptions.c b/src/dyldExceptions.c
new file mode 100644 (file)
index 0000000..39b0606
--- /dev/null
@@ -0,0 +1,212 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <mach-o/loader.h>
+
+//
+// BEGIN copy of code from libgcc.a source file unwind-dw2-fde-darwin.c
+//
+#define KEYMGR_API_MAJOR_GCC3           3       
+/* ... with these keys.  */
+#define KEYMGR_GCC3_LIVE_IMAGE_LIST    301     /* loaded images  */
+#define KEYMGR_GCC3_DW2_OBJ_LIST       302     /* Dwarf2 object list  */   
+#define KEYMGR_EH_GLOBALS_KEY           13 
+
+/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST.  Info about each resident image.  */
+struct live_images {
+  unsigned long this_size;                      /* sizeof (live_images)  */
+  struct mach_header *mh;                       /* the image info  */
+  unsigned long vm_slide;
+  void (*destructor)(struct live_images *);     /* destructor for this  */
+  struct live_images *next;
+  unsigned int examined_p;
+  void *fde;
+  void *object_info;
+  unsigned long info[2];                        /* Future use.  */
+};
+//
+// END copy of code from libgcc.a source file unwind-dw2-fde-darwin.c
+//
+
+
+//
+// dyld is built as stand alone executable with a static copy of libc, libstdc++, and libgcc.
+//
+// In order for C++ exceptions to work within dyld, the C++ exception handling code
+// must be able to find the exception handling frame data inside dyld.  The standard
+// exception handling code uses crt and keymgr to keep track of all images and calls
+// getsectdatafromheader("__eh_frame") to find the EH data for each image. We implement
+// our own copy of those functions below to enable exceptions within dyld.
+//
+// Note: This exception handling is completely separate from any user code exception .
+//              handling which has its own keymgr (in libSystem).
+// 
+
+
+static struct live_images   sDyldImage;  // zero filled
+static void*                           sObjectList = NULL;
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+static void*                           sEHGlobals = NULL;
+#endif
+
+
+// called by dyldStartup.s very early
+void dyld_exceptions_init(struct mach_header *mh, uintptr_t slide)
+{
+       sDyldImage.this_size = sizeof(struct live_images);
+       sDyldImage.mh = mh;
+       sDyldImage.vm_slide = slide;
+}
+
+
+
+//  Hack for gcc 3.5's use of keymgr includes accessing __keymgr_global
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+typedef struct Sinfo_Node {
+  uint32_t size;               /* Size of this node.  */
+  uint16_t major_version; /* API major version.  */
+  uint16_t minor_version;      /* API minor version.  */
+} Tinfo_Node;
+static const Tinfo_Node keymgr_info = { sizeof (Tinfo_Node), KEYMGR_API_MAJOR_GCC3, 0 };
+const Tinfo_Node* __keymgr_global[3] = { NULL, NULL, &keymgr_info };
+#endif
+
+static __attribute__((noreturn)) 
+void dyld_abort() 
+{
+       fprintf(stderr, "internal dyld error\n");
+       abort();
+}
+
+void* _keymgr_get_and_lock_processwide_ptr(unsigned int key)
+{
+       // The C++ exception handling code uses two keys. No other keys should be seen
+       if ( key == KEYMGR_GCC3_LIVE_IMAGE_LIST ) {
+               return &sDyldImage;
+       }
+       else if ( key == KEYMGR_GCC3_DW2_OBJ_LIST ) {
+               return sObjectList;
+       }
+       dyld_abort();
+}
+
+void _keymgr_set_and_unlock_processwide_ptr(unsigned int key, void* value)
+{
+       // The C++ exception handling code uses just this key. No other keys should be seen
+       if ( key == KEYMGR_GCC3_DW2_OBJ_LIST ) {
+               sObjectList = value;
+               return;
+       }
+       dyld_abort();
+}
+
+void _keymgr_unlock_processwide_ptr(unsigned int key)
+{
+       // The C++ exception handling code uses just this key. No other keys should be seen
+       if ( key == KEYMGR_GCC3_LIVE_IMAGE_LIST ) {
+               return;
+       }
+       dyld_abort();
+}
+       
+void* _keymgr_get_per_thread_data(unsigned int key)
+{
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+       // gcc 3.5 and later use this key
+       if ( key == KEYMGR_EH_GLOBALS_KEY )
+               return sEHGlobals;
+#endif
+
+       // used by std::termination which dyld does not use
+       dyld_abort();
+}
+
+void _keymgr_set_per_thread_data(unsigned int key, void *keydata)
+{
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+       // gcc 3.5 and later use this key
+       if ( key == KEYMGR_EH_GLOBALS_KEY ) {
+               sEHGlobals = keydata;
+               return;
+       }
+#endif
+       // used by std::termination which dyld does not use
+       dyld_abort();
+}
+
+#if __LP64__
+       #define LC_SEGMENT_COMMAND              LC_SEGMENT_64
+       #define macho_header                    mach_header_64
+       #define macho_segment_command   segment_command_64
+       #define macho_section                   section_64
+       #define getsectdatafromheader   getsectdatafromheader_64
+#else
+       #define LC_SEGMENT_COMMAND              LC_SEGMENT
+       #define macho_header                    mach_header
+       #define macho_segment_command   segment_command
+       #define macho_section                   section
+#endif
+
+// needed by C++ exception handling code to find __eh_frame section
+const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
+{
+       const struct load_command* cmd;
+       unsigned long i;
+        
+       cmd = (struct load_command*) ((char *)mh + sizeof(struct macho_header));
+       for(i = 0; i < mh->ncmds; i++) {
+           if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
+                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                       if ( strcmp(seg->segname, segname) == 0 ) {
+                               const struct macho_section* sect = (struct macho_section*)( (char*)seg + sizeof(struct macho_segment_command) );
+                               unsigned long j;
+                               for (j = 0; j < seg->nsects; j++) {
+                                       if ( strcmp(sect[j].sectname, sectname) == 0 ) {
+                                               *size = sect[j].size;
+                                               return (void*)(sect[j].addr);
+                                       }
+                               }
+                   }
+               }
+           cmd = (struct load_command*)( (char*)cmd + cmd->cmdsize );
+       }
+       return NULL;
+}
+
+
+// Hack for transition of rdar://problem/3933738
+// Can be removed later.
+// Allow C++ runtime to call getsectdatafromheader or getsectdatafromheader_64
+#if __ppc64__
+       #undef getsectdatafromheader
+       const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
+       {
+               return getsectdatafromheader_64(mh, segname, sectname, size);
+       }
+#endif
+
+
diff --git a/src/dyldInitialization.cpp b/src/dyldInitialization.cpp
new file mode 100644 (file)
index 0000000..8491e7e
--- /dev/null
@@ -0,0 +1,256 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <mach/mach.h>
+#include <mach-o/loader.h>
+#include <mach-o/ldsyms.h>
+#include <mach-o/reloc.h>
+#if __ppc__ || __ppc64__
+       #include <mach-o/ppc/reloc.h>
+#endif
+#include "dyld.h"
+
+#if __LP64__
+       #define macho_header                    mach_header_64
+       #define LC_SEGMENT_COMMAND              LC_SEGMENT_64
+       #define macho_segment_command   segment_command_64
+       #define macho_section                   section_64
+       #define RELOC_SIZE                              3
+#else
+       #define macho_header                    mach_header
+       #define LC_SEGMENT_COMMAND              LC_SEGMENT
+       #define macho_segment_command   segment_command
+       #define macho_section                   section
+       #define RELOC_SIZE                              2
+#endif
+
+
+//
+//  Code to bootstrap dyld into a runnable state
+//
+//
+
+namespace dyldbootstrap {
+
+
+typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[]);
+
+//
+// For a regular executable, the crt code calls dyld to run the executables initializers.
+// For a static executable, crt directly runs the initializers.
+// dyld (should be static) but is a dynamic executable and needs this hack to run its own initializers.
+// We pass argc, argv, etc in case libc.a uses those arguments
+//
+static void runDyldInitializers(const struct macho_header* mh, intptr_t slide, int argc, const char* argv[], const char* envp[], const char* apple[])
+{
+       const uint32_t cmd_count = mh->ncmds;
+       const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
+       const struct load_command* cmd = cmds;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               const uint8_t type = sect->flags & SECTION_TYPE;
+                                               if ( type == S_MOD_INIT_FUNC_POINTERS ){
+                                                       Initializer* inits = (Initializer*)(sect->addr + slide);
+                                                       const uint32_t count = sect->size / sizeof(uintptr_t);
+                                                       for (uint32_t i=0; i < count; ++i) {
+                                                               Initializer func = inits[i];
+                                                               func(argc, argv, envp, apple);
+                                                       }
+                                               }
+                                       }
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+}
+
+
+//
+// If the kernel does not load dyld at its preferred address, we need to apply 
+// fixups to various initialized parts of the __DATA segment
+//
+static void rebaseDyld(const struct macho_header* mh, intptr_t slide)
+{
+       // get interesting pointers into dyld
+       const uint32_t cmd_count = mh->ncmds;
+       const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
+       const struct load_command* cmd = cmds;
+       const struct macho_segment_command* linkEditSeg = NULL;
+       const struct dysymtab_command* dynamicSymbolTable = NULL;
+       const struct macho_section* nonLazySection = NULL;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       if ( strcmp(seg->segname, "__LINKEDIT") == 0 )
+                                               linkEditSeg = seg;
+                                       const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+                                       const struct macho_section* const sectionsEnd = &sectionsStart[seg->nsects];
+                                       for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+                                               const uint8_t type = sect->flags & SECTION_TYPE;
+                                               if ( type == S_NON_LAZY_SYMBOL_POINTERS ) 
+                                                       nonLazySection = sect;
+                                       }
+                               }
+                               break;
+                       case LC_DYSYMTAB:
+                               dynamicSymbolTable = (struct dysymtab_command *)cmd;
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       
+       // use reloc's to rebase all random data pointers
+       const uintptr_t relocBase = (uintptr_t)mh;
+       const relocation_info* const relocsStart = (struct relocation_info*)(linkEditSeg->vmaddr + slide + dynamicSymbolTable->locreloff - linkEditSeg->fileoff);
+       const relocation_info* const relocsEnd = &relocsStart[dynamicSymbolTable->nlocrel];
+       for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+               if ( (reloc->r_address & R_SCATTERED) == 0 ) {
+                       if (reloc->r_length == RELOC_SIZE) {
+                               switch(reloc->r_type) {
+                                       case GENERIC_RELOC_VANILLA:
+                                               *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
+                                               break;
+                               }
+                       }
+               }
+               else {
+                       const struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
+                       if (sreloc->r_length == RELOC_SIZE) {
+                               uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
+                               switch(sreloc->r_type) {
+                                       case GENERIC_RELOC_VANILLA:
+               #if __ppc__ || __ppc64__
+                                       case PPC_RELOC_PB_LA_PTR:
+               #elif __i386__
+                                       case GENERIC_RELOC_PB_LA_PTR:
+               #endif
+                                       // Note the use of PB_LA_PTR is unique here.  Seems like ld should strip out all lazy pointers
+                                       // but it does not.  But, since all lazy-pointers point within dyld, they can be slid too
+                                               *locationToFix += slide;
+                                               break;
+                               }
+                       }
+               }
+       }
+       
+       // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries)
+       if ( nonLazySection != NULL ) {
+               const uint32_t pointerCount = nonLazySection->size / sizeof(uintptr_t);
+               uintptr_t* const symbolPointers = (uintptr_t*)(nonLazySection->addr + slide);
+               for (uint32_t j=0; j < pointerCount; ++j) {
+                       symbolPointers[j] += slide;
+               }
+       }
+       
+       
+}
+
+//
+// For some reason the kernel loads dyld with __TEXT and __LINKEDIT writable
+// rdar://problem/3702311 
+//
+static void segmentProtectDyld(const struct macho_header* mh, intptr_t slide)
+{
+       const uint32_t cmd_count = mh->ncmds;
+       const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
+       const struct load_command* cmd = cmds;
+       for (uint32_t i = 0; i < cmd_count; ++i) {
+               switch (cmd->cmd) {
+                       case LC_SEGMENT_COMMAND:
+                               {
+                                       const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+                                       vm_address_t addr = seg->vmaddr + slide;
+                                       vm_size_t size = seg->vmsize;
+                                       const bool setCurrentPermissions = false;
+                                       vm_protect(mach_task_self(), addr, size, setCurrentPermissions, seg->initprot);
+                                       //fprintf(stderr, "dyld: segment %s, 0x%08X -> 0x%08X, set to %d\n", seg->segname, addr, addr+size-1, seg->initprot);
+                               }
+                               break;
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       
+}
+
+extern "C" void dyld_exceptions_init(const struct macho_header*, uintptr_t slide); // in dyldExceptions.cpp
+extern "C" void mach_init();
+
+//
+//  This is code to bootstrap dyld.  This work in normally done for a program by dyld and crt.
+//  In dyld we have to do this manually.
+//
+uintptr_t start(const struct mach_header* appsMachHeader, int argc, const char* argv[], intptr_t slide)
+{
+       // _mh_dylinker_header is magic symbol defined by static linker (ld), see <mach-o/ldsyms.h>
+       const struct macho_header* dyldsMachHeader =  (const struct macho_header*)(((char*)&_mh_dylinker_header)+slide);
+       
+       // if kernel had to slide dyld, we need to fix up load sensitive locations
+       // we have to do this before using any global variables
+       if ( slide != 0 ) {
+               rebaseDyld(dyldsMachHeader, slide);
+       }
+       
+       // enable C++ exceptions to work inside dyld
+       dyld_exceptions_init(dyldsMachHeader, slide);
+       
+       // allow dyld to use mach messaging
+       mach_init();
+
+       // set protection on segments (has to be done after mach_init)
+       segmentProtectDyld(dyldsMachHeader, slide);
+       
+       // kernel sets up env pointer to be just past end of agv array
+       const char** envp = &argv[argc+1];
+       
+       // kernel sets up apple pointer to be just past end of envp array
+       const char** apple = envp;
+       while(*apple != NULL) { ++apple; }
+       ++apple;
+
+       // run all C++ initializers inside dyld
+       runDyldInitializers(dyldsMachHeader, slide, argc, argv, envp, apple);
+       
+       // now that we are done bootstrapping dyld, call dyld's main
+       return dyld::_main(appsMachHeader, argc, argv, envp, apple);
+}
+
+
+
+
+} // end of namespace
+
+
+
+
diff --git a/src/dyldLibSystemThreadHelpers.h b/src/dyldLibSystemThreadHelpers.h
new file mode 100644 (file)
index 0000000..ac5e3dc
--- /dev/null
@@ -0,0 +1,52 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __DYLDLIBSYSTEMHELPERS__
+#define __DYLDLIBSYSTEMHELPERS__
+
+#include <stdint.h>
+
+
+namespace dyld {
+       //
+       // This file contains the synchronization utilities used by dyld to be thread safe.
+       // This struct is implemented in in libSystem (where pthreads is available)
+       // and passed to dyld to use.
+       //
+       struct ThreadingHelpers
+       {
+               uintptr_t       version;
+               void            (*lockForReading)();
+               void            (*unlockForReading)();
+               char*           (*getThreadBufferFor_dlerror)(uint32_t sizeRequired);
+       };
+};
+
+
+
+
+
+#endif // __DYLDLIBSYSTEMHELPERS__
+
diff --git a/src/dyldLock.cpp b/src/dyldLock.cpp
new file mode 100644 (file)
index 0000000..496ed92
--- /dev/null
@@ -0,0 +1,287 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <pthread.h>
+
+#include "dyldLock.h"
+
+// until the reader/writer locks are fully tested, we just use a simple recursive mutex
+#define REAL_READER_WRITER_LOCK 0
+
+
+
+//
+// This class implements a recursive reader/writer lock.
+// Recursive means a thread that has already aquired the lock can re-acquire it.
+// The lock allows either:
+//      a) one "writer" thread to hold lock
+//             b) multiple "reader" threads to hold
+//
+// A thread with the writer can acquire a reader lock.
+// A thread with a reader lock can acquire a writer lock iff it is the only thread with a reader lock
+//
+class RecursiveReaderWriterLock 
+{
+public:
+                       RecursiveReaderWriterLock() __attribute__((visibility("hidden")));
+       void    initIfNeeded();
+       
+       
+       void    lockForSingleWritingThread() __attribute__((visibility("hidden")));
+       void    unlockForSingleWritingThread() __attribute__((visibility("hidden")));
+       
+       void    lockForMultipleReadingThreads() __attribute__((visibility("hidden")));
+       void    unlockForMultipleReadingThreads() __attribute__((visibility("hidden")));
+
+private:
+#if REAL_READER_WRITER_LOCK
+       struct ThreadRecursionCount {
+               pthread_t       fThread;
+               uint32_t        fCount;
+       };
+       bool    writerThreadIsAnyThreadBut(pthread_t thread);
+       void    writerThreadRetain(pthread_t thread);
+       bool    writerThreadRelease(pthread_t thread);
+
+       enum { kMaxReaderThreads = 4 };
+       bool    readerThreadSetRetain(pthread_t thread);
+       bool    readerThreadSetRelease(pthread_t thread);
+       bool    readerThreadSetContainsAnotherThread(pthread_t thread);
+
+       ThreadRecursionCount    fWriterThread;
+       ThreadRecursionCount    fReaderThreads[kMaxReaderThreads];
+       pthread_cond_t                  fLockFree;
+       pthread_mutex_t                 fMutex;
+#else
+       pthread_mutex_t                 fMutex;
+#endif
+       bool                                    fInitialized;   // assumes this is statically initialized to false because sLock is static
+};
+
+
+//
+// initIfNeeded() is a hack so that when libSystem_debug.dylb is useable.
+// The problem is that Objective-C +load methods are called before C++ initialziers are run
+// If +load method makes a call into dyld, sLock is not initialized.  
+//
+// The long term solution is for objc and dyld to work more closely together so that instead
+// of running all +load methods before all initializers, we run each image's +load then its
+// initializers all in bottom up order.
+//
+// This lazy initialization is not thread safe, but as long as someone does not create a 
+// new thread in a +load method, the C++ constructor for sLock will be called before main()
+// so there will only be one thead.
+//
+void RecursiveReaderWriterLock::initIfNeeded()
+{
+       if ( ! fInitialized ) {
+               pthread_mutexattr_t recursiveMutexAttr;
+               pthread_mutexattr_init(&recursiveMutexAttr);
+               pthread_mutexattr_settype(&recursiveMutexAttr, PTHREAD_MUTEX_RECURSIVE);
+               pthread_mutex_init(&fMutex, &recursiveMutexAttr);
+       #if REAL_READER_WRITER_LOCK
+               pthread_cond_init(&fLockFree, NULL);
+               fWriterThread.fThread = NULL;
+               fWriterThread.fCount = 0;
+               for (int i=0; i < kMaxReaderThreads; ++i) {
+                       fReaderThreads[i].fThread = NULL;
+                       fReaderThreads[i].fCount = 0;
+               }
+       #endif
+               fInitialized = true;
+       }
+}
+
+RecursiveReaderWriterLock::RecursiveReaderWriterLock()
+{
+       initIfNeeded();
+}
+
+void RecursiveReaderWriterLock::lockForSingleWritingThread()
+{
+       this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+       pthread_mutex_lock(&fMutex);
+       pthread_t thisThread = pthread_self();
+       // wait as long as there is another writer or any readers on a different thread
+       while ( writerThreadIsAnyThreadBut(thisThread) || readerThreadSetContainsAnotherThread(thisThread) ) {
+               pthread_cond_wait(&fLockFree, &fMutex);
+       }
+       writerThreadRetain(thisThread);
+       pthread_mutex_unlock(&fMutex);
+#else
+       pthread_mutex_lock(&fMutex);
+#endif
+}
+
+void RecursiveReaderWriterLock::unlockForSingleWritingThread()
+{
+       this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+       pthread_mutex_lock(&fMutex);
+       if ( writerThreadRelease(pthread_self()) ) {
+               pthread_cond_broadcast(&fLockFree);
+       }
+       pthread_mutex_unlock(&fMutex);
+#else
+       pthread_mutex_unlock(&fMutex);
+#endif
+}
+
+
+void RecursiveReaderWriterLock::lockForMultipleReadingThreads()
+{
+       this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+       pthread_mutex_lock(&fMutex);
+       pthread_t thisThread = pthread_self();
+       // wait as long as there is a writer on another thread or too many readers already
+       while ( writerThreadIsAnyThreadBut(thisThread) || !readerThreadSetRetain(thisThread) ) {
+               pthread_cond_wait(&fLockFree, &fMutex);
+       }
+       pthread_mutex_unlock(&fMutex);
+#else
+       pthread_mutex_lock(&fMutex);
+#endif
+}
+
+
+void RecursiveReaderWriterLock::unlockForMultipleReadingThreads()
+{
+       this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+       pthread_mutex_lock(&fMutex);
+       if ( readerThreadSetRelease(pthread_self()) ) {
+               pthread_cond_broadcast(&fLockFree);
+       }
+       pthread_mutex_unlock(&fMutex);
+#else
+       pthread_mutex_unlock(&fMutex);
+#endif
+}
+
+#if REAL_READER_WRITER_LOCK
+bool RecursiveReaderWriterLock::writerThreadIsAnyThreadBut(pthread_t thread)
+{
+       return ( (fWriterThread.fThread != NULL) && (fWriterThread.fThread != thread) );
+}
+
+void RecursiveReaderWriterLock::writerThreadRetain(pthread_t thread)
+{
+       ++fWriterThread.fCount;
+}
+
+bool RecursiveReaderWriterLock::writerThreadRelease(pthread_t thread)
+{
+       return ( --fWriterThread.fCount == 0 );
+}
+
+
+bool RecursiveReaderWriterLock::readerThreadSetRetain(pthread_t thread)
+{
+       // if thread is already in set, bump its count
+       for (int i=0; i < kMaxReaderThreads; ++i) {
+               if ( fReaderThreads[i].fThread == thread ) {
+                       ++fReaderThreads[i].fCount;
+                       return true;
+               }
+       }
+       // find empty slot in set
+       for (int i=0; i < kMaxReaderThreads; ++i) {
+               if ( fReaderThreads[i].fThread == NULL ) {
+                       fReaderThreads[i].fThread = thread;
+                       fReaderThreads[i].fCount = 1;
+                       return true;
+               }
+       }
+
+       // all reader slots full
+       return false;
+}
+
+bool RecursiveReaderWriterLock::readerThreadSetRelease(pthread_t thread)
+{
+       for (int i=0; i < kMaxReaderThreads; ++i) {
+               if ( fReaderThreads[i].fThread == thread ) {
+                       if ( --fReaderThreads[i].fCount == 0 ) {
+                               fReaderThreads[i].fThread = NULL;
+                               return true;
+                       }
+                       return false;
+               }
+       }
+       // should never get here
+       return false;
+}
+
+bool RecursiveReaderWriterLock::readerThreadSetContainsAnotherThread(pthread_t thread)
+{
+       for (int i=0; i < kMaxReaderThreads; ++i) {
+               if ( (fReaderThreads[i].fThread != NULL) && (fReaderThreads[i].fThread != thread) ) 
+                       return true;
+       }
+       return false;
+}
+#endif
+
+
+// dyld's global reader/writer lock
+static RecursiveReaderWriterLock       sLock;
+
+
+LockReaderHelper::LockReaderHelper() 
+{ 
+       sLock.lockForMultipleReadingThreads();
+}
+
+LockReaderHelper::~LockReaderHelper() 
+{ 
+       sLock.unlockForMultipleReadingThreads();
+}
+
+
+LockWriterHelper::LockWriterHelper() 
+{ 
+       sLock.lockForSingleWritingThread();
+}
+
+LockWriterHelper::~LockWriterHelper() 
+{ 
+       sLock.unlockForSingleWritingThread();
+}
+
+
+// needed by lazy binding
+void lockForLazyBinding() 
+{
+       sLock.lockForMultipleReadingThreads();
+}
+
+void unlockForLazyBinding() 
+{
+       sLock.unlockForMultipleReadingThreads();
+}
+
+
+
diff --git a/src/dyldLock.h b/src/dyldLock.h
new file mode 100644 (file)
index 0000000..d6291fb
--- /dev/null
@@ -0,0 +1,87 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __DYLDLOCK__
+#define __DYLDLOCK__
+
+//
+// This file contains the syncronization utilities used by dyld to be thread safe.
+// Access to all dyld data structures is protected by a reader-writer lock.
+// This lock allows multiple "reader" threads to access dyld data structures at
+// the same time.  If there is a "writer" thread, it is the only thread allowed
+// access to dyld data structures.  
+//
+// The implementation of all dyld API's must acquire the global lock around accesses
+// to dyld's data structures.  This is done using the macros DYLD_*_LOCK_THIS_BLOCK.
+// Example:
+//
+//  void dyld_api_modifying_dyld() {
+//             DYLD_WRITER_LOCK_THIS_BLOCK;
+//             // free to do stuff here 
+//             // that modifies dyld data structures
+//     }
+//
+//  void dyld_api_examinging_dyld() {
+//             DYLD_READER_LOCK_THIS_BLOCK
+//             // can only do stuff here 
+//             // that examines but does not modify dyld data structures
+//     }
+//
+//  void dyld_api_state_free() {
+//             DYLD_NO_LOCK_THIS_BLOCK
+//             // can only do stuff here 
+//             // that does not require locking
+//     }
+//
+
+
+#define DYLD_READER_LOCK_THIS_BLOCK            LockReaderHelper _dyld_lock;
+#define DYLD_WRITER_LOCK_THIS_BLOCK            LockWriterHelper _dyld_lock;
+#define DYLD_NO_LOCK_THIS_BLOCK
+
+// used by dyld wrapper functions in libSystem
+class LockReaderHelper
+{
+public:
+       LockReaderHelper() __attribute__((visibility("hidden")));
+       ~LockReaderHelper() __attribute__((visibility("hidden")));
+};
+
+// used by dyld wrapper functions in libSystem
+class LockWriterHelper
+{
+public:
+       LockWriterHelper() __attribute__((visibility("hidden")));
+       ~LockWriterHelper() __attribute__((visibility("hidden")));
+};
+
+// used by lazy binding
+extern void lockForLazyBinding() __attribute__((visibility("hidden")));
+extern void unlockForLazyBinding() __attribute__((visibility("hidden")));
+
+
+
+#endif // __DYLDLOCK__
+
diff --git a/src/dyldNew.cpp b/src/dyldNew.cpp
new file mode 100644 (file)
index 0000000..a74d858
--- /dev/null
@@ -0,0 +1,74 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <new>
+#include <malloc/malloc.h>
+//#include <stdio.h>
+
+
+//
+// dyld does not use malloc anywhere, instead C++ new is used.
+// All dyld allocations go in dyld-only zone so as to be not co-mingled with target proccess's allocations
+//
+//
+//
+
+static malloc_zone_t* sZone = NULL;  // could be initialized to malloc_create_zone, but that would require careful ordering of initializers
+
+
+void* operator new(std::size_t len) throw (std::bad_alloc)
+{
+       if ( sZone == NULL ) {
+               sZone = malloc_create_zone(40960, 0);
+               malloc_set_zone_name(sZone, "dyld heap");
+       }
+       //fprintf(stderr, "new(%d)\n", len);
+       return malloc_zone_malloc(sZone, len);
+}
+
+void* operator new[](std::size_t len) throw (std::bad_alloc)
+{
+       if ( sZone == NULL ) {
+               sZone = malloc_create_zone(40960, 0);
+               malloc_set_zone_name(sZone, "dyld heap");
+       }
+       //fprintf(stderr, "new[](%d)\n", len);
+       return malloc_zone_malloc(sZone, len);
+}
+
+
+void operator delete(void* obj) throw()
+{
+       //fprintf(stderr, "delete(%p)\n", obj);
+       malloc_zone_free(sZone, obj);
+}
+
+
+void operator delete[](void* obj) throw()
+{
+       //fprintf(stderr, "delete[](%p)\n", obj);
+       malloc_zone_free(sZone, obj);
+}
+
+
diff --git a/src/dyldStartup.s b/src/dyldStartup.s
new file mode 100644 (file)
index 0000000..e69b9c9
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1999-2005 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@
+ */
+/*
+ * C runtime startup for i386 and ppc interface to the dynamic linker.
+ * This is the same as the entry point in crt0.o with the addition of the
+ * address of the mach header passed as the an extra first argument.
+ *
+ * Kernel sets up stack frame to look like:
+ *
+ *     | STRING AREA |
+ *     +-------------+
+ *     |      0      | 
+*      +-------------+
+ *     |  apple[n]   |
+ *     +-------------+
+ *            :
+ *     +-------------+
+ *     |  apple[0]   | 
+ *     +-------------+ 
+ *     |      0      |
+ *     +-------------+
+ *     |    env[n]   |
+ *     +-------------+
+ *            :
+ *            :
+ *     +-------------+
+ *     |    env[0]   |
+ *     +-------------+
+ *     |      0      |
+ *     +-------------+
+ *     | arg[argc-1] |
+ *     +-------------+
+ *            :
+ *            :
+ *     +-------------+
+ *     |    arg[0]   |
+ *     +-------------+
+ *     |     argc    |
+ *     +-------------+
+ * sp->        |      mh     | address of where the a.out's file offset 0 is in memory
+ *     +-------------+
+ *
+ *     Where arg[i] and env[i] point into the STRING AREA
+ */
+
+       .globl __dyld_start
+
+
+#ifdef __i386__
+       .data
+__dyld_start_static_picbase: 
+       .long   L__dyld_start_picbase
+
+
+       .text
+       .align 2
+# stable entry points into dyld
+       .globl  _stub_binding_helper
+_stub_binding_helper:
+       jmp     _stub_binding_helper_interface
+       nop
+       nop
+       nop
+       .globl  _dyld_func_lookup
+_dyld_func_lookup:
+       jmp     __Z18lookupDyldFunctionPKcPm
+
+       .text
+       .align  4, 0x90
+       .globl __dyld_start
+__dyld_start:
+       pushl   $0              # push a zero for debugger end of frames marker
+       movl    %esp,%ebp       # pointer to base of kernel frame
+       andl    $-16,%esp       # force SSE alignment
+       
+       # call dyldbootstrap::start(app_mh, argc, argv, slide)
+       call    L__dyld_start_picbase
+L__dyld_start_picbase: 
+       popl    %ebx            # set %ebx to runtime value of picbase
+       movl    __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
+       subl    %eax, %ebx      # slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
+       pushl   %ebx            # param4 = slide
+       lea     12(%ebp),%ebx   
+       pushl   %ebx            # param3 = argv
+       movl    8(%ebp),%ebx    
+       pushl   %ebx            # param2 = argc
+       movl    4(%ebp),%ebx    
+       pushl   %ebx            # param1 = mh
+       call    __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl 
+
+       # clean up stack and jump to result
+       movl    %ebp,%esp       # restore the unaligned stack pointer
+       addl    $8,%esp         # remove the mh argument, and debugger end
+                               #  frame marker
+       movl    $0,%ebp         # restore ebp back to zero
+       jmp     %eax            # jump to the entry point
+
+
+       .globl dyld_stub_binding_helper
+dyld_stub_binding_helper:
+       hlt
+L_end:
+#endif /* __i386__ */
+
+#if __ppc__ || __ppc64__
+#include <architecture/ppc/mode_independent_asm.h>
+
+       .data
+       .align 2
+__dyld_start_static_picbase: 
+       .g_long   L__dyld_start_picbase
+
+#if __ppc__    
+       .set L_mh_offset,0
+       .set L_argc_offset,4
+       .set L_argv_offset,8
+#else
+       .set L_mh_offset,0
+       .set L_argc_offset,8    ; stack is 8-byte aligned and there is a 4-byte hole between argc and argv
+       .set L_argv_offset,16
+#endif
+
+       .text
+       .align 2
+; stable entry points into dyld
+       .globl  _stub_binding_helper
+_stub_binding_helper:
+       b       _stub_binding_helper_interface
+       nop 
+       .globl  _dyld_func_lookup
+_dyld_func_lookup:
+       b       __Z18lookupDyldFunctionPKcPm
+       
+       
+       
+       .text
+       .align 2
+__dyld_start:
+       mr      r26,r1          ; save original stack pointer into r26
+       subi    r1,r1,GPR_BYTES ; make space for linkage
+       clrrgi  r1,r1,5         ; align to 32 bytes
+       addi    r0,0,0          ; load 0 into r0
+       stg     r0,0(r1)        ; terminate initial stack frame
+       stgu    r1,-SF_MINSIZE(r1); allocate minimal stack frame
+               
+       ; call dyldbootstrap::start(app_mh, argc, argv, slide)
+       lg      r3,L_mh_offset(r26)     ; r3 = mach_header
+       lwz     r4,L_argc_offset(r26)   ; r4 = argc (int == 4 bytes)
+       addi    r5,r26,L_argv_offset    ; r5 = argv
+       bcl     20,31,L__dyld_start_picbase     
+L__dyld_start_picbase: 
+       mflr    r31             ; put address of L__dyld_start_picbase in r31
+       addis   r6,r31,ha16(__dyld_start_static_picbase-L__dyld_start_picbase)
+       lg      r6,lo16(__dyld_start_static_picbase-L__dyld_start_picbase)(r6)
+       subf    r6,r6,r31       ; r6 = slide
+       bl      __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl 
+       
+       ; clean up stack and jump to result
+       mtctr   r3              ; Put entry point in count register
+       mr      r12,r3          ;  also put in r12 for ABI convention.
+       addi    r1,r26,GPR_BYTES; Restore the stack pointer and remove the
+                               ;  mach_header argument.
+       bctr                    ; jump to the program's entry point
+
+       .globl dyld_stub_binding_helper
+dyld_stub_binding_helper:
+       trap
+L_end:
+#endif /* __ppc__ */
+
+
diff --git a/src/dyld_debug.c b/src/dyld_debug.c
new file mode 100644 (file)
index 0000000..56c4cec
--- /dev/null
@@ -0,0 +1,249 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 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@
+ */
+
+int dummy_dyld_symbol = 1;
+
+#include <stdio.h> 
+#include <stdlib.h>
+
+// The following API's are deprecated.
+// In Mac OS X 10.4 we only do a minimal implementation of these API's 
+// to keep from breaking existing clients (Omni and MS Crash Reporters).
+//
+// This minmal implementation only allows inspection of one process and
+// only reveals the current images in that process (no notification of
+// later image changes). It assumes both processes use the same dyld
+// and dyld has not slid in either process.
+//
+#if __ppc__
+
+#include "mach-o/dyld_debug.h"
+#include "mach-o/dyld_gdb.h"
+
+// global state set up by _dyld_debug_subscribe_to_events() and accessed by _dyld_debug_module_name()
+static const struct dyld_image_info*   sImages = NULL;
+static uint32_t                                                        sImagesCount = 0;
+static task_port_t                                             sImagesTaskPort = 0;
+
+
+// reads an address range out of another process
+// returns a malloc'ed block that caller should free
+static void* xprocess_read(task_port_t target_task, const void* address, size_t len)
+{
+       void* result = NULL;
+       mach_vm_address_t page_address = (uint32_t)address & (-4096);
+       mach_vm_address_t  last_page_address = ((uint32_t)address + len + 4095) & (-4096);
+       mach_vm_size_t page_size = last_page_address - page_address;
+       uint8_t* local_start;
+       uint32_t local_len;
+       kern_return_t r = vm_read(
+               target_task,
+               page_address,
+               page_size,
+               (vm_offset_t*)&local_start,
+               &local_len);
+       if ( r == KERN_SUCCESS ) {
+               result = malloc(len);
+               if ( result != NULL ) 
+                       memcpy(result, &local_start[(uint32_t)address - page_address], len);
+               vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_len);
+       }
+       return result;
+}
+
+// reads a c-string out of another process.  The returned string should be vm_deallocated.
+// All strings must be less than 1 to 2 pages long
+static const char* xprocess_read_string(task_port_t target_task, const void* address)
+{
+       char* result = NULL;
+       mach_vm_address_t page_address = (uint32_t)address & (-4096);
+       mach_vm_size_t page_size = 0x2000;      // always read two pages
+       uint8_t* local_start;
+       uint32_t local_len;
+       kern_return_t r = vm_read(
+               target_task,
+               page_address,
+               page_size,
+               (vm_offset_t*)&local_start,
+               &local_len);
+       if ( r == KERN_SUCCESS ) {
+               const char* str = (char*)&local_start[(uint32_t)address - page_address];
+               return str;
+       }
+       return result;
+}
+
+
+// SPI into dyld to get address of _dyld_get_all_image_infos data structure
+static const struct dyld_all_image_infos* dyld_get_all_image_infos()
+{
+    static const struct dyld_all_image_infos* (*p)() = NULL;
+
+       if ( p == NULL )
+           _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
+       
+       if ( p != NULL )
+               return p();
+       else
+               return NULL;
+}
+
+
+
+/*
+ * _dyld_debug_module_name() is passed a dyld_debug_module struct and
+ * sets image_name and module_name as well as the nameCnts.  If the module
+ * does not refer to a valid module DYLD_INVALID_ARGUMENTS is returned.
+ */
+enum dyld_debug_return
+_dyld_debug_module_name(
+task_port_t target_task,
+unsigned long send_timeout,
+unsigned long rcv_timeout,
+boolean_t inconsistent_data_ok,
+struct dyld_debug_module module,
+char **image_name,
+unsigned long *image_nameCnt,
+char **module_name,
+unsigned long *module_nameCnt)
+{
+       // examine sImage* info set up by _dyld_debug_subscribe_to_events()
+       if ( sImagesTaskPort == target_task ) {
+               unsigned int i;
+               for (i=0; i < sImagesCount; ++i) {
+                       if ( module.header == sImages[i].imageLoadAddress ) {
+                               // copy requested string
+                               const char* path = xprocess_read_string(sImagesTaskPort, sImages[i].imageFilePath);
+                               if ( path != NULL ) {
+                                       *image_name = (char*)path;
+                                       *image_nameCnt = strlen(path);
+                                       *module_name = NULL;
+                                       *module_nameCnt = 0;
+                                       return DYLD_SUCCESS;
+                               }
+                       }
+               }       
+       }
+
+       // not supported
+       return DYLD_INVALID_ARGUMENTS;
+}
+
+
+/*
+ * set_dyld_debug_error_func() is called to register a function to be called
+ * when error occurs in the dyld debug API's.
+ */
+void
+_dyld_debug_set_error_func(
+void (*func)(struct dyld_debug_error_data *e))
+{
+       // do nothing
+}
+
+
+
+// Examine a mach_header in another process and determine its slid
+static ptrdiff_t slideForHeader(task_port_t target_task, const struct mach_header* otherAddressHeader)
+{
+       const struct mach_header* mh = xprocess_read(target_task, otherAddressHeader, 0x2000);
+       if ( mh != NULL ) {
+               int i;
+               const struct segment_command *sgp = 
+                       (const struct segment_command *)((char*)mh + sizeof(mh));
+
+               for (i = 0; i < mh->ncmds; i++){
+                       if (sgp->cmd == LC_SEGMENT) {
+                               if (sgp->fileoff == 0  &&  sgp->filesize != 0) {
+                                       return (uintptr_t)mh - (uintptr_t)sgp->vmaddr;
+                               }
+                       }
+                       sgp = (const struct segment_command *)((char *)sgp + sgp->cmdsize);
+               }
+               free((void*)mh);
+       }
+       return 0;  
+}
+
+
+/*
+ * _dyld_debug_subscribe_to_events creates a new thread that is will call the
+ * specified dyld_event_routine when dynamic link events occur in the target
+ * task.  This uses _dyld_debug_add_event_subscriber() and is just a different
+ * interface to get events.
+ */
+enum dyld_debug_return
+_dyld_debug_subscribe_to_events(
+task_port_t target_task,
+unsigned long send_timeout,
+unsigned long rcv_timeout,
+boolean_t inconsistent_data_ok,
+void (*dyld_event_routine)(struct dyld_event event))
+{
+       sImages = NULL;
+       sImagesCount = 0;
+       sImagesTaskPort = 0;
+       // get location of dyld_get_all_image_infos in this process
+       // It is possible that dyld slid in one of the processes, in which case this fails
+       const struct dyld_all_image_infos* infoOtherAddressSpace = dyld_get_all_image_infos();
+       if ( infoOtherAddressSpace != NULL ) {
+               const struct dyld_all_image_infos* infos;
+               infos = (const struct dyld_all_image_infos*)xprocess_read(target_task, infoOtherAddressSpace, sizeof(struct dyld_all_image_infos));
+               if ( infos != NULL ) {
+                       // sanity check version
+                       if ( infos->version == 1 ) {
+                               sImages = xprocess_read(target_task, infos->infoArray, infos->infoArrayCount * sizeof(struct dyld_image_info));
+                               if ( sImages != NULL ) {
+                                       int i;
+                                       // save info info into sImage* globals for use by later calls to _dyld_debug_module_name()
+                                       sImagesCount = infos->infoArrayCount;
+                                       sImagesTaskPort = target_task;
+                                       // tell caller about every image
+                                       for (i=0; i < infos->infoArrayCount; ++i) {
+                                               struct dyld_event addEvent;
+                                               bzero(&addEvent, sizeof(struct dyld_event));
+                                               const struct mach_header* mh = sImages[i].imageLoadAddress;
+                                               addEvent.type = DYLD_IMAGE_ADDED;
+                                               addEvent.arg[0].header           = (struct mach_header*)mh;
+                                               addEvent.arg[0].vmaddr_slide = slideForHeader(target_task, mh);
+                                               addEvent.arg[0].module_index = 0;
+                                               (*dyld_event_routine)(addEvent);
+                                       }
+                               }
+                       }
+                       // we free the dyld_all_image_infos struct, but not the array we copied
+                       // The array is left in sImage* for use by later calls to _dyld_debug_module_name()
+                       free((void*)infos);
+               }
+       }
+       
+       // tell client event handler no more images
+       struct dyld_event event;
+       event.type = DYLD_PAST_EVENTS_END;
+       (*dyld_event_routine)(event);
+
+       return DYLD_SUCCESS;
+}
+
+#endif
diff --git a/src/dyld_gdb.cpp b/src/dyld_gdb.cpp
new file mode 100644 (file)
index 0000000..89a1cd7
--- /dev/null
@@ -0,0 +1,227 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mach-o/loader.h>
+
+#include <vector>
+
+#include "mach-o/dyld_gdb.h"
+
+
+// old gdb interface to dyld only supported on 32-bit ppc and i386 (not ppc64_
+#if OLD_GDB_DYLD_INTERFACE
+
+unsigned int gdb_dyld_version = 2;
+
+
+/*
+ * gdb_dyld_state_changed() is a dummy routine called by dyld after images get
+ * added or removed/ Gdb is expected to set a break point at
+ * gdb_dyld_state_changed() then re-read dyld internal data as specified in
+ * the header file dyld_gdb.h
+ */
+void gdb_dyld_state_changed()
+{
+       // do nothing
+}
+
+#define NLIBRARY_IMAGES 200
+#define NOBJECT_IMAGES 1
+
+
+struct image {   
+       const char*                     physical_name;          // physical image name (file name)
+       uint32_t                        vmaddr_slide;           // the slide from the staticly linked address
+       const mach_header*  mh;                                 // address of the mach header of the image
+       uint32_t                        valid;                          // TRUE if this is struct is valid
+       const char*                     name;                           // image name for reporting errors
+};
+
+
+struct library_images { 
+       struct image                    images[NLIBRARY_IMAGES];
+       uint32_t                                nimages;
+       struct library_images*  next_images;
+};
+struct object_images { 
+       struct image                    images[NOBJECT_IMAGES];
+       uint32_t                                nimages;
+       struct library_images*  next_images;
+};
+
+unsigned int gdb_nobject_images                = NOBJECT_IMAGES;
+unsigned int gdb_object_image_size     = sizeof(image);
+unsigned int gdb_nlibrary_images       = NLIBRARY_IMAGES;
+unsigned int gdb_library_image_size    = sizeof(image);
+
+extern "C" {
+object_images   object_images = { {}, 0 , NULL };
+library_images library_images = { {}, 0 , NULL };
+void send_event(const struct dyld_event* event);
+}
+
+
+enum dyld_event_type {
+    DYLD_IMAGE_ADDED = 0,
+    DYLD_IMAGE_REMOVED = 5
+};
+
+struct dyld_event {
+    enum dyld_event_type               type;
+    const struct mach_header*   header;
+    uintptr_t                                  slide;
+};
+
+
+// gdb only notices changes bundles/dylibs loaded at runtime
+// if the "send_event()" function in dyld is called...
+void send_event(const struct dyld_event* event);
+void (*send_event_ptr)(const struct dyld_event* event) = &send_event;
+
+void addImageForgdb(const mach_header* mh, uintptr_t slide, const char* physicalPath, const char* logicalPath)
+{
+       struct library_images* li = &library_images;
+       while ( li->nimages >= NLIBRARY_IMAGES ) {
+               if ( li->next_images == NULL ) {
+                       struct library_images* li2 = new struct library_images();
+                       li2->nimages = 0;
+                       li2->next_images = NULL;
+                       li->next_images = li2;
+                       li = li2;
+               }
+               else {
+                       li = li->next_images;
+               }
+       }
+       image* info = &li->images[li->nimages++];
+       info->physical_name             = physicalPath;
+       info->vmaddr_slide              = slide;
+       info->mh                                = mh;
+       info->valid                             = 1;
+       info->name                              = logicalPath;
+       
+       // ping gdb about change
+       dyld_event event;
+       event.type = DYLD_IMAGE_ADDED;
+       event.header = mh;
+       event.slide = slide;
+       
+       // we have to indirect through a function pointer to keep gcc-3.5 from inlining away the function call
+       // rdar://problem/3830560
+       (*send_event_ptr)(&event);
+}
+
+// move this to after use, otherwise gcc will see it has an empty implementation and
+// optimize away the call site
+void send_event(const struct dyld_event* event)
+{
+       // This function exists to let gdb set a break point
+       // and catch libraries being added...
+}
+
+
+void removeImageForgdb(const mach_header* mh)
+{
+       for (struct library_images* li = &library_images; li != NULL; li = li->next_images) {
+               for( uint32_t n=0; n < li->nimages; ++n) {
+                       struct image* image = &li->images[n];
+                       if ( image->mh == mh ) {
+                               image->physical_name = NULL;
+                               image->vmaddr_slide = 0;
+                               image->mh                       = 0;
+                               image->valid            = 0;
+                               image->name                     = NULL;
+                               return;
+                       }
+               }
+       }
+}
+
+#endif
+
+static std::vector<dyld_image_info> sImageInfos;
+
+
+
+void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[])
+{
+       // set infoArray to NULL to denote it is in-use
+       dyld_all_image_infos.infoArray = NULL;
+       
+       // append all new images
+       for (uint32_t i=0; i < infoCount; ++i)
+               sImageInfos.push_back(info[i]);
+       dyld_all_image_infos.infoArrayCount = sImageInfos.size();
+       
+       // set infoArray back to base address of vector
+       dyld_all_image_infos.infoArray = &sImageInfos[0];
+
+       // tell gdb that about the new images
+       dyld_all_image_infos.notification(dyld_image_adding, infoCount, info);
+}
+
+void removeImageFromAllImages(const struct mach_header* loadAddress)
+{
+       dyld_image_info goingAway;
+       
+       // set infoArray to NULL to denote it is in-use
+       dyld_all_image_infos.infoArray = NULL;
+       
+       // remove image from infoArray
+       for (std::vector<dyld_image_info>::iterator it=sImageInfos.begin(); it != sImageInfos.end(); it++) {
+               if ( it->imageLoadAddress == loadAddress ) {
+                       goingAway = *it;
+                       sImageInfos.erase(it);
+                       break;
+               }
+       }
+       dyld_all_image_infos.infoArrayCount = sImageInfos.size();
+       
+       // set infoArray back to base address of vector
+       dyld_all_image_infos.infoArray = &sImageInfos[0];
+
+       // tell gdb that about the new images
+       dyld_all_image_infos.notification(dyld_image_removing, 1, &goingAway);
+}
+
+
+static void gdb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount, const dyld_image_info info[])
+{
+       // do nothing
+       // gdb sets a break point here to catch notifications
+       //fprintf(stderr, "dyld: gdb_image_notifier(%s, %d, ...)\n", mode ? "dyld_image_removing" : "dyld_image_adding", infoCount);
+       //for (uint32_t i=0; i < dyld_all_image_infos.infoArrayCount; ++i)
+       //      fprintf(stderr, "dyld: %d loading at %p %s\n", i, dyld_all_image_infos.infoArray[i].imageLoadAddress, dyld_all_image_infos.infoArray[i].imageFilePath);
+}
+
+
+
+struct dyld_all_image_infos  dyld_all_image_infos = { 1, 0, NULL, &gdb_image_notifier, false };
+
+
diff --git a/src/glue.c b/src/glue.c
new file mode 100644 (file)
index 0000000..eac9512
--- /dev/null
@@ -0,0 +1,129 @@
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <notify.h>
+#include <time.h>
+
+//
+// Stub functions needed for dyld to link with libc.a instead of libSystem.dylib
+//
+//
+static char* dyld_progname = "dyld";
+
+//
+// libc has calls to _dyld_lookup_and_bind to find args and environment.  Since
+// dyld links with a staic copy of libc, those calls need to find dyld's args and env
+// not the host process.  We implement a special _dyld_lookup_and_bind() that
+// just knows how to bind the few symbols needed by dyld.
+//
+void _dyld_lookup_and_bind(const char* symbolName, void** address, void* module)
+{
+       if ( strcmp(symbolName, "_environ") == 0 ) {
+               // dummy up empty environment list
+               static char *p = NULL;
+               static char **pp = &p;
+               *address = &pp;
+               return;
+       }
+       else if ( strcmp(symbolName, "___progname") == 0 ) {
+               *address = &dyld_progname;
+               return;
+       }
+       
+       fprintf(stderr, "dyld: internal error: unknown symbol '%s'\n", symbolName);
+}
+
+
+int NSIsSymbolNameDefined(const char* symbolName)
+{
+       if ( strcmp(symbolName, "___progname") == 0 ) {
+               return 1;
+       }
+       fprintf(stderr, "dyld: internal error: unknown symbol '%s'\n", symbolName);
+       return 0;
+}
+
+
+/*
+ * To avoid linking in libm.  These variables are defined as they are used in
+ * pthread_init() to put in place a fast sqrt().
+ */
+size_t hw_sqrt_len = 0;
+
+double
+sqrt(double x)
+{
+       return(0.0);
+}
+double
+hw_sqrt(double x)
+{
+       return(0.0);
+}
+
+/*
+ * More stubs to avoid linking in libm.  This works as along as we don't use
+ * long doubles.
+ */
+long
+__fpclassifyd(double x) 
+{
+       return(0);
+}
+
+long
+__fpclassify(long double x)
+{
+       return(0);
+}
+
+
+char* __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve)
+{
+       return NULL;
+}
+
+char* __hldtoa(/*long*/ double e, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve)
+{
+       return NULL;
+}
+
+int __fegetfltrounds(void) 
+{
+       return 1;                                       /* FE_NEAREST */
+}
+
+/*
+ * We have our own localtime() to avoid needing the notify API which is used
+ * by the code in libc.a for localtime() but is in libnotify.
+ */
+struct tm* localtime(const time_t* t)
+{
+       return (struct tm*)NULL;
+}
+
diff --git a/src/stub_binding_helper.s b/src/stub_binding_helper.s
new file mode 100644 (file)
index 0000000..e2a6d87
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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@
+ */
+
+#ifdef __i386__
+/*
+ * This is the interface for the stub_binding_helper for i386:
+ * The caller has pushed the address of the a lazy pointer to be filled in with
+ * the value for the defined symbol and pushed the address of the the mach
+ * header this pointer comes from.
+ *
+ * sp+4        address of lazy pointer
+ * sp+0        address of mach header
+ *
+ * After the symbol has been resolved and the pointer filled in this is to pop
+ * these arguments off the stack and jump to the address of the defined symbol.
+ */
+       .text
+       .align 4,0x90
+       .globl _stub_binding_helper_interface
+_stub_binding_helper_interface:
+       call    __ZN4dyld14bindLazySymbolEPK11mach_headerPm
+       addl    $8,%esp
+       jmpl    %eax
+#endif /* __i386__ */
+
+
+#if __ppc__ || __ppc64__
+#include <architecture/ppc/mode_independent_asm.h>
+/*
+ * This is the interface for the stub_binding_helper for the ppc:
+ * The caller has placed in r11 the address of the a lazy pointer to be filled
+ * in with the value for the defined symbol and placed in r12 the address of
+ * the the mach header this pointer comes from.
+ *
+ * r11 address of lazy pointer
+ * r12 address of mach header
+ */
+#define LRSAVE         MODE_CHOICE(8,16)
+#define STACK_SIZE     MODE_CHOICE(144,288)
+#define R3SAVE          MODE_CHOICE(56,112)
+#define R4SAVE          MODE_CHOICE(60,120)
+#define R5SAVE          MODE_CHOICE(64,128)
+#define R6SAVE          MODE_CHOICE(68,136)
+#define R7SAVE          MODE_CHOICE(72,144)
+#define R8SAVE          MODE_CHOICE(76,152)
+#define R9SAVE          MODE_CHOICE(80,160)
+#define R10SAVE         MODE_CHOICE(84,168)
+
+  
+       .text
+       .align 2
+       .globl _stub_binding_helper_interface
+_stub_binding_helper_interface:
+       mflr    r0                  ; get link register value
+       stg     r0,LRSAVE(r1)       ; save link register value in the linkage area
+       stgu    r1,-STACK_SIZE(r1)  ; save stack pointer and update it
+
+       stg     r3,R3SAVE(r1)   ; save all registers that could contain
+       stg     r4,R4SAVE(r1)   ;  parameters to the routine that is being
+       stg     r5,R5SAVE(r1)   ;  bound.
+       stg     r6,R6SAVE(r1)
+       stg     r7,R7SAVE(r1)
+       stg     r8,R8SAVE(r1)
+       stg     r9,R9SAVE(r1)
+       stg     r10,R10SAVE(r1)
+
+       mr      r3,r12          ; move address of mach header to 1st parameter
+       mr      r4,r11          ; move address of lazy pointer to 2nd parameter
+       ; call dyld::bindLazySymbol(mh, lazy_symbol_pointer_address)
+       bl      __ZN4dyld14bindLazySymbolEPK11mach_headerPm
+       mr      r12,r3          ; move the symbol`s address into r12
+       mtctr   r12             ; move the symbol`s address into count register
+
+       lg      r0,STACK_SIZE+LRSAVE(r1)        ; get old link register value
+
+       lg      r3,R3SAVE(r1)   ; restore all registers that could contain
+       lg      r4,R4SAVE(r1)   ;  parameters to the routine that was bound.
+       lg      r5,R5SAVE(r1)
+       lg      r6,R6SAVE(r1)
+       lg      r7,R7SAVE(r1)
+       lg      r8,R8SAVE(r1)
+       lg      r9,R9SAVE(r1)
+       lg      r10,R10SAVE(r1)
+
+       addi    r1,r1,STACK_SIZE; restore old stack pointer
+       mtlr    r0              ; restore link register
+
+       bctr                    ; jump to the symbol`s address that was bound
+
+#endif /* __ppc__ */
+
+
+
+
+
+
+
+
+
+
+
diff --git a/unit-tests/bin/exit-non-zero-pass.pl b/unit-tests/bin/exit-non-zero-pass.pl
new file mode 100755 (executable)
index 0000000..149724f
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+sub PASS
+{
+    my ($format, $args) = @_;
+    if(!defined $args)
+    { $args = []; }
+    printf("PASS \"$format\"\n", @$args);
+}
+
+sub FAIL
+{
+    my ($format, $args) = @_;
+    if(!defined $args)
+    { $args = []; }
+    printf("FAIL \"$format\"\n", @$args);
+}
+
+my $pass_string = shift @ARGV;
+my $fail_string = shift @ARGV;
+
+if(0 != system(@ARGV))
+{
+    PASS($pass_string);
+}
+else
+{
+    FAIL($fail_string);
+}
+exit 0;
+
diff --git a/unit-tests/bin/exit-zero-pass.pl b/unit-tests/bin/exit-zero-pass.pl
new file mode 100755 (executable)
index 0000000..54f4b32
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+sub PASS
+{
+    my ($format, $args) = @_;
+    if(!defined $args)
+    { $args = []; }
+    printf("PASS \"$format\"\n", @$args);
+}
+
+sub FAIL
+{
+    my ($format, $args) = @_;
+    if(!defined $args)
+    { $args = []; }
+    printf("FAIL \"$format\"\n", @$args);
+}
+
+my $pass_string = shift @ARGV;
+my $fail_string = shift @ARGV;
+
+if(0 == system(@ARGV))
+{
+    PASS($pass_string);
+}
+else
+{
+    FAIL($fail_string);
+}
+exit 0;
+
diff --git a/unit-tests/bin/make-recursive.pl b/unit-tests/bin/make-recursive.pl
new file mode 100755 (executable)
index 0000000..c980711
--- /dev/null
@@ -0,0 +1,119 @@
+#!/usr/bin/perl 
+
+use strict;
+use Data::Dumper;
+use File::Find;
+use Cwd qw(realpath);
+
+my @args = @ARGV;
+
+my $makefiles =
+{
+    'makefile' => undef,
+    'Makefile' => undef,
+};
+
+my $find_opts =
+{
+    'wanted' => \&find_callback,
+};
+
+my $keywords =
+{
+    'root'   => '',
+    'cwd'    => '',
+    'cmd'    => '',
+    'exit'   => '',
+    'stdout' => [],
+    'stderr' => [],
+};
+
+my $keyword;
+my $max_keyword_len = 0;
+foreach $keyword (keys %$keywords)
+{ if($max_keyword_len < length($keyword)) { $max_keyword_len = length($keyword); } }
+my $delim = ':';
+$max_keyword_len += length($delim) + length(' ');
+
+my $last_keyword = '';
+
+sub print_line
+{
+    my ($keyword, $val) = @_;
+
+    if(!exists($$keywords{$keyword}))
+    {
+       print STDERR "error: keyword $keyword not in \$keywords set\n";
+       exit(1);
+    }
+
+    my $keyword_len = 0;
+
+    if($keyword ne $last_keyword)
+    {
+       print("$keyword"); print($delim);
+       $keyword_len = length($keyword) + length($delim);
+    }
+    if($max_keyword_len > $keyword_len)
+    {
+       my $num_spaces = $max_keyword_len - $keyword_len;
+       print(' ' x $num_spaces);
+    }
+    print("$val");
+    if(0)
+    {
+       $last_keyword = $keyword;
+    }
+}
+
+my $root = '.';
+$root = &realpath($root);
+print_line("root", "$root\n");
+
+find($find_opts, $root);
+
+sub find_callback
+{
+    if(exists($$makefiles{$_}))
+    {
+       my $makefile = $_;
+       my $reldir = $File::Find::dir;
+       $reldir =~ s|^$root/||;
+       
+       &print_line("cwd", "\$root/$reldir\n");
+       my $cmd = [ "make" ];
+       
+       my $arg; foreach $arg (@ARGV) { push @$cmd, $arg; } # better way to do this?
+       &print_line("cmd", "@$cmd\n");
+
+        open(SAVEOUT, ">&STDOUT") || die("$!");
+        open(SAVEERR, ">&STDERR") || die("$!");
+       open(STDOUT, ">/tmp/unit-tests-stdout") || die("$!");
+       open(STDERR, ">/tmp/unit-tests-stderr") || die("$!");
+
+       my $exit = system(@$cmd);
+
+       close(STDOUT) || die("$!");
+       close(STDERR) || die("$!");
+        open(STDOUT, ">&SAVEOUT") || die("$!");
+        open(STDERR, ">&SAVEERR") || die("$!");
+
+       &print_line("exit", "$exit\n");
+
+       open(OUT, "</tmp/unit-tests-stdout") || die("$!");
+       while(<OUT>)
+       {
+           &print_line("stdout", "$_");
+       }
+       close(OUT) || die("$!");
+       unlink("/tmp/unit-tests-stdout");
+       
+       open(ERR, "</tmp/unit-tests-stderr") || die("$!");
+       while(<ERR>)
+       {
+           &print_line("stderr", "$_");
+       }
+       close(ERR) || die("$!");
+    }
+       unlink("/tmp/unit-tests-stderr");
+}
diff --git a/unit-tests/bin/result-filter.pl b/unit-tests/bin/result-filter.pl
new file mode 100755 (executable)
index 0000000..db07357
--- /dev/null
@@ -0,0 +1,120 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Data::Dumper;
+use File::Find;
+use Cwd;
+
+$Data::Dumper::Terse = 1;
+
+my $root = undef;
+my $entry = '';
+my $pass_count = 0;
+my $total_count = 0;
+
+# first match "root: "
+
+# a line starting with "cwd:" marks the beginning of a new test case
+# call process_entry() on each test case
+while(<>)
+{
+    if(m/^root:\s+(.*?)$/)
+    {
+       $root = $1;
+    }
+    elsif(m/^cwd:\s+(.*?)$/)
+    {
+       if(length($entry))
+       {
+           &process_entry($root, $entry);
+           $entry = '';
+       }
+       $entry .= $_;
+    }
+    else
+    {
+       $entry .= $_;
+    }
+}
+# don't forget last test case (no cwd: to mark end)
+if(length($entry))
+{
+    &process_entry($root, $entry);
+}
+
+# show totals
+my $percentage = $pass_count * 100 / $total_count;
+print "\n";
+printf " * * * %d of %d unit-tests passed (%.1f percent) * * *\n", $pass_count, $total_count, $percentage;
+
+
+sub process_entry
+{
+    my ($root, $lines) = @_;
+
+    # build an associative array of keys to value(s) 
+    my $lines_seq = [split /\n/, $lines];
+    #print Dumper($lines_seq);
+    my $tbl = { 'root' => $root, 'stdout' => [], 'stderr' => [] };
+    my $line;
+    foreach $line (@$lines_seq)
+    {
+       if($line =~ m/^(\w+):\s+(.*)$/)
+       {
+           my $key = $1;
+           my $val = $2;
+           if(!exists($$tbl{$key}))
+           { $$tbl{$key} = ''; }
+
+           if($key eq 'stdout' || $key eq 'stderr') # if type is @array
+           {
+               push @{$$tbl{$key}}, $val;
+           }
+           else
+           {
+               $$tbl{$key} .= $val;
+           }
+       }
+       else
+       {
+           print "ERROR: $line";
+       }
+    }
+    #print Dumper($tbl);
+    #return;
+
+    my $test_name = $$tbl{cwd};
+    if ($test_name =~ m|.*/([a-zA-Z0-9-+_]+)$|)
+    {
+       $test_name = $1;
+    }
+    
+    #if make failed (exit was non-zero), mark this as a failure
+    if(0 ne $$tbl{exit})
+    {
+       printf "%-40s FAIL Makefile failure\n", $test_name;
+       $total_count++;
+       return;
+    }
+    my $seen_result = 0;
+
+    # scan all stdout looking for lines that start with PASS or FAIL
+    foreach $line (@{$$tbl{stdout}})
+    {
+       if($line =~ m/^(PASS|XPASS|FAIL|XFAIL).+/)
+       {
+           printf "%-40s %s\n", $test_name, $line;
+           $total_count++;
+           if($line =~ m/^PASS.+/)
+           {
+               $pass_count++;
+           }
+           $seen_result = 1;
+       }
+    }
+    if(!$seen_result)
+    {
+       printf "%-40s AMBIGIOUS missing [X]PASS/[X]FAIL\n", $test_name;
+       $total_count++;
+    }
+}
diff --git a/unit-tests/include/common.makefile b/unit-tests/include/common.makefile
new file mode 100644 (file)
index 0000000..9cd0899
--- /dev/null
@@ -0,0 +1,12 @@
+# stuff to include in every test Makefile
+
+SHELL = /bin/sh
+
+CC              = gcc-4.0 ${ARCH}
+CCFLAGS = -Wall -g -std=c99
+
+CXX              = g++-4.0 ${ARCH}
+CXXFLAGS = -Wall -g
+
+RM      = rm
+RMFLAGS = -rf
diff --git a/unit-tests/include/test.h b/unit-tests/include/test.h
new file mode 100644 (file)
index 0000000..faca714
--- /dev/null
@@ -0,0 +1,35 @@
+#include <stdarg.h>
+#include <stdio.h>
+
+#define DEFINE_TEST_FUNC(name) \
+  static \
+  inline \
+  void \
+  name(const char *format, ...) \
+  { \
+    va_list args; \
+    va_start(args, format); \
+    common(stdout, #name, format, args); \
+    va_end(args); \
+    return; \
+  }
+
+static
+inline
+void
+common(FILE *file, const char *prefix, const char *format, va_list args)
+{
+  fprintf(file, "%s \"", prefix);
+  vfprintf(file, format, args);
+  fprintf(file, "\"\n"); // should check for trailing newline
+  return;
+}
+
+DEFINE_TEST_FUNC(PASS);
+DEFINE_TEST_FUNC(XPASS);
+DEFINE_TEST_FUNC(FAIL);
+DEFINE_TEST_FUNC(XFAIL);
+
+DEFINE_TEST_FUNC(UNTESTED);
+DEFINE_TEST_FUNC(UNSUPPORTED);
+DEFINE_TEST_FUNC(UNRESOLVED);
diff --git a/unit-tests/run-all-unit-tests b/unit-tests/run-all-unit-tests
new file mode 100755 (executable)
index 0000000..4a1d1c6
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+# cd into test-cases directory
+cd `echo "$0" | sed 's/run-all-unit-tests/test-cases/'`
+
+echo ""
+echo " * * * Running all unit tests for 32-bits * * *"
+
+# make clean
+../bin/make-recursive.pl clean > /dev/null
+
+# build default architecture
+../bin/make-recursive.pl | ../bin/result-filter.pl
+
+# if G5, then also run all test cases built for ppc64
+if [ `machine` = "ppc970" ] 
+then
+       echo ""
+       echo " * * * Running all unit tests for 64-bits * * *"
+       
+       # make clean
+       ../bin/make-recursive.pl clean > /dev/null
+
+       # build 64-bit architecture
+       ../bin/make-recursive.pl ARCH="-arch ppc64" | ../bin/result-filter.pl
+fi
+
+
diff --git a/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/Makefile b/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/Makefile
new file mode 100644 (file)
index 0000000..3aeab86
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main
+
+main : main.c libbar.dylib libfoo.dylib
+       ${CC} -I${TESTROOT}/include main.c -o main
+
+libfoo.dylib : foo.c libbar.dylib
+       ${CC} -I${TESTROOT}/include -dynamiclib foo.c -o libfoo.dylib libbar.dylib
+
+libbar.dylib : bar.c
+       ${CC} -I${TESTROOT}/include -dynamiclib bar.c -o libbar.dylib -install_name /usr/local/hide/libbar.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~  main libbar.dylib libfoo.dylib
diff --git a/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/bar.c b/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/bar.c
new file mode 100644 (file)
index 0000000..fa1d6fe
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
diff --git a/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/foo.c b/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/foo.c
new file mode 100644 (file)
index 0000000..fa1d6fe
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
diff --git a/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/main.c b/unit-tests/test-cases/NSAddImage-MATCH_BY_INSTALLNAME/main.c
new file mode 100644 (file)
index 0000000..9442bf1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+/// rdar://problem/4058724
+
+int main()
+{
+       // test that image can be found via install path
+       const struct mach_header * mh1 = NSAddImage("libbar.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
+       const struct mach_header * mh2 = NSAddImage("libfoo.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
+       if ( mh2 != NULL )
+               PASS("NSAddImage-MATCH_BY_INSTALLNAME");
+       else
+               FAIL("NSAddImage-MATCH_BY_INSTALLNAME");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/NSAddImage-RETURN_ONLY_IF_LOADED/Makefile b/unit-tests/test-cases/NSAddImage-RETURN_ONLY_IF_LOADED/Makefile
new file mode 100644 (file)
index 0000000..e02d140
--- /dev/null
@@ -0,0 +1,35 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main
+
+main : main.c
+       ${CC} -I${TESTROOT}/include main.c -o main
+
+clean:
+       ${RM} ${RMFLAGS} *~  main
diff --git a/unit-tests/test-cases/NSAddImage-RETURN_ONLY_IF_LOADED/main.c b/unit-tests/test-cases/NSAddImage-RETURN_ONLY_IF_LOADED/main.c
new file mode 100644 (file)
index 0000000..e8a3320
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+/// rdar://problem/3748251 
+
+int main()
+{
+       // test that NSAddImage() does not crash if image is not loaded
+       const struct mach_header * mh = NSAddImage("/System/Library/Frameworks/Cocoa.framework/Cocoa", NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED);
+       if ( mh == NULL )
+               PASS("NSAddImage-RETURN_ONLY_IF_LOADED");
+       else
+               FAIL("NSAddImage-RETURN_ONLY_IF_LOADED");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/NSAddImage-leafname/Makefile b/unit-tests/test-cases/NSAddImage-leafname/Makefile
new file mode 100644 (file)
index 0000000..38794a0
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       export DYLD_FALLBACK_LIBRARY_PATH="hide" && ./main
+
+all: main hide/libzzz.dylib
+
+main : main.c
+       ${CC} -I${TESTROOT}/include main.c -o main
+
+hide/libzzz.dylib:  zzz.c
+       mkdir -p hide
+       ${CC} zzz.c -dynamiclib -o hide/libzzz.dylib
+
+
+clean:
+       ${RM} ${RMFLAGS} *~  main hide
diff --git a/unit-tests/test-cases/NSAddImage-leafname/main.c b/unit-tests/test-cases/NSAddImage-leafname/main.c
new file mode 100644 (file)
index 0000000..28922af
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+/// rdar://problem/3751226
+
+int main()
+{
+       // test that NSAddImage() uses fallback path when given a leaf name
+       const struct mach_header * mh = NSAddImage("libzzz.dylib", NSADDIMAGE_OPTION_WITH_SEARCHING);
+       if ( mh != NULL )
+               PASS("NSAddImage-leafname");
+       else
+               FAIL("NSAddImage-leafname");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/NSAddImage-leafname/zzz.c b/unit-tests/test-cases/NSAddImage-leafname/zzz.c
new file mode 100644 (file)
index 0000000..80420c7
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+void zzz() {}
diff --git a/unit-tests/test-cases/bundle-basic/Makefile b/unit-tests/test-cases/bundle-basic/Makefile
new file mode 100644 (file)
index 0000000..2c905f2
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle
+
diff --git a/unit-tests/test-cases/bundle-basic/bundle.c b/unit-tests/test-cases/bundle-basic/bundle.c
new file mode 100644 (file)
index 0000000..64232df
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+// test to see if bss section is properly expanded 
+
+static int mydata[1000000];
+
+bool checkdata()
+{
+       return ( mydata[500000] == 0 );
+}
diff --git a/unit-tests/test-cases/bundle-basic/main.c b/unit-tests/test-cases/bundle-basic/main.c
new file mode 100644 (file)
index 0000000..27f7635
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 1;
+       }
+       
+       NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 1;
+       }
+       
+       NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
+       if ( sym == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 1;
+       }
+
+       CheckFunc func = NSAddressOfSymbol(sym);
+       if ( !func() ) {
+               FAIL("NSAddressOfSymbol failed");
+               return 1;
+       }
+
+       if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("NSUnLinkModule failed");
+               return 1;
+       }
+
+       if ( !NSDestroyObjectFileImage(ofi) ) {
+               FAIL("NSDestroyObjectFileImage failed");
+               return 1;
+       }
+
+       PASS("bundle-basic");
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/bundle-memory-load/Makefile b/unit-tests/test-cases/bundle-memory-load/Makefile
new file mode 100644 (file)
index 0000000..2c905f2
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle
+
diff --git a/unit-tests/test-cases/bundle-memory-load/bundle.c b/unit-tests/test-cases/bundle-memory-load/bundle.c
new file mode 100644 (file)
index 0000000..64232df
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+// test to see if bss section is properly expanded 
+
+static int mydata[1000000];
+
+bool checkdata()
+{
+       return ( mydata[500000] == 0 );
+}
diff --git a/unit-tests/test-cases/bundle-memory-load/main.c b/unit-tests/test-cases/bundle-memory-load/main.c
new file mode 100644 (file)
index 0000000..8f212f1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+#include <sys/types.h>
+#include <sys/stat.h> 
+#include <sys/mman.h> 
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+       int fd = open("test.bundle", O_RDONLY, 0);
+       if ( fd == -1 ) {
+               FAIL("open() failed");
+               return 1;
+       }
+
+       struct stat stat_buf;
+       if ( fstat(fd, &stat_buf) == -1) {
+               FAIL("fstat() failed");
+               return 1;
+       }
+
+       void* loadAddress = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
+       if ( loadAddress == ((void*)(-1)) ) {
+               FAIL("mmap() failed");
+               return 1;
+       }
+
+       close(fd);
+
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromMemory(loadAddress, stat_buf.st_size, &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromMemory failed");
+               return 1;
+       }
+       
+       NSModule mod = NSLinkModule(ofi, "he_he", NSLINKMODULE_OPTION_NONE);
+       if ( mod == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 1;
+       }
+       
+       NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
+       if ( sym == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 1;
+       }
+
+       CheckFunc func = NSAddressOfSymbol(sym);
+       if ( !func() ) {
+               FAIL("NSAddressOfSymbol failed");
+               return 1;
+       }
+
+       if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("NSUnLinkModule failed");
+               return 1;
+       }
+
+       if ( !NSDestroyObjectFileImage(ofi) ) {
+               FAIL("NSDestroyObjectFileImage failed");
+               return 1;
+       }
+       
+       // Should check that loadAddress is unmmaped now (by call to NSDestroyObjectFileImage)
+
+       PASS("bundle-memory-load");
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/bundle-multi-link/Makefile b/unit-tests/test-cases/bundle-multi-link/Makefile
new file mode 100644 (file)
index 0000000..ce5b2d4
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle
+
+
diff --git a/unit-tests/test-cases/bundle-multi-link/bundle.c b/unit-tests/test-cases/bundle-multi-link/bundle.c
new file mode 100644 (file)
index 0000000..9871eea
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+static int value = 0;
+
+int getValue()
+{
+   return value;
+}
+
+void setValue(int v)
+{
+   value = v;
+}
+
diff --git a/unit-tests/test-cases/bundle-multi-link/main.c b/unit-tests/test-cases/bundle-multi-link/main.c
new file mode 100644 (file)
index 0000000..267d540
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+
+///
+/// The point of this test case is to "load" a bundle once, but link it multiple times.
+/// Each link creats a new instantiation of the bundle (e.g. new base address and new globals).
+///
+///
+
+typedef void (*setter)(int);
+typedef int (*getter)(void);
+
+int main()
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 0;
+       }
+
+       NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 0;
+       }
+
+       NSSymbol sym = NSLookupSymbolInModule(mod, "_setValue");
+       if ( sym == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 0;
+       }
+
+       setter func = NSAddressOfSymbol(sym);
+       (*func)(1);
+       //fprintf(stderr, "address of foo() = %p in bundle first load %p\n", func, mod);
+
+
+       NSModule mod2 = NSLinkModule(ofi, "test2.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod2 == NULL ) {
+               FAIL("2nd NSLookupSymbolInModule failed");
+               return 0;
+       }
+       if ( mod == mod2 ) {
+               FAIL("2nd NSLinkModule return same function address as first");
+               return 0;
+       }
+
+       NSSymbol sym2getter = NSLookupSymbolInModule(mod2, "_getValue");
+       if ( sym2getter == NULL ) {
+               FAIL("2nd NSLookupSymbolInModule failed");
+               return 0;
+       }
+       getter func2getter = NSAddressOfSymbol(sym2getter);
+       if ( (*func2getter)() != 0 ) {
+               FAIL("_getValue() on second link returned non-zero");
+               return 0;
+       }
+
+       NSSymbol sym2 = NSLookupSymbolInModule(mod2, "_setValue");
+       if ( sym2 == NULL ) {
+               FAIL("2nd NSLookupSymbolInModule failed");
+               return 0;
+       }
+       setter func2 = NSAddressOfSymbol(sym2);
+       (*func2)(2);
+       
+       //fprintf(stderr, "address of foo() = %p in bundle second load %p\n", func2, mod2);
+       if ( func == func2 ) {
+               FAIL("2nd NSAddressOfSymbol return same function address as 1st");
+               return 0;
+       }
+       
+       
+       NSModule mod3 = NSLinkModule(ofi, "test3.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod3 == NULL ) {
+               FAIL("3rd NSLinkModule failed");
+               return 0;
+       }
+       if ( mod3 == mod ) {
+               FAIL("3rd NSLinkModule return same function address as 1st");
+               return 0;
+       }
+       if ( mod3 == mod2 ) {
+               FAIL("3rd NSLinkModule return same function address as 2nd");
+               return 0;
+       }
+
+   NSSymbol sym3 = NSLookupSymbolInModule(mod3, "_setValue");
+       if ( sym3 == NULL ) {
+               FAIL("3rd NSLookupSymbolInModule failed");
+               return 0;
+       }
+       setter func3 = NSAddressOfSymbol(sym3);
+       (*func3)(3);
+       //fprintf(stderr, "address of foo() = %p in bundle third load %p\n", func3, mod3);
+       if ( func3 == func ) {
+               FAIL("3rd NSAddressOfSymbol return same function address as 1st");
+               return 0;
+       }
+       if ( func3 == func2 ) {
+               FAIL("3rd NSAddressOfSymbol return same function address as 2nd");
+               return 0;
+       }
+               
+       if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("NSUnLinkModule failed");
+               return 0;
+       }
+
+       if ( !NSUnLinkModule(mod3, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("3rd NSUnLinkModule failed");
+               return 0;
+       }
+       
+       if ( !NSUnLinkModule(mod2, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("2nd NSUnLinkModule failed");
+               return 0;
+       }
+       
+       // now link again after unlinking everything
+       NSModule mod4 = NSLinkModule(ofi, "test4.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod4 == NULL ) {
+               FAIL("4th NSLinkModule failed");
+               return 0;
+       }
+
+       // check that this is really a new copy by verifying the getValue() returns zero
+       NSSymbol sym4getter = NSLookupSymbolInModule(mod2, "_getValue");
+       if ( sym4getter == NULL ) {
+               FAIL("2nd NSLookupSymbolInModule failed");
+               return 0;
+       }
+       getter func4getter = NSAddressOfSymbol(sym4getter);
+       if ( (*func4getter)() != 0 ) {
+               FAIL("_getValue() on fourth link returned non-zero");
+               return 0;
+       }
+       
+       if ( !NSUnLinkModule(mod4, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("4th NSUnLinkModule failed");
+               return 0;
+       }
+       
+       
+       if ( !NSDestroyObjectFileImage(ofi) ) {
+               FAIL("NSDestroyObjectFileImage failed");
+               return 0;
+       }
+       
+       PASS("bundle-multi-link");
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/bundle-multi-load/Makefile b/unit-tests/test-cases/bundle-multi-load/Makefile
new file mode 100644 (file)
index 0000000..ce5b2d4
--- /dev/null
@@ -0,0 +1,40 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle
+
+
diff --git a/unit-tests/test-cases/bundle-multi-load/bundle.c b/unit-tests/test-cases/bundle-multi-load/bundle.c
new file mode 100644 (file)
index 0000000..84955c4
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+int foo()
+{
+   return 4;
+}
+
diff --git a/unit-tests/test-cases/bundle-multi-load/main.c b/unit-tests/test-cases/bundle-multi-load/main.c
new file mode 100644 (file)
index 0000000..5d4d052
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+///
+/// The point of this test is to load the same bundle file multiple times and
+/// verify each time it is linked is a new instantiations (new globals, etc)
+///
+
+int main()
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 0;
+       }
+
+       NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 0;
+       }
+
+       NSSymbol sym = NSLookupSymbolInModule(mod, "_foo");
+       if ( sym == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 0;
+       }
+
+       void* func = NSAddressOfSymbol(sym);
+       fprintf(stderr, "1st address of foo() = %p in module %p in OFI %p\n", func, mod, ofi);
+
+
+       NSObjectFileImage ofi2;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi2) != NSObjectFileImageSuccess ) {
+               FAIL("2nd NSCreateObjectFileImageFromFile failed");
+               return 0;
+       }
+
+       NSModule mod2 = NSLinkModule(ofi2, "test2.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod2 == NULL ) {
+               FAIL("2nd NSLookupSymbolInModule failed");
+               return 0;
+       }
+       if ( mod == mod2 ) {
+               FAIL("2nd NSLinkModule return same function address as first\n");
+               return 0;
+       }
+
+       NSSymbol sym2 = NSLookupSymbolInModule(mod2, "_foo");
+       if ( sym2 == NULL ) {
+               FAIL("2nd NSLookupSymbolInModule failed\n");
+               return 0;
+       }
+
+       void* func2 = NSAddressOfSymbol(sym2);
+       fprintf(stderr, "2nd address of foo() = %p in module %p in OFI %p\n", func2, mod2, ofi2);
+       if ( func == func2 ) {
+               FAIL("2nd NSAddressOfSymbol return same function address as 1st\n");
+               return 0;
+       }
+       
+       
+       NSObjectFileImage ofi3;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi3) != NSObjectFileImageSuccess ) {
+               FAIL("3rd NSCreateObjectFileImageFromFile failed");
+               return 0;
+       }
+       NSModule mod3 = NSLinkModule(ofi3, "test3.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod3 == NULL ) {
+               FAIL("3rd NSLinkModule failed\n");
+               return 0;
+       }
+       if ( mod3 == mod ) {
+               FAIL("3rd NSLinkModule return same function address as 1st\n");
+               return 0;
+       }
+       if ( mod3 == mod2 ) {
+               FAIL("3rd NSLinkModule return same function address as 2nd\n");
+               return 0;
+       }
+
+   NSSymbol sym3 = NSLookupSymbolInModule(mod3, "_foo");
+       if ( sym3 == NULL ) {
+               FAIL("3rd NSLookupSymbolInModule failed\n");
+               return 0;
+       }
+       void* func3 = NSAddressOfSymbol(sym3);
+       fprintf(stderr, "3rd address of foo() = %p in module %p in OFI %p\n", func3, mod3, ofi3);
+       if ( func3 == func ) {
+               FAIL("3rd NSAddressOfSymbol return same function address as 1st\n");
+               return 0;
+       }
+       if ( func3 == func2 ) {
+               FAIL("3rd NSAddressOfSymbol return same function address as 2nd\n");
+               return 0;
+       }
+               
+       if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("NSUnLinkModule failed");
+               return 0;
+       }
+
+       if ( !NSUnLinkModule(mod3, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("3rd NSUnLinkModule failed");
+               return 0;
+       }
+       
+       // note, we are calling NSDestroyObjectFileImage() before NSUnLinkModule()
+       if ( !NSDestroyObjectFileImage(ofi2) ) {
+               FAIL("2nd NSDestroyObjectFileImage failed");
+               return 0;
+       }
+       if ( !NSUnLinkModule(mod2, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("2nd NSUnLinkModule failed");
+               return 0;
+       }
+       
+       if ( !NSDestroyObjectFileImage(ofi) ) {
+               FAIL("1st NSDestroyObjectFileImage failed");
+               return 0;
+       }
+       if ( !NSDestroyObjectFileImage(ofi3) ) {
+               FAIL("3rd NSDestroyObjectFileImage failed");
+               return 0;
+       }
+       
+       PASS("bundle-multi-load");
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/bundle-private/Makefile b/unit-tests/test-cases/bundle-private/Makefile
new file mode 100644 (file)
index 0000000..2c905f2
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle
+
diff --git a/unit-tests/test-cases/bundle-private/bundle.c b/unit-tests/test-cases/bundle-private/bundle.c
new file mode 100644 (file)
index 0000000..b7cdc4f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+// test to see if NSLINKMODULE_OPTION_PRIVATE works 
+
+void findme()
+{
+}
diff --git a/unit-tests/test-cases/bundle-private/main.c b/unit-tests/test-cases/bundle-private/main.c
new file mode 100644 (file)
index 0000000..86eac29
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 1;
+       }
+       
+       NSModule modPriv = NSLinkModule(ofi, "test.bundle-private", NSLINKMODULE_OPTION_PRIVATE);
+       if ( modPriv == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 1;
+       }
+       
+       NSSymbol symPriv = NSLookupSymbolInModule(modPriv, "_findme");
+       if ( symPriv == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 1;
+       }
+
+       if ( NSIsSymbolNameDefined("_findme") ) {
+               FAIL("NSIsSymbolNameDefined (incorrectly) found symbol in private bundle");
+               return 1;
+       }
+
+       NSModule modPublic = NSLinkModule(ofi, "test.bundle-public", NSLINKMODULE_OPTION_NONE);
+       if ( modPublic == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 1;
+       }
+       
+       NSSymbol symPublic = NSLookupSymbolInModule(modPublic, "_findme");
+       if ( symPublic == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 1;
+       }
+
+       if ( !NSIsSymbolNameDefined("_findme") ) {
+               FAIL("NSIsSymbolNameDefined did not found symbol in public bundle");
+               return 1;
+       }
+
+       if ( !NSUnLinkModule(modPriv, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("NSUnLinkModule failed");
+               return 1;
+       }
+
+       if ( !NSUnLinkModule(modPublic, NSUNLINKMODULE_OPTION_NONE) ) {
+               FAIL("NSUnLinkModule failed");
+               return 1;
+       }
+
+       if ( NSIsSymbolNameDefined("_findme") ) {
+               FAIL("NSIsSymbolNameDefined found unlinked symbol in public bundle");
+               return 1;
+       }
+
+       if ( !NSDestroyObjectFileImage(ofi) ) {
+               FAIL("NSDestroyObjectFileImage failed");
+               return 1;
+       }
+
+       PASS("bundle-private");
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/bundle-unlinkable/Makefile b/unit-tests/test-cases/bundle-unlinkable/Makefile
new file mode 100644 (file)
index 0000000..e7f9fd2
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c libstuff.dylib
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c libstuff.dylib
+
+libstuff.dylib : lib.c
+       ${CC} ${CCFLAGS} lib.c -dynamiclib -o libstuff.dylib -install_name libcantfind.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle libstuff.dylib
+
diff --git a/unit-tests/test-cases/bundle-unlinkable/bundle.c b/unit-tests/test-cases/bundle-unlinkable/bundle.c
new file mode 100644 (file)
index 0000000..8f91e11
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+extern int bar();
+
+
+int foo()
+{
+       return bar();
+}
+
diff --git a/unit-tests/test-cases/bundle-unlinkable/lib.c b/unit-tests/test-cases/bundle-unlinkable/lib.c
new file mode 100644 (file)
index 0000000..541b964
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+
+int bar()
+{
+       return 0;
+}      
\ No newline at end of file
diff --git a/unit-tests/test-cases/bundle-unlinkable/main.c b/unit-tests/test-cases/bundle-unlinkable/main.c
new file mode 100644 (file)
index 0000000..93af268
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <string.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 1;
+       }
+       
+       // make sure not-yet-linked-ofi is not visible through _dyld_get_image_name
+       int count = _dyld_image_count();
+       for(int i=0; i < count; ++i) {
+       const char* name = _dyld_get_image_name(i);
+               if ( strcmp(name, "test.bundle") == 0 ) {
+                       FAIL("unlinked test.bundle found via _dyld_get_image_name()");
+                       return 1;
+               }
+       }
+
+       NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+       if ( mod != NULL ) {
+               FAIL("NSLinkModule succeeded but should have failed");
+               return 1;
+       }
+       
+       // make sure link-failed-ofi is not visible through _dyld_get_image_name
+       count = _dyld_image_count();
+       for(int i=0; i < count; ++i) {
+               const char* name = _dyld_get_image_name(i);
+               if ( strcmp(name, "test.bundle") == 0 ) {
+                       FAIL("failed linked test.bundle found via _dyld_get_image_name()");
+                       return 1;
+               }
+       }
+
+       PASS("bundle-unlinkable");
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/bundle-unload-keep-mapped/Makefile b/unit-tests/test-cases/bundle-unload-keep-mapped/Makefile
new file mode 100644 (file)
index 0000000..2c905f2
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle
+
diff --git a/unit-tests/test-cases/bundle-unload-keep-mapped/bundle.c b/unit-tests/test-cases/bundle-unload-keep-mapped/bundle.c
new file mode 100644 (file)
index 0000000..938ea75
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+// test to see if bss section is properly expanded 
+
+static int mydata[10];
+
+bool checkdata()
+{
+       return ( mydata[10] == 0 );
+}
diff --git a/unit-tests/test-cases/bundle-unload-keep-mapped/main.c b/unit-tests/test-cases/bundle-unload-keep-mapped/main.c
new file mode 100644 (file)
index 0000000..c79b0fd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 1;
+       }
+       
+       NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+       if ( mod == NULL ) {
+               FAIL("NSLinkModule failed");
+               return 1;
+       }
+       
+       NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
+       if ( sym == NULL ) {
+               FAIL("NSLookupSymbolInModule failed");
+               return 1;
+       }
+
+       CheckFunc func = NSAddressOfSymbol(sym);
+       if ( !func() ) {
+               FAIL("NSAddressOfSymbol failed");
+               return 1;
+       }
+
+       if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) ) {  
+               FAIL("NSUnLinkModule failed");
+               return 1;
+       }
+
+       if ( !NSDestroyObjectFileImage(ofi) ) {
+               FAIL("NSDestroyObjectFileImage failed");
+               return 1;
+       }
+
+       // call function again, even though bundle is unloaded
+       func();
+       
+
+       PASS("bundle-basic");
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/bundle-v-dylib/Makefile b/unit-tests/test-cases/bundle-v-dylib/Makefile
new file mode 100644 (file)
index 0000000..e2df5ed
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c bar.dylib foo.bundle foo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c bar.dylib
+
+foo.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle -o foo.bundle foo.c
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib -o foo.dylib foo.c
+
+bar.dylib : bar.c
+       ${CC} ${CCFLAGS} -dynamiclib -o bar.dylib bar.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib bar.dylib
+
diff --git a/unit-tests/test-cases/bundle-v-dylib/bar.c b/unit-tests/test-cases/bundle-v-dylib/bar.c
new file mode 100644 (file)
index 0000000..65f9d64
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+
+void bar()
+{
+
+}
diff --git a/unit-tests/test-cases/bundle-v-dylib/foo.c b/unit-tests/test-cases/bundle-v-dylib/foo.c
new file mode 100644 (file)
index 0000000..91fbe46
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+
+void foo()
+{
+
+}
diff --git a/unit-tests/test-cases/bundle-v-dylib/main.c b/unit-tests/test-cases/bundle-v-dylib/main.c
new file mode 100644 (file)
index 0000000..4f0e3a9
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+
+void loadAsBundle(const char* path)
+{
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile(path, &ofi) == NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile() incorrectly allowed %s to be loaded", path);
+               exit(1);
+       }
+}
+
+void loadAsDylib(const char* path)
+{
+       if ( NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR) != NULL ) {
+               FAIL("NSAddImage() incorrectly allowed %s to be loaded", path);
+               exit(1);
+       }
+}
+
+
+extern void bar();
+
+int main()
+{
+       // verify that NSAddImage fails to load MH_BUNDLE
+       loadAsDylib("foo.bundle");
+
+       // verify that NSCreateObjectFileImageFromFile fails to load MH_DYLIB
+       loadAsBundle("foo.dylib");
+
+       // verify that NSCreateObjectFileImageFromFile fails to load MH_DYLIB already linked against main
+       loadAsBundle("bar.dylib");
+       // verify that bar.dylib was not unloaded when above failed
+       bar();
+       
+       PASS("bundle-v-dylib");
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/deadlock/Makefile b/unit-tests/test-cases/deadlock/Makefile
new file mode 100644 (file)
index 0000000..76d4808
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c bar.dylib foo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c foo.dylib
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib -o foo.dylib foo.c
+
+bar.dylib : bar.c
+       ${CC} ${CCFLAGS} -dynamiclib -o bar.dylib bar.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.dylib bar.dylib
+
diff --git a/unit-tests/test-cases/deadlock/bar.c b/unit-tests/test-cases/deadlock/bar.c
new file mode 100644 (file)
index 0000000..ea63b5f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+void bar()
+{
+
+}
diff --git a/unit-tests/test-cases/deadlock/foo.c b/unit-tests/test-cases/deadlock/foo.c
new file mode 100644 (file)
index 0000000..8b9c637
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+void foo()
+{
+
+}
diff --git a/unit-tests/test-cases/deadlock/main.c b/unit-tests/test-cases/deadlock/main.c
new file mode 100644 (file)
index 0000000..07ad467
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+#include <pthread.h>
+
+#include "test.h"
+
+/// rdar://problem/3811777
+
+//  barrier            thread 1                                                thread 2
+//                             add image
+//     1       
+//                                                                                             acquire sMyLock
+//     2
+//                             in callback acquire sMyLock             call lazy pointer
+//                             release sMyLock                                 release sMyLock
+
+extern void foo();
+
+
+static volatile int            sBarrier = 0;
+static pthread_mutex_t sBarrierMutex;
+static pthread_cond_t  sBarrierFree;
+
+static void blockUntilBarrier(int n)
+{
+       pthread_mutex_lock(&sBarrierMutex);
+       while ( sBarrier < n )  
+               pthread_cond_wait(&sBarrierFree, &sBarrierMutex);
+       pthread_mutex_unlock(&sBarrierMutex);
+}
+
+static void advanceToBarrier(int n)
+{
+       pthread_mutex_lock(&sBarrierMutex);
+       sBarrier = n;   
+       pthread_cond_broadcast(&sBarrierFree);
+       pthread_mutex_unlock(&sBarrierMutex);
+}
+
+
+
+
+
+static pthread_mutex_t sMyLock;
+
+static void* thread2(void* arg)
+{
+       // thread 2
+       blockUntilBarrier(1);
+       pthread_mutex_lock(&sMyLock);
+       advanceToBarrier(2);
+       foo();
+       pthread_mutex_unlock(&sMyLock);
+       return NULL;
+}
+
+
+
+static void myImageHandler(const struct mach_header *mh, intptr_t vmaddr_slide)
+{
+       // thread 1
+       if ( NSLookupSymbolInImage(mh, "_bar", 0) != NULL ) {
+               advanceToBarrier(1);
+               blockUntilBarrier(2);
+               pthread_mutex_lock(&sMyLock);
+               pthread_mutex_unlock(&sMyLock);
+       }
+}
+
+int main()
+{
+       pthread_mutex_init(&sBarrierMutex, NULL);
+       pthread_cond_init(&sBarrierFree, NULL);
+       pthread_mutex_init(&sMyLock, NULL);
+
+       // self-terminate this process if it locks up for two seconds
+       alarm(2);
+       
+       advanceToBarrier(0);
+
+       pthread_t pthread2;
+       if ( pthread_create(&pthread2, NULL, thread2, NULL) != 0 ) {
+               FAIL("pthread_create failed");
+               exit(0);
+       }
+
+       // thread 1
+       _dyld_register_func_for_add_image(&myImageHandler);
+       NSAddImage("bar.dylib", 0);
+       
+       PASS("deadlock");
+}
diff --git a/unit-tests/test-cases/dladdr/Makefile b/unit-tests/test-cases/dladdr/Makefile
new file mode 100644 (file)
index 0000000..b0ee016
--- /dev/null
@@ -0,0 +1,34 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main
+
diff --git a/unit-tests/test-cases/dladdr/main.c b/unit-tests/test-cases/dladdr/main.c
new file mode 100644 (file)
index 0000000..a57e708
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h> 
+#include <dlfcn.h> 
+#include <mach-o/dyld.h> 
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int bar()
+{
+       return 2;
+}
+
+static int foo()
+{
+       return 3;
+}
+
+int bar2()
+{
+       return 4;
+}
+
+// checks global symbol
+static void verifybar()
+{
+       Dl_info info;
+       if ( dladdr(&bar, &info) == 0 ) {
+               FAIL("dladdr(&bar, xx) failed");
+               exit(0);
+       }
+       if ( strcmp(info.dli_sname, "bar") != 0 ) {
+               if ( strcmp(info.dli_sname, "_bar") == 0 ) {
+                       XFAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+               } 
+               else {
+                       FAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+                       exit(0);
+               }
+       }
+       if ( info.dli_saddr != &bar) {
+               FAIL("dladdr()->dli_saddr is not &bar");
+               exit(0);
+       }
+       if ( info.dli_fbase != _dyld_get_image_header_containing_address(&bar) ) {
+               FAIL("dladdr()->dli_fbase is not image that contains &bar");
+               exit(0);
+       }
+}
+
+// checks local symbol (should resolve to previoius global symbol bar)
+static void verifyfoo()
+{
+       Dl_info info;
+       if ( dladdr(&foo, &info) == 0 ) {
+               FAIL("dladdr(&foo, xx) failed");
+               exit(0);
+       }
+       if ( strcmp(info.dli_sname, "bar") != 0 ) {
+               if ( strcmp(info.dli_sname, "_bar") == 0 ) {
+                       XFAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+               } 
+               else {
+                       FAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+                       exit(0);
+               }
+       }
+       if ( info.dli_saddr != &bar) {
+               FAIL("dladdr()->dli_saddr is not &bar");
+               exit(0);
+       }
+       if ( info.dli_fbase != _dyld_get_image_header_containing_address(&bar) ) {
+               FAIL("dladdr()->dli_fbase is not image that contains &bar");
+               exit(0);
+       }
+}
+
+
+int main()
+{
+       verifybar();
+       verifyfoo();
+
+  
+       PASS("dladdr");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlclose-basic/Makefile b/unit-tests/test-cases/dlclose-basic/Makefile
new file mode 100644 (file)
index 0000000..73451f0
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+test.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle -o test.bundle foo.c
+
+main : main.c test.bundle
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main  test.bundle
+       
+
diff --git a/unit-tests/test-cases/dlclose-basic/foo.c b/unit-tests/test-cases/dlclose-basic/foo.c
new file mode 100644 (file)
index 0000000..39ab8be
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+int foo()
+{
+  return 1;
+}
diff --git a/unit-tests/test-cases/dlclose-basic/main.c b/unit-tests/test-cases/dlclose-basic/main.c
new file mode 100644 (file)
index 0000000..ee7c122
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int main()
+{
+       // regular open
+       void* handle = dlopen("test.bundle", RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"test.bundle\", RTLD_LAZY) failed");
+               exit(1);
+       }
+       
+       // regular close
+       int result = dlclose(handle);
+       if ( result != 0 ) {
+               FAIL("dlclose() failed");
+               exit(1);
+       }
+       
+       // now try to close again (expect to fail)
+       result = dlclose(handle);
+       if ( result != -1 ) {
+               FAIL("dlclose() on released handle should have returned -1, but returned %d", result);
+               exit(1);
+       }
+       
+       // now try to close a bad handle value (expect to fail)
+       result = dlclose((void*)0x12345);
+       if ( result != -1 ) {
+               FAIL("dlclose() on bogus handle should have returned -1, but returned %d", result);
+               exit(1);
+       }
+         
+       PASS("dlclose-basic");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlclose-bundle-unload/Makefile b/unit-tests/test-cases/dlclose-bundle-unload/Makefile
new file mode 100644 (file)
index 0000000..84fc5b4
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle 
+
diff --git a/unit-tests/test-cases/dlclose-bundle-unload/foo.c b/unit-tests/test-cases/dlclose-bundle-unload/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlclose-bundle-unload/main.c b/unit-tests/test-cases/dlclose-bundle-unload/main.c
new file mode 100644 (file)
index 0000000..3e0798a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int main()
+{
+       // open same bundle three times
+       void* handle1 = dlopen("test.bundle", RTLD_LAZY);
+       if ( handle1 == NULL ) {
+               FAIL("dlclose-bundle-unload: dlopen(\"test.bundle\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
+               exit(0);
+       }
+       
+       void* handle2 = dlopen("test.bundle", RTLD_LAZY);
+       if ( handle2 == NULL ) {
+               FAIL("dlclose-bundle-unload: dlopen(\"test.bundle\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
+               exit(0);
+       }
+
+       void* handle3 = dlopen("test.bundle", RTLD_LAZY);
+       if ( handle3 == NULL ) {
+               FAIL("dlclose-bundle-unload: dlopen(\"test.bundle\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
+               exit(0);
+       }
+
+       // get symbol
+       void* sym = dlsym(handle1, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlclose-bundle-unload: dlsym(handle1, \"foo\") failed");
+               exit(0);
+       }
+
+       // close same bundle three times
+       if ( dlclose(handle3) != 0 ) {
+               FAIL("dlclose-bundle-unload: dlclose(handle3) != 0, dlerrr()=%s", dlerror());
+               exit(0);
+       }
+
+       if ( dlclose(handle2) != 0 ) {
+               FAIL("dlclose-bundle-unload: dlclose(handle2) != 0, dlerrr()=%s", dlerror());
+               exit(0);
+       }
+
+       if ( dlclose(handle1) != 0 ) {
+               FAIL("dlclose-bundle-unload: dlclose(handle1) != 0, dlerrr()=%s", dlerror());
+               exit(0);
+       }
+
+
+       // extra close should fail
+       if ( dlclose(handle1) == 0 ) {
+               FAIL("dlclose-bundle-unload: dlclose(handle4) == 0, but should have failed");
+               exit(0);
+       }
+
+
+       
+       PASS("dlclose-bundle-unload");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlerror/Makefile b/unit-tests/test-cases/dlerror/Makefile
new file mode 100644 (file)
index 0000000..7337131
--- /dev/null
@@ -0,0 +1,38 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main
+
diff --git a/unit-tests/test-cases/dlerror/main.c b/unit-tests/test-cases/dlerror/main.c
new file mode 100644 (file)
index 0000000..808dc56
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that the dlerror message is kept per thread
+///
+
+static void* work(void* arg)
+{
+       const char* str = (char*)arg;
+       for(int i=0; i < 1000; ++i) {
+               //fprintf(stderr, "dlopen(%s)\n", str);
+               void* handle = dlopen(str, RTLD_LAZY);
+               if ( handle != NULL ) {
+                       FAIL("dlopen(%s) unexpectedly succeeded", str);
+                       exit(0);
+               }
+               char* msg = dlerror();
+               //fprintf(stderr, "dlopen(%s) => %s\n", str, msg);
+               if ( (msg == NULL) || (strstr(msg, str) == NULL) ) {
+                       FAIL("dlerror() did not contain library name that could not be loaded", str);
+                       exit(0);
+               }
+               
+       
+       }
+       return 0;
+}
+
+
+
+int main()
+{
+       dlsym(RTLD_DEFAULT, "foobar");
+       fprintf(stderr, "%s\n", dlerror());
+
+       pthread_t worker1;
+       if ( pthread_create(&worker1, NULL, work, "/frazzle/bar") != 0 ) {
+               FAIL("pthread_create failed");
+               exit(0);
+       }
+
+       pthread_t worker2;
+       if ( pthread_create(&worker2, NULL, work, "/frazzle/foo") != 0 ) {
+               FAIL("pthread_create failed");
+               exit(0);
+       }
+       
+       pthread_t worker3;
+       if ( pthread_create(&worker3, NULL, work, "/frazzle/dazzle") != 0 ) {
+               FAIL("pthread_create failed");
+               exit(0);
+       }
+       
+       void* result;
+       fprintf(stderr, "waiting for worker 1\n");
+       pthread_join(worker1, &result);
+       fprintf(stderr, "waiting for worker 2\n");
+       pthread_join(worker2, &result);
+       fprintf(stderr, "waiting for worker 3\n");
+       pthread_join(worker3, &result);
+       
+       PASS("dlerror-thread-test");
+       return 0;
+}
diff --git a/unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/Makefile b/unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/Makefile
new file mode 100644 (file)
index 0000000..b20f99c
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main "`pwd`/libfoo.dylib"
+       export DYLD_LIBRARY_PATH="`pwd`/alt" && ./main "`pwd`/libfoo.dylib"
+
+all: main alt/libfoo.dylib
+
+main : main.c libfoo.dylib 
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib 
+
+
+alt/libfoo.dylib : foo.c
+       mkdir -p alt
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/alt/libfoo.dylib" -DALT 
+
+libfoo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/libfoo.dylib"
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libfoo.dylib alt/libfoo.dylib alt 
+
diff --git a/unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/foo.c b/unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/foo.c
new file mode 100644 (file)
index 0000000..0502e90
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+#ifdef ALT
+       return 1;
+#else
+       return 0;
+#endif
+}
diff --git a/unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/main.c b/unit-tests/test-cases/dlopen-DYLD_LIBRARY_PATH/main.c
new file mode 100644 (file)
index 0000000..8067d7c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h> // for getenv()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+typedef int (*fooproc)();
+
+int main(int argc, const char* argv[])
+{
+       void* handle = dlopen(argv[1], RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", argv[1]);
+               exit(0);
+       }
+       
+       fooproc sym = (fooproc)dlsym(handle, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"foo\") failed");
+               exit(0);
+       }
+       
+       int expectedResult = 0;
+       if ( getenv("DYLD_LIBRARY_PATH") != NULL )
+               expectedResult = 1;
+               
+       int actualResult = (*sym)();
+       
+       if ( actualResult != expectedResult )
+               FAIL("dlopen-DYLD_LIBRARY_PATH using wrong dylib");
+       else
+               PASS("dlopen-DYLD_LIBRARY_PATH");
+               
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/Makefile b/unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/Makefile
new file mode 100644 (file)
index 0000000..6a3e391
--- /dev/null
@@ -0,0 +1,70 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+#
+# tests combinations of dlopen() and LD_LIBRARY_PATH
+#
+# if dlopen() path contains a slash, LD_LIBRARY_PATH is ignored
+#
+# 1) leaf name found in current directory  (On linux this fails because . is usually not in default LD_LIBRARY_PATH path)
+# 2) cwd relative path 
+# 3) full path
+# 4) leaf name and LD_LIBRARY_PATH overrides cwd (On 10.3, this fails because cwd was always searched before LD_LIBRARY_PATH??)
+# 5) leaf name and LD_LIBRARY_PATH set to alternate directory
+# 6) fullpath and LD_LIBRARY_PATH set to alt
+#
+
+run: all
+       cd alt1 && ../main "libfoo.dylib" 1 "leafname found in cwd"
+       ./main "./alt1/libfoo.dylib" 1 "relative path"
+       ./main "`pwd`/alt2/libfoo.dylib" 2 "fullpath"
+       export LD_LIBRARY_PATH="`pwd`/alt1" && ./main "libfoo.dylib" 1 "leafname and LD_LIBRARY_PATH overrides cwd"
+       export LD_LIBRARY_PATH="`pwd`/alt1" && cd alt3 && ../main "libfoo.dylib" 1 "leafname and alt LD_LIBRARY_PATH"
+       export LD_LIBRARY_PATH="`pwd`/alt1" && ./main "`pwd`/alt2/libfoo.dylib" 2 "fullpath and LD_LIBRARY_PATH"
+
+all: main alt1/libfoo.dylib alt2/libfoo.dylib alt3
+
+main : main.c libfoo.dylib 
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib 
+
+
+alt1/libfoo.dylib : foo.c
+       mkdir -p alt1
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/alt1/libfoo.dylib" -DVALUE=1
+
+alt2/libfoo.dylib : foo.c
+       mkdir -p alt2
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/alt2/libfoo.dylib" -DVALUE=2
+
+libfoo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/libfoo.dylib" -DVALUE=0
+
+alt3 :
+       mkdir -p alt3
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libfoo.dylib alt1 alt2 alt3
+
diff --git a/unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/foo.c b/unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/foo.c
new file mode 100644 (file)
index 0000000..de65df5
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return VALUE;
+}
diff --git a/unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/main.c b/unit-tests/test-cases/dlopen-LD_LIBRARY_PATH/main.c
new file mode 100644 (file)
index 0000000..70f18bb
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h> // for getenv()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+typedef int (*fooproc)();
+
+//
+// argv[1] is path to dlopen()
+// argv[2] is exepect result from foo()
+// argv[3] is message
+//
+int main(int argc, const char* argv[])
+{
+       void* handle = dlopen(argv[1], RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen-LD_LIBRARY_PATH %s, dlopen(\"%s\") failed", argv[3], argv[1]);
+               exit(0);
+       }
+       
+       fooproc sym = (fooproc)dlsym(handle, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlopen-LD_LIBRARY_PATH %s, dlsym(handle, \"foo\") failed", argv[3]);
+               exit(0);
+       }
+       
+       int expectedResult = atoi(argv[2]);
+               
+       int actualResult = (*sym)();
+       
+       if ( actualResult != expectedResult )
+               FAIL("dlopen-LD_LIBRARY_PATH %s", argv[3]);
+       else
+               PASS("dlopen-LD_LIBRARY_PATH %s", argv[3]);
+               
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_GLOBAL/Makefile b/unit-tests/test-cases/dlopen-RTLD_GLOBAL/Makefile
new file mode 100644 (file)
index 0000000..260c1e0
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main foo.bundle bar.bundle
+       ./main foo.dylib bar.bundle
+
+all: main foo.bundle foo.dylib bar.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+foo.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o foo.bundle
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+bar.bundle : bar.c
+       ${CC} ${CCFLAGS} -flat_namespace -bundle bar.c -o bar.bundle -undefined suppress
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib bar.bundle
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_GLOBAL/bar.c b/unit-tests/test-cases/dlopen-RTLD_GLOBAL/bar.c
new file mode 100644 (file)
index 0000000..e8e0806
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int foo;
+
+int bar()
+{
+       return foo;
+}
+
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_GLOBAL/foo.c b/unit-tests/test-cases/dlopen-RTLD_GLOBAL/foo.c
new file mode 100644 (file)
index 0000000..8689597
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 0;
diff --git a/unit-tests/test-cases/dlopen-RTLD_GLOBAL/main.c b/unit-tests/test-cases/dlopen-RTLD_GLOBAL/main.c
new file mode 100644 (file)
index 0000000..a25854b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+
+
+int main(int argc, const char* argv[])
+{
+       // open first object which defines foo
+       void* handle = dlopen(argv[1], RTLD_GLOBAL);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", argv[1]);
+               exit(1);
+       }
+
+       // open second object which uses foo
+       void* handle2 = dlopen(argv[2], RTLD_NOW);
+       if ( handle2 == NULL ) {
+               FAIL("dlopen(\"%s\") failed", argv[2]);
+               exit(1);
+       }
+  
+       PASS("dlopen-RTLD_GLOBAL");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/Makefile b/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/Makefile
new file mode 100644 (file)
index 0000000..d7b6978
--- /dev/null
@@ -0,0 +1,44 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main 
+
+all: main 
+
+main : main.c foo.dylib bar.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c foo.dylib
+
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+bar.dylib : bar.c
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o bar.dylib 
+       
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.dylib bar.dylib
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/bar.c b/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/bar.c
new file mode 100644 (file)
index 0000000..73b29f2
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int bar()
+{
+       return 2;
+}
+
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/foo.c b/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/foo.c
new file mode 100644 (file)
index 0000000..d040e48
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/main.c b/unit-tests/test-cases/dlopen-RTLD_LOCAL-ignore/main.c
new file mode 100644 (file)
index 0000000..b2862c5
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int main(int argc, const char* argv[])
+{
+       // main alreadly links with foo.dylib
+       // now dynamically link with bar.dylib
+       void* handle = dlopen("./bar.dylib", RTLD_GLOBAL);
+       if ( handle == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlopen(\"%s\", RTLD_GLOBAL) failed: %s", argv[1], msg);
+               return EXIT_SUCCESS;
+       }
+
+       // verify we can find _foo
+       void* fooSym = dlsym(RTLD_DEFAULT, "foo");
+       if ( fooSym == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlsym(RTLD_DEFAULT, \"foo\") failed: %s", msg);
+               return EXIT_SUCCESS;
+       }
+       
+       // verify we can find _bar
+       void* barSym = dlsym(RTLD_DEFAULT, "bar");
+       if ( barSym == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlsym(RTLD_DEFAULT, \"bar\") failed: %s", msg);
+               return EXIT_SUCCESS;
+       }
+
+       // open foo privately (since it was already opened global, RTLD_LOCAL should have no effect
+       void* handleFoo = dlopen("./foo.dylib", RTLD_LOCAL);
+       if ( handleFoo == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", "./foo.dylib", msg);
+               return EXIT_SUCCESS;
+       }
+
+       // open foo privately (since it was already opened global, RTLD_LOCAL should have no effect
+       void* handleBar = dlopen("./bar.dylib", RTLD_LOCAL);
+       if ( handleBar == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", "./bar.dylib", msg);
+               return EXIT_SUCCESS;
+       }
+
+       // verify we can still find _foo
+       fooSym = dlsym(RTLD_DEFAULT, "foo");
+       if ( fooSym == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlsym(RTLD_DEFAULT, \"foo\") failed: %s", msg);
+               return EXIT_SUCCESS;
+       }
+       
+       // verify we can still find _bar
+       barSym = dlsym(RTLD_DEFAULT, "bar");
+       if ( barSym == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlsym(RTLD_DEFAULT, \"bar\") failed: %s", msg);
+               return EXIT_SUCCESS;
+       }
+  
+       PASS("dlopen-RTLD_LOCAL-ignore");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL/Makefile b/unit-tests/test-cases/dlopen-RTLD_LOCAL/Makefile
new file mode 100644 (file)
index 0000000..260c1e0
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main foo.bundle bar.bundle
+       ./main foo.dylib bar.bundle
+
+all: main foo.bundle foo.dylib bar.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+foo.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o foo.bundle
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+bar.bundle : bar.c
+       ${CC} ${CCFLAGS} -flat_namespace -bundle bar.c -o bar.bundle -undefined suppress
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib bar.bundle
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL/bar.c b/unit-tests/test-cases/dlopen-RTLD_LOCAL/bar.c
new file mode 100644 (file)
index 0000000..e8e0806
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int foo;
+
+int bar()
+{
+       return foo;
+}
+
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL/foo.c b/unit-tests/test-cases/dlopen-RTLD_LOCAL/foo.c
new file mode 100644 (file)
index 0000000..8689597
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 0;
diff --git a/unit-tests/test-cases/dlopen-RTLD_LOCAL/main.c b/unit-tests/test-cases/dlopen-RTLD_LOCAL/main.c
new file mode 100644 (file)
index 0000000..b8a30bc
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int main(int argc, const char* argv[])
+{
+       // open first object which defines foo
+       void* handle = dlopen(argv[1], RTLD_LOCAL);
+       if ( handle == NULL ) {
+               const char* msg = dlerror();
+               // Panther dlopen() fails on RTLD_LOCAL of a dylib
+               if ( strstr(msg, "RTLD_LOCAL") != NULL ) 
+                       XFAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", argv[1], msg);
+               else
+                       FAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", argv[1], msg);
+               return EXIT_SUCCESS;
+       }
+
+       // open second object which uses foo
+       void* handle2 = dlopen(argv[2], RTLD_NOW);
+       if ( handle2 != NULL ) {
+               FAIL("dlopen(\"%s\") succeeded but foo should have been not found", argv[2]);
+               return EXIT_SUCCESS;
+       }
+       const char* msg = dlerror();
+       if ( strstr(msg, "foo") == NULL ) {
+               FAIL("dlopen(\"%s\") correctly failed, but foo was not in error mesage: %s", argv[2], msg);
+               return EXIT_SUCCESS;
+       }
+  
+  
+       PASS("dlopen-RTLD_LOCAL");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_NODELETE/Makefile b/unit-tests/test-cases/dlopen-RTLD_NODELETE/Makefile
new file mode 100644 (file)
index 0000000..776d676
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_NODELETE/foo.c b/unit-tests/test-cases/dlopen-RTLD_NODELETE/foo.c
new file mode 100644 (file)
index 0000000..5cc9791
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 10;
\ No newline at end of file
diff --git a/unit-tests/test-cases/dlopen-RTLD_NODELETE/main.c b/unit-tests/test-cases/dlopen-RTLD_NODELETE/main.c
new file mode 100644 (file)
index 0000000..296479e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that RTLD_NODELETE prevents an image from being unloaded
+///
+
+static int trySO(const char* path)
+{      // main links against libfoo.dylib so it should already be loaded
+       void* handle = dlopen(path, RTLD_NODELETE);
+       if ( handle == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlopen(\"%s\" RTLD_NODELETE) failed but it should have worked: %s", path, msg);
+               exit(0);
+       }
+       void* sym = dlsym(handle, "foo");
+       if ( sym == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlsym(handle, \"foo\") failed but it should have worked: %s", msg);
+               exit(0);
+       }
+       
+       int result = dlclose(handle);
+       if ( result != 0 ) {
+               if ( result == 1 ) {
+                       // panther dyld returns 1 if you try to dlclose() a dylib
+                       XFAIL("dlclose(handle[%s]) returned %d", path, result);
+               }
+               else {
+                       FAIL("dlclose(handle) returned %d", result);
+                       exit(0);
+               }
+       }
+       
+       // now try to access foo.  If .so was unmapped, this will bus error
+       return *((int*)sym);
+}
+
+
+int main()
+{
+       trySO("test.bundle");
+       trySO("test.dylib");
+       
+       PASS("dlopen-RTLD_NODELETE");
+       return 0;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOLOAD/Makefile b/unit-tests/test-cases/dlopen-RTLD_NOLOAD/Makefile
new file mode 100644 (file)
index 0000000..624f4f1
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main libfoo.dylib
+
+main : main.c libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c libfoo.dylib -o main 
+
+libfoo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib
+
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libfoo.dylib
+       
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOLOAD/foo.c b/unit-tests/test-cases/dlopen-RTLD_NOLOAD/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOLOAD/main.c b/unit-tests/test-cases/dlopen-RTLD_NOLOAD/main.c
new file mode 100644 (file)
index 0000000..7383a8c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that RTLD_NOLOAD binds finds existing images
+///
+
+
+int main()
+{
+       // main links against libfoo.dylib so it should already be loaded
+       void* handle = dlopen("libfoo.dylib", RTLD_NOLOAD);
+       if ( handle == NULL ) {
+               const char* msg = dlerror();
+               // Panther dlcompat does not check existing loaded images (only those opened with dlopen)
+               if ( strstr(msg, "RTLD_NOLOAD") != NULL )
+                       XFAIL("dlopen(libfoo.dylib, RTLD_NOLOAD) failed but it should have worked: %s", msg);
+               else
+                       FAIL("dlopen(libfoo.dylib, RTLD_NOLOAD) failed but it should have worked: %s", msg);
+               return 0;
+       }
+       void* sym = dlsym(handle, "foo");
+       if ( sym == NULL ) {
+               const char* msg = dlerror();
+               FAIL("dlsym(handle, \"foo\") failed but it should have worked: %s", msg);
+               return 0;
+       }
+       
+       // libfobbulate.dylib does not exist, so load should return NULL
+       void* handle2 = dlopen("libfobbulate.dylib", RTLD_NOLOAD);
+       if ( handle2 != NULL ) {
+               FAIL("dlopen(libfobbulate.dylib, RTLD_NOLOAD) succeeded but it should have failed");
+               return 0;
+       }
+
+       
+       
+       PASS("dlopen-RTLD_NOLOAD");
+       return 0;
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOW/Makefile b/unit-tests/test-cases/dlopen-RTLD_NOW/Makefile
new file mode 100644 (file)
index 0000000..0d2ffe2
--- /dev/null
@@ -0,0 +1,47 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle foo.dylib foo_foo2.dylib
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c foo_foo2.dylib
+       ${CC} ${CCFLAGS} -bundle bundle.c foo_foo2.dylib -o test.bundle
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+foo_foo2.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -DFOO2 -o foo_foo2.dylib -install_name foo.dylib
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle foo.dylib foo_foo2.dylib
+
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOW/bundle.c b/unit-tests/test-cases/dlopen-RTLD_NOW/bundle.c
new file mode 100644 (file)
index 0000000..5772ff4
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern int foo();
+extern int foo2();
+
+void doit()
+{
+       foo();
+       foo2();
+}
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOW/foo.c b/unit-tests/test-cases/dlopen-RTLD_NOW/foo.c
new file mode 100644 (file)
index 0000000..e937770
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
+
+#if FOO2
+int foo2()
+{
+       return 10;
+}
+#endif
diff --git a/unit-tests/test-cases/dlopen-RTLD_NOW/main.c b/unit-tests/test-cases/dlopen-RTLD_NOW/main.c
new file mode 100644 (file)
index 0000000..2ebb4ad
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that TLD_NOW binds all lazy symbols.
+/// We do this by making sure a lazy symbol does not exist
+/// and dlopen() errors out with a message string
+/// that contains the missing symbol name.
+///
+
+
+int main()
+{
+       void* handle = dlopen("test.bundle", RTLD_NOW);
+       if ( handle == NULL ) {
+               const char* msg = dlerror();
+               if ( strstr(msg, "foo2") != NULL ) {
+                       PASS("dlopen-RTLD_NOW");
+                       exit(0);
+               }
+               FAIL("dlopen(test.bundle, RTLD_NOW) failed but error message did not contain foo2: %s", msg);
+               exit(0);
+       }
+       FAIL("dlopen(test.bundle, RTLD_NOW) succeed but should have failed because foo2 does not exist");
+       exit(0);
+}
diff --git a/unit-tests/test-cases/dlopen-basic/Makefile b/unit-tests/test-cases/dlopen-basic/Makefile
new file mode 100644 (file)
index 0000000..776d676
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
diff --git a/unit-tests/test-cases/dlopen-basic/foo.c b/unit-tests/test-cases/dlopen-basic/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlopen-basic/main.c b/unit-tests/test-cases/dlopen-basic/main.c
new file mode 100644 (file)
index 0000000..7ce2f89
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+static void trySO(const char* path)
+{
+       void* handle = dlopen(path, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", path);
+               exit(0);
+       }
+       
+       void* sym = dlsym(handle, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"foo\") failed");
+               exit(0);
+       }
+       
+       int result = dlclose(handle);
+       if ( result != 0 ) {
+               if ( result == 1 ) {
+                       // panther dyld returns 1 if you try to dlclose() a dylib
+                       XFAIL("dlclose(handle) returned %d", result);
+               }
+               else {
+                       FAIL("dlclose(handle) returned %d", result);
+                       exit(0);
+               }
+       }
+
+}
+
+
+
+int main()
+{
+       trySO("test.bundle");
+       trySO("test.dylib");
+  
+       PASS("dlopen-basic bundle and dylib");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-initializer/Makefile b/unit-tests/test-cases/dlopen-initializer/Makefile
new file mode 100644 (file)
index 0000000..e307053
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test1.dylib test2.dylib
+
+main : main.c test1.dylib test2.dylib test3.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test1.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -DINIT_NAME=myinit -o test1.dylib
+
+test2.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -DINIT_NAME=_init -o test2.dylib
+
+test3.dylib : bar.c
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o test3.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test1.dylib test2.dylib test3.dylib
+
diff --git a/unit-tests/test-cases/dlopen-initializer/bar.c b/unit-tests/test-cases/dlopen-initializer/bar.c
new file mode 100644 (file)
index 0000000..e055874
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+static int initCount = 0;
+
+
+void _init()
+{
+       initCount++;
+}
+
+int getInitCount()
+{
+       return initCount;
+}
+
diff --git a/unit-tests/test-cases/dlopen-initializer/foo.c b/unit-tests/test-cases/dlopen-initializer/foo.c
new file mode 100644 (file)
index 0000000..9ffde51
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+static int initCount = 0;
+
+void INIT_NAME() __attribute__((constructor));
+
+void INIT_NAME()
+{
+       initCount++;
+}
+
+int getInitCount()
+{
+       return initCount;
+}
+
diff --git a/unit-tests/test-cases/dlopen-initializer/main.c b/unit-tests/test-cases/dlopen-initializer/main.c
new file mode 100644 (file)
index 0000000..5dc4f2e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+typedef int (*getInitCountProc)(void);
+
+
+static void trySO(const char* path)
+{
+       void* handle = dlopen(path, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", path);
+               exit(0);
+       }
+       
+       getInitCountProc sym = (getInitCountProc)dlsym(handle, "getInitCount");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"getInitCount\") failed");
+               exit(0);
+       }
+
+       int count = (*sym)();
+       if ( count != 1 ) {
+               FAIL("initializer in %s called %d times", path, count);
+               exit(0);
+       }
+
+}
+
+
+
+int main()
+{
+       trySO("test1.dylib");
+       trySO("test2.dylib");
+       //trySO("test3.dylib");         // Mac OS X 10.4 does not automatically run _init functions
+       PASS("dlopen-initializer");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-local-and-global/Makefile b/unit-tests/test-cases/dlopen-local-and-global/Makefile
new file mode 100644 (file)
index 0000000..90f8872
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main-local-first  
+       ./main-global-first 
+
+all: main-local-first main-global-first foo.bundle foo.dylib 
+
+main-local-first : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -DLOCAL_FIRST -o main-local-first
+
+main-global-first : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -o main-global-first 
+
+foo.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o foo.bundle
+
+foo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib main-global-first main-local-first
+
diff --git a/unit-tests/test-cases/dlopen-local-and-global/bar.c b/unit-tests/test-cases/dlopen-local-and-global/bar.c
new file mode 100644 (file)
index 0000000..e8e0806
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int foo;
+
+int bar()
+{
+       return foo;
+}
+
+
diff --git a/unit-tests/test-cases/dlopen-local-and-global/foo.c b/unit-tests/test-cases/dlopen-local-and-global/foo.c
new file mode 100644 (file)
index 0000000..8689597
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 0;
diff --git a/unit-tests/test-cases/dlopen-local-and-global/main.c b/unit-tests/test-cases/dlopen-local-and-global/main.c
new file mode 100644 (file)
index 0000000..5c3b97e
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+#include <string.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+
+static void* openWithModeGetSymbol(const char* path, int mode, const char* symbol)
+{
+       void* handle = dlopen(path, mode);
+       if ( handle == NULL ) {
+               const char* msg = dlerror();
+               if ( ((mode & RTLD_LOCAL) != 0) && (strstr(msg, "RTLD_LOCAL") != NULL) )
+                       XFAIL("dlopen(\"%s\") failed: %s", path, msg);
+               else
+                       FAIL("dlopen(\"%s\") failed: %s", path, msg);
+               exit(0);
+       }
+       
+       void* sym = dlsym(handle, symbol);
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"%s\") failed", symbol);
+               exit(0);
+       }
+       return sym;
+}
+
+static void trySO(const char* path) 
+{
+#if LOCAL_FIRST
+       void* symLocal = openWithModeGetSymbol(path, RTLD_LOCAL, "foo");
+       void* symGlobal = openWithModeGetSymbol(path, RTLD_GLOBAL, "foo");
+#else
+       void* symGlobal = openWithModeGetSymbol(path, RTLD_GLOBAL, "foo");
+       void* symLocal = openWithModeGetSymbol(path, RTLD_LOCAL, "foo");
+#endif
+       if ( symLocal != symGlobal ) {
+               FAIL("global load after local load failed");
+               exit(0);
+       }
+}
+
+
+int main(int argc, const char* argv[])
+{
+       trySO("foo.bundle");
+       trySO("foo.dylib");
+  
+       PASS("dlopen-local-and-global");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-multi/Makefile b/unit-tests/test-cases/dlopen-multi/Makefile
new file mode 100644 (file)
index 0000000..776d676
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+       ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
diff --git a/unit-tests/test-cases/dlopen-multi/foo.c b/unit-tests/test-cases/dlopen-multi/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlopen-multi/main.c b/unit-tests/test-cases/dlopen-multi/main.c
new file mode 100644 (file)
index 0000000..180e91e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int main()
+{
+       void* handle1 = dlopen("test.bundle", RTLD_LAZY);
+       void* handle2 = dlopen("test.bundle", RTLD_LAZY);
+       void* handle3 = dlopen("test.dylib", RTLD_LAZY);
+       void* handle4 = dlopen("test.dylib", RTLD_LAZY);        
+       if ((NULL == handle1)||(NULL == handle2)) {
+               FAIL("dlopen(\"test.bundle\") failed");
+       }
+       if ((NULL == handle3)||(NULL == handle4)) {
+               FAIL("dlopen(\"test.dylib\") failed");
+       }
+       if (handle1 != handle2) {
+               FAIL("dlopen handle1 and handle2 are not equal %p != %p",handle1,handle2);
+       }
+       if (handle3 != handle4) {
+               FAIL("dlopen handle3 and handle4 are not equal %p != %p",handle3,handle4);
+       }
+       if (dlclose(handle4)) {
+               XFAIL("Could not close handle4");
+       }
+       if (dlclose(handle2)) {
+               FAIL("Could not close handle2");
+       }
+       void* sym = dlsym(handle1, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle1, \"foo\") failed");
+               exit(0);
+       }
+       sym = dlsym(handle3, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle3, \"foo\") failed");
+               exit(0);
+       }
+       if (dlclose(handle1)) {
+               XFAIL("Could not close handle1");
+       }
+       if (dlclose(handle3)) {
+               XFAIL("Could not close handle3");
+       }
+       
+       PASS("dlopen-multi");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlopen-zero/Makefile b/unit-tests/test-cases/dlopen-zero/Makefile
new file mode 100644 (file)
index 0000000..92ea1b0
--- /dev/null
@@ -0,0 +1,37 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main 
+
diff --git a/unit-tests/test-cases/dlopen-zero/main.c b/unit-tests/test-cases/dlopen-zero/main.c
new file mode 100644 (file)
index 0000000..7240521
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int foo()
+{
+       return 42;
+}
+
+
+int main()
+{
+       // passing NULL as path to dlopen() has the special meaning of
+       // "get handle to main executable"
+       void* handle = dlopen(NULL, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(NULL, RTLD_LAZY) failed");
+               exit(1);
+       }
+       
+       // make sure we find "foo" in this main executable
+       void* sym = dlsym(handle, "foo");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"foo\") failed");
+               exit(1);
+       }
+       if ( sym != &foo ) {
+               FAIL("dlsym(handle, \"foo\") returned wrong address");
+               exit(1);
+       }
+  
+       PASS("dlopen-zero");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_DEFAULT/Makefile b/unit-tests/test-cases/dlsym-RTLD_DEFAULT/Makefile
new file mode 100644 (file)
index 0000000..d029efe
--- /dev/null
@@ -0,0 +1,45 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+       ${CC} ${CCFLAGS}  -I${TESTROOT}/include -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+       ${CC} ${CCFLAGS}  -I${TESTROOT}/include -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
diff --git a/unit-tests/test-cases/dlsym-RTLD_DEFAULT/foo.c b/unit-tests/test-cases/dlsym-RTLD_DEFAULT/foo.c
new file mode 100644 (file)
index 0000000..675f4df
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <string.h>
+#include <dlfcn.h>
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+char* strdup(const char* str)
+{
+       return "from foo";
+}
+
+typedef char* (*strdupProc)(const char* str);
+
+
+void myinit() __attribute__((constructor));
+void myinit()
+{
+       strdupProc sym = (strdupProc)dlsym(RTLD_DEFAULT, "strdup");
+       if ( sym == NULL ) {
+               FAIL("dlsym(RTLD_DEFAULT, \"strdup\") failed");
+               exit(0);
+       }
+       
+       const char* result = (*sym)("hello");
+       if ( strcmp(result, "from main") != 0 ) {
+               FAIL("dlsym(RTLD_DEFAULT, \"strdup\") returned wrong strdup: %s", result);
+               exit(0);
+       }
+
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_DEFAULT/main.c b/unit-tests/test-cases/dlsym-RTLD_DEFAULT/main.c
new file mode 100644 (file)
index 0000000..ed3d884
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+typedef char* (*strdupProc)(const char* str);
+
+
+char* strdup(const char* str)
+{
+       return "from main";
+}
+
+
+static void trySO(const char* path)
+{
+       void* handle = dlopen(path, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", path);
+               exit(0);
+       }
+       
+       strdupProc sym = (strdupProc)dlsym(RTLD_DEFAULT, "strdup");
+       if ( sym == NULL ) {
+               FAIL("dlsym(RTLD_DEFAULT, \"strdup\") failed");
+               exit(0);
+       }
+       
+       const char* result = (*sym)("hello");
+       if ( strcmp(result, "from main") != 0 ) {
+               FAIL("dlsym(RTLD_DEFAULT, \"strdup\") returned wrong strdup: %s", result);
+               exit(0);
+       }
+
+}
+
+
+
+int main()
+{
+       trySO("test.bundle");
+       trySO("test.dylib");
+  
+       PASS("dlsym-RTLD_DEFAULT bundle and dylib");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_NEXT/Makefile b/unit-tests/test-cases/dlsym-RTLD_NEXT/Makefile
new file mode 100644 (file)
index 0000000..af0dec0
--- /dev/null
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c test.bundle test.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : test.c foo1.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle test.c foo1.dylib -o test.bundle
+
+test.dylib : test.c foo2.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c foo2.dylib -o test.dylib
+
+foo1.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo1.dylib
+
+foo2.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo2.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle test.dylib foo1.dylib foo2.dylib
+
diff --git a/unit-tests/test-cases/dlsym-RTLD_NEXT/foo.c b/unit-tests/test-cases/dlsym-RTLD_NEXT/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_NEXT/main.c b/unit-tests/test-cases/dlsym-RTLD_NEXT/main.c
new file mode 100644 (file)
index 0000000..5c1064b
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This process has five foo functions.  They are in:
+///            main, test.bundle, test.dylib, foo1.dylib, foo2.dylib
+///
+/// Both test.bundle and test.dylib call dlsym(RTLD_NEXT, "foo");
+/// They should find the ones in foo1.dylib and foo2.dylib respectively.
+/// We test this be looking up those symbols explictly.
+///
+
+
+int foo()
+{
+       return 0;
+}
+
+typedef void* (*TestProc)(void);
+
+static void trySO(const char* pathToLoad, const char* indirectLibrary)
+{
+       void* indirectHandle = dlopen(indirectLibrary, RTLD_LAZY);
+       if ( indirectHandle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", indirectLibrary);
+               exit(0);
+       }
+       
+       void* indirectFoo = (TestProc)dlsym(indirectHandle, "foo");
+       if ( indirectFoo == NULL ) {
+               FAIL("dlsym(handle, \"test\") failed");
+               exit(0);
+       }
+
+       void* handle = dlopen(pathToLoad, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", pathToLoad);
+               exit(0);
+       }
+       
+       TestProc sym = (TestProc)dlsym(handle, "test");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"test\") failed");
+               exit(0);
+       }
+       
+       void* targetFoo = (*sym)();
+       
+       //printf("targetFoo = %p, indirectFoo = %p\n", targetFoo, indirectFoo);
+        
+       if ( targetFoo != indirectFoo ) {
+               FAIL("dlsym-RTLD_NEXT wrong foo found");
+               exit(0);
+       }
+       
+}
+
+
+
+int main()
+{
+       trySO("test.bundle", "foo1.dylib");
+       trySO("test.dylib", "foo2.dylib");
+  
+       PASS("dlsym-RTLD_NEXT bundle and dylib");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_NEXT/test.c b/unit-tests/test-cases/dlsym-RTLD_NEXT/test.c
new file mode 100644 (file)
index 0000000..0d4b463
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+void* test()
+{
+       return dlsym(RTLD_NEXT, "foo");
+}
+
+int foo()
+{
+       return 2;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/dlsym-RTLD_SELF/Makefile b/unit-tests/test-cases/dlsym-RTLD_SELF/Makefile
new file mode 100644 (file)
index 0000000..af0dec0
--- /dev/null
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c test.bundle test.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : test.c foo1.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle test.c foo1.dylib -o test.bundle
+
+test.dylib : test.c foo2.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c foo2.dylib -o test.dylib
+
+foo1.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo1.dylib
+
+foo2.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo2.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle test.dylib foo1.dylib foo2.dylib
+
diff --git a/unit-tests/test-cases/dlsym-RTLD_SELF/foo.c b/unit-tests/test-cases/dlsym-RTLD_SELF/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_SELF/main.c b/unit-tests/test-cases/dlsym-RTLD_SELF/main.c
new file mode 100644 (file)
index 0000000..ce7c3a8
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This process has five foo functions.  They are in:
+///            main, test.bundle, test.dylib, foo1.dylib, foo2.dylib
+///
+/// Both test.bundle and test.dylib call dlsym(RTLD_SELF, "foo");
+/// They should find the ones in their own linkage unit and
+/// call FAIL() otherwise.
+/// We also check that this works in the main executable.
+///
+
+#ifdef RTLD_SELF 
+
+int foo()
+{
+       return 0;
+}
+
+typedef void (*TestProc)(void);
+
+static void trySO(const char* pathToLoad)
+{
+       void* handle = dlopen(pathToLoad, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlopen(\"%s\") failed", pathToLoad);
+               exit(0);
+       }
+       
+       TestProc sym = (TestProc)dlsym(handle, "test");
+       if ( sym == NULL ) {
+               FAIL("dlsym(handle, \"test\") failed");
+               exit(0);
+       }
+       
+       (*sym)();       
+}
+
+#endif
+
+
+int main()
+{
+#ifdef RTLD_SELF 
+       trySO("test.bundle");
+       trySO("test.dylib");
+
+       if ( dlsym(RTLD_SELF, "foo") != &foo ) {
+               FAIL("dlsym(RTLD_SELF, \"foo\") returned wrong value");
+       }
+       
+       PASS("dlsym-RTLD_SELF bundle and dylib");
+#else
+       XFAIL("dlsym-RTLD_SELF not implemented");
+#endif
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlsym-RTLD_SELF/test.c b/unit-tests/test-cases/dlsym-RTLD_SELF/test.c
new file mode 100644 (file)
index 0000000..b4ae941
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int foo()
+{
+       return 2;
+}
+
+void test()
+{
+#ifdef RTLD_SELF
+       if ( dlsym(RTLD_SELF, "foo") != &foo )
+               FAIL("dlsym(RTLD_SELF, \"foo\") returned wrong value");
+#endif
+}
diff --git a/unit-tests/test-cases/dlsym-error/Makefile b/unit-tests/test-cases/dlsym-error/Makefile
new file mode 100644 (file)
index 0000000..92ea1b0
--- /dev/null
@@ -0,0 +1,37 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main 
+
diff --git a/unit-tests/test-cases/dlsym-error/main.c b/unit-tests/test-cases/dlsym-error/main.c
new file mode 100644 (file)
index 0000000..cb4a9d6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int foo()
+{
+       return 42;
+}
+
+
+int main()
+{
+       void* handle = (void*)0x12345;  // bogus value
+       
+       // expect dlsym() to return NULL
+       void* sym = dlsym(handle, "foo");
+       if ( sym != NULL ) {
+               FAIL("dlsym(handle, \"foo\") should not have succeeded");
+               exit(1);
+       }
+       // expect dlerro() to mention "handle"
+       if ( strstr(dlerror(), "handle") == NULL ) {
+               FAIL("dlerror() after dlsym(handle, \"foo\") does not mention \"handle\"");
+               exit(1);
+       }
+       
+       PASS("dlsym-error");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dlsym-indirect/Makefile b/unit-tests/test-cases/dlsym-indirect/Makefile
new file mode 100644 (file)
index 0000000..b363103
--- /dev/null
@@ -0,0 +1,53 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main foo.dylib
+       ./main foo.bundle
+
+all: main 
+
+main : main.c foo.bundle foo.dylib foo3.dylib 
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+foo.bundle : foo.c foo1.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle foo.c foo1.dylib -o foo.bundle
+
+foo.dylib : foo.c foo1.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib foo.c foo1.dylib -o foo.dylib
+
+foo1.dylib : foo1.c foo2.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo1.c -o foo1.dylib foo2.dylib
+
+foo2.dylib : foo2.c
+       ${CC} ${CCFLAGS} -dynamiclib foo2.c -o foo2.dylib
+
+foo3.dylib : foo3.c
+       ${CC} ${CCFLAGS} -dynamiclib foo3.c -o foo3.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib foo1.dylib foo2.dylib foo3.dylib
+
diff --git a/unit-tests/test-cases/dlsym-indirect/foo.c b/unit-tests/test-cases/dlsym-indirect/foo.c
new file mode 100644 (file)
index 0000000..81f7dcf
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlsym-indirect/foo1.c b/unit-tests/test-cases/dlsym-indirect/foo1.c
new file mode 100644 (file)
index 0000000..eda5424
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo1()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlsym-indirect/foo2.c b/unit-tests/test-cases/dlsym-indirect/foo2.c
new file mode 100644 (file)
index 0000000..a17cf3d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo2()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlsym-indirect/foo3.c b/unit-tests/test-cases/dlsym-indirect/foo3.c
new file mode 100644 (file)
index 0000000..923e363
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo3()
+{
+       return 10;
+}
diff --git a/unit-tests/test-cases/dlsym-indirect/main.c b/unit-tests/test-cases/dlsym-indirect/main.c
new file mode 100644 (file)
index 0000000..e619d82
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that dlsym() will search indirect libraries
+///  rdar://problem/4047391
+///
+
+
+
+int main(int argc, const char* argv[])
+{
+       const char* path = argv[1];
+       const char* otherPath = "foo3.dylib";
+
+       void* handle = dlopen(path, RTLD_LAZY);
+       if ( handle == NULL ) {
+               FAIL("dlsym-indirect dlopen(\"%s\") failed", path);
+               exit(0);
+       }
+       
+       void* handle3 = dlopen(otherPath, RTLD_LAZY);
+       if ( handle3 == NULL ) {
+               FAIL("dlsym-indirect dlopen(\"%s\") failed", otherPath);
+               exit(0);
+       }
+       
+       void* foo = dlsym(handle, "foo");
+       if ( foo == NULL ) {
+               FAIL("dlsym-indirect dlsym(handle, \"foo\") failed");
+               exit(0);
+       }
+       void* foo1 = dlsym(handle, "foo1");
+       if ( foo1 == NULL ) {
+               FAIL("dlsym-indirect dlsym(handle, \"foo1\") failed");
+               //exit(0);
+       }
+       void* foo2 = dlsym(handle, "foo2");
+       if ( foo2 == NULL ) {
+               FAIL("dlsym-indirect dlsym(handle, \"foo2\") failed");
+               //exit(0);
+       }
+       void* foo3 = dlsym(handle, "foo3");
+       if ( foo3 != NULL ) {
+               FAIL("dlsym-indirect dlsym(handle, \"foo3\") should have failed");
+               //exit(0);
+       }
+       PASS("dlsym-indirect %s", path);
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dyld-launched-prebound/Makefile b/unit-tests/test-cases/dyld-launched-prebound/Makefile
new file mode 100644 (file)
index 0000000..4eb418a
--- /dev/null
@@ -0,0 +1,34 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ${TESTROOT}/bin/exit-zero-pass.pl "_dyld_launched_prebound() was implemented" "_dyld_launched_prebound() was not implemented" ./main
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main
+
diff --git a/unit-tests/test-cases/dyld-launched-prebound/main.c b/unit-tests/test-cases/dyld-launched-prebound/main.c
new file mode 100644 (file)
index 0000000..b4bf269
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+  _dyld_launched_prebound();
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dyld-slide/Makefile b/unit-tests/test-cases/dyld-slide/Makefile
new file mode 100644 (file)
index 0000000..35f422d
--- /dev/null
@@ -0,0 +1,33 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ${TESTROOT}/bin/exit-zero-pass.pl "dyld did slide" "dyld did not slide" ./main
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} main
diff --git a/unit-tests/test-cases/dyld-slide/main.c b/unit-tests/test-cases/dyld-slide/main.c
new file mode 100644 (file)
index 0000000..ad5b149
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdlib.h> // EXIT_SUCCESS
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+//
+// This builds an executable that is just big enough to force dyld to slide a bit
+//
+
+#define ARRAY_SIZE 301800000
+
+int bigarray1[ARRAY_SIZE];
+int bigarray2[ARRAY_SIZE];
+
+int
+main()
+{
+       // call a dyld function that will internally throw an exception to test dyld slide properly
+       NSAddImage("/foo/bar", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+       
+       return EXIT_SUCCESS;
+}
+
+
diff --git a/unit-tests/test-cases/fallback-with-suid/Makefile b/unit-tests/test-cases/fallback-with-suid/Makefile
new file mode 100644 (file)
index 0000000..f2a630d
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       export HOME="`pwd`/hide" && ./main user
+       export HOME="`pwd`/hide" && ./main-suid root
+
+all: main main-suid
+
+main: main.c hide/lib/libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+       
+main-suid: main
+       cp main main-suid
+       sudo chown root main-suid
+       sudo chmod 4755 main-suid
+
+hide/lib/libfoo.dylib : foo.c
+       mkdir -p hide/lib
+       ${CC} ${CCFLAGS} foo.c -dynamiclib -o hide/lib/libfoo.dylib
+
+clean:
+       ${RM} ${RMFLAGS} *~ main main-suid hide
+
diff --git a/unit-tests/test-cases/fallback-with-suid/foo.c b/unit-tests/test-cases/fallback-with-suid/foo.c
new file mode 100644 (file)
index 0000000..fa1d6fe
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
diff --git a/unit-tests/test-cases/fallback-with-suid/main.c b/unit-tests/test-cases/fallback-with-suid/main.c
new file mode 100644 (file)
index 0000000..a0ce919
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h> // strcmp(), strncmp()
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+//
+// binaries set to run as some other user id never use $HOME part of fallback-path
+//
+
+int main(int argc, const char *argv[])
+{
+       const struct mach_header* mh = NSAddImage("/foo/bar/libfoo.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+
+       if ( strcmp(argv[1], "root") == 0 ) {
+               if ( mh == NULL )
+                       PASS("fallback-with-suid root");
+               else
+                       FAIL("fallback-with-suid root");
+       }
+       else {
+               if ( mh != NULL )
+                       PASS("fallback-with-suid user");
+               else
+                       FAIL("fallback-with-suid user");
+       }
+       
+       return EXIT_SUCCESS;
+}
+
diff --git a/unit-tests/test-cases/flat-data/Makefile b/unit-tests/test-cases/flat-data/Makefile
new file mode 100644 (file)
index 0000000..5f54e4b
--- /dev/null
@@ -0,0 +1,42 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c libbar.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libbar.dylib
+
+
+libbar.dylib : bar.c getbar.c
+       ${CC} ${CCFLAGS} -dynamiclib getbar.c bar.c -o libbar.dylib -flat_namespace
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libbar.dylib 
+
diff --git a/unit-tests/test-cases/flat-data/bar.c b/unit-tests/test-cases/flat-data/bar.c
new file mode 100644 (file)
index 0000000..a53bfdd
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+int bar = 2;
diff --git a/unit-tests/test-cases/flat-data/getbar.c b/unit-tests/test-cases/flat-data/getbar.c
new file mode 100644 (file)
index 0000000..020d7ad
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int bar;
+
+int* getbar()
+{
+       return &bar;
+}
+
diff --git a/unit-tests/test-cases/flat-data/main.c b/unit-tests/test-cases/flat-data/main.c
new file mode 100644 (file)
index 0000000..fc85a6e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+// getbar() is implemented in libbar.dylib which has its own bar
+// libbar.dylib is built flat-namespace so it should use the bar from main
+// libbar.dylib is built multi_module so that the static linker won't complain
+// about two bar's.
+
+extern int* getbar();
+int bar = 1;
+
+int main()
+{
+       if ( getbar() != &bar )
+               FAIL("flat-data found wrong bar");
+       else
+               PASS("flat-data");
+
+       return EXIT_SUCCESS;
+}
+
diff --git a/unit-tests/test-cases/flat-lookup-everywhere/Makefile b/unit-tests/test-cases/flat-lookup-everywhere/Makefile
new file mode 100644 (file)
index 0000000..d1b99b5
--- /dev/null
@@ -0,0 +1,34 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       DYLD_INSERT_LIBRARIES="/usr/lib/libMallocDebug.A.dylib" DYLD_FORCE_FLAT_NAMESPACE="" ./main
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -framework CoreFoundation -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main
+
diff --git a/unit-tests/test-cases/flat-lookup-everywhere/main.c b/unit-tests/test-cases/flat-lookup-everywhere/main.c
new file mode 100644 (file)
index 0000000..fb2c2a1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main()
+{
+  CFStringRef string = CFStringCreateWithFormat(NULL, NULL, CFSTR(""));
+  PASS("flat-lookup-everywhere");
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/flat-prebound/Makefile b/unit-tests/test-cases/flat-prebound/Makefile
new file mode 100644 (file)
index 0000000..b30c674
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+
+libfoo.dylib : foo.c libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libbar.dylib -flat_namespace -prebind -seg1addr 20000
+
+
+libbar.dylib : bar.c
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib -prebind -seg1addr 30000
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libbar.dylib libfoo.dylib
+
diff --git a/unit-tests/test-cases/flat-prebound/bar.c b/unit-tests/test-cases/flat-prebound/bar.c
new file mode 100644 (file)
index 0000000..4bf747a
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int bar()
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/flat-prebound/foo.c b/unit-tests/test-cases/flat-prebound/foo.c
new file mode 100644 (file)
index 0000000..5f951e8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int bar();
+
+int foo()
+{
+       return bar();
+}
diff --git a/unit-tests/test-cases/flat-prebound/main.c b/unit-tests/test-cases/flat-prebound/main.c
new file mode 100644 (file)
index 0000000..b43924f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+// foo() internally calls bar()
+// libfoo.dylib is build flat and prebound to libbar.dylib
+// but the bar in this main executable should override the prebound bar
+
+extern int foo();
+
+int main()
+{
+       if ( foo() != 0 )
+               FAIL("flat-prebound found wrong bar");
+       else
+               PASS("flat-prebound");
+
+       return EXIT_SUCCESS;
+}
+
+int bar()
+{
+       return 0;
+}
diff --git a/unit-tests/test-cases/framework-fallback/Makefile b/unit-tests/test-cases/framework-fallback/Makefile
new file mode 100644 (file)
index 0000000..adf063d
--- /dev/null
@@ -0,0 +1,37 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all : main
+
+main: main.c
+       ${CC} main.c -o main  -I${TESTROOT}/include
+
+clean:
+       ${RM} ${RMFLAGS} main
+       
+       
diff --git a/unit-tests/test-cases/framework-fallback/main.c b/unit-tests/test-cases/framework-fallback/main.c
new file mode 100644 (file)
index 0000000..13f8146
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+///
+/// rdar://problem/3736945
+///
+///  Test that a std framework can be dynamically loaded via the fallback paths
+///
+///
+
+
+
+int
+main(int argc, const char* argv[])
+{
+       const struct mach_header *image;
+
+       image = NSAddImage("Carbon.framework/Carbon",
+                       NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING);
+       if ( image != NULL )
+               PASS("Carbon loaded");
+       else
+               FAIL("Could not load Carbon");
+
+       return 0;
+}
+
diff --git a/unit-tests/test-cases/ignore-bad-files/Makefile b/unit-tests/test-cases/ignore-bad-files/Makefile
new file mode 100644 (file)
index 0000000..b5c0a4c
--- /dev/null
@@ -0,0 +1,71 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+#  This test the ability of dyld to continue searching if a file was found but not usable.
+#  Uses DYLD_LIBRARY_PATH to search through many bogus files 
+#
+#
+
+
+run: all
+       export DYLD_LIBRARY_PATH=locations/datafile:locations/exec:locations/dir && ${TESTROOT}/bin/exit-non-zero-pass.pl "ignore-bad-files intended failure" "ignore-bad-files intended failure" ./main
+       export DYLD_LIBRARY_PATH=locations/datafile:locations/exec:locations/dir:locations/real && ${TESTROOT}/bin/exit-zero-pass.pl "ignore-bad-files intended success" "ignore-bad-files intended success" ./main
+
+all: main locations/real/libfoo.dylib locations/exec/libfoo.dylib locations/datafile/libfoo.dylib locations/dir/libfoo.dylib 
+
+main: main.c locations/real/libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c locations/real/libfoo.dylib
+
+
+# real dylib to use
+locations/real/libfoo.dylib : foo.c
+       mkdir -p locations/real
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o locations/real/libfoo.dylib foo.c -install_name libfoo.dylib
+
+# not a dylib - but a mach-o main executable
+locations/exec/libfoo.dylib : main.c
+       mkdir -p locations/exec
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o locations/exec/libfoo.dylib main.c foo.c
+
+# some random data file
+locations/datafile/libfoo.dylib : main.c
+       mkdir -p locations/datafile
+       cat main.c > locations/datafile/libfoo.dylib
+
+# not a file - but a directory
+locations/dir/libfoo.dylib : 
+       mkdir -p locations/dir/libfoo.dylib
+
+# file with wrong architecture
+#locations/wrongarch/libfoo.dylib : 
+#      mkdir -p locations/wrongarch
+#      ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o locations/wrongarch/libfoo.dylib foo.c -install_name libfoo.dylib -arch ppc64
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main locations
+
diff --git a/unit-tests/test-cases/ignore-bad-files/foo.c b/unit-tests/test-cases/ignore-bad-files/foo.c
new file mode 100644 (file)
index 0000000..4315d22
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+void foo() {}
diff --git a/unit-tests/test-cases/ignore-bad-files/main.c b/unit-tests/test-cases/ignore-bad-files/main.c
new file mode 100644 (file)
index 0000000..72d7abe
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern void foo();
+
+int
+main(int argc, const char* argv[])
+{
+       foo();
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/image-suffix/Makefile b/unit-tests/test-cases/image-suffix/Makefile
new file mode 100644 (file)
index 0000000..3c39e98
--- /dev/null
@@ -0,0 +1,152 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run :  check1 check2 check3 check4 check5 check6 check7 check8  
+
+all :  main1 main2 main3 main4 main5 main6 main7 main8  
+
+main : main.c libfoo.dylib
+       ${CC} -I${TESTROOT}/include main.c -o main libfoo.dylib
+
+libfoo.dylib : foo.c
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib -o $$PWD/libfoo.dylib
+
+libfoo_debug.dylib : foo.c
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib  -DDEBUG -o $$PWD/libfoo_debug.dylib -install_name $$PWD/libfoo.dylib
+
+hide/libfoo.dylib : foo.c
+       mkdir -p $$PWD/hide
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib  -o $$PWD/hide/libfoo.dylib -install_name $$PWD/libfoo.dylib
+
+hide/libfoo_debug.dylib : foo.c
+       mkdir -p $$PWD/hide
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib  -o $$PWD/hide/libfoo_debug.dylib -install_name $$PWD/libfoo.dylib
+
+# bar_debug has bar_debug as install name
+libbar.dylib : foo.c
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib -o $$PWD/libbar.dylib
+
+libbar_debug.dylib : foo.c
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib  -DDEBUG -o $$PWD/libbar_debug.dylib 
+
+hide/libbar.dylib : foo.c
+       mkdir -p $$PWD/hide
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib  -o $$PWD/hide/libbar.dylib -install_name $$PWD/libbar.dylib
+
+hide/libbar_debug.dylib : foo.c
+       mkdir -p $$PWD/hide
+       ${CC} -I${TESTROOT}/include  foo.c -dynamiclib  -o $$PWD/hide/libbar_debug.dylib -install_name $$PWD/libbar_debug.dylib
+
+clean:
+       rm -rf libfoo.dylib libfoo_debug.dylib hide libbar.dylib libbar_debug.dylib main1 main2 main3 main4 main5 main6 main7 main8
+
+
+#
+# check1: main links with libfoo.dylib sets DYLD_IMAGE_SUFFIX=_debug and dynamically loads libfoo.dylib
+#   (fails on 10.3)
+#
+main1 : main.c libfoo.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main1 libfoo.dylib
+
+check1:        main1
+       DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main1 libfoo.dylib
+       DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main1 $$PWD/libfoo.dylib
+
+
+#
+# check2: main links with libfoo_debug.dylib and dynamically loads libfoo.dylib
+#
+main2 : main.c libfoo_debug.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main2 libfoo_debug.dylib
+
+check2:        main2
+       echo "pwd-1 is ${PWD}"
+       echo "pwd-2 is $$PWD"
+       pwd
+       ./main2 $$PWD/libfoo.dylib
+
+
+#
+# check3: main links with libfoo.dylib sets DYLD_LIBRARY_PATH=hide and dynamically loads libfoo.dylib
+#
+main3 : main.c libfoo.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main3 libfoo.dylib
+
+check3:        main3
+       DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && ./main3 $$PWD/libfoo.dylib
+
+
+#
+# check4: main links with libfoo.dylib sets DYLD_LIBRARY_PATH=hide, DYLD_IMAGE_SUFFIX=_debug and dynamically loads libfoo.dylib
+#   (fails on 10.3)
+#
+main4 : main.c libfoo.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main4 libfoo.dylib
+
+check4:        main4
+       DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main4 $$PWD/libfoo.dylib
+
+
+#
+# check5: main links with libbar.dylib sets DYLD_IMAGE_SUFFIX=_debug and dynamically loads libbar.dylib
+#   (fails on 10.3)
+#
+main5 : main.c libbar.dylib libbar_debug.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main5 libbar.dylib
+
+check5:        main5
+       DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main5 $$PWD/libbar.dylib
+
+
+#
+# check6: main links with libbar_debug.dylib and dynamically loads libbar.dylib
+#   (fails on 10.3)
+#
+main6 : main.c libbar_debug.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main6 libbar_debug.dylib
+
+check6:        main6
+        DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main6 $$PWD/libbar.dylib
+
+
+#
+# check7: main links with libbar.dylib sets DYLD_LIBRARY_PATH=hide and dynamically loads libbar.dylib
+#
+main7 : main.c libbar.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main7 libbar.dylib
+
+check7:        main7
+       DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && ./main7 $$PWD/libbar.dylib
+
+
+#
+# check8: main links with libbar.dylib sets DYLD_LIBRARY_PATH=hide, DYLD_IMAGE_SUFFIX=_debug and dynamically loads libbar.dylib
+#   (fails on 10.3)
+#
+main8 : main.c libbar.dylib
+       ${CC} -I${TESTROOT}/include  main.c -o main8 libbar.dylib
+
+check8:        main8
+       DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main8 $$PWD/libbar.dylib
diff --git a/unit-tests/test-cases/image-suffix/foo.c b/unit-tests/test-cases/image-suffix/foo.c
new file mode 100644 (file)
index 0000000..a267f20
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+
+void foo()
+{
+       printf("foo");
+}
diff --git a/unit-tests/test-cases/image-suffix/main.c b/unit-tests/test-cases/image-suffix/main.c
new file mode 100644 (file)
index 0000000..79edd75
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+int main(int argc, const char* argv[])
+{
+       if ( argc < 2 ) {
+               FAIL("too few arguments to main()");
+               return EXIT_SUCCESS;
+       }
+
+       uint32_t imageCount = _dyld_image_count();
+       const struct mach_header* mh = NSAddImage(argv[1], 0);
+       if ( imageCount != _dyld_image_count() ) {
+               FAIL("image count changed");
+               return EXIT_SUCCESS;
+       }
+       
+       PASS("images loaded properly");
+       return EXIT_SUCCESS;
+}
+
diff --git a/unit-tests/test-cases/init-order/Makefile b/unit-tests/test-cases/init-order/Makefile
new file mode 100644 (file)
index 0000000..dfa47dd
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main
+
+
+main: main.c libtest.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c  libtest.dylib
+
+libtest.dylib: foo1.c foo2.c base.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib  -o libtest.dylib  foo1.c foo2.c base.c -init _myDashInit
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main  libtest.dylib
+       
diff --git a/unit-tests/test-cases/init-order/base.c b/unit-tests/test-cases/init-order/base.c
new file mode 100644 (file)
index 0000000..2cdb40a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "base.h"
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static int state = 1;
+bool badOrder = false;
+
+void setState(int nextState)
+{
+       if ( nextState == state )
+               ++state;
+       else
+               badOrder = true;
+
+}
+
+
+void baseCheck()
+{
+       if ( badOrder ) {
+               switch ( state ) {
+                       case 1:
+                               FAIL("init-order -init not run first");
+                               break;
+                       case 2:
+                               FAIL("init-order myInit1 not run second");
+                               break;
+                       case 3:
+                               FAIL("init-order myInit2 not run third");
+                               break;
+                       case 4:
+                               FAIL("init-order myInit3 not run fourth");
+                               break;
+               }
+       }
+       else
+               PASS("init-order");
+}
+
diff --git a/unit-tests/test-cases/init-order/base.h b/unit-tests/test-cases/init-order/base.h
new file mode 100644 (file)
index 0000000..1dbf697
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern void setState(int);
+extern void baseCheck();
+
diff --git a/unit-tests/test-cases/init-order/foo1.c b/unit-tests/test-cases/init-order/foo1.c
new file mode 100644 (file)
index 0000000..b8808ae
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+
+
+
+// should run second because first initiallzer in first .o file
+static __attribute__((constructor)) void myInit1() 
+{
+       //fprintf(stderr, "myInit1()\n");
+       setState(2);
+}
+
+
+// should run thrid because second initiallzer in first .o file
+static __attribute__((constructor)) void myInit2() 
+{
+       //fprintf(stderr, "myInit2()\n");
+       setState(3);
+}
+
+
+// should run first becuase -init runs first
+void myDashInit() 
+{
+       //fprintf(stderr, "myDashInit()\n");
+       setState(1);
+}
+
diff --git a/unit-tests/test-cases/init-order/foo2.c b/unit-tests/test-cases/init-order/foo2.c
new file mode 100644 (file)
index 0000000..646358b
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+
+// should run fourth because first initiallzer in second .o file
+static __attribute__((constructor)) void myInit3() 
+{
+       //fprintf(stderr, "myInit3()\n");
+       setState(4);
+}
+
diff --git a/unit-tests/test-cases/init-order/foo3.c b/unit-tests/test-cases/init-order/foo3.c
new file mode 100644 (file)
index 0000000..c92a444
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+int __attribute__((weak))      coal1 = 3;
+int __attribute__((weak))      coal2 = 2;
+
+static __attribute__((constructor)) void myinit() 
+{
+       //fprintf(stderr, "myinit() in foo1.c\n");
+       baseVerifyCoal1("in foo3", &coal1);
+       baseVerifyCoal2("in foo3", &coal2);
+}
+
diff --git a/unit-tests/test-cases/init-order/main.c b/unit-tests/test-cases/init-order/main.c
new file mode 100644 (file)
index 0000000..b210384
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "base.h"
+
+int main()
+{
+       baseCheck();
+       return EXIT_SUCCESS;
+}
+
+
diff --git a/unit-tests/test-cases/initializer-args/Makefile b/unit-tests/test-cases/initializer-args/Makefile
new file mode 100644 (file)
index 0000000..3b5e6be
--- /dev/null
@@ -0,0 +1,34 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main arg1 arg2
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main
+
diff --git a/unit-tests/test-cases/initializer-args/main.c b/unit-tests/test-cases/initializer-args/main.c
new file mode 100644 (file)
index 0000000..79e43e0
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static int    my_argc = 0;
+static char **my_argv = NULL;
+static char **my_envp = NULL;
+static char **my_appl = NULL;
+
+void
+__attribute__((constructor))
+my_init(int argc, char **argv, char **envp, char **appl)
+{
+  my_argc = argc;
+  my_argv = argv;
+  my_envp = envp;
+  my_appl = appl;
+}
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+  if(argc == my_argc
+  && argv == my_argv
+  && envp == my_envp
+  && appl == my_appl)
+  {
+    PASS("initializer/constructor was called with arguments");
+  }
+  else
+  {
+    FAIL("initializer/constructor was not called with arguments");
+  }
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/insert-libraries-with-initializer/Makefile b/unit-tests/test-cases/insert-libraries-with-initializer/Makefile
new file mode 100644 (file)
index 0000000..352ec10
--- /dev/null
@@ -0,0 +1,35 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       export DYLD_INSERT_LIBRARIES="libfoo.dylib" && ./main
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o libfoo.dylib foo.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libfoo.dylib
+
diff --git a/unit-tests/test-cases/insert-libraries-with-initializer/foo.c b/unit-tests/test-cases/insert-libraries-with-initializer/foo.c
new file mode 100644 (file)
index 0000000..60a2d84
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdlib.h>
+
+#include "test.h"
+
+static
+void
+__attribute__((constructor))
+my_init()
+{
+  PASS("initializer/constructor was called");
+  exit(EXIT_SUCCESS);
+}
+
diff --git a/unit-tests/test-cases/insert-libraries-with-initializer/main.c b/unit-tests/test-cases/insert-libraries-with-initializer/main.c
new file mode 100644 (file)
index 0000000..bb193e7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+  FAIL("initializer/constructor was not called");
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/insert-libraries-with-suid/Makefile b/unit-tests/test-cases/insert-libraries-with-suid/Makefile
new file mode 100644 (file)
index 0000000..7e6ad2a
--- /dev/null
@@ -0,0 +1,38 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       export DYLD_INSERT_LIBRARIES="/usr/lib/libldap.dylib:/usr/lib/libpcap.dylib" && ./main
+
+all: main
+
+main: main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+       sudo chown root main
+       sudo chmod 4755 main
+
+clean:
+       ${RM} ${RMFLAGS} *~ main
+
diff --git a/unit-tests/test-cases/insert-libraries-with-suid/main.c b/unit-tests/test-cases/insert-libraries-with-suid/main.c
new file mode 100644 (file)
index 0000000..0571cd9
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h> // strcmp(), strncmp()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+//
+// binaries set to run as some other user id never use DYLD_INSERT_LIBRARIES
+// That environment variable is cleared by dyld (its right-hand-side is set to empty)
+//
+
+int main(int argc, const char *argv[])
+{
+       const char* rhs = getenv("DYLD_INSERT_LIBRARIES");
+       if ( rhs == NULL )
+        FAIL("insert-libraries-with-suid DYLD_INSERT_LIBRARIES not set");
+       else if ( rhs[0] != '\0' )
+        FAIL("insert-libraries-with-suid DYLD_INSERT_LIBRARIES not cleared");
+       else
+               PASS("insert-libraries-with-suid");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/lazy-pointer-binding/Makefile b/unit-tests/test-cases/lazy-pointer-binding/Makefile
new file mode 100644 (file)
index 0000000..9a7f756
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main 
+
+main : main.c libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+
+libfoo.dylib : foo.c
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libfoo.dylib
+
diff --git a/unit-tests/test-cases/lazy-pointer-binding/foo.c b/unit-tests/test-cases/lazy-pointer-binding/foo.c
new file mode 100644 (file)
index 0000000..53d2618
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>  // fprintf(), NULL
+
+bool floattest(double p1, float p2, double p3, float p4, double p5, float p6,
+                               double p7, float p8, double p9, float p10, double p11, float p12,
+                               double p13, float p14)
+{
+       if ( p1 != 1.0 )
+               return false;
+       if ( p2 != 2.0 )
+               return false;
+       if ( p3 != 3.0 )
+               return false;
+       if ( p4 != 4.0 )
+               return false;
+       if ( p5 != 5.0 )
+               return false;
+       if ( p6 != 6.0 )
+               return false;
+       if ( p7 != 7.0 )
+               return false;
+       if ( p8 != 8.0 )
+               return false;
+       if ( p9 != 9.0 )
+               return false;
+       if ( p10 != 10.0 )
+               return false;
+       if ( p11 != 11.0 )
+               return false;
+       if ( p12 != 12.0 )
+               return false;
+       if ( p13 != 13.0 )
+               return false;
+       if ( p14 != 14.0 )
+               return false;
+       return true;
+}
+                               
+bool inttest(long long p1, long long p2, long long p3, long long p4, long long p5)
+{
+       if ( p1 != 0x100000002)
+               return false;
+       if ( p2 != 0x300000004)
+               return false;
+       if ( p3 != 0x500000006)
+               return false;
+       if ( p4 != 0x700000008)
+               return false;
+       if ( p5 != 0x90000000A)
+               return false;
+       return true;
+}
+
+
diff --git a/unit-tests/test-cases/lazy-pointer-binding/main.c b/unit-tests/test-cases/lazy-pointer-binding/main.c
new file mode 100644 (file)
index 0000000..c2554b2
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>  
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern bool floattest(double p1, float p2, double p3, float p4, double p5, float p6,
+                                       double p7, float p8, double p9, float p10, double p11, float p12,
+                                       double p13, float p14);
+                               
+extern bool inttest(long long p1, long long p2, long long p3, long long p4, long long p5);
+
+
+
+int main()
+{
+       if ( ! floattest(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0) ) {
+               FAIL("lazy-pointer-binding float parameters");
+               return EXIT_SUCCESS;
+       }
+       
+       if ( ! inttest(0x100000002, 0x300000004, 0x500000006, 0x700000008, 0x90000000A) ) {
+               FAIL("lazy-pointer-binding int parameters");
+               return EXIT_SUCCESS;
+       }
+       
+       PASS("lazy-pointer-binding");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/lib-name-overload/Makefile b/unit-tests/test-cases/lib-name-overload/Makefile
new file mode 100644 (file)
index 0000000..52c2e50
--- /dev/null
@@ -0,0 +1,59 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+###
+### rdar://problem/3684168
+###
+### The process has two different libfoo.dylib.  
+### When DYLD_LIBRARY_PATH is used, both resolve to the same library.
+### It gets worse.  One of the libraries re-exports from the other. 
+### So, without loop detection in dyld, it will infinitely recurse.
+###
+
+PWD = `pwd`
+
+
+run : all
+       # verify it runs as-is
+       ./main
+       # verify dyld doesn't hang on the circularity
+       DYLD_LIBRARY_PATH=$(PWD) && export DYLD_LIBRARY_PATH && ${TESTROOT}/bin/exit-zero-pass.pl "lib-name-overload" "lib-name-overload" ./main
+
+all : main 
+
+other/libfoo.dylib : foo2.c
+       mkdir -p other
+       gcc foo2.c -dynamiclib  -o $(PWD)/other/libfoo.dylib 
+
+libfoo.dylib : foo.c other/libfoo.dylib
+       gcc foo.c -dynamiclib $(PWD)/other/libfoo.dylib -sub_library libfoo -o $(PWD)/libfoo.dylib 
+
+main : main.c libfoo.dylib
+       gcc main.c -I${TESTROOT}/include -o main libfoo.dylib
+
+       
+clean:
+       rm -rf main other libfoo.dylib
\ No newline at end of file
diff --git a/unit-tests/test-cases/lib-name-overload/foo.c b/unit-tests/test-cases/lib-name-overload/foo.c
new file mode 100644 (file)
index 0000000..4b2ea98
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+int foo = 0;
+
diff --git a/unit-tests/test-cases/lib-name-overload/foo2.c b/unit-tests/test-cases/lib-name-overload/foo2.c
new file mode 100644 (file)
index 0000000..b34dc76
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+int foo2 = 0;
+
+
diff --git a/unit-tests/test-cases/lib-name-overload/main.c b/unit-tests/test-cases/lib-name-overload/main.c
new file mode 100644 (file)
index 0000000..73cc95a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+///
+/// rdar://problem/3684168
+///
+
+
+
+extern int foo2;
+
+int main()
+{
+       return foo2;
+}
diff --git a/unit-tests/test-cases/loader_path-dup/Makefile b/unit-tests/test-cases/loader_path-dup/Makefile
new file mode 100644 (file)
index 0000000..a89a431
--- /dev/null
@@ -0,0 +1,66 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+### 
+### This test case is to verify that two different dylibs with the same name  
+### and each loaded via the same @loader_path does not confuse dyld
+### into just loading one of them.
+### 
+
+## Note, until ld understands @loader_path we have to do a funky make
+
+
+run: all
+       ./main
+
+all: main
+
+foo/libfoo.dylib : foo.c foo/libbase.dylib
+       mkdir -p foo
+       ${CC} foo.c foo/libbase.dylib -dynamiclib -o "`pwd`/foo/libfoo.dylib" 
+       
+foo/libbase.dylib : base.c 
+       mkdir -p foo
+       ${CC} base.c -DFOO -dynamiclib -o foo/libbase.dylib  
+       
+
+bar/libbar.dylib : bar.c bar/libbase.dylib
+       mkdir -p bar
+       ${CC} bar.c bar/libbase.dylib -dynamiclib -o "`pwd`/bar/libbar.dylib" 
+       
+bar/libbase.dylib : base.c 
+       mkdir -p bar
+       ${CC} base.c -Dbar -dynamiclib -o bar/libbase.dylib  
+       
+
+main : main.c foo/libfoo.dylib bar/libbar.dylib
+       ${CC} -I${TESTROOT}/include main.c -o main foo/libfoo.dylib bar/libbar.dylib 
+       # this breaks partial makes, but ld can't see @loader_path or it freaks
+       install_name_tool -change foo/libbase.dylib  '@loader_path/libbase.dylib'      foo/libfoo.dylib
+       install_name_tool -change bar/libbase.dylib  '@loader_path/libbase.dylib'      bar/libbar.dylib
+
+
+clean:
+       ${RM} ${RMFLAGS} *~  main foo bar
diff --git a/unit-tests/test-cases/loader_path-dup/bar.c b/unit-tests/test-cases/loader_path-dup/bar.c
new file mode 100644 (file)
index 0000000..edd9f35
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+extern int base;
+
+bool bar()
+{
+       return (base == 2);
+}
diff --git a/unit-tests/test-cases/loader_path-dup/base.c b/unit-tests/test-cases/loader_path-dup/base.c
new file mode 100644 (file)
index 0000000..03b9160
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+#if FOO
+int base = 1;
+#else
+int base = 2;
+#endif
+
diff --git a/unit-tests/test-cases/loader_path-dup/foo.c b/unit-tests/test-cases/loader_path-dup/foo.c
new file mode 100644 (file)
index 0000000..7f0cfbb
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdbool.h>
+
+
+extern int base;
+
+bool foo()
+{
+       return (base == 1);
+}
diff --git a/unit-tests/test-cases/loader_path-dup/main.c b/unit-tests/test-cases/loader_path-dup/main.c
new file mode 100644 (file)
index 0000000..9c12ccc
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+extern bool foo();
+extern bool bar();
+
+int main()
+{
+       if ( foo() && bar() )
+               PASS("loader_path");
+       else
+               FAIL("loader_path-dup both libraries not loaded");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/loader_path/Makefile b/unit-tests/test-cases/loader_path/Makefile
new file mode 100644 (file)
index 0000000..6b34207
--- /dev/null
@@ -0,0 +1,52 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       ./main
+
+all: main
+
+hide/hole/libfoo.dylib : foo.c
+       mkdir -p hide/hole
+       ${CC} foo.c -dynamiclib -o hide/hole/libfoo.dylib -install_name libfoo.dylib
+       
+hide/libbar.dylib : bar.c hide/hole/libfoo.dylib
+       ${CC} bar.c -dynamiclib -o hide/libbar.dylib -install_name libbar.dylib hide/hole/libfoo.dylib
+       install_name_tool -change libfoo.dylib '@loader_path/hole/libfoo.dylib'  hide/libbar.dylib
+
+hide/libfoo3.dylib : foo.c
+       ${CC} foo.c -dynamiclib -o hide/libfoo3.dylib -install_name libfoo3.dylib 
+
+libfoo2.dylib : foo.c
+       ${CC} foo.c -dynamiclib -o libfoo2.dylib
+
+
+main : main.c libfoo2.dylib hide/libbar.dylib hide/libfoo3.dylib
+       ${CC} -I${TESTROOT}/include main.c -o main hide/libbar.dylib libfoo2.dylib 
+       install_name_tool -change libfoo2.dylib '@loader_path/libfoo2.dylib'      main
+       install_name_tool -change libbar.dylib  '@loader_path/hide/libbar.dylib'  main
+
+clean:
+       ${RM} ${RMFLAGS} *~  main libfoo.dylib hide libfoo2.dylib
diff --git a/unit-tests/test-cases/loader_path/bar.c b/unit-tests/test-cases/loader_path/bar.c
new file mode 100644 (file)
index 0000000..902e563
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+void bar() {}
diff --git a/unit-tests/test-cases/loader_path/foo.c b/unit-tests/test-cases/loader_path/foo.c
new file mode 100644 (file)
index 0000000..1bcf3c2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+void foo()
+{
+}
diff --git a/unit-tests/test-cases/loader_path/main.c b/unit-tests/test-cases/loader_path/main.c
new file mode 100644 (file)
index 0000000..141931f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+
+int main()
+{
+       NSAddImage("@loader_path/hide/libfoo3.dylib", 0);
+
+       PASS("loader_path");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/missing-symlink-framework-fallback-path/Foo.c b/unit-tests/test-cases/missing-symlink-framework-fallback-path/Foo.c
new file mode 100644 (file)
index 0000000..100cfc6
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2005 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@
+ */
diff --git a/unit-tests/test-cases/missing-symlink-framework-fallback-path/Makefile b/unit-tests/test-cases/missing-symlink-framework-fallback-path/Makefile
new file mode 100644 (file)
index 0000000..4cfeb68
--- /dev/null
@@ -0,0 +1,48 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       export DYLD_FALLBACK_FRAMEWORK_PATH="dir" && ${TESTROOT}/bin/exit-zero-pass.pl "pass message" "fail message" ./main
+
+all: main dir/Foo.framework/Versions/Current/Foo
+
+Foo.framework/Versions/Current/Foo:
+       mkdir -p Foo.framework/Versions/A
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o Foo.framework/Versions/A/Foo Foo.c
+       cd Foo.framework/Versions/ && ln -s A Current
+       cd Foo.framework/ && ln -s Versions/Current/Foo Foo
+
+dir/Foo.framework/Versions/Current/Foo:
+       $(MAKE) Foo.framework/Versions/Current/Foo
+       rm -f Foo.framework/Foo
+       mkdir dir
+       mv Foo.framework dir
+
+main:
+       $(MAKE) Foo.framework/Versions/Current/Foo
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -F. -framework Foo -o main main.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main dir/ Foo.framework/
diff --git a/unit-tests/test-cases/missing-symlink-framework-fallback-path/main.c b/unit-tests/test-cases/missing-symlink-framework-fallback-path/main.c
new file mode 100644 (file)
index 0000000..46698ad
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+  
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/non-weak-library/Makefile b/unit-tests/test-cases/non-weak-library/Makefile
new file mode 100644 (file)
index 0000000..41f097c
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       cd absent/  && ../${TESTROOT}/bin/exit-non-zero-pass.pl "pass message" "fail message" ./main
+       cd present/ && ./main
+
+all: foo.c main.c
+       ${CC} -dynamiclib -prebind -seg1addr 400000 -o libfoo.dylib foo.c
+       mkdir -p absent/
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -lfoo -DLIB_ABSENT  -o absent/main  main.c
+       mkdir -p present/
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -lfoo -DLIB_PRESENT -o present/main main.c
+       mv libfoo.dylib present/
+
+clean:
+       ${RM} ${RMFLAGS} *~ libfoo.dylib absent/main present/{main,libfoo.dylib}
diff --git a/unit-tests/test-cases/non-weak-library/foo.c b/unit-tests/test-cases/non-weak-library/foo.c
new file mode 100644 (file)
index 0000000..c57adba
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+int foo()
+{
+  return 10;
+}
diff --git a/unit-tests/test-cases/non-weak-library/main.c b/unit-tests/test-cases/non-weak-library/main.c
new file mode 100644 (file)
index 0000000..de02062
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+
+int
+main(int argc, char **argv)
+{
+#if defined(LIB_PRESENT)
+  PASS("pass message");
+#endif
+#if defined(LIB_ABSENT)
+  FAIL("fail message");
+#endif
+
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/partial-library-load/Makefile b/unit-tests/test-cases/partial-library-load/Makefile
new file mode 100644 (file)
index 0000000..2cff519
--- /dev/null
@@ -0,0 +1,57 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+###
+### rdar://problem/3884004 Libraries can be half-baked if an error occurs during their first use
+###
+### We indirectly load libfoo which depends on libbar.  The libbar that is loaded does not contain
+### what libfoo needs, so libfoo fails to bind.  The bug was that libfoo was left marked as bound,
+### so the next use of libfoo seemed to succeed, when it should have failed.
+###
+
+
+run: all
+       export DYLD_IMAGE_SUFFIX="_missing" && ${TESTROOT}/bin/exit-zero-pass.pl "partial-library-load" "partial-library-load" ./main
+
+all: main test.bundle
+
+main : main.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c libfoo.dylib
+       ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c libfoo.dylib
+
+libfoo.dylib : foo.c libbar_missing.dylib libbar.dylib
+       ${CC} ${CCFLAGS} foo.c -dynamiclib -o libfoo.dylib libbar.dylib
+
+libbar_missing.dylib : bar.c
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar_missing.dylib -install_name libbar.dylib
+
+libbar.dylib : bar.c
+       ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib -DHAS_BAR2=1 
+
+clean:
+       ${RM} ${RMFLAGS} *~ main test.bundle libfoo.dylib libbar.dylib libbar_missing.dylib
+
diff --git a/unit-tests/test-cases/partial-library-load/bar.c b/unit-tests/test-cases/partial-library-load/bar.c
new file mode 100644 (file)
index 0000000..400e1bf
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int bar1 = 1;
+#if HAS_BAR2
+int bar2 = 2;
+#endif
+int bar3 = 3;
+
diff --git a/unit-tests/test-cases/partial-library-load/bundle.c b/unit-tests/test-cases/partial-library-load/bundle.c
new file mode 100644 (file)
index 0000000..a7aad9e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+extern int foo();
+
+void bun()
+{
+       foo();
+
+}
+
diff --git a/unit-tests/test-cases/partial-library-load/foo.c b/unit-tests/test-cases/partial-library-load/foo.c
new file mode 100644 (file)
index 0000000..8abc708
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int bar1;
+extern int bar2;
+extern int bar3;
+
+
+
+int foo()
+{
+       return bar1 + bar2 + bar3;
+}
diff --git a/unit-tests/test-cases/partial-library-load/main.c b/unit-tests/test-cases/partial-library-load/main.c
new file mode 100644 (file)
index 0000000..0c81554
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <string.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+
+int main()
+{
+       // load bundle which indirectly loads libfoo and libbar
+       NSObjectFileImage ofi;
+       if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+               FAIL("NSCreateObjectFileImageFromFile failed");
+               return 1;
+       }
+       
+       // link bundle, this will fail because bar2 is missing from libbar
+       NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+       if ( mod != NULL ) {
+               FAIL("NSLinkModule succeeded but should have failed");
+               return 1;
+       }
+
+       // load libfoo, this should fail because it can't be loaded
+       const struct mach_header* mh = NSAddImage("libfoo.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+       if ( mh != NULL ) {
+               return 1;
+       }
+       
+#if 0  
+       // find foo
+       NSSymbol sym = NSLookupSymbolInImage(mh, "_foo", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+       if ( sym == NULL ) {
+               FAIL("NSLookupSymbolInImage failed");
+               return 1;
+       }
+
+       // if foo() was only partially bound, this will crash
+       int (*fooPtr)() = NSAddressOfSymbol(sym);
+       (*fooPtr)();
+#endif 
+       return 0;
+}
\ No newline at end of file
diff --git a/unit-tests/test-cases/sym-link-load/Makefile b/unit-tests/test-cases/sym-link-load/Makefile
new file mode 100644 (file)
index 0000000..00dd9ac
--- /dev/null
@@ -0,0 +1,83 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+### 
+### This test case is to verify that dyld cannot be tricked into loading 
+### the "same" library twice. 
+### 
+### The tricky scenario is:
+###  1) a library dyld is to load is specified with a symlink path
+###  2) the library the that is the target of the symlink is already loaded 
+###  via a different path.  In this case becuase of DYLD_LIBRARY_PATH.
+### 
+### 
+### 
+### 
+
+
+
+run: all
+       ./main
+       export DYLD_LIBRARY_PATH="`pwd`/fake" && ./main
+       
+
+all: main real/liblink.dylib  real/libtest.dylib fake/libtest.dylib
+
+
+main: main.c stub/libtest.dylib stub/liblink.dylib real/libbase.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c  stub/libtest.dylib stub/liblink.dylib real/libbase.dylib
+
+stub/libtest.dylib: test.c
+       mkdir -p stub
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c -DDO_NOTHING -o stub/libtest.dylib -install_name "`pwd`/real/libtest.dylib"
+       
+stub/liblink.dylib: link.c
+       mkdir -p stub
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib link.c -o stub/liblink.dylib -install_name "`pwd`/real/liblink.dylib"
+       
+
+real/libbase.dylib: base.c
+       mkdir -p real
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib base.c -o "`pwd`/real/libbase.dylib"
+       
+real/libtest.dylib: test.c real/libbase.dylib
+       mkdir -p real
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c real/libbase.dylib -o "`pwd`/real/libtest.dylib"
+       
+real/liblink.dylib: link.c
+       mkdir -p real
+       cd real && ln -s libtest.dylib liblink.dylib
+       
+
+fake/libtest.dylib: test.c real/libbase.dylib
+       mkdir -p fake
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c real/libbase.dylib -o "`pwd`/fake/libtest.dylib" -install_name "`pwd`/real/libtest.dylib"
+       
+       
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main real stub fake
+       
diff --git a/unit-tests/test-cases/sym-link-load/base.c b/unit-tests/test-cases/sym-link-load/base.c
new file mode 100644 (file)
index 0000000..663274e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "base.h"
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static int initCount = 0;
+
+void setState(int x)
+{
+       ++initCount;
+}
+
+
+void baseCheck()
+{
+       switch ( initCount ) {
+               case 0:
+                       FAIL("sym-link-load no initializers run");
+                       break;
+               case 1:
+                       PASS("sym-link-load");
+                       break;
+               case 2:
+               default:
+                       FAIL("sym-link-load initializers double run (library double loaded)");
+                       break;
+       }
+}
+
diff --git a/unit-tests/test-cases/sym-link-load/base.h b/unit-tests/test-cases/sym-link-load/base.h
new file mode 100644 (file)
index 0000000..1dbf697
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern void setState(int);
+extern void baseCheck();
+
diff --git a/unit-tests/test-cases/sym-link-load/link.c b/unit-tests/test-cases/sym-link-load/link.c
new file mode 100644 (file)
index 0000000..42c87ba
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
diff --git a/unit-tests/test-cases/sym-link-load/main.c b/unit-tests/test-cases/sym-link-load/main.c
new file mode 100644 (file)
index 0000000..b210384
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "base.h"
+
+int main()
+{
+       baseCheck();
+       return EXIT_SUCCESS;
+}
+
+
diff --git a/unit-tests/test-cases/sym-link-load/test.c b/unit-tests/test-cases/sym-link-load/test.c
new file mode 100644 (file)
index 0000000..5b1e221
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+
+#ifndef DO_NOTHING
+
+// should run second because first initiallzer in first .o file
+static __attribute__((constructor)) void test_init() 
+{
+       //fprintf(stderr, "test_init()\n");
+       setState(1);
+}
+
+#endif
diff --git a/unit-tests/test-cases/text-relocs/Makefile b/unit-tests/test-cases/text-relocs/Makefile
new file mode 100644 (file)
index 0000000..92225e9
--- /dev/null
@@ -0,0 +1,46 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+### 
+### This test case is to verify __TEXT reliocations work
+### 
+### 
+
+
+
+run: all
+       ./main
+
+all: main 
+
+main: main.c libbar.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libbar.dylib
+
+libbar.dylib: foo.s bar.c
+       ${CC} ${CCFLAGS} -dynamiclib -o libbar.dylib bar.c foo.s -read_only_relocs suppress -Os
+       
+clean:
+       ${RM} ${RMFLAGS} *~ main libbar.dylib
+
diff --git a/unit-tests/test-cases/text-relocs/bar.c b/unit-tests/test-cases/text-relocs/bar.c
new file mode 100644 (file)
index 0000000..9224e92
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <stdbool.h>
+
+extern int* foo;
+
+bool testBar()
+{
+       return (*foo == 10);
+}
+
+int bar = 10;
+
diff --git a/unit-tests/test-cases/text-relocs/foo.s b/unit-tests/test-cases/text-relocs/foo.s
new file mode 100644 (file)
index 0000000..7f8821e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+       .text
+       .globl _foo
+_foo:
+       .long   _bar
+       
+       
diff --git a/unit-tests/test-cases/text-relocs/main.c b/unit-tests/test-cases/text-relocs/main.c
new file mode 100644 (file)
index 0000000..a702c2e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <stdbool.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern bool testBar();
+
+int main(int argc, const char* argv[])
+{
+       if ( testBar() )
+               PASS("text-reloc");
+       else
+               FAIL("text-reloc");
+       return EXIT_SUCCESS;
+}
+
+
diff --git a/unit-tests/test-cases/weak-coalesce-c++/Makefile b/unit-tests/test-cases/weak-coalesce-c++/Makefile
new file mode 100644 (file)
index 0000000..4f38eeb
--- /dev/null
@@ -0,0 +1,53 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+run: all
+       ./dynamic-test
+
+all: dynamic-test  static-test
+
+
+static-test: a1.o a2.o main.o
+       $(CXX) -I${TESTROOT}/include a1.o a2.o main.o -o static-test
+
+dynamic-test: main.o a1.o liba2.dylib
+       $(CXX) -I${TESTROOT}/include  main.o a1.o -L. -la2 -o dynamic-test
+
+liba2.dylib: a2.o
+       $(CXX) -I${TESTROOT}/include a2.o -dynamiclib -o liba2.dylib
+
+a1.o: a1.cc a.h
+       $(CXX) -I${TESTROOT}/include -c a1.cc
+
+a2.o: a2.cc a.h
+       $(CXX) -I${TESTROOT}/include -c a2.cc
+
+main.o: main.cc
+       $(CXX) -I${TESTROOT}/include -c main.cc
+       
+       
+clean:
+       ${RM} ${RMFLAGS} *.o *.dylib static-test dynamic-test 
diff --git a/unit-tests/test-cases/weak-coalesce-c++/a.h b/unit-tests/test-cases/weak-coalesce-c++/a.h
new file mode 100644 (file)
index 0000000..574026d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+template <typename X>
+struct wrapper {
+  static X x;
+};
+
+template <typename X> X wrapper<X>::x;
diff --git a/unit-tests/test-cases/weak-coalesce-c++/a1.cc b/unit-tests/test-cases/weak-coalesce-c++/a1.cc
new file mode 100644 (file)
index 0000000..0395912
--- /dev/null
@@ -0,0 +1,4 @@
+#include "a.h"
+
+int  get_x_1 (void)   { return wrapper<int>::x; }
+void set_x_1 (int x_) { wrapper<int>::x = x_; }
diff --git a/unit-tests/test-cases/weak-coalesce-c++/a2.cc b/unit-tests/test-cases/weak-coalesce-c++/a2.cc
new file mode 100644 (file)
index 0000000..b3a3fed
--- /dev/null
@@ -0,0 +1,4 @@
+#include "a.h"
+
+int  get_x_2 (void)   { return wrapper<int>::x; }
+void set_x_2 (int x_) { wrapper<int>::x = x_; }
diff --git a/unit-tests/test-cases/weak-coalesce-c++/main.cc b/unit-tests/test-cases/weak-coalesce-c++/main.cc
new file mode 100644 (file)
index 0000000..3915e94
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern void set_x_1(int);
+extern void set_x_2(int);
+extern int  get_x_1(void);
+extern int  get_x_2(void);
+
+int main()
+{
+       set_x_1 (17);
+       set_x_2 (76);
+
+       if (get_x_1() == 76 && get_x_2() == 76)
+               PASS("weak-coalesce=c++");
+       else
+               FAIL("weak-coalesce=c++");
+}
diff --git a/unit-tests/test-cases/weak-coalesce/Makefile b/unit-tests/test-cases/weak-coalesce/Makefile
new file mode 100644 (file)
index 0000000..13bdf37
--- /dev/null
@@ -0,0 +1,52 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+run: all
+       ./main
+
+all: main
+
+
+main: main.c libfoo1.dylib libbase.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo1.dylib libbase.dylib
+
+libfoo1.dylib: foo1.c libfoo2.dylib libbase.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo1.dylib foo1.c libfoo2.dylib libbase.dylib
+
+libfoo2.dylib: foo2.c libfoo3.dylib libbase.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo2.dylib foo2.c libfoo3.dylib libbase.dylib
+
+libfoo3.dylib: foo3.c libbase.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo3.dylib foo3.c libbase.dylib -prebind -seg1addr 20000
+
+libbase.dylib: base.c
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libbase.dylib base.c -prebind -seg1addr 10000
+
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main  libfoo1.dylib libfoo2.dylib libfoo3.dylib libbase.dylib
+
diff --git a/unit-tests/test-cases/weak-coalesce/base.c b/unit-tests/test-cases/weak-coalesce/base.c
new file mode 100644 (file)
index 0000000..0deff52
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "base.h"
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static bool wasProblem = false;
+
+static const char*     coal1Where = NULL;
+static int*                    coal1Addr = NULL;
+static int                     checkInCountCoal1 = 0;
+
+void baseVerifyCoal1(const char* where, int* addr)
+{
+       //fprintf(stderr, "baseVerifyCoal1(%s, %p)\n", where, addr);
+       ++checkInCountCoal1;
+       if ( coal1Where == NULL ) {
+               coal1Where = where;
+               coal1Addr = addr;
+       }
+       else {
+               if ( addr != coal1Addr ) {
+                       fprintf(stderr, "coal1 resolved to different locations.  %p in %s and %p in %s\n", 
+                               coal1Addr, coal1Where, addr, where);
+                       wasProblem = true;
+               }       
+       }
+}
+
+
+static const char*     coal2Where = NULL;
+static int*                    coal2Addr = NULL;
+static int                     checkInCountCoal2 = 0;
+
+void baseVerifyCoal2(const char* where, int* addr)
+{
+       //fprintf(stderr, "baseVerifyCoal2(%s, %p)\n", where, addr);
+       ++checkInCountCoal2;
+       if ( coal2Where == NULL ) {
+               coal2Where = where;
+               coal2Addr = addr;
+       }
+       else {
+               if ( addr != coal2Addr ) {
+                       fprintf(stderr, "coal2 resolved to different locations.  %p in %s and %p in %s\n", 
+                               coal2Addr, coal2Where, addr, where);
+                       wasProblem = true;
+               }       
+       }
+}
+
+
+
+void baseCheck()
+{
+       if ( wasProblem || (checkInCountCoal1 != 4) || (checkInCountCoal2 != 4) )
+               FAIL("weak-coal");
+       else
+               PASS("weak-coal");
+}
+
diff --git a/unit-tests/test-cases/weak-coalesce/base.h b/unit-tests/test-cases/weak-coalesce/base.h
new file mode 100644 (file)
index 0000000..482b832
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern void baseCheck();
+
+extern int coal1;
+extern int coal2;
+
+extern void baseVerifyCoal1(const char* where, int* addr);
+extern void baseVerifyCoal2(const char* where, int* addr);
diff --git a/unit-tests/test-cases/weak-coalesce/foo1.c b/unit-tests/test-cases/weak-coalesce/foo1.c
new file mode 100644 (file)
index 0000000..0707e0d
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+
+
+int __attribute__((weak)) coal1 = 1;
+int __attribute__((weak)) coal2 = 1;
+
+
+static __attribute__((constructor)) void myinit() 
+{
+       //fprintf(stderr, "myinit() in foo1.c\n");
+       baseVerifyCoal1("in foo1", &coal1);
+       baseVerifyCoal2("in foo1", &coal2);
+}
+
+
diff --git a/unit-tests/test-cases/weak-coalesce/foo2.c b/unit-tests/test-cases/weak-coalesce/foo2.c
new file mode 100644 (file)
index 0000000..a5770d4
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+
+int                                                    coal1 = 2;
+int __attribute__((weak))      coal2 = 2;
+
+static __attribute__((constructor)) void myinit() 
+{
+       //fprintf(stderr, "myinit() in foo1.c\n");
+       baseVerifyCoal1("in foo2", &coal1);
+       baseVerifyCoal2("in foo2", &coal2);
+}
diff --git a/unit-tests/test-cases/weak-coalesce/foo3.c b/unit-tests/test-cases/weak-coalesce/foo3.c
new file mode 100644 (file)
index 0000000..c92a444
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include "base.h"
+
+int __attribute__((weak))      coal1 = 3;
+int __attribute__((weak))      coal2 = 2;
+
+static __attribute__((constructor)) void myinit() 
+{
+       //fprintf(stderr, "myinit() in foo1.c\n");
+       baseVerifyCoal1("in foo3", &coal1);
+       baseVerifyCoal2("in foo3", &coal2);
+}
+
diff --git a/unit-tests/test-cases/weak-coalesce/main.c b/unit-tests/test-cases/weak-coalesce/main.c
new file mode 100644 (file)
index 0000000..6f4f9e1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "base.h"
+
+int main()
+{
+
+       //fprintf(stderr, "myinit() in foo1.c\n");
+       baseVerifyCoal1("in main", &coal1);
+       baseVerifyCoal2("in main", &coal2);
+
+       baseCheck();
+       return EXIT_SUCCESS;
+}
+
+
diff --git a/unit-tests/test-cases/weak-library/Makefile b/unit-tests/test-cases/weak-library/Makefile
new file mode 100644 (file)
index 0000000..b4eb71c
--- /dev/null
@@ -0,0 +1,39 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       cd absent/  && ../${TESTROOT}/bin/exit-zero-pass.pl "pass message" "fail message" ./main
+       cd present/ && ../${TESTROOT}/bin/exit-zero-pass.pl "pass message" "fail message" ./main
+
+all: foo.c main.c
+       ${CC} -dynamiclib -prebind -seg1addr 400000 -o libfoo.dylib foo.c
+       mkdir -p absent/
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -Wl,-weak-lfoo -o absent/main main.c
+       mkdir -p present/
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -Wl,-weak-lfoo -o present/main main.c
+       mv libfoo.dylib present/
+
+clean:
+       ${RM} ${RMFLAGS} *~ libfoo.dylib absent present
diff --git a/unit-tests/test-cases/weak-library/foo.c b/unit-tests/test-cases/weak-library/foo.c
new file mode 100644 (file)
index 0000000..55808e4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include "foo.h"
+
+int foo()
+{
+  return 10;
+}
diff --git a/unit-tests/test-cases/weak-library/foo.h b/unit-tests/test-cases/weak-library/foo.h
new file mode 100644 (file)
index 0000000..78d1afd
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+extern int foo();
diff --git a/unit-tests/test-cases/weak-library/main.c b/unit-tests/test-cases/weak-library/main.c
new file mode 100644 (file)
index 0000000..b16a8e4
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+
+int
+main(int argc, char **argv)
+{
+  return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/weak-override/Makefile b/unit-tests/test-cases/weak-override/Makefile
new file mode 100644 (file)
index 0000000..26f8617
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+run: all
+       ./main
+
+all: main
+
+
+main: main.c libfoo.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+libfoo.dylib: foo.c 
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo.dylib foo.c
+
+clean:
+       ${RM} ${RMFLAGS} *~ main  libfoo.dylib 
+
diff --git a/unit-tests/test-cases/weak-override/foo.c b/unit-tests/test-cases/weak-override/foo.c
new file mode 100644 (file)
index 0000000..dcce76e
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+
+
+
+int __attribute__((weak)) myfunc()
+{
+       return 0;
+}
+
+int __attribute__((weak)) foo()
+{
+       return myfunc();
+}
diff --git a/unit-tests/test-cases/weak-override/main.c b/unit-tests/test-cases/weak-override/main.c
new file mode 100644 (file)
index 0000000..d958a78
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+// foo is defined in libfoo.dylib
+// it calls myfunc() 
+extern int foo();
+
+int main()
+{
+       if ( foo() == 10 )
+               PASS("weak-override");
+       else
+               FAIL("weak-override");
+       return EXIT_SUCCESS;
+}
+
+
+// myfunc() also defined in libfoo.dylib but weak there, so this should override
+int myfunc()
+{
+       return 10;
+}
+
diff --git a/unit-tests/test-cases/weak-symbol-flat/Makefile b/unit-tests/test-cases/weak-symbol-flat/Makefile
new file mode 100644 (file)
index 0000000..f49610d
--- /dev/null
@@ -0,0 +1,44 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       (export DYLD_IMAGE_SUFFIX=_missing  && ./main) || echo "FAIL \"weak-symbol-flat\""
+        ./main 1
+
+all : main libfoo.dylib libfoo_missing.dylib
+
+libfoo.dylib : foo.c 
+       ${CC} -dynamiclib -DSYMBOL_PRESENT -o libfoo.dylib foo.c
+       
+libfoo_missing.dylib : foo.c 
+       ${CC} -dynamiclib -o libfoo_missing.dylib foo.c -install_name libfoo.dylib
+
+main: main.c libfoo.dylib
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -I${TESTROOT}/include -L. -lfoo -o main  main.c -flat_namespace
+
+clean:
+       ${RM} ${RMFLAGS} *~ libfoo.dylib libfoo_missing.dylib main
+       
+       
diff --git a/unit-tests/test-cases/weak-symbol-flat/foo.c b/unit-tests/test-cases/weak-symbol-flat/foo.c
new file mode 100644 (file)
index 0000000..b4b8cea
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+#ifdef SYMBOL_PRESENT
+int foo()
+{
+       return 10;
+}
+
+#endif
+
diff --git a/unit-tests/test-cases/weak-symbol-flat/foo.h b/unit-tests/test-cases/weak-symbol-flat/foo.h
new file mode 100644 (file)
index 0000000..7f4d4ab
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <AvailabilityMacros.h>
+
+int foo() WEAK_IMPORT_ATTRIBUTE;
diff --git a/unit-tests/test-cases/weak-symbol-flat/main.c b/unit-tests/test-cases/weak-symbol-flat/main.c
new file mode 100644 (file)
index 0000000..146fe81
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h> // EXIT_SUCCESS
+
+#include "test.h"
+#include "foo.h"
+
+int main(int argc, const char *argv[])
+{
+       if (argc > 1) {
+               // when arg is passed, libfoo is used and foo should be defined
+               if ( &foo == NULL ) 
+                       FAIL("weak-symbol-flat foo not found");
+               else if ( foo() != 10 )
+                       FAIL("weak-symbol-flat foo not found");
+               else
+                       PASS("weak-symbol-flat when symbol found");
+       }
+       else {
+               // when no args are passed, libfoo_missing is used and foo should be undefined
+               if ( &foo != NULL ) 
+                       FAIL("weak-symbol-flat foo found");
+               else
+                       PASS("weak-symbol-flat when symbol missing");
+       }
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/weak-symbol/Makefile b/unit-tests/test-cases/weak-symbol/Makefile
new file mode 100644 (file)
index 0000000..e24ee52
--- /dev/null
@@ -0,0 +1,35 @@
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+       export DYLD_IMAGE_SUFFIX=_missing && ${TESTROOT}/bin/exit-zero-pass.pl "weak-symbol" "weak-symbol" ./main
+
+all: foo.c main.c
+       ${CC} foo.c -dynamiclib -o libfoo.dylib  -DSYMBOL_PRESENT 
+       ${CC} foo.c -dynamiclib -o libfoo_missing.dylib -install_name libfoo.dylib
+       export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -I${TESTROOT}/include -L. -lfoo main.c -o main  
+
+clean:
+       ${RM} ${RMFLAGS} *~ libfoo.dylib libfoo_missing.dylib main
diff --git a/unit-tests/test-cases/weak-symbol/foo.c b/unit-tests/test-cases/weak-symbol/foo.c
new file mode 100644 (file)
index 0000000..c7a3409
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#if SYMBOL_PRESENT
+int foo()
+{
+  return 10;
+}
+#endif
diff --git a/unit-tests/test-cases/weak-symbol/foo.h b/unit-tests/test-cases/weak-symbol/foo.h
new file mode 100644 (file)
index 0000000..7f4d4ab
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <AvailabilityMacros.h>
+
+int foo() WEAK_IMPORT_ATTRIBUTE;
diff --git a/unit-tests/test-cases/weak-symbol/main.c b/unit-tests/test-cases/weak-symbol/main.c
new file mode 100644 (file)
index 0000000..e5c8905
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005 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@
+ */
+#include <stdio.h>
+#include <stdlib.h> // EXIT_SUCCESS
+
+#include "test.h"
+#include "foo.h"
+
+int main(int argc, const char* argv[])
+{ 
+       if ( &foo == NULL )
+       {
+               PASS("weak-symbol not available");
+       }
+       return 0;
+}