]> git.saurik.com Git - apple/dyld.git/commitdiff
dyld-210.2.3.tar.gz mac-os-x-108 mac-os-x-1081 mac-os-x-1082 mac-os-x-1083 mac-os-x-1084 mac-os-x-1085 v210.2.3
authorApple <opensource@apple.com>
Fri, 27 Jul 2012 18:00:50 +0000 (18:00 +0000)
committerApple <opensource@apple.com>
Fri, 27 Jul 2012 18:00:50 +0000 (18:00 +0000)
124 files changed:
doc/ReleaseNotes.txt [new file with mode: 0644]
doc/man/man3/dlopen.3
dyld.xcodeproj/project.pbxproj
include/mach-o/dyld_gdb.h
include/mach-o/dyld_priv.h
include/objc-shared-cache.h [new file with mode: 0644]
launch-cache/Architectures.hpp
launch-cache/MachOBinder.hpp
launch-cache/MachOFileAbstraction.hpp
launch-cache/MachOLayout.hpp
launch-cache/MachORebaser.hpp
launch-cache/ObjCLegacyAbstraction.hpp
launch-cache/ObjCModernAbstraction.hpp
launch-cache/dsc_extractor.cpp
launch-cache/dsc_iterator.cpp
launch-cache/dsc_slider.cpp [deleted file]
launch-cache/dsc_slider.h [deleted file]
launch-cache/dyld_cache_format.h
launch-cache/dyld_shared_cache_util.cpp
launch-cache/update_dyld_shared_cache.cpp
src/ImageLoader.cpp
src/ImageLoader.h
src/ImageLoaderMachO.cpp
src/ImageLoaderMachO.h
src/ImageLoaderMachOClassic.cpp
src/ImageLoaderMachOCompressed.cpp
src/dyld.cpp
src/dyld.h
src/dyldAPIs.cpp
src/dyldAPIsInLibSystem.cpp
src/dyldExceptions.c
src/dyldInitialization.cpp
src/dyldLibSystemGlue.c
src/dyldLibSystemInterface.h
src/dyldStartup.s
src/dyld_debug.c
src/glue.c
src/start_glue.s [new file with mode: 0644]
src/stub_binding_helper.s
unit-tests/build-iPhoneOS-unit-tests
unit-tests/include/common.makefile
unit-tests/run-all-unit-tests
unit-tests/test-cases/DYLD_LIBRARY_PATH-dyld_env/main.c
unit-tests/test-cases/DYLD_VERSIONED_FRAMEWORK_PATH-basic/Makefile
unit-tests/test-cases/DYLD_VERSIONED_FRAMEWORK_PATH-basic/main.c
unit-tests/test-cases/DYLD_VERSIONED_LIBRARY_PATH-basic/Makefile
unit-tests/test-cases/DYLD_VERSIONED_LIBRARY_PATH-basic/main.c
unit-tests/test-cases/DYLD_VERSIONED_LIBRARY_PATH-dyld_env-restrict/main.c
unit-tests/test-cases/DYLD_VERSIONED_LIBRARY_PATH-dyld_env/main.c
unit-tests/test-cases/addend/main.c
unit-tests/test-cases/bundle-memory-load-fat/Makefile
unit-tests/test-cases/bundle-unload-keep-mapped/bundle.c
unit-tests/test-cases/crt-apple/Makefile
unit-tests/test-cases/crt-apple/main.c
unit-tests/test-cases/crt-custom/Makefile
unit-tests/test-cases/crt-custom/mystart.s
unit-tests/test-cases/dlopen_preflight-cycle/Makefile [new file with mode: 0644]
unit-tests/test-cases/dlopen_preflight-cycle/bar.c [new file with mode: 0644]
unit-tests/test-cases/dlopen_preflight-cycle/baz.c [new file with mode: 0644]
unit-tests/test-cases/dlopen_preflight-cycle/foo.c [new file with mode: 0644]
unit-tests/test-cases/dlopen_preflight-cycle/main.c [new file with mode: 0644]
unit-tests/test-cases/dyld-slide/Makefile [deleted file]
unit-tests/test-cases/dyld-slide/main.c [deleted file]
unit-tests/test-cases/fallback-non-unique-leaf-names/main.c
unit-tests/test-cases/image-state-deny-all_image_infos/Makefile [new file with mode: 0644]
unit-tests/test-cases/image-state-deny-all_image_infos/bar.c [new file with mode: 0644]
unit-tests/test-cases/image-state-deny-all_image_infos/main.c [new file with mode: 0644]
unit-tests/test-cases/image-suffix/main.c
unit-tests/test-cases/initializer-bounds-check/Makefile
unit-tests/test-cases/initializer-bounds-check/main.c
unit-tests/test-cases/insert-libraries-with-suid/Makefile
unit-tests/test-cases/interpose-shared-cache/main.c
unit-tests/test-cases/interpose-shared-cache/mymalloc.c
unit-tests/test-cases/loader_path-symlink/Makefile [new file with mode: 0644]
unit-tests/test-cases/loader_path-symlink/bar.c [new file with mode: 0644]
unit-tests/test-cases/loader_path-symlink/foo.c [new file with mode: 0644]
unit-tests/test-cases/loader_path-symlink/main.c [new file with mode: 0644]
unit-tests/test-cases/pie-text-reloc/Makefile
unit-tests/test-cases/re-export-symbol-dylib/Makefile [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/bar.c [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/baz.c [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/baz.exp [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/foo.c [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/foo.exp [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/frob.c [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol-dylib/main.c [new file with mode: 0644]
unit-tests/test-cases/re-export-symbol/Makefile
unit-tests/test-cases/read-only-stubs/main.c
unit-tests/test-cases/restrict-environ/Makefile
unit-tests/test-cases/rpath-dlopen-rm-executable/main.c
unit-tests/test-cases/rpath-introspection/Makefile [new file with mode: 0644]
unit-tests/test-cases/rpath-introspection/foo.c [new file with mode: 0644]
unit-tests/test-cases/rpath-introspection/main.c [new file with mode: 0644]
unit-tests/test-cases/rpath-loader_path-dlopen/main.c
unit-tests/test-cases/suid-environ/Makefile
unit-tests/test-cases/symbol-resolver-basic/Makefile
unit-tests/test-cases/symbol-resolver-interposed/Makefile [new file with mode: 0644]
unit-tests/test-cases/symbol-resolver-interposed/foo.c [new file with mode: 0644]
unit-tests/test-cases/symbol-resolver-interposed/foo.h [new file with mode: 0644]
unit-tests/test-cases/symbol-resolver-interposed/main.c [new file with mode: 0644]
unit-tests/test-cases/symbol-resolver-interposed/myfoo.c [new file with mode: 0644]
unit-tests/test-cases/symbol-resolver-pointer/Makefile
unit-tests/test-cases/terminator-bounds-check/Makefile [new file with mode: 0644]
unit-tests/test-cases/terminator-bounds-check/main.c [new file with mode: 0644]
unit-tests/test-cases/text-relocs-perms/foo.c
unit-tests/test-cases/text-relocs-perms/main.c
unit-tests/test-cases/text-relocs/Makefile
unit-tests/test-cases/text-relocs/space.s
unit-tests/test-cases/tlv-initializer/Makefile
unit-tests/test-cases/tlv-initializer/get.s
unit-tests/test-cases/tlv-initializer/main.c
unit-tests/test-cases/tlv-terminators/Makefile
unit-tests/test-cases/upward-dylib-init-order/Makefile [new file with mode: 0644]
unit-tests/test-cases/upward-dylib-init-order/b.c [new file with mode: 0644]
unit-tests/test-cases/upward-dylib-init-order/c.c [new file with mode: 0644]
unit-tests/test-cases/upward-dylib-init-order/common.c [new file with mode: 0644]
unit-tests/test-cases/upward-dylib-init-order/common.h [new file with mode: 0644]
unit-tests/test-cases/upward-dylib-init-order/main.c [new file with mode: 0644]
unit-tests/test-cases/upward-dylib-init-order/u.c [new file with mode: 0644]
unit-tests/test-cases/upward-dylib/Makefile
unit-tests/test-cases/upward-dylib/down.c
unit-tests/test-cases/upward-dylib/down.h
unit-tests/test-cases/upward-dylib/main.c
unit-tests/test-cases/upward-dylib/main2.c [new file with mode: 0644]

diff --git a/doc/ReleaseNotes.txt b/doc/ReleaseNotes.txt
new file mode 100644 (file)
index 0000000..33ce9ad
--- /dev/null
@@ -0,0 +1,1769 @@
+
+dyld-208
+<rdar://problem/10879179> Correct @path to still work with symlinks
+
+dyld-207
+<rdar://problem/10825175> dyld should give a better error message if you try to use a newer binary on older OS
+<rdar://problem/10753356> backtraces of LC_MAIN binaries end in tlv_get_addr+136, instead libdyld should export "_start" symbol
+<rdar://problem/10733082> Fix up @rpath based paths during introspection
+<rdar://problem/10657737> Interposition tuples are not respected when binding with resolvers
+
+dyld-206
+<rdar://problem/10442813> Give some warning that DYLD_ env vars are disabled
+
+dyld-205
+<rdar://problem/10583252> Add dyld to uuidArray to enable symbolication of stackshots
+
+dyld-204.1
+<rdar://problem/10643239> fix initializer ordering of upwardly linked dylibs
+
+dyld-204
+<rdar://problem/10613880> dyld misreads very large addends
+<rdar://problem/10568559> Perform method list sort even if __DATA,__objc_opt_rw is absent
+<rdar://problem/10568179> Remove category attaching from dyld shared cache
+<rdar://problem/10582497> Shared cache method list sorting breaks protocol extended type encodings
+
+dyld-203.1
+<rdar://problem/10491874> initializer not run in only upwardly linked dylib
+
+dyld-203
+<rdar://problem/10419267> update_dyld_shared_cache does not build with libc++
+<rdar://problem/10435247> dyld does not build with libc++
+<rdar://problem/10409027> Add functions to get min OS and sdk versions program was linked with
+<rdar://problem/10399676> DYLD_FRAMEWORK_PATH not mentioned in dlopen() man page
+<rdar://problem/10371927> dsc_extractor not updating LC_FUNCTION_STARTS
+
+dyld-202
+<rdar://problem/8818423> Get rid of crt1.o and jump straight into main() from dyld
+<rdar://problem/10332417> image denied loading by gc_enforcer is left in dyld_all_images_info array
+
+dyld-201
+<rdar://problem/8867781> Use spin lock to guard sAllImageInfos
+
+dyld-200.3
+<rdar://problem/9855733> genCaches fails: "header size miscalculation 0x00006000"
+
+dyld-200.2
+<rdar://problem/9784634> dsc_iterator.cpp needs cases for v7 variants
+
+dyld-200
+<rdar://problem/8942979> update_dyld_shared_cache should accept an 'overlay' along with a 'root' directory option
+Remove PowerPC support
+
+--------------
+dyld-199.5 (iOS 5)
+<rdar://problem/9955829> Update initial image list size
+
+dyld-199.4
+<rdar://problem/9855733> genCaches fails: header size miscalculation
+
+dyld-199.3 
+<rdar://problem/7338034> Repair ivar offsets in dyld shared cache
+
+dyld-199.2
+<rdar://problem/8981046> improve Xcode upload of iOS dylibs
+
+dyld-199.1
+<rdar://problem/9510382> correctly adjust ARM movw when in dyld shared cache
+
+dyld-199
+<rdar://problem/9439764> update_dyld_shared_cache requires weak-linked frameworks to be present at shared cache generation time
+<rdar://problem/9447838> Remove armv7 variants from dyld
+
+dyld-198.1
+<rdar://problem/8312145> back out previous change DYLD_XXX restrict check
+
+dyld-198
+<rdar://problem/9035759> corrupt load commands can pass sniff test if 32-bit wraps around
+<rdar://problem/8312145> dyld should restrict DYLD_XXX debugging facilities
+<rdar://problem/7942521> dyld should not allow loading of dylibs without valid signatures
+enable DYLD_PRINT_REBASINGS
+
+dyld-197
+<rdar://problem/7945496> dyld should range check the fixup location of all bindings
+<rdar://problem/8963406> range check initializers and terminators to be within image
+
+dyld-196.2
+<rdar://problem/8987681> dyld should support new armv7 variants
+
+dyld-196.1
+<rdar://problem/9107912> support re-exported symbols from re-exported libraries
+
+dyld-196
+<rdar://problem/9078764> movw/movt don't work in dyld shared cache
+
+
+---------------------
+dyld-195.3 (Mac OS X 10.7.0)
+<rdar://problem/9279770> update_dyld_shared_cache missed libstdc++?
+<rdar://problem/9361288> i386 dyld shared cache overflows after adding libclh.dylib
+
+dyld-195.2
+<rdar://problem/9161945> spurious warning about embedded framework not being put in dyld shared cache
+
+dyld-195
+<rdar://problem/8360915> C++ 0x thread_local destructor support
+<rdar://problem/8960832> update_dyld_shared_cache -verify finds differences
+<rdar://problem/8971061> more verbose messages when vm_protect() fails 
+
+dyld-194.1
+Fix uses of libc++abi-static.a
+
+dyld-194
+<rdar://problem/8919005> make interposing available to open source
+<rdar://problem/8874282> __thread implementation doesn't preserve enough registers (ABI issue)
+<rdar://problem/8873628> clang built update_dyld_shared_cache fails at runtime
+
+dyld-193
+<rdar://problem/8735709> dyld should honor CS_RESTRICT in _main like hasRestrictedSegment
+<rdar://problem/8164591> update_dyld_shared_cache -overlay optimizations
+
+dyld-192.1
+<rdar://problem/8812589> dyld has NULL paths in image info array
+
+dyld-192
+<rdar://problem/8750829> dyld's map+slide should be an all or nothing operation 
+
+dyld-191.3
+<rdar://problem/8890875> overriding shared cache dylibs with resolvers fails
+dyld-191.2
+<rdar://problem/8844174> dyld_stub_binder called repeatedly for $VARIANT$ functions
+<rdar://problem/8845480> update_dyld_shared_cache crash when fat dylib truncated
+
+dyld-191.1
+<rdar://problem/8770940> update_dyld_shared_cache is failing
+
+dyld-191
+<rdar://problem/8736495> ASLR/PIE: dyld's "random padding" algorithm is deterministic
+<rdar://problem/8663923> race condition with flat-namespace lazy binding
+<rdar://problem/8755380> libdyld fails to build with clang-127
+
+dyld-190.1
+remove libdyld.a target
+
+dyld-190
+<rdar://problem/8706192> _NSGetExecutablePath documentation is ambiguous about bufsize
+<rdar://problem/8686676> 11A315: LC_DYLD_ENVIRONMENT does not expand @executable_path
+<rdar://problem/8718137> dyld should avoid arc4random for dylib randomization
+<rdar://problem/8691207> tune trie traversal code for 10.7 compiler
+<rdar://problem/8576479> breaking libSystem into dylibs slows down dyld binding, shared cache should compensate
+<rdar://problem/8686427> update_dyld_shared_cache should not be built no-pie
+
+dyld-189
+<rdar://problem/8274426> dyld(1) man page feedback
+<rdar://problem/8564762> LC_DYLD_ENVIRONMENT should still be honored with __RESTRICT,__restrict section present
+<rdar://problem/8630416> 11A307: DYLD_SHARED_REGION=private crashes
+<rdar://problem/8611968> don't slide shared cache if ASLR disabled (main executable didn't slide)
+
+dyld-188
+<rdar://problem/4472406> Dynamic linking memory usage seems unusually high for trivial programs
+
+dyld-187
+<rdar://problem/8597637> madvise MADV_FREE calls for LINKEDIT are failing in dyld during launch in iOS
+<rdar://problem/8602453> dyld allImageInfos messed up with duplicate IOKit
+
+dyld-186
+<rdar://problem/8109857> dyld: Pick up changes from libsystem_kernel reorganisation in dyld's build.
+<rdar://problem/5847052> Shared Region Base Should Slide at Boot Time 
+<rdar://problem/6650578> Multiple /dev/urandom accesses on every process exec
+
+dyld-185
+<rdar://problem/8345025> text relocs don't work if only S_ATTR_EXT_RELOC is used
+<rdar://problem/8400815> DYLD_FORCE_FLAT_NAMESPACE=YES causes process to spin in DYLD-STUB$$bzero
+
+dyld-184
+<rdar://problem/8554137> Add cache slide value to dyld_all_image_infos
+
+dyld-183.1
+<rdar://problem/8521882> dyld proper does not need dyld_stub_binder.o
+
+dyld-183
+<rdar://problem/8274192> dyld needs to call new kernel interface to register metadata
+<rdar://problem/8448281> ASLR side build causes 15-30% regression in most launch times
+<rdar://problem/8440902> Support version-checked framework/library override paths
+<rdar://problem/8440934> Support LC_DYLD_ENVIRONMENT load command
+<rdar://problem/8454987> function starts info should be copied into dyld shared cache
+
+dyld-182
+<rdar://problem/8432001> Merge Jasper dyld changes to trunk
+
+dyld-181.1
+<rdar://problem/8455429> 11A270: FNPLicensingService crashes
+
+dyld-181
+<rdar://problem/8403002> 11A238a: AutoDesk AutoCAD beta 4 crashes on launch (dyld)
+<rdar://problem/8345799> update_dyld_shared_cache-173 project fails to build with LLVM compiler 2.0.
+
+dyld-180
+<rdar://problem/8352892> 8F63: dyld-179.4 fails on missing /usr/local/lib/system/libc.a
+<rdar://problem/8344449> 11A238a: AutoDesk AutoCAD beta 4 crashes on launch
+<rdar://problem/8313034> 11A244: overlapping files in libdyld & update_dyld_shared_cache
+
+
+dyld-179.7 (iOS 4.2)
+<rdar://problem/8543820> range check initializers
+
+dyld-179.6 
+<rdar://problem/8515776> dyld_shared_cache_extract_dylibs shouldn't return '-1' when arch already exists
+
+dyld-179.5 
+<rdar://problem/8425790> Need a version of dyld_shared_cache_extract_dylbs that lipo's results
+<rdar://problem/8365622> Need a version of dyld_shared_cache_extract_dylbs that reports progress
+<rdar://problem/8320866> back out work around for 8151909
+
+dyld-179.4
+<rdar://problem/8305479> images in shared cache are bound against different IOKit than found at runtime
+
+dyld-179.3.1
+<rdar://problem/8327834> 11A245: Photoshop CS4 fails in SmokeTest because of crash in FNPLicensingService (dyld)
+
+dyld-179.3
+<rdar://problem/8305049> 11A238a: All Adobe CS4 applications crash on launch
+
+dyld-179.2
+<rdar://problem/8290793> 11A239: leaks throws an exception, doesn't work
+
+dyld-179.1
+<rdar://problem/8284123> libdsc.a in Jasper SDK needs to be arm version (is x86 version)
+
+dyld-179
+<rdar://problem/8284944> update_dyld_shared_cache does not work with individual symbol re-exports
+
+dyld-178
+<rdar://problem/8284044> Support __thread variables exported from dylibs
+<rdar://problem/7356532> update dyld_all_image_infos more often, for better crash logs
+
+dyld-177
+<rdar://problem/8214567> We need an extractor able to pull the shared symbols cache apart
+<rdar://problem/8263666> Don't put slide info in dyld shared cache in Jasper
+<rdar://problem/8268602> dyld does not prevent loading of unsigned dylib
+
+dyld-176
+<rdar://problem/8253549> split seg info wrong for x86_64 stub helpers
+
+dyld-175
+<rdar://problem/8235734> ObjC optimized shared cache does not slide
+
+dyld-174
+<rdar://problem/8198287> Need to merge Apex ObjC method list optimizations in dyld shared cache to TOT dyld
+<rdar://problem/8115131> implement ASLR for dyld shared cache for iOS
+
+dyld-173
+<rdar://problem/8144421> fix permissions on rebased binary not slid
+
+dyld-172.2
+<rdar://problem/8191063> dyld should not include SystemIntegrity headers on embedded platform
+Have DYLD_PRINT_BINDINGS print out when resolver functions are called
+
+dyld-172.1
+<rdar://problem/8166086> fix visibility of dyld_func_lookup depending if libdyld is .a or .dylib
+
+dyld-172
+Add hack to work around 8151909
+Alter project to build for both kinds of libSystems
+
+dyld-171
+Add support for individual symbol re-exports
+Add support for building for iOS
+
+dyld-170
+<rdar://problem/7508424> ER: more metadata for dyld errors
+
+dyld-169
+<rdar://problem/7995213> update_dyld_shared_cache needs to support resolver functions
+Implement some cxa stuff to work with next c++abi.a
+
+dyld-168
+<rdar://problem/7901042> dyld should move shared cache file into /var/run instead of open-unlinking
+<rdar://problem/7940222> private shared cache calls mmap twice for each range
+<rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount
+<rdar://problem/7935000> 11A168: update_dyld_shared_cache problems during install
+<rdar://problem/7918210> use of C++ thread local initializer causes infinite recursion
+<rdar://problem/7932725> (from iPhoneOS) dyld should stub out mach_error_string for 8KB RAM savings per process
+<rdar://problem/7937695> (from iPhoneOS) verify that replacement is in this image
+
+dyld-167.2
+<rdar://problem/7956031> dyld: Use libsystem_mach.a from /usr/local/lib/dyld to build dyld
+
+dyld-167.1
+<rdar://problem/7901042> dyld should move shared cache file into /tmp instead of open-unlinking
+
+dyld-167
+<rdar://problem/7859049> dyld support for function specialization
+<rdar://problem/7740779> dyld should directly call __cxa_finalize(), part 2
+<rdar://problem/7796738> dyld support for thread local variables
+
+
+dyld-166
+<rdar://problem/7739489> ER: facility to detect which images were loaded at runtime
+<rdar://problem/7818451> update_dyld_shared_cache -verify fails
+
+
+dyld-165
+<rdar://problem/7770139> update_dyld_shared_cache should suppress warnings for embedded frameworks
+<rdar://problem/7744084> Sort method lists in dyld shared cache
+
+
+dyld-164
+<rdar://problem/7733433> Move libdyldapis over to a dylib target for Libsystem
+<rdar://problem/7675254> pruneEnvironmentVariables does not update gLinkContext.apple
+
+
+dyld-163
+<rdar://problem/7740033> Warning message is misleading
+<rdar://problem/7740658> update_dyld_shared_cache should not run past end of splitseginfo if zero terminator is missing
+<rdar://problem/6666832> dyld should directly call __cxa_finalize(), part 1
+
+
+dyld-162
+<rdar://problem/7662176> crash in update_dyld_shared_cache when checking if current cache is out of date
+<rdar://problem/7444994> ER: Support upward dylib dependencies
+
+
+dyld-161
+<rdar://problem/7628929> __builtin_return_address broke for PPC
+<rdar://problem/7658265> SWBDC error: 'ld: duplicate symbol' while building 'dyld-160~48' in '11A108a-llvmgcc-2324.3'
+
+
+dyld-160
+<rdar://problem/7234280> Environment variable to cause dyld to dump rpaths used during loading
+<rdar://problem/7595563> update_dyld_shared_cache failed: internal error, new trie allocated to far from fLinkeditBase
+<rdar://problem/7589167> dyld still slides executables when PIE is disabled by the kernel
+
+
+dyld-159
+<rdar://problem/7343139> update_dyld_shared_cache fails to find roots when targetting NFS
+<rdar://problem/7484408> dyld does not call initializers from all S_MOD_INIT_FUNC_POINTERS sections
+<rdar://problem/7544082> move _dyld_func_lookup prototype to dyld_priv.h
+
+
+dyld-158
+<rdar://problem/7486405> dyld attempts to load libraries via rpath when already loaded
+<rdar://problem/5274722> dyld shared cache can be more random
+
+
+dyld-157
+<rdar://problem/7481480> switch to use libc++abi-static.a instead of libstdc++-static.a
+
+
+dyld-156
+<rdar://problem/7408768> remove DYLD_NO_PIE from man page
+<rdar://problem/7445102> support multiple dylibs with non-intersected weak symbols in shared cache
+<rdar://problem/7466900> dyld sends bogus library unload notice to CoreSymbolication during dlopen_preflight()
+<rdar://problem/7455017> spelling: "was build against" -> "was built against"
+
+
+dyld-155
+<rdar://problem/7451030> sjlj based exception support needs to be conditionalized for arm - not iPhoneOS
+
+
+dyld-154
+<rdar://problem/7272661> Need to enable CoreSymbolication load/unload notices on iPhoneOS
+
+
+dyld-153
+<rdar://problem/7327864> add field to dyld_all_image_infos pointing to dyld_all_image_infos
+
+
+dyld-152
+<rdar://problem/7302432> Minimize system calls and mach messages during dyld startup
+<rdar://problem/7302383> Why is checkSharedRegionDisable() !__LP64__
+
+
+dyld-151
+<rdar://problem/7223037> dyld support for sliding PIE binaries in the kernel
+<rdar://problem/7165731> libdyld does not install multiple headers at installhdrs time
+<rdar://problem/6937560> dlopen() crash when executable contains LC_RPATH and executable file is deleted while running
+<rdar://problem/6916014> leak in dyld during dlopen when using DYLD_ variables
+
+
+----------------------------------
+
+dyld-150  ( iPhoneOS 3.1 )
+<rdar://problem/7043575> flat_namespace linkage error in update_dyld_shared_cache should be a warning not an error
+<rdar://problem/7084861> Have dyld save load addr + UUID for executable images
+<rdar://problem/7101832> Libsystem fails to link with latest gcc: dyld missing _dyld_func_lookup
+
+
+dyld-149
+<rdar://problem/7017050> dlopen() not working with non-canonical paths
+<rdar://problem/7033445> update_dyld_shared_cache fails creating shared cache
+
+
+dyld-148
+<rdar://problem/7022281> shared cache file offsets are inconsistent
+
+
+dyld-147
+<rdar://problem/6995143> move install location for update_dyld_shared_cache and man page to local
+<rdar://problem/7014995> imageFileModDate in dyld_all_image_infos is sometimes bogus for the first image therein
+<rdar://problem/7014397> dyld_shared_cache_util should optionally print VM load addresses for each dylib
+<rdar://problem/7014783> uuid_t not defined in dyld_priv.h
+
+
+dyld-146
+<rdar://problem/7008875> Save load information (load addr + UUID) to dyld_all_image_infos for images from outside the shared cache
+<rdar://problem/7007923> update_dyld_shared_cache should improve warning above deployment target
+
+
+dyld-145
+<rdar://problem/7000405> optimize stubs in dyld shared cache to be no-PIC
+<rdar://problem/6995143> dyld_shared_cache_util built by dyld target should go in platform directory
+<rdar://problem/7001159> dyld_shared_cache_util should list LC_REEXPORT_DYLIB libraries as dependents
+
+
+dyld-144
+<rdar://problem/6995143> dyld_shared_cache_util built by dyld target should go in platform directory
+<rdar://problem/6775261> API: Detect shared cache overrides
+
+
+dyld-143
+<rdar://problem/6956867> ER: Tool to list the contents of a dyld shared cache image
+<rdar://problem/6959334> ARM support for dsc_iterator
+
+
+dyld-142
+<rdar://problem/6965455> text relocs fail in large segments
+<rdar://problem/6945944> Variable whose data is overwritten needs to be marked `volatile'
+<rdar://problem/6921370> dyld option to print time for each initializer, Apple's or the app's
+
+
+dyld-141
+<rdar://problem/6927281> update_dyld_shared_cache assumes -root path contains no symlinks
+sync with SnowLeopard dyld-132.13
+
+
+dyld-140
+<rdar://problem/6153040> load code signature from file, and before mapping the file
+
+
+dyld-139.1
+<rdar://problem/6868811> Northstar7C62: dyld-139 fails to build
+
+
+dyld-139
+<rdar://problem/6780449> dyld on iPhoneOS uses libgcc_eh.a which uses pthread_key_create which does not work
+<rdar://problem/6780192> dyld can leak when an internal exception in thrown
+<rdar://problem/6331300> support compressed LINKEDIT on iPhone
+sync with SnowLeopard dyld-132.11
+
+
+dyld-138.1
+<rdar://problem/6790993> New mechanism to instruct dyld whether to check for libs outside the shared cache
+
+
+dyld-138
+<rdar://problem/6814596> need to handle symlinks when dylib is in cache but file is intentionally missing
+<rdar://problem/6825135> dyld should avoid stat()ing libraries present in the shared cache unless magic override file is present
+
+
+dyld-137 
+<rdar://problem/6792383> dyld reports image not found if it is in the shared cache but no binary is present on disk
+sync with SnowLeopard dyld-132.10
+
+
+dyld-136
+<rdar://problem/6776343> dyld reports bogus fat offset when registering shared cache signature
+
+
+dyld-135
+<rdar://problem/6268421> iPhone: Need objc optimizations in iPhone OS shared cache
+
+
+dyld-134
+<rdar://problem/4759373> build armv6 dyld with Thumb
+sync with SnowLeopard
+
+
+
+dyld-133.1
+fix for all arm architectures
+
+
+dyld-133
+<rdar://problem/6268380> make dyld that uses shared cache on iPhone OS
+
+
+----------------------------------
+
+dyld-132.13 ( Mac OS X 10.6 )
+<rdar://problem/6898370> classic images not unmapped when unloaded
+
+
+dyld-132.12 
+<rdar://problem/6882159> dyld's dtrace notification should be done after rebasing
+
+
+dyld-132.11 
+<rdar://problem/6803496> Remove dyld workaround for McAfee VirusScan
+<rdar://problem/6849505> Add gating mechanism to dyld support system order file generation process
+
+
+dyld-132.10
+<rdar://problem/6785160> dyld's abort_report_np() doesn't abort
+<rdar://problem/6794063> 10A331: CUPS crashes when calling sandbox_init
+
+
+dyld-132.9 
+<rdar://problem/5910137> dlopen_preflight() on image in shared cache leaves it loaded but not objc initialized
+<rdar://problem/6739742> Exception Backtrace being obscured by _mh_execute_header
+<rdar://problem/6766057> Silverlight Preferences.app crashes
+
+
+dyld-132.8 
+<rdar://problem/6735870> dlopen() leaks send right obtained from mach_thread_self()
+<rdar://problem/6732715> dyld's calloc() allocates too few bytes
+<rdar://problem/6678640> dyld lazy binding is not thread safe
+
+
+dyld-132.7
+<rdar://problem/6651342> need a way other than setgid to have dyld launch a process securely, ignoring DYLD_ env vars etc
+<rdar://problem/6721803> Need mapping of files to their offsets into the dyld_shared_cache files on disk
+
+
+dyld-132.6
+<rdar://problem/6618466> update_dyld_shared_cache -overlay should check root dyld caches
+<rdar://problem/6619554> NSCreateObjectFileImageFromMemory() call vm_deallocate even if application used malloc()
+
+
+dyld-132.5
+<rdar://problem/6655235> dyld is missing some binding optimizations
+<rdar://problem/6647316> symbol lookups in the new trie structure should be faster
+<rdar://problem/6570879> weak binding done too early with inserted libraries
+
+
+dyld-132.4
+<rdar://problem/6629428> improve statistics output
+<rdar://problem/6628413> better error message if LC_RPATH is used in dylib destined for shared cache
+<rdar://problem/6622898> dladdr() broke when image has debug symbols
+<rdar://problem/6555720> 10A264: Google Earth 5.0 crashes on quit 
+<rdar://problem/6591933> man page should better explain update_dyld_shared_cache -root option
+
+
+dyld-132.3
+<rdar://problem/6527653> remove setjmp/longjmp from _simple_printf in dyld
+<rdar://problem/6580333> Typo in dyld(3) man page
+<rdar://problem/6510301> race condition in pre-10.6 style lazy pointer binding
+<rdar://problem/6573344> make cheaper dladdr() that just returns image path
+<rdar://problem/6563887> 10A266 - Adobe InDesign CS4 crashes on launch
+<rdar://problem/6570113> dyld is not setting imageFileModDate in dyld_image_info
+<rdar://problem/6493245> Logic Pro crashes after creating a new document on SnowLeopard
+
+
+dyld-132.2
+<rdar://problem/6293143> adopt new CoresSymbolication notification mechanism
+<rdar://problem/6536810> Alter libdyld.a to not need libsystem to link with dylib1.o
+<rdar://problem/6530593> 10A256a: update_dyld_shared_cache -verify crashes (probably due to lack of a shared cache)
+
+
+dyld-132.1
+<rdar://problem/6552051> update_dyld_shared_cache failed: no writable segment in Cocoa framework
+
+
+dyld-132
+<rdar://problem/6490500> CrashTracer: [USER] 1 crash in Neverwinter Nights 2 
+
+
+dyld-131
+<rdar://problem/6501078> libgmalloc broken on 10A10246 and 10A251 (libgmalloc not inserted early enough)
+
+
+dyld-130
+<rdar://problem/6497528> Rosetta circular dependency spew
+<rdar://problem/6347414> @rpath and @loader_path Should be Documented in man page
+Prune unneeded load commands from shared cache images
+
+
+dyld-129
+<rdar://problem/6479007> dyld-128 no longer builds for armv6
+<rdar://problem/6481443> 10A244: iTunes crashes trying to load MobileDevice.framework
+
+
+dyld-128
+<rdar://problem/6474295> ImageLoader objects can be made smaller
+<rdar://problem/6198151> dyld spin in SecurityAgent
+<rdar://problem/6285470> ImageLoaderMachO::makeImportSegmentWritable() doesn't do it
+
+
+dyld-127
+<rdar://problem/6464419> Add all_image_infos for CrashReporter
+some fixes for compressed LINKEDIT 
+
+
+dyld-126
+<rdar://problem/6459812> x86_64 export trie nodes may have large negative address
+<rdar://problem/6442327> update_dyld_shared_cache man page should be updated to reflect new SL behavior
+
+
+dyld-125
+<rdar://problem/6347414> @rpath and @loader_path should be documented in man page
+<rdar://problem/6421511> Add NOP after trap instruction in _dyld_fatal_error
+
+
+dyld-124
+<rdar://problem/6273311> update_dyld_shared_cache should not automatically run by default
+Add support for arm shared caches
+Add support for __program_vars section
+Add more -verify sanity checks
+
+
+dyld-123
+<rdar://problem/6117580> Add -verify option to update_dyld_shared_cache
+<rdar://problem/6408758> [dyld] Errors reported by the upcoming compiler flags verifier
+<rdar://problem/6408518> 10A224: update_dyld_shared_cache warns about a condition in B&I-built frameworks
+<rdar://problem/4697610> stop shadowing old data structures
+<rdar://problem/6409800> dyld implicit-libSystem breaks valgrind
+
+
+dyld-122
+<rdar://problem/6361143> Need a way to determine if a gdb call to dlopen() would block
+<rdar://problem/6328003> Drop Rosetta shared cache generation by default / at install
+<rdar://problem/6400750> "terminaton function" misspelled
+<rdar://problem/6399150> Make it easier to use shared caches from foreign systems
+<rdar://problem/6369189> SnowLeopard10A210: MATLAB 7.6 crashes on launch
+
+
+dyld-121.1
+<rdar://problem/6364434> CrashTracer: crash in iTunes at com.apple.QuickTimeComponents.component 
+
+
+dyld-121
+<rdar://problem/6373929> libdyld.a is missing dyld_stub_binder
+
+
+dyld-120
+<rdar://problem/6315338> 10A197 - After Effects 8.0.2 fails to launch after installation 
+
+
+dyld-119
+<rdar://problem/6364540> 10A212: update_dyld_shared_cache failed: string buffer exhausted
+<rdar://problem/6357561> Oracle client crashes
+
+
+dyld-118.1
+<rdar://problem/6350500> Cope with duplicate protocol references in shared cache construction
+
+
+dyld-118
+<rdar://problem/6336723> 10A197 vs 10A190: Applications warm launch time slowdown due to dyld
+
+
+dyld-117
+<rdar://problem/6318449> 10A198 - Final Cut Pro 6.0.4 crashes on launch [INTRODUCED BY dyld-115 IN 10A197]
+
+
+dyld-116
+<rdar://problem/6004942> Pandora Desktop (Adobe AIR Framework) crashes on launch [INTRODUCED BY dyld-101 IN 10A14]
+<rdar://problem/6250902> dyld should use libunwind
+<rdar://problem/5408556> Possible leak originating in speech at LoadEngine
+<rdar://problem/6315314> update_dyld_shared_cache manpage typos 'parition', 'assignes', 'choosen'
+
+
+dyld-115
+<rdar://problem/6061574> LINKEDIT content could be greatly compressed
+
+
+dyld-114
+<rdar://problem/6231688> update_dyld_shared_cache needs to provide progress that the Installer can display
+<rdar://problem/6231686> update_dyld_shared_cache needs to be able to look at an Installation sandbox
+<rdar://problem/6293143> dyld isn't calling csdlc_notify on library unload
+<rdar://problem/6277916> warning, could not bind Mail.app because realpath() failed on /AppleInternal/.../XILog.framework
+
+
+dyld-113
+<rdar://problem/6252320> NSAddressOfSymbol(NULL) should return NULL and not crash
+<rdar://problem/6255192> dlopen() should fail to load (non-pie) executables
+
+
+dyld-112
+<rdar://problem/6188100> _replacement misspelled as _replacement in dyld-interposing.h
+<rdar://problem/6176037> make _dyld_find_unwind_sections() faster
+
+
+dyld-111
+<rdar://problem/6161821> improve bad relocation error message
+<rdar://problem/6190458> Need load/unload notification sent to com.apple.vmudl service when requested
+<rdar://problem/6188100> _replacement misspelled as _replacement in dyld-interposing.h
+
+
+dyld-110
+<rdar://problem/5703616> check libSystem is correct in shared cache file before loading it
+<rdar://problem/5557882> function names returned by dladdr do not match reality
+<rdar://problem/5780431> update_dyld_shared_cache .map files should be written atomically
+<rdar://problem/6145451> dlopen(RTLD_NOLOAD) does not need to throw an internal exception
+<rdar://problem/4090265> Explanation for the RTLD_NEXT flag in dlsym(3) needs clarification
+<rdar://problem/5951327> DYLD_FALLBACK_LIBRARY_PATH should not apply to dlopen() of a partial path
+<rdar://problem/6182301> No shared cache present on first boot
+
+
+dyld-109
+<rdar://problem/5925940> Safe Boot should disable dyld shared cache
+<rdar://problem/5706594> CrashTracer: crash in preFetch() reading off end of LINKEDIT
+<rdar://problem/6109435> DYLD_NO_PIE env variable should be documented in dyld manpage
+<rdar://problem/6127437> put all dylibs in shared cache - not just ones used by more than one app
+<rdar://problem/6169686> Leaked fSegmentsArray and image segments during failed dlopen_preflight
+
+
+dyld-108.1
+<rdar://problem/6156702> armv7/armv5 specific settings needed for dyld
+<rdar://problem/6156653> dyld shouldn't set VALID_ARCHS
+
+
+dyld-108
+<rdar://problem/6120723> ER: dyld based Objective-C selector uniquing
+
+
+dyld-107
+<rdar://problem/5274720> update_dyld_shared_cache should require all source dylibs be owned by root
+<rdar://problem/6073702> Limit what might go in the dyld shared cache
+<rdar://problem/5869973> DYLD_ROOT_PATH should apply to LC_RPATH rpaths
+<rdar://problem/5505043> Grow initial dyld pool if needed
+<rdar://problem/5807857> there should be some way to temporarily turn off -pie
+<rdar://problem/6050482> If pie, ignore preferred load address
+<rdar://problem/6053800> Put all_image_infos in its own section to it is easy to find
+
+
+dyld-106
+allow update_dyld_shared_cache to be build 64-bit
+<rdar://problem/5280258> dyld error handling fails in low memory, _simple_salloc() result not checked
+<rdar://problem/4047718> dyld should provide executing program name in incompatible cpu-subtype error message
+
+
+dyld-105
+<rdar://problem/5957134> It should work to set DYLD_FALLBACK_LIBRARY_PATH to empty
+<rdar://problem/5366292> Remove the exceptions made in 4804594 for filemaker
+<rdar://problem/5922117> Remove Tiger-era hacks in dyld for old app compatibility
+<rdar://problem/5901958> Make RTLD_MAIN_ONLY public
+<rdar://problem/5819435> die more gracefully when load commands are malformed
+<rdar://problem/5953438> SWB: dyld build failure when built with -fstack-protector
+<rdar://problem/5950134> dyld man page mis-spelling
+<rdar://problem/5943045> update_dyld_shared_cache does not work when run manually
+
+
+dyld-104
+<rdar://problem/5901583> The optimization to reuse install names as fPath was lost
+<rdar://problem/5888343> Add JIT field to dyld_all_image_infos
+Add _dyld_find_unwind_sections()
+
+
+dyld-103
+<rdar://problem/5805956> NSLinkModule() can crash
+<rdar://problem/5620189> dyld: obsoleted deprecated APIs
+work around for <rdar://problem/5736393>
+add test cases for lazy dylib loading
+
+
+dyld-102
+<rdar://problem/5394977> Man page typo for update_dyld_shared_cache
+<rdar://problem/5490738> Add "malloc is initialized" to the dyld_all_image_infos struct
+<rdar://problem/4045952> better handling of open() errors
+<rdar://problem/5377739> remove <mach-o/dyld_debug.h>
+<rdar://problem/5629960> Use <mach/shared_region.h> instead of <mach/shared_memory_server.h>
+<rdar://problem/5775824> dyld and libdyld should not force building with gcc 4.0
+
+
+dyld-101
+<rdar://problem/5725845> make it easier to find dyld_all_image_infos
+<rdar://problem/5363402> Need _dyld_get_image_slide(const struct mach_header* mh)
+<rdar://problem/5708213> dyld: push code signatures for libs to kernel
+
+
+dyld-100
+<rdar://problem/4737476> dyld falls over when asked to map a split seg library not in the shared region
+<rdar://problem/5595695> dyld: interposing does not work when replacee is thumb
+<rdar://problem/5596017> dyld: all PIE programs crash on launch
+<rdar://problem/5575446> BigBear: not loading libraries at their preferred addresses
+<rdar://problem/5490089> dyld support for arm subtypes
+<rdar://problem/5539483> dyld's prefetching should be turned off for prebound images (and perhaps entirely?)
+<rdar://problem/5602284> dyld-95.3 doesn't build with gcc 4.2
+merge in arm support
+<rdar://problem/5504633> ADOBE: Premiere Pro crashes on quit
+
+----------------------------------
+
+dyld-96.2 (Mac OS X 10.5.2)
+<rdar://problem/5694507> 10.5.2 Regression: 9C18 MeetingMaker crash on launch
+
+dyld-96.1
+<rdar://problem/5537155> update_dyld_shared_cache can crash if dylibs modified out from under it
+<rdar://problem/5562562> crash when dyld interposes on system with partially invalid cache
+<rdar://problem/5563394> com.apple.dyld message spew
+<rdar://problem/5565230> CFSTRs cause crashes in Leopard
+<rdar://problem/5566103> if system shuts down during update_dyld_shared_cache, tmp file is never cleaned up
+<rdar://problem/5623353> dlopen() and dlopen_preflight() can leak on failure
+
+
+
+dyld-95.3 (Mac OS X 10.5)
+<rdar://problem/5503905> Increase initial dyld pool size for 64-bit programs
+
+
+dyld-95.2
+<rdar://problem/5495438> make ppc dyld cache a different file for rosetta
+
+
+dyld-95.1
+<rdar://problem/5388895> McAfee VirusScan fails to launch on Leopard9A513
+
+
+dyld-95
+<rdar://problem/5392427> 9A516 - Keep getting disk full errors
+
+
+dyld-94
+<rdar://problem/5366233> Leopard (9a499): dyld crash with recursive calls to dlclose()
+
+
+dyld-93
+<rdar://problem/4804594> FileMaker Server 8.0v4 helper tools broken by @executable_path security change
+<rdar://problem/5364239> Use msync(MS_SYNC) when building dyld cache
+
+
+dyld-92
+<rdar://problem/5322907> Skype Crashes during launch
+
+
+dyld-91.2
+<rdar://problem/5313172> dlopen() looks too far up stack, can cause crash
+
+
+dyld-91.1
+<rdar://problem/5288790> dyld warning about dtracehelper is too noisy?
+<rdar://problem/5311611> Lots of task_self_trap() system calls in ImageLoader::recursiveInitialization()
+
+
+dyld-91
+<rdar://problem/5249477> use of @loader_path based RPATH can cause dyld to leak
+<rdar://problem/4910107> Dyld_stubs should not be writable on x86
+
+
+dyld-90.2
+<rdar://problem/4860414> generating dyld shared cache generation on first boot makes time to MacBuddy very slow
+
+
+dyld-90.1
+<rdar://problem/5274718> truncated dyld cache file after panic causes hang at boot
+
+
+dyld-90
+<rdar://problem/4892216> stop special casing main executables initializers
+<rdar://problem/4170040> DYLD_INSERT_LIBRARIES doesn't work correctly with initializer functions
+
+
+dyld-89
+<rdar://problem/5097116> dyld could asynchronously request pages it will need
+<rdar://problem/5272001> handle when argv[0] is NULL.
+<rdar://problem/5186317> Foundation built on 9A436 doesn't launch 64 bit apps
+partial fix for: <rdar://problem/4910107> Dyld_stubs should not be writable on x86
+
+
+dyld-88
+<rdar://problem/5233126> update_dyld_shared_cache keeps spewing messages to console
+<rdar://problem/4795421> optimize LINKEDIT region of dyld shared cache
+<rdar://problem/5244184> Support extended __dyld section with NXArgc, etc addresses
+remove call to __xlocale_init()
+Update __OPEN_SOURCE__ conditionals
+
+
+dyld-87
+<rdar://problem/5203587> CFM games use private _dyld_fork_* routines - add back
+<rdar://problem/5231152> better handling of NOLOAD with symlinked dylibs
+
+
+dyld-86.1
+Fix DYLD_SHARED_REGION=private
+update man page
+
+
+dyld-86
+<rdar://problem/4960876> update_dyld_shared_cache fails on @executable_path framework
+<rdar://problem/5213017> [Leopard]: 9A441/442: unable to log in after switching to arabic
+<rdar://problem/5221505> dlopen via CFBundleLoad keeps searching after finding a loadable object
+
+
+dyld-85.2
+<rdar://problem/5202525> MatLab 2007a (7.4) doesn't launch on Leopard9A441
+Never optimize ppc shared cache on intel
+Fix LINKEDIT size in shared cache .map files
+Fix how PIEs are moved to work with NX
+Call pthread_init_keys to work with latest Libc
+
+
+dyld-85.1
+<rdar://problem/5215536> Leopard9A447: Meeting Maker and Microsoft apps will not launch on Intel.
+
+
+dyld-85
+<rdar://problem/5193485> 9A436: Adobe: Photoshop CS3 crashed on pressing Command-C after Command-A
+<rdar://problem/4892382> Use _dyld_initializer
+
+
+dyld-84
+<rdar://problem/5194274> 9A438 dlopen_preflight() corrupts all_image_info list causing Symbolication crashes
+<rdar://problem/5195384> B&I needs an ENV variable to turn off "dyld: ioctl to register dtrace DOF section failed" warnings
+<rdar://problem/4819036> remove support for __image_notify sections
+remove all update_prebinding code
+
+
+dyld-83
+<rdar://problem/4819047> use _simple_dprintf() instead of fprintf()
+remove -progress option from update_dyld_shared_cache
+update_dyld_shared_cache no longer tells rosetta to flush its caches
+<rdar://problem/5110291> update_dyld_shared_cache error message gives an errno value rather than an error string
+<rdar://problem/3968392> dyld interposing doesn't work with dlsym() lookup
+<rdar://problem/5163803> dlopen_preflight() of MH_BUNDLE leaks
+<rdar://problem/5067898&5184629> integrate ImageLoader changes into leopard dyld
+<rdar://problem/5179640> translated (ppc) dyld should not attempt to register DOF sections
+<rdar://problem/5135363> Some dyld library paths are not canonicalized, causing tools using those paths to defenestrate themselves
+
+
+dyld-82.5
+<rdar://problem/5147450> REGR: Leopard9A419: Firefox hangs on launch
+
+
+dyld-82.4
+<rdar://problem/5150283> Leopard9A420: interposing of libMallocDebug or libgmalloc broken
+Fix so problems like <rdar://problem/5149971> are warnings instead of errors
+
+
+dyld-82.3
+<rdar://problem/5148533> 9A420: dyld: ioctl to register dtrace DOF section failed
+
+
+dyld-82.2
+<rdar://problem/5135896> dyld frees string returned by dyld_image_state_change_handler
+<rdar://problem/5133621> better handling than "corrupt binary, library ordinal too big"
+
+
+dyld-82.1
+<rdar://problem/5125295> dyld changes needed to support read-only DOF
+
+
+
+dyld-82
+<rdar://problem/5115360> don't need to hold dyld global lock while running initializers
+<rdar://problem/5094847> dyld leaks when dlopen fails
+<rdar://problem/5128758> dyld leaks two blocks after bundle unload
+
+
+dyld-81
+<rdar://problem/5016782> auto update dyld shared caches if missing or out of date
+
+
+dyld-80.1
+<rdar://problem/5090212> Erronious "unsafe use of @rpath" dyld error
+<rdar://problem/5066570> 9A384: update_dyld_shared_cache fails after ditto'ing matador root with debug info
+<rdar://problem/5093704> Uninitialized ImageLoader->fRegisteredDOF field
+
+
+dyld-80 (Leopard9A400)
+<rdar://problem/4971149> Use new shared region syscalls
+<rdar://problem/5073851> @rpath does not work with -rpath @executable_path/...
+<rdar://problem/5067376> Firefox causes segfault during update_dyld_shared_cache
+
+
+dyld-79.3
+<rdar://problem/4971149> Use new shared region syscalls
+
+dyld-79.2
+<rdar://problem/5073851> @rpath does not work with -rpath @executable_path/...
+
+dyld-79.1 (Leopard9A396)
+fix use of LC_REEXPORTED_DYLIB
+
+
+dyld-79 (Leopard9A392)
+<rdar://problem/5039911> Support Apple PIE (address space randomization)
+<rdar://problem/5055814> update_dyld_shared_cache should warning and not quit if a specified root is missing
+<rdar://problem/5058918> DOF registration needs to switch from /dev/helper to /dev/dtracehelper
+<rdar://problem/5042252> don't error out when a cache line crossing i386 stub cannot be bound
+
+
+dyld-78.2 (Leopard9A387)
+<rdar://problem/5050338> 9A385: Mail (anything using Message.framework) takes a ridiculous amount of time to launch
+
+
+dyld-78.1 (Leopard9A385)
+Fix override of _malloc_lock to be data instead of code
+
+
+dyld-78
+<rdar://problem/5040417> when loading a bundle, dyld is not making a copy of name
+<rdar://problem/5001598> 9A343 KidPix 3 : SpellChecker bundle is not loaded
+<rdar://problem/5028176> dyld cache does not recognize dynamic load of library via symbolic link
+
+
+dyld-77.1
+Back out 4892382 until B&I build fleet has fixed kernel
+
+
+dyld-77
+<rdar://problem/4892382> Use _dyld_initializer
+<rdar://problem/4838967> Look at reduction/elimination of per-framework cost (don't touch __dyld section)
+<rdar://problem/4920999> libdyldapis.a: make initialization as lean as possible
+<rdar://problem/3896792> dyld should malloc never-to-be-freed blocks from its own pool
+<rdar://problem/4980326> Libraries feeding into Libsystem should contain version numbers (libdyldapis)
+Install update_prebinding symlink
+Addend warnings to end of shared cache .map files
+Conditionalize away update_prebinding support
+dladdr() should not remove 's' from "start"
+
+
+dyld-76.2
+<rdar://problem/4987676> hang at boot, Libc changes
+
+dyld-76.1
+<rdar://problem/4979617> x86_64: dyld share cache does not work for AppKit
+
+
+dyld-76
+<rdar://problem/4958744> Rosetta apps crash after update_dyld_shared_cache
+<rdar://problem/4953905> Long-standing typo for "file to short" error from dlopen() / dlerror()
+
+
+dyld-75.1
+Enable ppc shared cache generation on intel machines
+
+
+dyld-75
+<rdar://problem/4931772> 64-byte crossing fast stubs should be bound early to avoid threading issues
+<rdar://problem/4217374> support new intel stub segment that is marked not-writable
+
+
+dyld-74
+<rdar://problem/4893418> register dtrace DOF sections with kernel
+<rdar://problem/4898960> 10.4.9 Regression: Math Kernel crash with TiNovi 8P114
+
+
+dyld-73.2
+<rdar://problem/4889617> Leopard 9A921: Dyld error "lazy pointer not found" loading/running java
+
+
+dyld-73.1 (Leopard9A328)
+<rdar://problem/4883565> 9A326: update_prebinding crashes at end of install
+
+
+dyld-73 (Leopard9A326)
+<rdar://problem/4876600> REGR: 9A322 All Java apps crashing at dyld's misaligned_stack_error
+
+
+dyld-72 (Leopard9A322)
+<rdar://problem/4853532> Maya 8 crashes on launch on Leopard9A309
+<rdar://problem/4791766> ProTools 7.1.1cs1 for Intel hangs on launch on Leopard9A309
+<rdar://problem/4388957> x86 crashes in the binding helper do not have proper backtrace
+
+
+dyld-71  (Leopard9A320)
+<rdar://problem/4824553> inform rosetta of each library in the dyld shared cache
+<rdar://problem/4853825> 9A316: Dreamweaver MX 2004 crashes on launch in dyld's addImage
+
+
+dyld-70 (Leopard9A315)
+support split-seg dylibs built with LC_SEGMENT_SPLIT_INFO
+support --progress option in update_dyld_shared_cache so that installer can run it
+
+
+dyld-69.1 (Leopard9A309)
+<rdar://problem/4826097> 9A305: Firefox 2.0 crashes on launch
+<rdar://problem/4827641> httpd is dying in dyld after libobjc.dylib is unloaded
+
+
+dyld-69 (Leopard9A305)
+<rdar://problem/3532018> ER: dlclose() should be able to unload dylibs
+<rdar://problem/3584130> runtime support for RPATH
+
+
+dyld-68 (Leopard9A296)
+<rdar://problem/4797707> rosetta doesn't work when shared cache is present
+<rdar://problem/4800592> shared cache for 64-bit archs does not work when some dylibs are invalid
+
+
+dyld-67.1 (Leopard9A292)
+<rdar://problem/4754048> support 64-bit programs built with new 10.5 subtype
+
+
+dyld-67
+<rdar://problem/4764143> CrashReporter needs a new way to distinguish fatal dyld errors
+<rdar://problem/4610810> support dlopen(NULL, RTLD_FIRST)
+Move base address of ppc64 dyld to match new memory layout
+Move base address of 64-bit shared caches to match new memory layout
+Move location of shared cache file to /var/db/dyld
+Add support for LC_REEXPORT_DYLIB
+Use shared cache if it exists
+Requires ld64-63.1 or later built dylibs for shared cache generation
+
+
+dyld-66.3 (Leopard9A276)
+<rdar://problem/4742808> dyld fails to build with Libc changes in 4632326
+<rdar://problem/4754048> support 64-bit programs built with new 10.5 subtype
+
+
+dyld-66.2 (Leopard9A260)
+<rdar://problem/4718046> Leopard9A259: Backtraces in crash reports are not getting symbolicated
+<rdar://problem/4714894> dyld should get rosetta process name from standard location
+
+
+dyld-66.1 (Leopard9A259)
+Fix for build breakage with Libc-436
+
+
+dyld-66 
+Preliminary shared cache support
+<rdar://problem/4109087> <mach-o/dyld_gdb.h> is in Darwin but not Dev Tools package
+<rdar://problem/4710378> export shared range regions for gdb
+<rdar://problem/4697552> __pthread_tsd_first appears to be initialized too late in dyld
+<rdar://problem/4589305> don't use @executable_path or fallback searching in setuid programs
+
+
+dyld-65.1 (Leopard9A252)
+fix B&I build failure with Libc-435
+
+
+dyld-65 (Leopard9A247)
+<rdar://problem/4653725> jump table entry at end of segment can crash
+<rdar://problem/4644563> Mathematica 5.2 (64-bit MathKernel) always crashes on 9A229
+<rdar://problem/4088447> dlsym man page needs to be more specific about RTLD_DEFAULT
+<rdar://problem/4092461> Change wording in SEARCHING section in dlopen man page
+<rdar://problem/4560992> Man page for dyld has misspelling: cheep
+<rdar://problem/4579459> dyld(3) man page should point to Mach-O Programming Topics URL
+
+
+dyld-64 (Leopard9A224)
+<rdar://problem/4620487> No man page for dlopen_preflight(3)
+<rdar://problem/4363960> dyld lazy binding of fast stubs is not completely thread safe
+<rdar://problem/4628677> remove use of load_shared_file()
+
+
+dyld-63 (Leopard9A215)
+<rdar://problem/4530861> Would like way to quiet dynamic loader
+<rdar://problem/4513256> deprecated old APIs for Leopard
+<rdar://problem/4590713> NSCreateObjectFileImageFromMemory crashes when image is a MH_EXECUTABLE
+
+
+dyld-62.1 (Leopard9A206)
+<rdar://problem/4598215> prebound old stubs failure prevents uTest from running on i386
+
+
+dyld-62 (Leopard9A202)
+<rdar://problem/4589041> an image with an open non-zero base address does not load more efficiently
+<rdar://problem/4590567> Leopard9A190: NSAddImage() crashes when called from x86_64 process
+<rdar://problem/4578484> /usr/lib/libAPSimple.dylib: mmap error
+<rdar://problem/4557971> need to force interposing for rosetta processes
+
+
+dyld-61 (Leopard9A179)
+<rdar://problem/4528739> dyld calls close(-1)
+<rdar://problem/4506173> _stub_binding_helper_interface isn't using movdqa
+<rdar://problem/4548652> dyld tries to mmap 0 size segments and fails with conforming mmap
+<rdar://problem/4536652> Load dyld above 4GB for x86-64
+Move apple parameters on stack when DYLD_ variables are removed
+
+
+dyld-60 (Leopard9A160)
+<rdar://problem/4379896> Suresec #203: dyld environment with suid binaries
+<rdar://problem/4148690> SureSec si#187 linker: environment variables
+<rdar://problem/3915210> print warning message if DYLD_INSERT_LIBRARIES is set (then ignored) for a setuid/setgid program
+<rdar://problem/4359815> dyld's disableIfBadUser() routine can fail for constant strings
+
+
+dyld-59 (Leopard9A156)
+<rdar://problem/4452274> ER: dlopen_preflight()
+
+
+dyld-58 (Leopard9A154)
+<rdar://problem/3827070> implement RTLD_SELF
+<rdar://problem/4045952> better handling of open() errors
+<rdar://problem/4198200> would like dlopen(RTLD_FIRST) so that dlsym variant that does not search dependent libraries
+<rdar://problem/4508801> dyld needs to adopt to Unix conformance changes
+<rdar://problem/4507650> Crash on Leopard9A146 when GC rejects loading a library on Intel
+
+
+dyld-57 (Leopard9A144)
+<rdar://problem/4423668> pthread tsd entries doubly owned by DYLD and Libsystem... (Leopard)
+<rdar://problem/4492351> dyld should automatically stop using the shared region if unavailable
+<rdar://problem/4494723> If instantiateFromLoadedImage fails, dyld crashes
+<rdar://problem/4494725> isCompatibleMachO needs to know about x86-64
+
+
+dyld-56 (Leopard9A140)
+<rdar://problem/3908479> 64-bit dyld should load at around the last 4G - not in the first 4G
+<rdar://problem/4486559> 64 bit: app crashes immediately if -pagezero_size >= 0x0ffffffff
+<rdar://problem/4486804> dyld needs to build for x86-64
+<rdar://problem/4149233> dyld_debug API shim has leak
+<rdar://problem/4490848> dyld does not slide properly on Intel
+
+
+dyld-55 (Leopard9A138)
+<rdar://problem/4430145> dlopen() should fail if bundle has objc code incompatible with runtime environment
+<rdar://problem/4340954> libdyld: make non-POSIX header definitions visible when _POSIX_C_SOURCE is defined
+<rdar://problem/4393607> A flat_namespace image with a reference to an internal private_extern should resolve immediately
+<rdar://problem/4401777> dlopen() man page is missing RTLD_NOLOAD and RTLD_NODELETE
+<rdar://problem/4427324> _CFExecutableLinkedOnOrAfter() fails on 64 bit
+<rdar://problem/4442283> dyld needs to support x86-64
+
+
+dyld-54 (Leopard9A80)
+<rdar://problem/4030730> remove ppc64 workarounds for fixed bugs
+<rdar://problem/4051922> Memory error in removePathWithPrefix()
+<rdar://problem/4258921> dyld does not properly swap CPU subtype from fat file header
+<rdar://problem/4361806> dyld does not compile for open source
+<rdar://problem/4363188> ADOBE XCODE 2.2: ZeroLink can cause wrong typeinfos to be used
+Sync with Chardonnay (except for 4313830 and 4215516)
+
+
+dyld-53 (Leopard9A42)
+<rdar://problem/4254657> Add -fno-exceptions to Release target of libdyld
+<rdar://problem/4326451> Wrong number of seconds reported by DYLD_PRINT_STATISTICS on Intel
+
+
+dyld-52 (Leopard9Axxx)
+<rdar://problem/4172797> dyld changes for new libstdc++ project
+
+
+dyld-51 (Clueless)
+<rdar://problem/3866740> STD:VSX: dlclose() should return non-zero value on failure.
+<rdar://problem/3944469> STD:BUILD: dyld references non-conforming member name for PPC64
+<rdar://problem/4116234> The gdb list of images should be updated before dyld bases and binds each image
+<rdar://problem/3916854> interposing does not handle stacking/nesting of interposing functions
+<rdar://problem/4090063> use of DYLD_INTERPOSE() causes compiler warnings with -std=c99 -pedantic
+<rdar://problem/3992272> SWB: dyld-32 fails to link using 4.0 compiler (gcc-4042) on Tiger8A371
+
+dyld-50 (Leopard9Axxx)
+Convert to build with gcc-4.0
+<rdar://problem/3992272> SWB: dyld-32 fails to link using 4.0 compiler (gcc-4042) on Tiger8A371
+
+----------------------------------
+
+
+
+dyld-46.16 (Mac OS X 10.4.11) 
+<rdar://problem/5146059&5334400> raise bail out limit in update_prebinding to 100 errors
+
+dyld-46.15
+<rdar://problem/5334280> [SUIncaSoho] update_prebinding can only handle 2MB of ppc unprebound dylibs on intel
+<rdar://problem/5146059&5334400> update_prebinding fails if a prebound dylib depends on a non-prebound dylib
+
+dyld-46.14
+<rdar://problem/4814545&5260830> prebinding zeroes out files if an error occurs (such as no vm space left)
+<rdar://problem/4948045&5257758> Rare & unknown root cause: Corruption of Kerberos framework during SU
+
+dyld-46.13
+<rdar://problem/4975286> dyld crashes starting threaded program
+<rdar://problem/5050570> 10.4.9 Regression: SuTiNovi8P132: update_prebinding never reaches steady state
+<rdar://problem/5116499> 10.4.9 Regression: SuTiNovi8P132: update_prebinding never reaches steady state
+<rdar://problem/5160205> [SUTiSoHo] update_prebinding crashes when a weak linked dylib is missing
+<rdar://problem/5165777> [SUIncaSoHo] update_prebinding crashes when a weak linked dylib is missing
+
+dyld-46.12
+<rdar://problem/4898960> 10.4.9 Regression: Math Kernel crash with TiNovi 8P114
+
+dyld-46.11
+<rdar://problem/4642940> dyld's x86_64 support should be open source
+<rdar://problem/4604221> 10.4.x: an image with an open non-zero base address does not load more efficiently
+<rdar://problem/4864380> [SUTiNovi] A flat_namespace image with a reference to an internal private_extern should resolve immediately
+<rdar://problem/4870982> [SUTiNovi] 10.4.8 regression: ppc X program segmentation fault in 10.4.8, worked in 10.4.7
+<rdar://problem/4765099> [SUIncaNovi] 10.4.8 regression: ppc X program segmentation fault in 10.4.8, worked in 10.4.7
+<rdar://problem/4864373> [SUIncaNovi] A flat_namespace image with a reference to an internal private_extern should resolve immediately
+
+dyld-46.10
+<rdar://problem/4787033> dyld-46.9 fails to build in Nicoya
+
+dyld-46.9 (Inca8K...)
+<rdar://problem/4653725> jump table entry at end of segment can crash
+
+dyld-46.8 (Inca8K1073)
+<rdar://problem/4645490> Mathematica 5.2 (64-bit MathKernel) always crashes on Inca
+
+dyld-46.7 (Inca8K1072)
+<rdar://problem/4622201> dyld lazy binding of fast stubs is not completely thread safe
+
+dyld-46.6 (Inca8K1061)
+<rdar://problem/4607261> Inca: don't write warning to stderr for setuid binaries
+
+dyld-46.5 (Inca8K1059)
+<rdar://problem/4598215> prebound old stubs failure prevents uTest from running on i386
+
+dyld-46.4 (Inca8K1057)
+<rdar://problem/4590567> NSAddImage() crashes when called from x86_64 process
+<rdar://problem/4589041> an image with an open non-zero base address does not load more efficiently
+
+dyld-46.3 (Inca8K1054)
+<rdar://problem/4557971> need to force interposing for rosetta processes
+re-enable setuid security fixes for 4525062 and 4525053
+
+dyld-46.2 (Inca8K1046)
+<rdar://problem/4551683> Adobe CS2 no longer launches
+<rdar://problem/4536652> Load dyld above 4GB for x86-64
+
+dyld-46.1 (Inca8K1040)
+rdar://problem/4538177 dyld does not slide on x86_64
+
+dyld-46 (Inca...)
+re-enable x86_64
+
+
+dyld-45.3 (SUSecurity )
+<rdar://problem/4607244> *SecUpd: Chardonnay* don't write warning to stderr for setuid binaries
+<rdar://problem/4607243> *SecUpd: Tiger* don't write warning to stderr for setuid binaries
+
+dyld-45.2 (SUSecurity )
+<rdar://problem/4525062> *SecUpd: Chardonnay* SureSec si#187 remove all DYLD_ env vars for setuid binaries
+<rdar://problem/4148690> *SecUpd: Tiger* SureSec si#187 remove all DYLD_ env vars for setuid binaries
+<rdar://problem/4525053> *SecUpd: Chardonnay* Suresec #203: don't use $HOME with suid binaries
+<rdar://problem/4379896> *SecUpd: Tiger* Suresec #203: don't use $HOME with suid binaries
+
+
+dyld-45.1 (SUTiLondon...)
+back out <rdar://problem/4379896> Suresec #203: dyld environment with suid binaries [SUTi]
+
+
+dyld-45 (SUTiLondon...)
+<rdar://problem/4522929> sync all 10.4.x dyld trains
+<rdar://problem/4320078> dyld fix for gcc-3.3 C++ needs to get in SU
+<rdar://problem/4501854> 64-bit dlopen crashes when opening fat bundle
+<rdar://problem/4148690> SureSec si#187 linker: environment variables [SUTi]
+<rdar://problem/4379896> Suresec #203: dyld environment with suid binaries [SUTi]
+<rdar://problem/4525062> SureSec si#187 linker: environment variables [SUChard]
+<rdar://problem/4525053> Suresec #203: dyld environment with suid binaries [SUChard]
+
+dyld-44.23 (Inca8...)
+<rdar://problem/4498577> Crash using Core Image under Rosetta running InDesign CS2 w/ Magma Effects
+
+dyld-44.22 (Inca8K1030)
+<rdar://problem/4498515> Stub binding helper changes for FP args for x86-64
+
+dyld-44.21 (Inca8K1030)
+<rdar://problem/4497724> printf doesn't work for x86-64
+
+dyld-44.20 (Inca8K1029)
+<rdar://problem/4494725> isCompatibleMachO needs to know about x86-64
+
+dyld-44.19 (Inca8J1028)
+two small x86_64 fixes
+
+dyld-44.18 (Inca8J1027)
+<rdar://problem/4442283> dyld needs to support x86-64
+
+dyld-44.17 (Chardonnay8G1152)
+<rdar://problem/4381131> prebound fast stubs not ignored for flat_namespace dylibs
+
+dyld-44.16 (Chardonnay8G1141)
+<rdar://problem/4360528> Sherlock often crashes in dyld::bindLazySymbol on launch
+
+dyld-44.15 (Chardonnay8G1137)
+<rdar://problem/4356145> no apps can launch with /usr/lib/libMallocDebug.A.dylib on 8G1133
+
+dyld-44.14 (Chardonnay8F1110)
+<rdar://problem/4321820> System Integrity: changes needed for dyld
+
+dyld-44.13 (Chardonnay8F1108)
+<rdar://problem/4313830> pthread tsd entries doubly owned by DYLD and Libsystem... (Chardonnay)
+
+dyld-44.12 (Chardonnay8F1108)
+<rdar://problem/4318081> never pass shared_region_map_file_np() a zero-length region
+
+dyld-44.11 (Chardonnay8F1104)
+<rdar://problem/4303000> dyld launch code should special case if there is only one prebound image with weak exports
+
+dyld-44.10 (Chardonnay8F1100)
+<rdar://problem/4296378> dyld fails to link with Libc-391.1.13
+
+dyld-44.9 (Chardonnay8F1093)
+<rdar://problem/4212667> XCode2.1 + gcc 3.3 + C++ exception + Bundle Bug
+<rdar://problem/4278103> low disk space code path executed with 44GB free
+
+dyld-44.8 (Chardonnay8F1079)
+<rdar://problem/4215516> dyld lazy binding code should use movdqa
+
+dyld-44.7 (Chardonnay8B1072)
+<rdar://problem/4247155> fix for rosetta crashes
+
+dyld-44.6 (Chardonnay8B1072)
+<rdar://problem/4179957> Optimizing system should only progress once
+
+dyld-44.5 (Chardonnay8B1052)
+<rdar://problem/4164559> New intel stub support
+
+dyld-44.4 (Chardonnay8B1051)
+<rdar://problem/4178195> Leopard 9A14: Finder crashes burning a CD
+<rdar://problem/4186248> dyld lazy binding code needs to save/restore all possible register parameters
+<rdar://problem/4172797> use new libstdc++-static
+
+dyld-44.3 (Chardonnay8B1051)
+<rdar://problem/4189498> dyld should recognize byte-swapped Mach-O files
+<rdar://problem/4194105> dyld should only update prebound external relocations if they change
+
+dyld-44.2 (SUTiDenver8F10) [Mac OS X 10.4.3]
+<rdar://problem/4189935> Tiger breaks NSCreateObjectFileImageFromMemory with fat Mach-O
+<rdar://problem/4139432> dyld does not load libraries correctly if matching install_name in /usr/lib
+<rdar://problem/4153431> CrashTracer: ..269 crashes at com.adobe.Acrobat.framework: RunAcrobat + 424
+
+dyld-44.1 (Chardonnay)
+<rdar://problem/4132378> __attribute__ ((regparm (3), stdcall)) doesn't work for inter-image calls
+<rdar://problem/4111112> dyld should automatically set DYLD_SHARED_REGION to avoid
+
+dyld-44 (Chardonnay)
+<rdar://problem/4170213> merge SUTiCambridge dyld and Karma dyld into Chardonnay
+
+
+dyld-43.1 (SUTiCambridge8C20)  [Mac OS X 10.4.2]
+Update open source APSL headers
+<rdar://problem/4120834> update_prebinding should gracefully handle low disk space
+<rdar://problem/4108674> prebinding should not change n_value of .obj_class_name symbols
+<rdar://problem/4057081> dyld gets into infinite loop with dlsym if dylib dependencies contain loops
+<rdar://problem/4072295> FilesBuster crashed in dyld
+<rdar://problem/4104022> DYLD_ROOT_PATH crashes program if any component does not start with /
+<rdar://problem/4104027> dyld writes past end of buffer when checking environment variables
+<rdar://problem/4106921> dyld_image_removing notification never sent
+<rdar://problem/4121907> ANN: DR020
+
+
+dyld-43 (Tiger8A428)  [Mac OS X 10.4.0]
+rdar://problem/4067311 PACE protected Mach-O apps crash under Tiger 8a420
+
+
+dyld-42 (Tiger8A420)
+rdar://problem/4058724 FileMaker JDBC extension does not work in Tiger
+
+
+dyld-41 (Tiger8A417)
+rdar://problem/4047633 Adobe Photoshop CS2: Scripting Save for Web runs out of memory unexpectedly when compared to 10.3.8.
+
+
+dyld-40 (Tiger8A413)
+rdar://problem/4047391 dyld no longer follow dependent libraries using dlopen
+
+
+dyld-39 (Tiger8A406)
+rdar://problem/4034570 DT P1: MATLAB R14sp2 does not run on Tiger
+rdar://problem/4028274 DT P1: GLSLShowpieces crashes when built and run
+
+
+dyld-38 (Tiger8A402)
+rdar://problem/3820219 Tiger + MOTU Digital Performer + hit play = Digital Performer crashes
+rdar://problem/3978682 If an excutable & a framework with the same base name are in the same folder, you get a dyld error if you use full path
+rdar://problem/3987135 MATLAB unresolved symbol __XEditResPutWidgetInfo on Tiger
+rdar://problem/4027813 dlsym man page documents unsupported RTDL_SELF
+
+
+dyld-37 (Tiger8A399)
+rdar://problem/4001668 Safari hang inside CFBundleDYLDGetSymbolByNameWithSearch in Flash plug-in upon opening www.espn.com
+rdar://problem/3853454 dyld needs to call sys_icache_invalidate() after instruction fix-ups
+rdar://problem/3984074 Soldier of Fortune II crashes at start of gameplay on Tiger8A36
+rdar://problem/4008399 Malicious user can set Tiger dyld fallback paths in setuid process
+rdar://problem/4021002 Aliens vs Predator II with latest update does not run
+
+
+dyld-36 (Tiger8A393)
+rdar://problem/3970385 [Tiger] 8A323: Aliens VS Predator 2 Freezes On Launch
+rdar://problem/3839120 _dyld_get_image_header_containing_address returning NULL when it shouldn't
+rdar://problem/3925105 update_prebinding crashes on /usr/lib/libnetsnmptrapd.5.dylib
+
+
+dyld-35 (Tiger8A384)
+rdar://problem/3984074 Soldier of Fortune II crashes at start of gameplay on Tiger8A367
+rdar://problem/4003637 Typo blocks support of -init for 64-bits
+rdar://problem/4003891 improve mmap() failure error msg
+
+
+dyld-34 (Tiger8A381)
+rdar://problem/3976215 dlopen() should look for a library with matching name and architecture  
+rdar://problem/3978682  executable and dylibs can be confused
+rdar://problem/3819111 dlopen() ignores LD_LIBRARY_PATH        
+rdar://problem/3956709 Insufficient documentation for dlopen   
+
+
+dyld-33 (Tiger8A379)
+rdar://problem/3941826 8A340: Tron 2.0 does not launch 
+rdar://problem/3848965 James Bond 007 Nightfire fails to launch        
+rdar://problem/3947513 No One Lives Forever 2 crashes on Quit on Tiger8A347
+rdar://problem/3779999 Spyhunter crashes upon launch on Tiger8A244     
+
+
+dyld-32 (Tiger8A367)
+rdar://problem/3974486 PowerMail launch fails: weak linking of library but not symbols 
+rdar://problem/3974797 can update_prebinding only complain about stuff I actually have installed?
+rdar://problem/3979715 synchronizing attribute name with section name  
+
+
+dyld-31 (Tiger8A362)
+rdar://problem/3958479 Third party "crash reporter" app backtraces have no symbols for our libraries/APIs
+rdar://problem/3966025 add DYLD_INTERPOSE macro to an apple internal header
+rdar://problem/3968283 For interposing support section-by-type and section-by-name     
+
+
+dyld-30 (Tiger8A357)
+rdar://problem/3947090  objc runtime / two-level namespace crash when using new interposing libMallocDebug or libgmalloc
+
+
+dyld-29 (Tiger8A356)
+rdar://problem/3960729  update_prebinding needs to fflush() every output line
+rdar://problem/3960657  Why are my crashreporter logs all useless?
+
+
+dyld-28 (Tiger8A354)
+rdar://problem/3510780 _dyld_get_image_header_containing_address man page is wrong
+rdar://problem/3798074 STD: dlclose() does not unload bundles  
+rdar://problem/3882857 dyld no longer finds framework file if not in Framework hierarchy
+rdar://problem/3898206 dlopen() does not support library searching as linkage at launch does
+rdar://problem/3921479 dyld(1) should not document unimplemented env vars      
+rdar://problem/3935714 Support RTLD_NODELETE   
+rdar://problem/3942919 can't use _debug libSystem      
+
+
+dyld-27 (Tiger8A350)
+rdar://problem/3902088  update_prebinding needs to provide progress information
+
+
+dyld-26 (Tiger8A348)
+rdar://problem/3943033  hang upon boot, permissions and startup thrash
+
+
+dyld-25 (Tiger8A347)
+rdar://problem/3916220  Main executable unmapped 
+rdar://problem/3812732  Microsoft Error Reporting crashes on Tiger  
+rdar://problem/3943349  dyld project should install mach-o/dyld_debug.h
+rdar://problem/3943546  mach-o/dyld_debug.h should be deprecated
+rdar://problem/3933738  use getsectdatafromheader_64
+
+
+dyld-24 (Tiger8A345)
+rdar://problem/3941688  update_prebinding needs a --dry-run option
+
+
+dyld-23
+rdar://problem/3799069  Need coalescing across dylibs
+rdar://problem/3859973  problem with weaklink using darwine
+rdar://problem/3938167  dyld does not work with XLF generated binaries and provided libraries
+rdar://problem/3935377  STD: dyld needs to include sys/time.h and sys/types.h
+rdar://problem/3930361  STD: dyld must create a stub for ___fegetfltrounds
+rdar://problem/3934712 STD:VSX: more dlfcn.h namespace issues
+
+
+dyld-22.5 (Tiger8A340)
+rdar://problem/3788633 MatLab 7.0 fails to launch on Tiger8A246        
+rdar://problem/3919674 prebound flat-namespace libraries are bound wrong
+
+
+dyld-22.4
+rdar://problem/3915914  make update_prebinding more robust
+
+
+dyld-22.3 (Tiger8A333)
+rdar://problem/3920720  dyld missing symbols because Xcode not add -fvisibility=hidden
+
+
+dyld-22.2 (Tiger8A330)
+rdar://problem/3909873  Transmit.app crashes with symbol not found
+
+
+dyld-22.1
+rdar://problem/3908248  Crash in apps when launched from MallocDebug (BlockMove symbol not found if DYLD_FORCE_FLAT_NAMESPACE is set)
+
+
+dyld-22 (Tiger8A325)
+rdar://problem/3903866  reduce LINKEDIT page usage by better use of two-level hints
+rdar://problem/3884004 Libraries can be half-baked if an error occurs during their first use   
+rdar://problem/3899047 interposing doesn't work on 8A317 with dyld-21  
+rdar://problem/3514720 Adobe bundle kernel panics system       
+
+
+dyld-21 (Tiger8A322)
+rdar://problem/3745562 Support two-level interposing with insert libraries (malloc-debug)
+rdar://problem/3892061 8A316: Selecting any application in Finder in the column view crashes finder
+rdar://problem/3894540 DYLD_PRINT_SEGMENTS no longer works on 8A317    
+
+
+dyld-20 (Tiger8A317)
+rdar://problem/32957877        Support @loader_path in dylib commands
+rdar://problem/33837173        need SPI to set fallback symbol lookup
+rdar://problem/33891778        dyld (__DATA,__dyld) function pointers should drift as little as possible
+Fix issue with new prebinding overwriting symlinks
+
+
+dyld-19 (Tiger8A315)
+rdar://problem/3823664 dyld reports corrupt executable
+rdar://problem/3847571 dyld submission number should be embedded in dyld
+rdar://problem/3865141 dyld_all_image_infos should contain bit that says if process is using the shared region
+rdar://problem/3884103 dyld needs to use -msoft-float for ppc64
+rdar://problem/3886337 PPC_RELOC_PB_LA_PTR not recognized by ppc64 
+Clean up/document dyld-gdb interface
+
+
+dyld-18.3 (prebinding sideworld build)
+prebinding enhancements
+
+dyld-18.2 (Tiger8A306)
+rdar://problem/3782982 Fix for Macromedia apps (Flash 7.2)
+
+dyld-18.1
+rdar://problem/3864644 DVD player crash (loading memory based bundle)
+
+dyld-18 (Tiger8A303)
+rdar://problem/3866877 STD:VSX dlsym() faults when passed a bad handle.
+rdar://problem/3862043 typo in dyld function name
+rdar://problem/3857000 dyld should limit its exported symbols
+rdar://problem/3835208 want better error message for incompatible libraries
+dyld now built with dead-code-stripping
+better launch performance when hundreds of libraries are used
+more bug fixes in update_prebinding in dyld
+
+
+dyld-17.1 (Tiger8A301)
+rdar://problem/3672757 initial implementation of update_prebinding in dyld
+rdar://problem/3847376 dyld does not slide itself properly (partial fix)
+rdar://problem/3843028 STD: make dlfcn.h posix compliant
+rdar://problem/3856182 STD: add includes
+rdar://problem/3782982 infrastructure work on compatibility for Macromedia apps
+Other 64-bit tweaks
+
+
+dyld-16.1 (Tiger8A296)
+rdar://problem/3768530 dyld should adopt shared_region_map_file_np() 
+
+
+dyld-15 (Gordian 64-bit side world build only)
+rdar://problem/3834744 64-bit dyld needs to handle mh->cputype != host_info cputype
+Other 64-bit clean ups
+
+
+dyld-14 (Tiger8A280)
+rdar://problem/3811777 Deadlock in dyld code, seen in Merlin and Mail
+rdar://problem/3793075 Update to fix: DVD Player crashes at launch with disc in drive
+rdar://problem/3830560 Don't let gcc-3.5 optimize away send_event
+rdar://problem/3826169 Update dlfcn.h header to Apple header and acknowledge Peter and Jorge
+rdar://problem/3793861 Update dlopen(3) man page to reflect new implementation
+rdar://problem/3559013 libdyld.a needs to build for ppc64      
+Added DYLD_PRINT_OPTS
+Added DYLD_PRINT_ENV
+Deprecated 10 APIs
+
+
+dyld-13 (Gordian 64-bit side world build only)
+rdar://problem/3560664 Add ppc64 support
+rdar://problem/3819144 Opening PDF in Safari crashes 
+rdar://problem/3793861 Update dlopen man pages
+rdar://problem/3765271 Build with gcc-3.5 
+rdar://problem/3762685 Make own prototype for task_self_trap() 
+rdar://problem/3799467 Mozilla tries to open a dylib using a bundle API
+rdar://problem/3812263 Add dyld SPI so Shark can interpose lazy pointer lookup
+Added emacs major-mode and tab-width directives
+
+
+dyld-12.4 (Tiger8A271)
+tweak so dyld can use libc.a built with long double support
+
+
+dyld-12.3 (no-build)
+rdar://problem/3765271 switch dyld to build with gcc-3.5
+
+
+dyld-12.2 (Tiger8A265)
+rdar://problem/3793075 DVD Player crashes at launch with disc in drive
+
+
+dyld-12.1 (Tiger8A255)
+rdar://problem/3749360 a flat lookup needs to search everywhere and not short-circuit to own image 
+
+
+dyld-12 (Tiger8A231)
+rdar://problem/3751226 make dyld thread safe (libdyld.a should come from new dyld project)
+rdar://problem/3654650 integrate dlopen() and friends into dyld
+
+
+dyld-11.3 (Tiger8A225)
+rdar://problem/3751226 NSAddImage() with leaf name doesn't use fallback path
+
+
+dyld-11.1 (Tiger8A223)
+rdar://problem/3749251 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED implies NSADDIMAGE_OPTION_RETURN_ON_ERROR" 
+
+
+dyld-11 (Tiger8A220)
+rdar://problem/3684168 prevent DYLD_LIBRARY_PATH from causing circular reference when two dylib have same leaf name 
+rdar://problem/3698212 implement _dyld_launched_prebound()
+rdar://problem/3696924 suppport frameworks without symlink to current version
+rdar://problem/3692136 Support DYLD_PRINT_LIBRARIES_POST_LAUNCH
+rdar://problem/3685517 make find-image-for-address faster via caching
+rdar://problem/3661976 -force_flat_namespace should disable prebinding
+rdar://problem/3702311 make dyld's __TEXT read-only
+rdar://problem/3669059 do cpu sub-type checking on thin files
+rdar://problem/3696002 Support C++ vague linkage that resolves internally
+rdar://problem/3725847 run initializers in inserted libraries
+rdar://problem/3731063 pass arc/argv to initializers
+rdar://problem/3731100 don't write on __dyld section unless necessary
+rdar://problem/3731633 use mmap() instead of map_fd()
+rdar://problem/3676934 don't double read first page of images, use pread()
+rdar://problem/3725372 ignore environment variables for setuid binaries
+
+
+dyld-10.2 (Tiger8A157)
+rdar://problem/3668765 Macromedia apps don't launch
+
+
+dyld-10.1 (Tiger8A156)
+rdar://problem/3691952 Fix-n-continue broke in Objective-C
+
+
+dyld-10 (Tiger8A148)
+rdar://problem/3686995 implement dyld_call_module_initializers_for_dylib and do parameter sanity checking of module parameters
+rdar://problem/3674139 Make @executable_path work when main executable is a symlink
+rdar://problem/3688719 Support CW built binaries built with -data_before
+
+
+dyld-9
+rdar://problem/3682744 GoLive crash (NSIsSymbolDefinedWithHint should try harder)
+rdar://problem/3660691 iTunes crash with partial plugin
+rdar://problem/3684167 DYLD_IMAGE_SUFFIX broke
+rdar://problem/3672670 Fix uninitialized variable in objc hook
+
+
+dyld-8 (Tiger8A144)
+rdar://problem/3680627 handle weaklib when prebound
+rdar://problem/3672670 new hook for objc 
+
+
+dyld-7 (Tiger8A141)
+rdar://problem/3669059 Support cpu-sub-type selection
+rdar://problem/3675131 allow text relocations
+rdar://problem/3675614 fix lazy pointer usage in termination routines
+rdar://problem/3673658 Allow NSUnLinkModule to be called with NULL
+
+
+dyld-6 (Tiger8A139)
+rdar://problem/3649313 clean up <mach-o/dyld.h>
+rdar://problem/3661976 support MH_FORCE_FLAT
+rdar://problem/3659666 DYLD_FORCE_FLAT_NAMESPACE should disable prebinding
+Better error reporting
+Faster flat namespace lookups
+Better implementation of NSLinkEditError
+
+
+dyld-5 (Tiger8A135)
+rdar://problem/3665738 fix binding of private_extern within multi-module libs
+rdar://problem/3667763 use hints supplied in APIs
+Set error_string for CrashReporter
+Better error message when library can't be found
+Properly use ZeroLink bundle notifier
+
+
+dyld-4 (Tiger8A133)
+rdar://problem/3663433 allmemory shows 8000 pages are missing
+
+
+dyld-3 
+rdar://problem/3659408 Proper searching in umbrellas
+rdar://problem/3657040 Better error messages when symbols not found
+rdar://problem/3657197 Add ~/Library/Frameworks to fallback path
+Properly use DYLD_IMAG_SUFFIX
+Initial CrashReporter support
+
+
+dyld-2 (Tiger8A132)
+Support: NSNameOfSymbol, NSModuleForSymbol, NSLibraryNameForModule, and NSMakePrivateModulePublic
+Add more functionality to DYLD_IGNORE_PREBINDING environment variable
+
+
+dyld-1
+Initial submission of dyld rewrite.
index 60c2527b8ee9a1628db1046e24a0a328d697e0cd..679d267865a95cafad013ea58568d6f456145ec0 100644 (file)
@@ -1,4 +1,4 @@
-.Dd Aug 28, 2008
+.Dd Nov 7, 2011
 .Os
 .Dt DLOPEN 3
 .Sh NAME
 .Os
 .Dt DLOPEN 3
 .Sh NAME
@@ -123,15 +123,18 @@ searches for a compatible Mach-O file in the directories specified by a set of e
 the process's current working directory.
 When set, the environment variables must contain a colon-separated list of directory paths, 
 which can be absolute or relative to the current working directory. The environment variables 
 the process's current working directory.
 When set, the environment variables must contain a colon-separated list of directory paths, 
 which can be absolute or relative to the current working directory. The environment variables 
-are LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, and DYLD_FALLBACK_LIBRARY_PATH. 
-The first two variables have no default value. The default value of DYLD_FALLBACK_LIBRARY_PATH
-is $HOME/lib;/usr/local/lib;/usr/lib. 
+are LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, and DYLD_FALLBACK_LIBRARY_PATH, but if the path specified
+is formatted like a framework, then DYLD_FRAMEWORK_PATH and DYLD_FALLBACK_FRAMEWORK_PATH are
+used instead.
+The non-fallback variables have no default value. The default value of DYLD_FALLBACK_LIBRARY_PATH
+is $HOME/lib:/usr/local/lib:/usr/lib, and DYLD_FALLBACK_FRAMEWORK_PATH is 
+$HOME/Library/Frameworks:/Library/Frameworks:/Network/Library/Frameworks:/System/Library/Frameworks. 
 .Fn dlopen 
 searches the directories specified in the environment variables in the order they are listed. 
 .Pp
 When 
 .Fa path
 .Fn dlopen 
 searches the directories specified in the environment variables in the order they are listed. 
 .Pp
 When 
 .Fa path
-doesn't contain a slash character (i.e. it is just a leaf name), 
+doesn't contain a slash character (i.e. it is just a leaf name and therefore not a framework), 
 .Fn dlopen
 searches the following the following until it finds a compatible Mach-O file: $LD_LIBRARY_PATH, 
 $DYLD_LIBRARY_PATH, current working directory, $DYLD_FALLBACK_LIBRARY_PATH.
 .Fn dlopen
 searches the following the following until it finds a compatible Mach-O file: $LD_LIBRARY_PATH, 
 $DYLD_LIBRARY_PATH, current working directory, $DYLD_FALLBACK_LIBRARY_PATH.
@@ -149,7 +152,8 @@ $DYLD_LIBRARY_PATH (with leaf name from
 .Pp
 Note: There are no configuration files to control dlopen searching.  
 .Pp
 .Pp
 Note: There are no configuration files to control dlopen searching.  
 .Pp
-Note: If the main executable is a set[ug]id binary, then all environment variables are ignored, and only a full path can be used. 
+Note: If the main executable is a set[ug]id binary or codesigned with entitlements, 
+then all environment variables are ignored, and only a full path can be used. 
 .Pp
 Note: Mac OS X uses "universal" files to combine 32-bit and 64-bit libraries.  This means there are no separate 32-bit and 64-bit search paths.
 .Pp
 .Pp
 Note: Mac OS X uses "universal" files to combine 32-bit and 64-bit libraries.  This means there are no separate 32-bit and 64-bit search paths.
 .Pp
index 21650208c07feb210f1dadfbf2232bdaeb094063..504873ce1a416ac08347dcebcc455fbd7c98d759 100644 (file)
@@ -3,7 +3,7 @@
        archiveVersion = 1;
        classes = {
        };
        archiveVersion = 1;
        classes = {
        };
-       objectVersion = 45;
+       objectVersion = 46;
        objects = {
 
 /* Begin PBXAggregateTarget section */
        objects = {
 
 /* Begin PBXAggregateTarget section */
@@ -13,6 +13,7 @@
                        buildPhases = (
                                F908135111D3ED9000626CC1 /* usr|include|mach-o */,
                                F908137011D3FB5000626CC1 /* usr|include */,
                        buildPhases = (
                                F908135111D3ED9000626CC1 /* usr|include|mach-o */,
                                F908137011D3FB5000626CC1 /* usr|include */,
+                               F9C69EFC14EC8AB8009CAE2E /* usr|local|include */,
                                F908137111D3FB5000626CC1 /* usr|local|include|mach-o */,
                                F908137211D3FB5000626CC1 /* usr|share|man|man1 */,
                                F908137311D3FB5000626CC1 /* usr|share|man|man3 */,
                                F908137111D3FB5000626CC1 /* usr|local|include|mach-o */,
                                F908137211D3FB5000626CC1 /* usr|share|man|man1 */,
                                F908137311D3FB5000626CC1 /* usr|share|man|man3 */,
                F9A221E70F3A6D7C00D15F73 /* dyldLibSystemGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A221E60F3A6D7C00D15F73 /* dyldLibSystemGlue.c */; };
                F9A6D6E4116F9DF20051CC16 /* threadLocalVariables.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A6D6E2116F9DF20051CC16 /* threadLocalVariables.c */; };
                F9A6D70C116FBBD10051CC16 /* threadLocalHelpers.s in Sources */ = {isa = PBXBuildFile; fileRef = F9A6D70B116FBBD10051CC16 /* threadLocalHelpers.s */; };
                F9A221E70F3A6D7C00D15F73 /* dyldLibSystemGlue.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A221E60F3A6D7C00D15F73 /* dyldLibSystemGlue.c */; };
                F9A6D6E4116F9DF20051CC16 /* threadLocalVariables.c in Sources */ = {isa = PBXBuildFile; fileRef = F9A6D6E2116F9DF20051CC16 /* threadLocalVariables.c */; };
                F9A6D70C116FBBD10051CC16 /* threadLocalHelpers.s in Sources */ = {isa = PBXBuildFile; fileRef = F9A6D70B116FBBD10051CC16 /* threadLocalHelpers.s */; };
-               F9B0912911F11D3400096D49 /* dsc_slider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9B0912811F11D3400096D49 /* dsc_slider.cpp */; };
-               F9B0913911F11DD300096D49 /* dsc_slider.h in usr|local|include|mach-o */ = {isa = PBXBuildFile; fileRef = F9B0913811F11DAB00096D49 /* dsc_slider.h */; };
                F9BA514B0ECE4F4200D1D62E /* dyld_stub_binder.s in Sources */ = {isa = PBXBuildFile; fileRef = F99EFC0D0EAD60E8001032B8 /* dyld_stub_binder.s */; };
                F9BA514B0ECE4F4200D1D62E /* dyld_stub_binder.s in Sources */ = {isa = PBXBuildFile; fileRef = F99EFC0D0EAD60E8001032B8 /* dyld_stub_binder.s */; };
+               F9C69EFE14EC8AD2009CAE2E /* objc-shared-cache.h in usr|local|include */ = {isa = PBXBuildFile; fileRef = F9C69EFD14EC8ABF009CAE2E /* objc-shared-cache.h */; };
                F9CE307A1208F1B50098B590 /* dsc_extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9CE30781208F1B50098B590 /* dsc_extractor.cpp */; };
                F9CE307B1208F1C60098B590 /* dsc_extractor.h in usr|local|include|mach-o */ = {isa = PBXBuildFile; fileRef = F9CE30791208F1B50098B590 /* dsc_extractor.h */; };
                F9CE307A1208F1B50098B590 /* dsc_extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9CE30781208F1B50098B590 /* dsc_extractor.cpp */; };
                F9CE307B1208F1C60098B590 /* dsc_extractor.h in usr|local|include|mach-o */ = {isa = PBXBuildFile; fileRef = F9CE30791208F1B50098B590 /* dsc_extractor.h */; };
+               F9D1001814D8D13D00099D91 /* dsc_extractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9CE30781208F1B50098B590 /* dsc_extractor.cpp */; };
+               F9D1001D14D8D19500099D91 /* dsc_iterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9F2A56E0F7AEEE300B7C9EB /* dsc_iterator.cpp */; };
                F9D238DB0A9E2FD0002B55C7 /* update_dyld_shared_cache.1 in usr|share|man|man1 */ = {isa = PBXBuildFile; fileRef = F9D238D90A9E19A0002B55C7 /* update_dyld_shared_cache.1 */; };
                F9D238DB0A9E2FD0002B55C7 /* update_dyld_shared_cache.1 in usr|share|man|man1 */ = {isa = PBXBuildFile; fileRef = F9D238D90A9E19A0002B55C7 /* update_dyld_shared_cache.1 */; };
+               F9D49CCC1458B95200F86ADD /* start_glue.s in Sources */ = {isa = PBXBuildFile; fileRef = F9D49CCB1458B95200F86ADD /* start_glue.s */; };
                F9ED4CD60630A7F100DF4E74 /* dyld_gdb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9ED4CC60630A7F100DF4E74 /* dyld_gdb.cpp */; };
                F9ED4CD70630A7F100DF4E74 /* dyld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9ED4CC70630A7F100DF4E74 /* dyld.cpp */; };
                F9ED4CD90630A7F100DF4E74 /* dyldAPIs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9ED4CC90630A7F100DF4E74 /* dyldAPIs.cpp */; };
                F9ED4CD60630A7F100DF4E74 /* dyld_gdb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9ED4CC60630A7F100DF4E74 /* dyld_gdb.cpp */; };
                F9ED4CD70630A7F100DF4E74 /* dyld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9ED4CC70630A7F100DF4E74 /* dyld.cpp */; };
                F9ED4CD90630A7F100DF4E74 /* dyldAPIs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9ED4CC90630A7F100DF4E74 /* dyldAPIs.cpp */; };
                        remoteGlobalIDString = F9F2A5580F7AEE9800B7C9EB;
                        remoteInfo = libdsc;
                };
                        remoteGlobalIDString = F9F2A5580F7AEE9800B7C9EB;
                        remoteInfo = libdsc;
                };
+               F9D1004614D8D91100099D91 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = F9ED4C8B0630A72300DF4E74 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = F9D1001114D8D0BA00099D91;
+                       remoteInfo = dsc_extractor;
+               };
                F9ED4CA60630A78A00DF4E74 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = F9ED4C8B0630A72300DF4E74 /* Project object */;
                F9ED4CA60630A78A00DF4E74 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = F9ED4C8B0630A72300DF4E74 /* Project object */;
                        name = "usr|local|include|mach-o";
                        runOnlyForDeploymentPostprocessing = 1;
                };
                        name = "usr|local|include|mach-o";
                        runOnlyForDeploymentPostprocessing = 1;
                };
-               F9B0913511F11D8B00096D49 /* usr|local|include|mach-o */ = {
+               F9C69EFC14EC8AB8009CAE2E /* usr|local|include */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 8;
-                       dstPath = "usr/local/include/mach-o";
+                       dstPath = /usr/local/include;
                        dstSubfolderSpec = 0;
                        files = (
                        dstSubfolderSpec = 0;
                        files = (
-                               F9B0913911F11DD300096D49 /* dsc_slider.h in usr|local|include|mach-o */,
+                               F9C69EFE14EC8AD2009CAE2E /* objc-shared-cache.h in usr|local|include */,
                        );
                        );
-                       name = "usr|local|include|mach-o";
+                       name = "usr|local|include";
                        runOnlyForDeploymentPostprocessing = 1;
                };
                F9D238DD0A9E2FEE002B55C7 /* usr|share|man|man1 */ = {
                        runOnlyForDeploymentPostprocessing = 1;
                };
                F9D238DD0A9E2FEE002B55C7 /* usr|share|man|man1 */ = {
                F9AB709D0BA75730002F6068 /* dyldLibSystemInterface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dyldLibSystemInterface.h; path = src/dyldLibSystemInterface.h; sourceTree = "<group>"; };
                F9AC7E930B7BB67700FEB38B /* version.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = version.c; sourceTree = BUILT_PRODUCTS_DIR; };
                F9B01E3D0739ABDE00CF981B /* dyld.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; name = dyld.exp; path = src/dyld.exp; sourceTree = SOURCE_ROOT; };
                F9AB709D0BA75730002F6068 /* dyldLibSystemInterface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dyldLibSystemInterface.h; path = src/dyldLibSystemInterface.h; sourceTree = "<group>"; };
                F9AC7E930B7BB67700FEB38B /* version.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = version.c; sourceTree = BUILT_PRODUCTS_DIR; };
                F9B01E3D0739ABDE00CF981B /* dyld.exp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.exports; name = dyld.exp; path = src/dyld.exp; sourceTree = SOURCE_ROOT; };
-               F9B0912311F11D1600096D49 /* libdsc_slider.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdsc_slider.a; sourceTree = BUILT_PRODUCTS_DIR; };
-               F9B0912811F11D3400096D49 /* dsc_slider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsc_slider.cpp; sourceTree = "<group>"; };
-               F9B0913811F11DAB00096D49 /* dsc_slider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsc_slider.h; sourceTree = "<group>"; };
+               F9C69EFD14EC8ABF009CAE2E /* objc-shared-cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "objc-shared-cache.h"; path = "include/objc-shared-cache.h"; sourceTree = "<group>"; };
                F9CE30781208F1B50098B590 /* dsc_extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsc_extractor.cpp; sourceTree = "<group>"; };
                F9CE30791208F1B50098B590 /* dsc_extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsc_extractor.h; sourceTree = "<group>"; };
                F9CE30781208F1B50098B590 /* dsc_extractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsc_extractor.cpp; sourceTree = "<group>"; };
                F9CE30791208F1B50098B590 /* dsc_extractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsc_extractor.h; sourceTree = "<group>"; };
+               F9D1001214D8D0BA00099D91 /* dsc_extractor.bundle */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = dsc_extractor.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
                F9D238D90A9E19A0002B55C7 /* update_dyld_shared_cache.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; path = update_dyld_shared_cache.1; sourceTree = "<group>"; };
                F9D238D90A9E19A0002B55C7 /* update_dyld_shared_cache.1 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.man; path = update_dyld_shared_cache.1; sourceTree = "<group>"; };
+               F9D49CCB1458B95200F86ADD /* start_glue.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; name = start_glue.s; path = src/start_glue.s; sourceTree = "<group>"; };
                F9E572000A66EF41007D9BE9 /* dlopen_preflight.3 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = dlopen_preflight.3; sourceTree = "<group>"; };
                F9ED4C980630A76000DF4E74 /* dyld */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dyld; sourceTree = BUILT_PRODUCTS_DIR; };
                F9ED4C9F0630A76B00DF4E74 /* libdyld.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdyld.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                F9E572000A66EF41007D9BE9 /* dlopen_preflight.3 */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = dlopen_preflight.3; sourceTree = "<group>"; };
                F9ED4C980630A76000DF4E74 /* dyld */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = dyld; sourceTree = BUILT_PRODUCTS_DIR; };
                F9ED4C9F0630A76B00DF4E74 /* libdyld.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libdyld.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               F9D1001014D8D0BA00099D91 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                F9F2A5570F7AEE9800B7C9EB /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                F9F2A5570F7AEE9800B7C9EB /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                F93937460A94FC4700070A07 /* update_dyld_shared_cache.cpp */,
                                F9F2A56E0F7AEEE300B7C9EB /* dsc_iterator.cpp */,
                                F9F2A56F0F7AEEE300B7C9EB /* dsc_iterator.h */,
                                F93937460A94FC4700070A07 /* update_dyld_shared_cache.cpp */,
                                F9F2A56E0F7AEEE300B7C9EB /* dsc_iterator.cpp */,
                                F9F2A56F0F7AEEE300B7C9EB /* dsc_iterator.h */,
-                               F9B0912811F11D3400096D49 /* dsc_slider.cpp */,
-                               F9B0913811F11DAB00096D49 /* dsc_slider.h */,
                                F9CE30781208F1B50098B590 /* dsc_extractor.cpp */,
                                F9CE30791208F1B50098B590 /* dsc_extractor.h */,
                                F99B8E620FEC11B400701838 /* dyld_shared_cache_util.cpp */,
                                F9CE30781208F1B50098B590 /* dsc_extractor.cpp */,
                                F9CE30791208F1B50098B590 /* dsc_extractor.h */,
                                F99B8E620FEC11B400701838 /* dyld_shared_cache_util.cpp */,
                                F93937320A94FAF700070A07 /* update_dyld_shared_cache */,
                                F9F2A5590F7AEE9800B7C9EB /* libdsc.a */,
                                F99B8E670FEC121100701838 /* dyld_shared_cache_util */,
                                F93937320A94FAF700070A07 /* update_dyld_shared_cache */,
                                F9F2A5590F7AEE9800B7C9EB /* libdsc.a */,
                                F99B8E670FEC121100701838 /* dyld_shared_cache_util */,
-                               F9B0912311F11D1600096D49 /* libdsc_slider.a */,
+                               F9D1001214D8D0BA00099D91 /* dsc_extractor.bundle */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                        );
                        name = Products;
                        sourceTree = "<group>";
                                F9ED4CCD0630A7F100DF4E74 /* dyldLock.h */,
                                F9ED4CCE0630A7F100DF4E74 /* dyldNew.cpp */,
                                F9ED4CCF0630A7F100DF4E74 /* dyldStartup.s */,
                                F9ED4CCD0630A7F100DF4E74 /* dyldLock.h */,
                                F9ED4CCE0630A7F100DF4E74 /* dyldNew.cpp */,
                                F9ED4CCF0630A7F100DF4E74 /* dyldStartup.s */,
+                               F9D49CCB1458B95200F86ADD /* start_glue.s */,
                                F99EFC0D0EAD60E8001032B8 /* dyld_stub_binder.s */,
                                F9ED4CD00630A7F100DF4E74 /* glue.c */,
                                F9ED4CD10630A7F100DF4E74 /* ImageLoader.cpp */,
                                F99EFC0D0EAD60E8001032B8 /* dyld_stub_binder.s */,
                                F9ED4CD00630A7F100DF4E74 /* glue.c */,
                                F9ED4CD10630A7F100DF4E74 /* ImageLoader.cpp */,
                                F939F219078F1A2100AC144F /* dyld_debug.h */,
                                F9ED4CEA0630A80600DF4E74 /* dyld.h */,
                                F99EE6AE06B48D4200BF1992 /* dlfcn.h */,
                                F939F219078F1A2100AC144F /* dyld_debug.h */,
                                F9ED4CEA0630A80600DF4E74 /* dyld.h */,
                                F99EE6AE06B48D4200BF1992 /* dlfcn.h */,
+                               F9C69EFD14EC8ABF009CAE2E /* objc-shared-cache.h */,
                        );
                        name = include;
                        sourceTree = "<group>";
                        );
                        name = include;
                        sourceTree = "<group>";
                };
 /* End PBXGroup section */
 
                };
 /* End PBXGroup section */
 
+/* Begin PBXHeadersBuildPhase section */
+               F9D1000E14D8D0BA00099D91 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXHeadersBuildPhase section */
+
 /* Begin PBXNativeTarget section */
                F93937310A94FAF700070A07 /* update_dyld_shared_cache */ = {
                        isa = PBXNativeTarget;
 /* Begin PBXNativeTarget section */
                F93937310A94FAF700070A07 /* update_dyld_shared_cache */ = {
                        isa = PBXNativeTarget;
                        dependencies = (
                                F99B8EA00FEC195800701838 /* PBXTargetDependency */,
                                F9CE330B120F40EA0098B590 /* PBXTargetDependency */,
                        dependencies = (
                                F99B8EA00FEC195800701838 /* PBXTargetDependency */,
                                F9CE330B120F40EA0098B590 /* PBXTargetDependency */,
+                               F9D1004714D8D91100099D91 /* PBXTargetDependency */,
                        );
                        name = update_dyld_shared_cache;
                        productName = update_dyld_shared_cache;
                        );
                        name = update_dyld_shared_cache;
                        productName = update_dyld_shared_cache;
                        productReference = F99B8E670FEC121100701838 /* dyld_shared_cache_util */;
                        productType = "com.apple.product-type.tool";
                };
                        productReference = F99B8E670FEC121100701838 /* dyld_shared_cache_util */;
                        productType = "com.apple.product-type.tool";
                };
-               F9B0912211F11D1600096D49 /* libdsc_slider */ = {
+               F9D1001114D8D0BA00099D91 /* dsc_extractor */ = {
                        isa = PBXNativeTarget;
                        isa = PBXNativeTarget;
-                       buildConfigurationList = F9B0912A11F11D3400096D49 /* Build configuration list for PBXNativeTarget "libdsc_slider" */;
+                       buildConfigurationList = F9D1001714D8D0F100099D91 /* Build configuration list for PBXNativeTarget "dsc_extractor" */;
                        buildPhases = (
                        buildPhases = (
-                               F9B0912011F11D1600096D49 /* Sources */,
-                               F9B0913511F11D8B00096D49 /* usr|local|include|mach-o */,
+                               F9D1000E14D8D0BA00099D91 /* Headers */,
+                               F9D1000F14D8D0BA00099D91 /* Sources */,
+                               F9D1001014D8D0BA00099D91 /* Frameworks */,
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
                        );
                        buildRules = (
                        );
                        dependencies = (
                        );
-                       name = libdsc_slider;
-                       productName = libdsc_slider;
-                       productReference = F9B0912311F11D1600096D49 /* libdsc_slider.a */;
-                       productType = "com.apple.product-type.library.static";
+                       name = dsc_extractor;
+                       productName = dsc_extractor;
+                       productReference = F9D1001214D8D0BA00099D91 /* dsc_extractor.bundle */;
+                       productType = "com.apple.product-type.library.dynamic";
                };
                F9ED4C970630A76000DF4E74 /* dyld */ = {
                        isa = PBXNativeTarget;
                };
                F9ED4C970630A76000DF4E74 /* dyld */ = {
                        isa = PBXNativeTarget;
 /* Begin PBXProject section */
                F9ED4C8B0630A72300DF4E74 /* Project object */ = {
                        isa = PBXProject;
 /* Begin PBXProject section */
                F9ED4C8B0630A72300DF4E74 /* Project object */ = {
                        isa = PBXProject;
+                       attributes = {
+                               LastUpgradeCheck = 0440;
+                       };
                        buildConfigurationList = F9D8C7E9087B087300E93EFB /* Build configuration list for PBXProject "dyld" */;
                        buildConfigurationList = F9D8C7E9087B087300E93EFB /* Build configuration list for PBXProject "dyld" */;
-                       compatibilityVersion = "Xcode 3.1";
+                       compatibilityVersion = "Xcode 3.2";
                        developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                        developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                F93937310A94FAF700070A07 /* update_dyld_shared_cache */,
                                F9F2A5580F7AEE9800B7C9EB /* libdsc */,
                                F99B8E550FEC10F600701838 /* dyld_shared_cache_util */,
                                F93937310A94FAF700070A07 /* update_dyld_shared_cache */,
                                F9F2A5580F7AEE9800B7C9EB /* libdsc */,
                                F99B8E550FEC10F600701838 /* dyld_shared_cache_util */,
-                               F9B0912211F11D1600096D49 /* libdsc_slider */,
+                               F9D1001114D8D0BA00099D91 /* dsc_extractor */,
                        );
                };
 /* End PBXProject section */
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                        shellPath = /bin/sh;
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                        shellPath = /bin/sh;
-                       shellScript = "if [ \"${INSTALL_LOCATION}\" = \"\" ] \nthen\n     # on iOS, libdyld builds arm libdsc.a and u_d_s_c builds intel libdsc.a\n     # on MacOSX, to avoid collision, u_d_s_c does not install libdsc.a\n\trm -rf ${DSTROOT}/usr/local/include\n\trm -rf ${DSTROOT}/usr/local/lib\nfi\n";
+                       shellScript = "if [ \"${INSTALL_LOCATION}\" = \"\" ] \nthen\n     # on iOS, libdyld builds arm libdsc.a and u_d_s_c builds intel libdsc.a\n     # on MacOSX, to avoid collision, u_d_s_c does not install libdsc.a\n\trm -rf ${DSTROOT}/usr/local/include\n\trm -rf ${DSTROOT}/usr/local/lib\nfi\n\nif [ -n \"${RC_PURPLE}\" ]\nthen\n    mkdir -p \"${DSTROOT}/Developer/Platforms/iPhoneOS.platform/usr/lib\"\n    mv \"${DSTROOT}/Developer/Platforms/iPhoneOS.platform/usr/local/lib/dsc_extractor.bundle\" \"${DSTROOT}/Developer/Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle\"\nfi";
                        showEnvVarsInLog = 0;
                };
                F99B8EB60FEC236500701838 /* suppress macosx dyld_shared_cache_util */ = {
                        showEnvVarsInLog = 0;
                };
                F99B8EB60FEC236500701838 /* suppress macosx dyld_shared_cache_util */ = {
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               F9B0912011F11D1600096D49 /* Sources */ = {
+               F9D1000F14D8D0BA00099D91 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               F9B0912911F11D3400096D49 /* dsc_slider.cpp in Sources */,
+                               F9D1001814D8D13D00099D91 /* dsc_extractor.cpp in Sources */,
+                               F9D1001D14D8D19500099D91 /* dsc_iterator.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                F906E2240639E96400B13DB2 /* dyld_debug.c in Sources */,
                                F9A6D6E4116F9DF20051CC16 /* threadLocalVariables.c in Sources */,
                                F9A6D70C116FBBD10051CC16 /* threadLocalHelpers.s in Sources */,
                                F906E2240639E96400B13DB2 /* dyld_debug.c in Sources */,
                                F9A6D6E4116F9DF20051CC16 /* threadLocalVariables.c in Sources */,
                                F9A6D70C116FBBD10051CC16 /* threadLocalHelpers.s in Sources */,
+                               F9D49CCC1458B95200F86ADD /* start_glue.s in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        target = F9F2A5580F7AEE9800B7C9EB /* libdsc */;
                        targetProxy = F9CE330A120F40EA0098B590 /* PBXContainerItemProxy */;
                };
                        target = F9F2A5580F7AEE9800B7C9EB /* libdsc */;
                        targetProxy = F9CE330A120F40EA0098B590 /* PBXContainerItemProxy */;
                };
+               F9D1004714D8D91100099D91 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = F9D1001114D8D0BA00099D91 /* dsc_extractor */;
+                       targetProxy = F9D1004614D8D91100099D91 /* PBXContainerItemProxy */;
+               };
                F9ED4CA70630A78A00DF4E74 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = F9ED4C970630A76000DF4E74 /* dyld */;
                F9ED4CA70630A78A00DF4E74 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = F9ED4C970630A76000DF4E74 /* dyld */;
                        buildSettings = {
                                COPY_PHASE_STRIP = YES;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                        buildSettings = {
                                COPY_PHASE_STRIP = YES;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                INSTALLHDRS_COPY_PHASE = YES;
                                PRODUCT_NAME = libdyld;
                                ZERO_LINK = NO;
                                INSTALLHDRS_COPY_PHASE = YES;
                                PRODUCT_NAME = libdyld;
                                ZERO_LINK = NO;
                F93937350A94FB2900070A07 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                F93937350A94FB2900070A07 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CLANG_CXX_LIBRARY = "libc++";
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
-                               GCC_DYNAMIC_NO_PIC = YES;
-                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
+                               GCC_DYNAMIC_NO_PIC = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_THREADSAFE_STATICS = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_THREADSAFE_STATICS = NO;
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               PREBINDING = NO;
+                               HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
                                PRODUCT_NAME = update_dyld_shared_cache;
                                VALID_ARCHS = "x86_64 i386";
                        };
                                PRODUCT_NAME = update_dyld_shared_cache;
                                VALID_ARCHS = "x86_64 i386";
                        };
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = x86_64;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ARCHS = x86_64;
+                               CLANG_CXX_LIBRARY = "libc++";
                                COPY_PHASE_STRIP = NO;
                                CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                COPY_PHASE_STRIP = NO;
                                CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_DYNAMIC_NO_PIC = NO;
                                GCC_OPTIMIZATION_LEVEL = s;
                                GCC_THREADSAFE_STATICS = NO;
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                GCC_OPTIMIZATION_LEVEL = s;
                                GCC_THREADSAFE_STATICS = NO;
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
+                               HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
                                INSTALL_PATH = "$(INSTALL_LOCATION)/usr/$(LOCAL)/bin";
                                LOCAL = "$(LOCAL_$(RC_TARGET_CONFIG))";
                                LOCAL_iPhone = local;
                                INSTALL_PATH = "$(INSTALL_LOCATION)/usr/$(LOCAL)/bin";
                                LOCAL = "$(LOCAL_$(RC_TARGET_CONFIG))";
                                LOCAL_iPhone = local;
-                               PREBINDING = NO;
                                PRODUCT_NAME = update_dyld_shared_cache;
                                STRIP_INSTALLED_PRODUCT = YES;
                                STRIP_STYLE = debugging;
                                PRODUCT_NAME = update_dyld_shared_cache;
                                STRIP_INSTALLED_PRODUCT = YES;
                                STRIP_STYLE = debugging;
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_MODEL_TUNING = G5;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                INSTALL_PATH = "$(INSTALL_LOCATION)/usr/local/bin";
                                GCC_MODEL_TUNING = G5;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                INSTALL_PATH = "$(INSTALL_LOCATION)/usr/local/bin";
-                               PREBINDING = NO;
                                PRODUCT_NAME = dyld_shared_cache_util;
                        };
                        name = Debug;
                                PRODUCT_NAME = dyld_shared_cache_util;
                        };
                        name = Debug;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                INSTALL_PATH = "$(INSTALL_LOCATION)/usr/local/bin";
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
                                INSTALL_PATH = "$(INSTALL_LOCATION)/usr/local/bin";
-                               PREBINDING = NO;
                                PRODUCT_NAME = dyld_shared_cache_util;
                                SKIP_INSTALL = NO;
                        };
                        name = Release;
                };
                                PRODUCT_NAME = dyld_shared_cache_util;
                                SKIP_INSTALL = NO;
                        };
                        name = Release;
                };
-               F9B0912411F11D1700096D49 /* Debug */ = {
+               F9D1001314D8D0BB00099D91 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                COPY_PHASE_STRIP = NO;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                COPY_PHASE_STRIP = NO;
+                               DYLIB_COMPATIBILITY_VERSION = "";
+                               DYLIB_CURRENT_VERSION = "";
+                               EXECUTABLE_EXTENSION = bundle;
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
-                               GCC_MODEL_TUNING = G5;
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_OPTIMIZATION_LEVEL = 0;
-                               INSTALL_PATH = /usr/local/lib;
-                               PREBINDING = NO;
-                               PRODUCT_NAME = libdsc_slider;
+                               INSTALL_PATH = "$(INSTALL_LOCATION)/usr/local/lib";
+                               MACH_O_TYPE = mh_bundle;
+                               OTHER_LDFLAGS = "-Wl,-exported_symbol,_dyld_shared_cache_extract_dylibs_progress";
+                               PRODUCT_NAME = dsc_extractor;
                        };
                        name = Debug;
                };
                        };
                        name = Debug;
                };
-               F9B0912511F11D1700096D49 /* Release */ = {
+               F9D1001414D8D0BB00099D91 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               COPY_PHASE_STRIP = NO;
+                               COPY_PHASE_STRIP = YES;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
-                               INSTALLHDRS_COPY_PHASE = YES;
-                               INSTALL_PATH = /usr/local/lib;
-                               PRODUCT_NAME = dsc_slider;
+                               DYLIB_COMPATIBILITY_VERSION = "";
+                               DYLIB_CURRENT_VERSION = "";
+                               EXECUTABLE_EXTENSION = bundle;
+                               GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
+                               INSTALL_PATH = "$(INSTALL_LOCATION)/usr/local/lib";
+                               MACH_O_TYPE = mh_bundle;
+                               OTHER_LDFLAGS = "-Wl,-exported_symbol,_dyld_shared_cache_extract_dylibs_progress";
+                               PRODUCT_NAME = dsc_extractor;
                                ZERO_LINK = NO;
                        };
                        name = Release;
                                ZERO_LINK = NO;
                        };
                        name = Release;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               ARCHS = (
-                                       i386,
-                                       x86_64,
-                               );
+                               ARCHS = "$(ARCHS_STANDARD_64_BIT)";
                                BASE_ADDRESS_armv4t = 0x2fe00000;
                                BASE_ADDRESS_armv5 = 0x2fe00000;
                                BASE_ADDRESS_armv6 = 0x2fe00000;
                                BASE_ADDRESS_armv7 = 0x2fe00000;
                                BASE_ADDRESS_armv4t = 0x2fe00000;
                                BASE_ADDRESS_armv5 = 0x2fe00000;
                                BASE_ADDRESS_armv6 = 0x2fe00000;
                                BASE_ADDRESS_armv7 = 0x2fe00000;
+                               BASE_ADDRESS_armv7f = 0x2fe00000;
+                               BASE_ADDRESS_armv7k = 0x2fe00000;
                                BASE_ADDRESS_i386 = 0x8fe00000;
                                BASE_ADDRESS_ppc = 0x8fe00000;
                                BASE_ADDRESS_x86_64 = 0x7fff5fc00000;
                                BASE_ADDRESS_i386 = 0x8fe00000;
                                BASE_ADDRESS_ppc = 0x8fe00000;
                                BASE_ADDRESS_x86_64 = 0x7fff5fc00000;
+                               CLANG_CXX_LIBRARY = "libc++";
                                CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
                                DEAD_CODE_STRIPPING = YES;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
                                DEAD_CODE_STRIPPING = YES;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                        "$(BASE_ADDRESS_$(CURRENT_ARCH))",
                                        "@$(DERIVED_SOURCES_DIR)/archives.txt",
                                        "-nostdlib",
                                        "$(BASE_ADDRESS_$(CURRENT_ARCH))",
                                        "@$(DERIVED_SOURCES_DIR)/archives.txt",
                                        "-nostdlib",
-                                       "-lgcc",
                                        "-Wl,-e,__dyld_start",
                                        "-Wl,-dylinker",
                                        "-Wl,-dylinker_install_name,/usr/lib/dyld",
                                );
                                        "-Wl,-e,__dyld_start",
                                        "-Wl,-dylinker",
                                        "-Wl,-dylinker_install_name,/usr/lib/dyld",
                                );
-                               PREBINDING = NO;
                                PRODUCT_NAME = dyld;
                                STRIPFLAGS = "-S";
                                UNSTRIPPED_PRODUCT = NO;
                                PRODUCT_NAME = dyld;
                                STRIPFLAGS = "-S";
                                UNSTRIPPED_PRODUCT = NO;
                F9D8C7E0087B087300E93EFB /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                F9D8C7E0087B087300E93EFB /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ARCHS = (
-                                       x86_64,
-                                       i386,
-                               );
+                               ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
                                BASE_ADDRESS_armv4t = 0x2fe00000;
                                BASE_ADDRESS_armv5 = 0x2fe00000;
                                BASE_ADDRESS_armv6 = 0x2fe00000;
                                BASE_ADDRESS_armv7 = 0x2fe00000;
                                BASE_ADDRESS_armv4t = 0x2fe00000;
                                BASE_ADDRESS_armv5 = 0x2fe00000;
                                BASE_ADDRESS_armv6 = 0x2fe00000;
                                BASE_ADDRESS_armv7 = 0x2fe00000;
+                               BASE_ADDRESS_armv7f = 0x2fe00000;
+                               BASE_ADDRESS_armv7k = 0x2fe00000;
                                BASE_ADDRESS_i386 = 0x8fe00000;
                                BASE_ADDRESS_ppc = 0x8fe00000;
                                BASE_ADDRESS_x86_64 = 0x7fff5fc00000;
                                BASE_ADDRESS_i386 = 0x8fe00000;
                                BASE_ADDRESS_ppc = 0x8fe00000;
                                BASE_ADDRESS_x86_64 = 0x7fff5fc00000;
+                               CLANG_CXX_LIBRARY = "libc++";
                                CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
                                DEAD_CODE_STRIPPING = YES;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
                                DEAD_CODE_STRIPPING = YES;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                        "$(BASE_ADDRESS_$(CURRENT_ARCH))",
                                        "@$(DERIVED_SOURCES_DIR)/archives.txt",
                                        "-nostdlib",
                                        "$(BASE_ADDRESS_$(CURRENT_ARCH))",
                                        "@$(DERIVED_SOURCES_DIR)/archives.txt",
                                        "-nostdlib",
-                                       "-lgcc",
                                        "-Wl,-e,__dyld_start",
                                        "-Wl,-dylinker",
                                        "-Wl,-dylinker_install_name,/usr/lib/dyld",
                                );
                                        "-Wl,-e,__dyld_start",
                                        "-Wl,-dylinker",
                                        "-Wl,-dylinker_install_name,/usr/lib/dyld",
                                );
-                               PREBINDING = NO;
                                PRODUCT_NAME = dyld;
                                STRIPFLAGS = "-S";
                                UNSTRIPPED_PRODUCT = NO;
                                PRODUCT_NAME = dyld;
                                STRIPFLAGS = "-S";
                                UNSTRIPPED_PRODUCT = NO;
                                GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
                                HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
                                INSTALL_PATH = /usr/lib/system;
                                GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO;
                                HEADER_SEARCH_PATHS = "$(SRCROOT)/include";
                                INSTALL_PATH = /usr/lib/system;
-                               PREBINDING = NO;
                                PRODUCT_NAME = dyld;
                                WARNING_CFLAGS = (
                                        "-Wmost",
                                PRODUCT_NAME = dyld;
                                WARNING_CFLAGS = (
                                        "-Wmost",
                                INSTALL_PATH = /usr/lib/system;
                                OTHER_LDFLAGS = (
                                        "-nodefaultlibs",
                                INSTALL_PATH = /usr/lib/system;
                                OTHER_LDFLAGS = (
                                        "-nodefaultlibs",
-                                       "-lSystem",
+                                       "-Wl,-upward-lSystem",
                                        "-umbrella",
                                        System,
                                );
                                        "-umbrella",
                                        System,
                                );
-                               PREBINDING = NO;
                                PRODUCT_NAME = dyld;
                                SEPARATE_STRIP = YES;
                                STRIP_INSTALLED_PRODUCT = YES;
                                PRODUCT_NAME = dyld;
                                SEPARATE_STRIP = YES;
                                STRIP_INSTALLED_PRODUCT = YES;
                F9D8C7EA087B087300E93EFB /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                F9D8C7EA087B087300E93EFB /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CLANG_CXX_LIBRARY = "compiler-default";
                        };
                        name = Debug;
                };
                F9D8C7EC087B087300E93EFB /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Debug;
                };
                F9D8C7EC087B087300E93EFB /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               CLANG_CXX_LIBRARY = "compiler-default";
                        };
                        name = Release;
                };
                        };
                        name = Release;
                };
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                COPY_PHASE_STRIP = NO;
                                GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
                                GCC_MODEL_TUNING = G5;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_SYMBOLS_PRIVATE_EXTERN = YES;
                                INSTALL_PATH = /usr/local/lib;
                                GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
                                GCC_MODEL_TUNING = G5;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_SYMBOLS_PRIVATE_EXTERN = YES;
                                INSTALL_PATH = /usr/local/lib;
-                               PREBINDING = NO;
                                PRODUCT_NAME = dsc;
                        };
                        name = Debug;
                                PRODUCT_NAME = dsc;
                        };
                        name = Debug;
                                COPY_PHASE_STRIP = NO;
                                GCC_ENABLE_CPP_EXCEPTIONS = NO;
                                GCC_ENABLE_CPP_RTTI = NO;
                                COPY_PHASE_STRIP = NO;
                                GCC_ENABLE_CPP_EXCEPTIONS = NO;
                                GCC_ENABLE_CPP_RTTI = NO;
-                               GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_ENABLE_OBJC_EXCEPTIONS = NO;
                                GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
                                GCC_MODEL_TUNING = G5;
                                GCC_ENABLE_OBJC_EXCEPTIONS = NO;
                                GCC_INLINES_ARE_PRIVATE_EXTERN = YES;
                                GCC_MODEL_TUNING = G5;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               F9B0912A11F11D3400096D49 /* Build configuration list for PBXNativeTarget "libdsc_slider" */ = {
+               F9D1001714D8D0F100099D91 /* Build configuration list for PBXNativeTarget "dsc_extractor" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        isa = XCConfigurationList;
                        buildConfigurations = (
-                               F9B0912411F11D1700096D49 /* Debug */,
-                               F9B0912511F11D1700096D49 /* Release */,
+                               F9D1001314D8D0BB00099D91 /* Debug */,
+                               F9D1001414D8D0BB00099D91 /* Release */,
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                        );
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
index 04137accc65e3f5b351b1a78900a343bd49bbf7e..eaadf6488b8c5e32e81b0f7ea05799c23f11093d 100644 (file)
@@ -35,7 +35,7 @@ extern "C" {
 /*
  * Prior to Mac OS 10.4, this is the interface gdb used to discover the mach-o images loaded in a process
  */
 /*
  * Prior to Mac OS 10.4, this is the interface gdb used to discover the mach-o images loaded in a process
  */
-#if __ppc__ || __i386__
+#if __i386__
 /*
  * 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
 /*
  * 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
index b33c23197c2ac77d5b905fa1a4312e8fe6341318..9464fb818e339e7ed794da295709bb919f02664d 100644 (file)
@@ -178,6 +178,41 @@ extern const char* dyld_image_path_containing_address(const void* addr);
 
 
 
 
 
 
+
+//
+// This is finds the SDK version a binary was built against.
+// Returns zero on error, or if SDK version could not be determined.
+//
+// Exists in Mac OS X 10.8 and later 
+extern uint32_t dyld_get_sdk_version(const struct mach_header* mh);
+
+
+//
+// This is finds the SDK version the main executable was built against.
+// Returns zero on error, or if SDK version could not be determined.
+//
+// Exists in Mac OS X 10.8 and later 
+extern uint32_t dyld_get_program_sdk_version();
+
+
+//
+// This is finds the min OS version a binary was built to run on.
+// Returns zero on error, or if no min OS recorded in binary.
+//
+// Exists in Mac OS X 10.8 and later 
+extern uint32_t dyld_get_min_os_version(const struct mach_header* mh);
+
+
+//
+// This is finds the min OS version the main executable was built to run on.
+// Returns zero on error, or if no min OS recorded in binary.
+//
+// Exists in Mac OS X 10.8 and later 
+extern uint32_t dyld_get_program_min_os_version();
+
+
+
+
 #if __IPHONE_OS_VERSION_MIN_REQUIRED   
 //
 // Returns if any OS dylib has overridden its copy in the shared cache
 #if __IPHONE_OS_VERSION_MIN_REQUIRED   
 //
 // Returns if any OS dylib has overridden its copy in the shared cache
diff --git a/include/objc-shared-cache.h b/include/objc-shared-cache.h
new file mode 100644 (file)
index 0000000..b7db57d
--- /dev/null
@@ -0,0 +1,1363 @@
+/* 
+ * Copyright (c) 2008 Apple 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@
+ */
+
+/*
+Portions derived from:
+
+--------------------------------------------------------------------
+lookup8.c, by Bob Jenkins, January 4 1997, Public Domain.
+hash(), hash2(), hash3, and mix() are externally useful functions.
+Routines to test the hash are included if SELF_TEST is defined.
+You can use this free for any purpose.  It has no warranty.
+--------------------------------------------------------------------
+
+------------------------------------------------------------------------------
+perfect.c: code to generate code for a hash for perfect hashing.
+(c) Bob Jenkins, September 1996, December 1999
+You may use this code in any way you wish, and it is free.  No warranty.
+I hereby place this in the public domain.
+Source is http://burtleburtle.net/bob/c/perfect.c
+------------------------------------------------------------------------------
+*/
+
+/*
+ * objc-selopt.h
+ * Interface between libobjc and dyld 
+ * for selector uniquing in the dyld shared cache.
+ *
+ * When building the shared cache, dyld locates all selectors and selector 
+ * references in the cached images. It builds a perfect hash table out of 
+ * them and writes the table into the shared cache copy of libobjc.
+ * libobjc then uses that table as the builtin selector list.
+ *
+ * Versioning
+ * The table has a version number. dyld and objc can both ignore the table 
+ * if the other used the wrong version number.
+ *
+ * Completeness
+ * Not all libraries are in the shared cache. Libraries that are in the 
+ * shared cache and were optimized are specially marked. Libraries on 
+ * disk never include those marks.
+ *
+ * Coherency
+ * Libraries optimized in the shared cache can be replaced by unoptimized 
+ * copies from disk when loaded. The copy from disk is not marked and will 
+ * be fixed up by libobjc. The shared cache copy is still mapped into the 
+ * process, so the table can point to cstring data in that library's part 
+ * of the shared cache without trouble.
+ * 
+ * Atomicity
+ * dyld writes the table itself last. If dyld marks some metadata as 
+ * updated but then fails to write a table for some reason, libobjc 
+ * fixes up all metadata as if it were not marked.
+ */
+
+#ifndef _OBJC_SELOPT_H
+#define _OBJC_SELOPT_H
+
+/*
+  DO NOT INCLUDE ANY objc HEADERS HERE
+  dyld USES THIS FILE AND CANNOT SEE THEM
+*/
+#include <stdint.h>
+#include <stdlib.h>
+#ifdef SELOPT_WRITE
+#include <ext/hash_map>
+#endif
+/*
+  DO NOT INCLUDE ANY objc HEADERS HERE
+  dyld USES THIS FILE AND CANNOT SEE THEM
+*/
+
+#ifndef STATIC_ASSERT
+#   define STATIC_ASSERT(x) _STATIC_ASSERT2(x, __LINE__)
+#   define _STATIC_ASSERT2(x, line) _STATIC_ASSERT3(x, line)
+#   define _STATIC_ASSERT3(x, line)                                     \
+        typedef struct {                                                \
+            int _static_assert[(x) ? 0 : -1];                           \
+        } _static_assert_ ## line __attribute__((unavailable)) 
+#endif
+
+#define SELOPT_DEBUG 0
+
+#define S32(x) x = little_endian ? OSSwapHostToLittleInt32(x) : OSSwapHostToBigInt32(x)
+#define S64(x) x = little_endian ? OSSwapHostToLittleInt64(x) : OSSwapHostToBigInt64(x)
+
+namespace objc_opt {
+
+typedef int32_t objc_stringhash_offset_t;
+typedef uint8_t objc_stringhash_check_t;
+
+#ifdef SELOPT_WRITE
+
+// Perfect hash code is at the end of this file.
+
+struct perfect_hash {
+    uint32_t capacity;
+    uint32_t occupied;
+    uint32_t shift;
+    uint32_t mask;
+    uint64_t salt;
+    
+    uint32_t scramble[256];
+    uint8_t *tab;  // count == mask+1; free with delete[]
+    
+    perfect_hash() : tab(0) { }
+    
+    ~perfect_hash() { if (tab) delete[] tab; }
+};
+
+struct eqstr {
+    bool operator()(const char* s1, const char* s2) const {
+        return strcmp(s1, s2) == 0;
+    }
+};
+
+// cstring => cstring's vmaddress
+// (used for selector names and class names)
+typedef __gnu_cxx::hash_map<const char *, uint64_t, __gnu_cxx::hash<const char *>, eqstr> string_map;
+
+// class name => (class vmaddress, header_info vmaddress)
+typedef __gnu_cxx::hash_multimap<const char *, std::pair<uint64_t, uint64_t>, __gnu_cxx::hash<const char *>, eqstr> class_map;
+
+static perfect_hash make_perfect(const string_map& strings);
+
+#endif
+
+static uint64_t lookup8( uint8_t *k, size_t length, uint64_t level);
+
+// Precomputed perfect hash table of strings.
+// Base class for precomputed selector table and class table.
+// Edit objc-sel-table.s and OPT_INITIALIZER if you change this structure.
+struct objc_stringhash_t {
+    uint32_t capacity;
+    uint32_t occupied;
+    uint32_t shift;
+    uint32_t mask;
+    uint32_t zero;
+    uint32_t unused; // alignment pad
+    uint64_t salt;
+    
+    uint32_t scramble[256];
+    uint8_t tab[0];                   /* tab[mask+1] (always power-of-2) */
+    // uint8_t checkbytes[capacity];  /* check byte for each string */
+    // int32_t offsets[capacity];     /* offsets from &capacity to cstrings */
+
+    objc_stringhash_check_t *checkbytes() { return (objc_stringhash_check_t *)&tab[mask+1]; }
+    const objc_stringhash_check_t *checkbytes() const { return (const objc_stringhash_check_t *)&tab[mask+1]; }
+
+    objc_stringhash_offset_t *offsets() { return (objc_stringhash_offset_t *)&checkbytes()[capacity]; }
+    const objc_stringhash_offset_t *offsets() const { return (const objc_stringhash_offset_t *)&checkbytes()[capacity]; }
+
+    uint32_t hash(const char *key) const
+    {
+        uint64_t val = lookup8((uint8_t*)key, strlen(key), salt);
+        uint32_t index = (uint32_t)(val>>shift) ^ scramble[tab[val&mask]];
+        return index;
+    }
+
+    // The check bytes areused to reject strings that aren't in the table
+    // without paging in the table's cstring data. This checkbyte calculation 
+    // catches 4785/4815 rejects when launching Safari; a perfect checkbyte 
+    // would catch 4796/4815.
+    objc_stringhash_check_t checkbyte(const char *key) const
+    {
+        return 
+            ((key[0] & 0x7) << 5)
+            |
+            (strlen(key) & 0x1f);
+    }
+
+#define INDEX_NOT_FOUND (~(uint32_t)0)
+
+    uint32_t getIndex(const char *key) const 
+    {
+        uint32_t h = hash(key);
+
+        // Use check byte to reject without paging in the table's cstrings
+        objc_stringhash_check_t h_check = checkbytes()[h];
+        objc_stringhash_check_t key_check = checkbyte(key);
+        bool check_fail = (h_check != key_check);
+#if ! SELOPT_DEBUG
+        if (check_fail) return INDEX_NOT_FOUND;
+#endif
+
+        const char *result = (const char *)this + offsets()[h];
+        if (0 != strcmp(key, result)) return INDEX_NOT_FOUND;
+
+#if SELOPT_DEBUG
+        if (check_fail) abort();
+#endif
+
+        return h;
+    }
+
+#ifdef SELOPT_WRITE
+
+    size_t size() 
+    {
+        return sizeof(objc_stringhash_t) 
+            + mask+1 
+            + capacity * sizeof(objc_stringhash_check_t) 
+            + capacity * sizeof(objc_stringhash_offset_t);
+    }
+
+    void byteswap(bool little_endian) 
+    {
+        // tab and checkbytes are arrays of bytes, no swap needed
+        for (uint32_t i = 0; i < 256; i++) {
+            S32(scramble[i]);
+        }
+        objc_stringhash_offset_t *o = offsets();
+        for (uint32_t i = 0; i < capacity; i++) {
+            S32(o[i]);
+        }
+        
+        S32(capacity);
+        S32(occupied);
+        S32(shift);
+        S32(mask);
+        S32(zero);
+        S64(salt);
+    }
+
+    const char *write(uint64_t base, size_t remaining, string_map& strings)
+    {        
+        if (sizeof(objc_stringhash_t) > remaining) {
+            return "selector section too small (metadata not optimized)";
+        }
+
+        if (strings.size() == 0) {
+            bzero(this, sizeof(objc_stringhash_t));
+            return NULL;
+        }
+        
+        perfect_hash phash = make_perfect(strings);
+        if (phash.capacity == 0) {
+            return "perfect hash failed (metadata not optimized)";
+        }
+
+        // Set header
+        capacity = phash.capacity;
+        occupied = phash.occupied;
+        shift = phash.shift;
+        mask = phash.mask;
+        zero = 0;
+        unused = 0;
+        salt = phash.salt;
+
+        if (size() > remaining) {
+            return "selector section too small (metadata not optimized)";
+        }
+        
+        // Set hash data
+        for (uint32_t i = 0; i < 256; i++) {
+            scramble[i] = phash.scramble[i];
+        }
+        for (uint32_t i = 0; i < phash.mask+1; i++) {
+            tab[i] = phash.tab[i];
+        }
+        
+        // Set offsets to ""
+        for (uint32_t i = 0; i < phash.capacity; i++) {
+            offsets()[i] = 
+                (objc_stringhash_offset_t)offsetof(objc_stringhash_t, zero);
+        }
+        // Set checkbytes to 0
+        for (uint32_t i = 0; i < phash.capacity; i++) {
+            checkbytes()[i] = 0;
+        }
+        
+        // Set real string offsets and checkbytes
+#       define SHIFT (64 - 8*sizeof(objc_stringhash_offset_t))
+        string_map::const_iterator s;
+        for (s = strings.begin(); s != strings.end(); ++s) {
+            int64_t offset = s->second - base;
+            if ((offset<<SHIFT)>>SHIFT != offset) {
+                return "selector offset too big (metadata not optimized)";
+            }
+
+            uint32_t h = hash(s->first);
+            offsets()[h] = (objc_stringhash_offset_t)offset;
+            checkbytes()[h] = checkbyte(s->first);
+        }
+#       undef SHIFT
+        
+        return NULL;
+    }
+
+// SELOPT_WRITE
+#endif
+};
+
+
+// Precomputed selector table.
+// Edit objc-sel-table.s and OPT_INITIALIZER if you change this structure.
+struct objc_selopt_t : objc_stringhash_t { 
+    const char *get(const char *key) const 
+    {
+        uint32_t h = getIndex(key);
+        if (h == INDEX_NOT_FOUND) return NULL;
+        
+        return (const char *)this + offsets()[h];
+    }
+};
+
+// Precomputed class list.
+// Edit objc-sel-table.s and OPT_INITIALIZER if you change these structures.
+
+struct objc_classheader_t {
+    objc_stringhash_offset_t clsOffset;
+    objc_stringhash_offset_t hiOffset;
+
+    // For duplicate class names:
+    // clsOffset = count<<1 | 1
+    // duplicated classes are duplicateOffsets[hiOffset..hiOffset+count-1]
+    bool isDuplicate() const { return clsOffset & 1; }
+    uint32_t duplicateCount() const { return clsOffset >> 1; }
+    uint32_t duplicateIndex() const { return hiOffset; }
+};
+
+
+struct objc_clsopt_t : objc_stringhash_t {
+    // ...objc_stringhash_t fields...
+    // objc_classheader_t classOffsets[capacity]; /* offsets from &capacity to class_t and header_info */
+    // uint32_t duplicateCount;
+    // objc_classheader_t duplicateOffsets[duplicatedClasses];
+
+    objc_classheader_t *classOffsets() { return (objc_classheader_t *)&offsets()[capacity]; }
+    const objc_classheader_t *classOffsets() const { return (const objc_classheader_t *)&offsets()[capacity]; }
+    
+    uint32_t& duplicateCount() { return *(uint32_t *)&classOffsets()[capacity]; }
+    const uint32_t& duplicateCount() const { return *(const uint32_t *)&classOffsets()[capacity]; }
+
+    objc_classheader_t *duplicateOffsets() { return (objc_classheader_t *)(&duplicateCount()+1); }
+    const objc_classheader_t *duplicateOffsets() const { return (const objc_classheader_t *)(&duplicateCount()+1); }
+
+    // 0/NULL/NULL: not found
+    // 1/ptr/ptr: found exactly one
+    // n/NULL/NULL:  found N - use getClassesAndHeaders() instead
+    uint32_t getClassAndHeader(const char *key, void*& cls, void*& hi) const 
+    {
+        uint32_t h = getIndex(key);
+        if (h == INDEX_NOT_FOUND) { 
+            cls = NULL;
+            hi = NULL;
+            return 0;
+        }
+
+        const objc_classheader_t& clshi = classOffsets()[h];
+        if (! clshi.isDuplicate()) {
+            // class appears in exactly one header
+            cls = (void *)((const char *)this + clshi.clsOffset);
+            hi  = (void *)((const char *)this + clshi.hiOffset);
+            return 1;
+        } 
+        else {
+            // class appears in more than one header - use getClassesAndHeaders
+            cls = NULL;
+            hi = NULL;
+            return clshi.duplicateCount();
+        }
+    }
+
+    void getClassesAndHeaders(const char *key, void **cls, void **hi) const 
+    {
+        uint32_t h = getIndex(key);
+        if (h == INDEX_NOT_FOUND) return;
+
+        const objc_classheader_t& clshi = classOffsets()[h];
+        if (! clshi.isDuplicate()) {
+            // class appears in exactly one header
+            cls[0] = (void *)((const char *)this + clshi.clsOffset);
+            hi[0]  = (void *)((const char *)this + clshi.hiOffset);
+        } 
+        else {
+            // class appears in more than one header
+            uint32_t count = clshi.duplicateCount();
+            const objc_classheader_t *list = 
+                &duplicateOffsets()[clshi.duplicateIndex()];
+            for (uint32_t i = 0; i < count; i++) {
+                cls[i] = (void *)((const char *)this + list[i].clsOffset);
+                hi[i]  = (void *)((const char *)this + list[i].hiOffset);
+            }
+        }
+    }
+
+#ifdef SELOPT_WRITE
+
+    size_t size() 
+    {
+        return
+            objc_stringhash_t::size()
+            + capacity * sizeof(objc_classheader_t)
+            + sizeof(duplicateCount())
+            + duplicateCount() * sizeof(objc_classheader_t);
+    }
+
+    void byteswap(bool little_endian) 
+    {
+        objc_classheader_t *o;
+        
+        o = classOffsets();
+        for (uint32_t i = 0; i < capacity; i++) {
+            S32(o[i].clsOffset);
+            S32(o[i].hiOffset);
+        }
+
+        o = duplicateOffsets();
+        for (uint32_t i = 0; i < duplicateCount(); i++) {
+            S32(o[i].clsOffset);
+            S32(o[i].hiOffset);
+        }
+
+        S32(duplicateCount());
+
+        objc_stringhash_t::byteswap(little_endian);
+    }
+    
+    const char *write(uint64_t base, size_t remaining, 
+                      string_map& strings, class_map& classes, bool verbose)
+    {
+        const char *err;
+        err = objc_stringhash_t::write(base, remaining, strings);
+        if (err) return err;
+
+        if (size() > remaining) {
+            return "selector section too small (metadata not optimized)";
+        }
+
+        // Set class offsets to &zero
+        objc_stringhash_offset_t zeroOffset = 
+            (objc_stringhash_offset_t)offsetof(objc_stringhash_t, zero);
+        for (uint32_t i = 0; i < capacity; i++) {
+            classOffsets()[i].clsOffset = zeroOffset;
+            classOffsets()[i].hiOffset = zeroOffset;
+        }
+        
+        // Set real class offsets
+#       define SHIFT (64 - 8*sizeof(objc_stringhash_offset_t))
+        class_map::const_iterator c;
+        for (c = classes.begin(); c != classes.end(); ++c) {
+            uint32_t h = getIndex(c->first);
+            if (h == INDEX_NOT_FOUND) {
+                return "class list busted (metadata not optimized)";
+            }
+
+            if (classOffsets()[h].clsOffset != zeroOffset) {
+                // already did this class
+                continue;
+            }
+
+            uint32_t count = classes.count(c->first);
+            if (count == 1) {
+                // only one class with this name
+
+                int64_t coff = c->second.first - base;
+                int64_t hoff = c->second.second - base;
+                if ((coff<<SHIFT)>>SHIFT != coff) {
+                    return "class offset too big (metadata not optimized)";
+                }
+                if ((hoff<<SHIFT)>>SHIFT != hoff) {
+                    return "header offset too big (metadata not optimized)";
+                }
+
+                classOffsets()[h].clsOffset = (objc_stringhash_offset_t)coff;
+                classOffsets()[h].hiOffset  = (objc_stringhash_offset_t)hoff;
+            }
+            else {
+                // class name has duplicates - write them all now
+                if (verbose) {
+                    fprintf(stderr, "update_dyld_shared_cache: %u duplicates of Objective-C class %s\n", count, c->first);
+                }
+
+                uint32_t dest = duplicateCount();
+                duplicateCount() += count;                
+                if (size() > remaining) {
+                    return "selector section too small (metadata not optimized)";
+                }
+
+                // classOffsets() instead contains count and array index
+                classOffsets()[h].clsOffset = count*2 + 1;
+                classOffsets()[h].hiOffset = dest;
+
+                std::pair<class_map::const_iterator, class_map::const_iterator>
+                    duplicates = classes.equal_range(c->first);
+                class_map::const_iterator dup;
+                for (dup = duplicates.first; dup != duplicates.second; ++dup) {
+                    int64_t coff = dup->second.first - base;
+                    int64_t hoff = dup->second.second - base;
+                    if ((coff<<SHIFT)>>SHIFT != coff) {
+                        return "class offset too big (metadata not optimized)";
+                    }
+                    if ((hoff<<SHIFT)>>SHIFT != hoff) {
+                        return "header offset too big (metadata not optimized)";
+                    }
+                    
+                    duplicateOffsets()[dest].clsOffset = (objc_stringhash_offset_t)coff;
+                    duplicateOffsets()[dest].hiOffset  = (objc_stringhash_offset_t)hoff;
+                    dest++;
+                }
+            } 
+        }
+#       undef SHIFT
+        
+        return NULL;
+    }
+
+// SELOPT_WRITE
+#endif
+};
+
+// Precomputed image list.
+struct objc_headeropt_t;
+
+// Precomputed class list.
+struct objc_clsopt_t;
+
+// Edit objc-sel-table.s if you change this value.
+enum { VERSION = 12 };
+
+// Top-level optimization structure.
+// Edit objc-sel-table.s and OPT_INITIALIZER if you change this structure.
+struct objc_opt_t {
+    uint32_t version;
+    int32_t selopt_offset;
+    int32_t headeropt_offset;
+    int32_t clsopt_offset;
+
+    const objc_selopt_t* selopt() const { 
+        if (selopt_offset == 0) return NULL;
+        return (objc_selopt_t *)((uint8_t *)this + selopt_offset);
+    }
+    objc_selopt_t* selopt() { 
+        if (selopt_offset == 0) return NULL;
+        return (objc_selopt_t *)((uint8_t *)this + selopt_offset);
+    }
+
+    struct objc_headeropt_t* headeropt() const { 
+        if (headeropt_offset == 0) return NULL;
+        return (struct objc_headeropt_t *)((uint8_t *)this + headeropt_offset);
+    }
+
+    struct objc_clsopt_t* clsopt() const { 
+        if (clsopt_offset == 0) return NULL;
+        return (objc_clsopt_t *)((uint8_t *)this + clsopt_offset);
+    }
+};
+
+// sizeof(objc_opt_t) must be pointer-aligned
+STATIC_ASSERT(sizeof(objc_opt_t) % sizeof(void*) == 0);
+
+// Initializer for empty opt of type uint32_t[].
+#define X8(x) x, x, x, x, x, x, x, x
+#define X64(x) X8(x), X8(x), X8(x), X8(x), X8(x), X8(x), X8(x), X8(x)
+#define X256(x) X64(x), X64(x), X64(x), X64(x)
+#define OPT_INITIALIZER {                                           \
+        /* objc_opt_t */                                            \
+        objc_opt::VERSION, 16, 0, 0,                                \
+        /* objc_selopt_t */                                         \
+        4, 4, 63, 3, 0, 0, 0,0, X256(0), 0, 0, 16, 16, 16, 16       \
+        /* no objc_headeropt_t */                                   \
+        /* no objc_clsopt_t */                                      \
+}
+
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 64-bit values reversibly.
+mix() takes 48 machine instructions, but only 24 cycles on a superscalar
+  machine (like Intel's new MMX architecture).  It requires 4 64-bit
+  registers for 4::2 parallelism.
+All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of
+  (a,b,c), and all deltas of bottom bits were tested.  All deltas were
+  tested both on random keys and on keys that were nearly all zero.
+  These deltas all cause every bit of c to change between 1/3 and 2/3
+  of the time (well, only 113/400 to 287/400 of the time for some
+  2-bit delta).  These deltas all cause at least 80 bits to change
+  among (a,b,c) when the mix is run either forward or backward (yes it
+  is reversible).
+This implies that a hash using mix64 has no funnels.  There may be
+  characteristics with 3-bit deltas or bigger, I didn't test for
+  those.
+--------------------------------------------------------------------
+*/
+#define mix64(a,b,c) \
+{ \
+  a -= b; a -= c; a ^= (c>>43); \
+  b -= c; b -= a; b ^= (a<<9); \
+  c -= a; c -= b; c ^= (b>>8); \
+  a -= b; a -= c; a ^= (c>>38); \
+  b -= c; b -= a; b ^= (a<<23); \
+  c -= a; c -= b; c ^= (b>>5); \
+  a -= b; a -= c; a ^= (c>>35); \
+  b -= c; b -= a; b ^= (a<<49); \
+  c -= a; c -= b; c ^= (b>>11); \
+  a -= b; a -= c; a ^= (c>>12); \
+  b -= c; b -= a; b ^= (a<<18); \
+  c -= a; c -= b; c ^= (b>>22); \
+}
+
+/*
+--------------------------------------------------------------------
+hash() -- hash a variable-length key into a 64-bit value
+  k     : the key (the unaligned variable-length array of bytes)
+  len   : the length of the key, counting by bytes
+  level : can be any 8-byte value
+Returns a 64-bit value.  Every bit of the key affects every bit of
+the return value.  No funnels.  Every 1-bit and 2-bit delta achieves
+avalanche.  About 41+5len instructions.
+
+The best hash table sizes are powers of 2.  There is no need to do
+mod a prime (mod is sooo slow!).  If you need less than 64 bits,
+use a bitmask.  For example, if you need only 10 bits, do
+  h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+  for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+
+By Bob Jenkins, Jan 4 1997.  bob_jenkins@burtleburtle.net.  You may
+use this code any way you wish, private, educational, or commercial,
+but I would appreciate if you give me credit.
+
+See http://burtleburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^^64
+is acceptable.  Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+static uint64_t lookup8( uint8_t *k, size_t length, uint64_t level)
+// uint8_t *k;        /* the key */
+// uint64_t  length;   /* the length of the key */
+// uint64_t  level;    /* the previous hash, or an arbitrary value */
+{
+  uint64_t a,b,c;
+  size_t len;
+
+  /* Set up the internal state */
+  len = length;
+  a = b = level;                         /* the previous hash value */
+  c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */
+
+  /*---------------------------------------- handle most of the key */
+  while (len >= 24)
+  {
+    a += (k[0]        +((uint64_t)k[ 1]<< 8)+((uint64_t)k[ 2]<<16)+((uint64_t)k[ 3]<<24)
+     +((uint64_t)k[4 ]<<32)+((uint64_t)k[ 5]<<40)+((uint64_t)k[ 6]<<48)+((uint64_t)k[ 7]<<56));
+    b += (k[8]        +((uint64_t)k[ 9]<< 8)+((uint64_t)k[10]<<16)+((uint64_t)k[11]<<24)
+     +((uint64_t)k[12]<<32)+((uint64_t)k[13]<<40)+((uint64_t)k[14]<<48)+((uint64_t)k[15]<<56));
+    c += (k[16]       +((uint64_t)k[17]<< 8)+((uint64_t)k[18]<<16)+((uint64_t)k[19]<<24)
+     +((uint64_t)k[20]<<32)+((uint64_t)k[21]<<40)+((uint64_t)k[22]<<48)+((uint64_t)k[23]<<56));
+    mix64(a,b,c);
+    k += 24; len -= 24;
+  }
+
+  /*------------------------------------- handle the last 23 bytes */
+  c += length;
+  switch(len)              /* all the case statements fall through */
+  {
+  case 23: c+=((uint64_t)k[22]<<56);
+  case 22: c+=((uint64_t)k[21]<<48);
+  case 21: c+=((uint64_t)k[20]<<40);
+  case 20: c+=((uint64_t)k[19]<<32);
+  case 19: c+=((uint64_t)k[18]<<24);
+  case 18: c+=((uint64_t)k[17]<<16);
+  case 17: c+=((uint64_t)k[16]<<8);
+    /* the first byte of c is reserved for the length */
+  case 16: b+=((uint64_t)k[15]<<56);
+  case 15: b+=((uint64_t)k[14]<<48);
+  case 14: b+=((uint64_t)k[13]<<40);
+  case 13: b+=((uint64_t)k[12]<<32);
+  case 12: b+=((uint64_t)k[11]<<24);
+  case 11: b+=((uint64_t)k[10]<<16);
+  case 10: b+=((uint64_t)k[ 9]<<8);
+  case  9: b+=((uint64_t)k[ 8]);
+  case  8: a+=((uint64_t)k[ 7]<<56);
+  case  7: a+=((uint64_t)k[ 6]<<48);
+  case  6: a+=((uint64_t)k[ 5]<<40);
+  case  5: a+=((uint64_t)k[ 4]<<32);
+  case  4: a+=((uint64_t)k[ 3]<<24);
+  case  3: a+=((uint64_t)k[ 2]<<16);
+  case  2: a+=((uint64_t)k[ 1]<<8);
+  case  1: a+=((uint64_t)k[ 0]);
+    /* case 0: nothing left to add */
+  }
+  mix64(a,b,c);
+  /*-------------------------------------------- report the result */
+  return c;
+}
+
+
+#ifdef SELOPT_WRITE
+
+/*
+------------------------------------------------------------------------------
+This generates a minimal perfect hash function.  That means, given a
+set of n keys, this determines a hash function that maps each of
+those keys into a value in 0..n-1 with no collisions.
+
+The perfect hash function first uses a normal hash function on the key
+to determine (a,b) such that the pair (a,b) is distinct for all
+keys, then it computes a^scramble[tab[b]] to get the final perfect hash.
+tab[] is an array of 1-byte values and scramble[] is a 256-term array of 
+2-byte or 4-byte values.  If there are n keys, the length of tab[] is a 
+power of two between n/3 and n.
+
+I found the idea of computing distinct (a,b) values in "Practical minimal 
+perfect hash functions for large databases", Fox, Heath, Chen, and Daoud, 
+Communications of the ACM, January 1992.  They found the idea in Chichelli 
+(CACM Jan 1980).  Beyond that, our methods differ.
+
+The key is hashed to a pair (a,b) where a in 0..*alen*-1 and b in
+0..*blen*-1.  A fast hash function determines both a and b
+simultaneously.  Any decent hash function is likely to produce
+hashes so that (a,b) is distinct for all pairs.  I try the hash
+using different values of *salt* until all pairs are distinct.
+
+The final hash is (a XOR scramble[tab[b]]).  *scramble* is a
+predetermined mapping of 0..255 into 0..smax-1.  *tab* is an
+array that we fill in in such a way as to make the hash perfect.
+
+First we fill in all values of *tab* that are used by more than one
+key.  We try all possible values for each position until one works.
+
+This leaves m unmapped keys and m values that something could hash to.
+If you treat unmapped keys as lefthand nodes and unused hash values
+as righthand nodes, and draw a line connecting each key to each hash
+value it could map to, you get a bipartite graph.  We attempt to
+find a perfect matching in this graph.  If we succeed, we have
+determined a perfect hash for the whole set of keys.
+
+*scramble* is used because (a^tab[i]) clusters keys around *a*.
+------------------------------------------------------------------------------
+*/
+
+typedef uint64_t  ub8;
+#define UB8MAXVAL 0xffffffffffffffffLL
+#define UB8BITS 64
+typedef uint32_t  ub4;
+#define UB4MAXVAL 0xffffffff
+#define UB4BITS 32
+typedef uint16_t  ub2;
+#define UB2MAXVAL 0xffff
+#define UB2BITS 16
+typedef uint8_t ub1;
+#define UB1MAXVAL 0xff
+#define UB1BITS 8
+
+#define TRUE  1
+#define FALSE 0
+
+#define SCRAMBLE_LEN 256 // ((ub4)1<<16)                    /* length of *scramble* */
+#define RETRY_INITKEY 2048  /* number of times to try to find distinct (a,b) */
+#define RETRY_PERFECT 4     /* number of times to try to make a perfect hash */
+
+
+/* representation of a key */
+struct key
+{
+  ub1        *name_k;                                      /* the actual key */
+  ub4         len_k;                         /* the length of the actual key */
+  ub4         hash_k;                 /* the initial hash value for this key */
+/* beyond this point is mapping-dependent */
+  ub4         a_k;                            /* a, of the key maps to (a,b) */
+  ub4         b_k;                            /* b, of the key maps to (a,b) */
+  struct key *nextb_k;                               /* next key with this b */
+};
+typedef  struct key  key;
+
+/* things indexed by b of original (a,b) pair */
+struct bstuff
+{
+  ub2  val_b;                                        /* hash=a^tabb[b].val_b */
+  key *list_b;                   /* tabb[i].list_b is list of keys with b==i */
+  ub4  listlen_b;                                        /* length of list_b */
+  ub4  water_b;           /* high watermark of who has visited this map node */
+};
+typedef  struct bstuff  bstuff;
+
+/* things indexed by final hash value */
+struct hstuff
+{
+  key *key_h;                   /* tabh[i].key_h is the key with a hash of i */
+};
+typedef  struct hstuff hstuff;
+
+/* things indexed by queue position */
+struct qstuff
+{
+  bstuff *b_q;                        /* b that currently occupies this hash */
+  ub4     parent_q;     /* queue position of parent that could use this hash */
+  ub2     newval_q;      /* what to change parent tab[b] to to use this hash */
+  ub2     oldval_q;                              /* original value of tab[b] */
+};
+typedef  struct qstuff  qstuff;
+
+
+/*
+------------------------------------------------------------------------------
+Find the mapping that will produce a perfect hash
+------------------------------------------------------------------------------
+*/
+
+/* return the ceiling of the log (base 2) of val */
+static ub4  log2u(ub4 val)
+{
+  ub4 i;
+  for (i=0; ((ub4)1<<i) < val; ++i)
+    ;
+  return i;
+}
+
+/* compute p(x), where p is a permutation of 0..(1<<nbits)-1 */
+/* permute(0)=0.  This is intended and useful. */
+static ub4  permute(ub4 x, ub4 nbits)
+// ub4 x;                                       /* input, a value in some range */
+// ub4 nbits;                                 /* input, number of bits in range */
+{
+  int i;
+  int mask   = ((ub4)1<<nbits)-1;                                /* all ones */
+  int const2 = 1+nbits/2;
+  int const3 = 1+nbits/3;
+  int const4 = 1+nbits/4;
+  int const5 = 1+nbits/5;
+  for (i=0; i<20; ++i)
+  {
+    x = (x+(x<<const2)) & mask; 
+    x = (x^(x>>const3));
+    x = (x+(x<<const4)) & mask;
+    x = (x^(x>>const5));
+  }
+  return x;
+}
+
+/* initialize scramble[] with distinct random values in 0..smax-1 */
+static void scrambleinit(ub4 *scramble, ub4 smax)
+// ub4      *scramble;                            /* hash is a^scramble[tab[b]] */
+// ub4       smax;                    /* scramble values should be in 0..smax-1 */
+{
+  ub4 i;
+
+  /* fill scramble[] with distinct random integers in 0..smax-1 */
+  for (i=0; i<SCRAMBLE_LEN; ++i)
+  {
+    scramble[i] = permute(i, log2u(smax));
+  }
+}
+
+
+/* 
+ * put keys in tabb according to key->b_k
+ * check if the initial hash might work 
+ */
+static int inittab(bstuff *tabb, ub4 blen, key *keys, ub4 nkeys, int complete)
+// bstuff   *tabb;                     /* output, list of keys with b for (a,b) */
+// ub4       blen;                                            /* length of tabb */
+// key      *keys;                               /* list of keys already hashed */
+// int       complete;        /* TRUE means to complete init despite collisions */
+{
+  int  nocollision = TRUE;
+  ub4 i;
+
+  memset((void *)tabb, 0, (size_t)(sizeof(bstuff)*blen));
+
+  /* Two keys with the same (a,b) guarantees a collision */
+  for (i = 0; i < nkeys; i++) {
+    key *mykey = keys+i;
+    key *otherkey;
+
+    for (otherkey=tabb[mykey->b_k].list_b; 
+        otherkey; 
+        otherkey=otherkey->nextb_k)
+    {
+      if (mykey->a_k == otherkey->a_k)
+      {
+        nocollision = FALSE;
+       if (!complete)
+         return FALSE;
+      }
+    }
+    ++tabb[mykey->b_k].listlen_b;
+    mykey->nextb_k = tabb[mykey->b_k].list_b;
+    tabb[mykey->b_k].list_b = mykey;
+  }
+
+  /* no two keys have the same (a,b) pair */
+  return nocollision;
+}
+
+
+/* Do the initial hash for normal mode (use lookup and checksum) */
+static void initnorm(key *keys, ub4 nkeys, ub4 alen, ub4 blen, ub4 smax, ub8 salt)
+// key      *keys;                                          /* list of all keys */
+// ub4       alen;                    /* (a,b) has a in 0..alen-1, a power of 2 */
+// ub4       blen;                    /* (a,b) has b in 0..blen-1, a power of 2 */
+// ub4       smax;                   /* maximum range of computable hash values */
+// ub4       salt;                     /* used to initialize the hash function */
+// gencode  *final;                          /* output, code for the final hash */
+{
+  ub4 loga = log2u(alen);                            /* log based 2 of blen */
+  ub4 i;
+  for (i = 0; i < nkeys; i++) {
+    key *mykey = keys+i;
+    ub8 hash = lookup8(mykey->name_k, mykey->len_k, salt);
+    mykey->a_k = (loga > 0) ? hash>>(UB8BITS-loga) : 0;
+    mykey->b_k = (blen > 1) ? hash&(blen-1) : 0;
+  }
+}
+
+
+/* Try to apply an augmenting list */
+static int apply(bstuff *tabb, hstuff *tabh, qstuff *tabq, ub4 blen, ub4 *scramble, ub4 tail, int rollback)
+// bstuff *tabb;
+// hstuff *tabh;
+// qstuff *tabq;
+// ub4     blen;
+// ub4    *scramble;
+// ub4     tail;
+// int     rollback;          /* FALSE applies augmenting path, TRUE rolls back */
+{
+  ub4     hash;
+  key    *mykey;
+  bstuff *pb;
+  ub4     child;
+  ub4     parent;
+  ub4     stabb;                                         /* scramble[tab[b]] */
+
+  /* walk from child to parent */
+  for (child=tail-1; child; child=parent)
+  {
+    parent = tabq[child].parent_q;                    /* find child's parent */
+    pb     = tabq[parent].b_q;             /* find parent's list of siblings */
+
+    /* erase old hash values */
+    stabb = scramble[pb->val_b];
+    for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+    {
+      hash = mykey->a_k^stabb;
+      if (mykey == tabh[hash].key_h)
+      {                            /* erase hash for all of child's siblings */
+       tabh[hash].key_h = (key *)0;
+      }
+    }
+
+    /* change pb->val_b, which will change the hashes of all parent siblings */
+    pb->val_b = (rollback ? tabq[child].oldval_q : tabq[child].newval_q);
+
+    /* set new hash values */
+    stabb = scramble[pb->val_b];
+    for (mykey=pb->list_b; mykey; mykey=mykey->nextb_k)
+    {
+      hash = mykey->a_k^stabb;
+      if (rollback)
+      {
+       if (parent == 0) continue;                  /* root never had a hash */
+      }
+      else if (tabh[hash].key_h)
+      {
+       /* very rare: roll back any changes */
+        apply(tabb, tabh, tabq, blen, scramble, tail, TRUE);
+       return FALSE;                                  /* failure, collision */
+      }
+      tabh[hash].key_h = mykey;
+    }
+  }
+  return TRUE;
+}
+
+
+/*
+-------------------------------------------------------------------------------
+augment(): Add item to the mapping.
+
+Construct a spanning tree of *b*s with *item* as root, where each
+parent can have all its hashes changed (by some new val_b) with 
+at most one collision, and each child is the b of that collision.
+
+I got this from Tarjan's "Data Structures and Network Algorithms".  The
+path from *item* to a *b* that can be remapped with no collision is 
+an "augmenting path".  Change values of tab[b] along the path so that 
+the unmapped key gets mapped and the unused hash value gets used.
+
+Assuming 1 key per b, if m out of n hash values are still unused, 
+you should expect the transitive closure to cover n/m nodes before 
+an unused node is found.  Sum(i=1..n)(n/i) is about nlogn, so expect
+this approach to take about nlogn time to map all single-key b's.
+-------------------------------------------------------------------------------
+*/
+static int augment(bstuff *tabb, hstuff *tabh, qstuff *tabq, ub4 blen, ub4 *scramble, ub4 smax, bstuff *item, ub4 nkeys, 
+                  ub4 highwater)
+// bstuff   *tabb;                                        /* stuff indexed by b */
+// hstuff   *tabh;  /* which key is associated with which hash, indexed by hash */
+// qstuff   *tabq;            /* queue of *b* values, this is the spanning tree */
+// ub4       blen;                                            /* length of tabb */
+// ub4      *scramble;                      /* final hash is a^scramble[tab[b]] */
+// ub4       smax;                                 /* highest value in scramble */
+// bstuff   *item;                           /* &tabb[b] for the b to be mapped */
+// ub4       nkeys;                         /* final hash must be in 0..nkeys-1 */
+// ub4       highwater;        /* a value higher than any now in tabb[].water_b */
+{
+  ub4  q;                      /* current position walking through the queue */
+  ub4  tail;              /* tail of the queue.  0 is the head of the queue. */
+  ub4  limit=UB1MAXVAL+1;
+  ub4  highhash = smax;
+
+  /* initialize the root of the spanning tree */
+  tabq[0].b_q = item;
+  tail = 1;
+
+  /* construct the spanning tree by walking the queue, add children to tail */
+  for (q=0; q<tail; ++q)
+  {
+    bstuff *myb = tabq[q].b_q;                        /* the b for this node */
+    ub4     i;                              /* possible value for myb->val_b */
+
+    if (q == 1) 
+      break;                                  /* don't do transitive closure */
+
+    for (i=0; i<limit; ++i)
+    {
+      bstuff *childb = (bstuff *)0;             /* the b that this i maps to */
+      key    *mykey;                       /* for walking through myb's keys */
+
+      for (mykey = myb->list_b; mykey; mykey=mykey->nextb_k)
+      {
+       key    *childkey;
+       ub4 hash = mykey->a_k^scramble[i];
+
+       if (hash >= highhash) break;                        /* out of bounds */
+       childkey = tabh[hash].key_h;
+
+       if (childkey)
+       {
+         bstuff *hitb = &tabb[childkey->b_k];
+
+         if (childb)
+         {
+           if (childb != hitb) break;            /* hit at most one child b */
+         }
+         else
+         {
+           childb = hitb;                        /* remember this as childb */
+           if (childb->water_b == highwater) break;     /* already explored */
+         }
+       }
+      }
+      if (mykey) continue;             /* myb with i has multiple collisions */
+
+      /* add childb to the queue of reachable things */
+      if (childb) childb->water_b = highwater;
+      tabq[tail].b_q      = childb;
+      tabq[tail].newval_q = i;     /* how to make parent (myb) use this hash */
+      tabq[tail].oldval_q = myb->val_b;            /* need this for rollback */
+      tabq[tail].parent_q = q;
+      ++tail;
+
+      if (!childb)
+      {                                  /* found an *i* with no collisions? */
+       /* try to apply the augmenting path */
+       if (apply(tabb, tabh, tabq, blen, scramble, tail, FALSE))
+         return TRUE;        /* success, item was added to the perfect hash */
+
+       --tail;                    /* don't know how to handle such a child! */
+      }
+    }
+  }
+  return FALSE;
+}
+
+
+/* find a mapping that makes this a perfect hash */
+static int perfect(bstuff *tabb, hstuff *tabh, qstuff *tabq, ub4 blen, ub4 smax, ub4 *scramble, ub4 nkeys)
+{
+  ub4 maxkeys;                           /* maximum number of keys for any b */
+  ub4 i, j;
+
+#if SELOPT_DEBUG
+  fprintf(stderr, "           blen %d smax %d nkeys %d\n", blen, smax, nkeys);
+#endif
+
+  /* clear any state from previous attempts */
+  memset((void *)tabh, 0, sizeof(hstuff)*smax);
+  memset((void *)tabq, 0, sizeof(qstuff)*(blen+1));
+
+  for (maxkeys=0,i=0; i<blen; ++i) 
+    if (tabb[i].listlen_b > maxkeys) 
+      maxkeys = tabb[i].listlen_b;
+
+  /* In descending order by number of keys, map all *b*s */
+  for (j=maxkeys; j>0; --j)
+    for (i=0; i<blen; ++i)
+      if (tabb[i].listlen_b == j)
+       if (!augment(tabb, tabh, tabq, blen, scramble, smax, &tabb[i], nkeys, 
+                    i+1))
+       {
+         return FALSE;
+       }
+
+  /* Success!  We found a perfect hash of all keys into 0..nkeys-1. */
+  return TRUE;
+}
+
+
+/* guess initial values for alen and blen */
+static void initalen(ub4 *alen, ub4 *blen, ub4 smax, ub4 nkeys)
+// ub4      *alen;                                      /* output, initial alen */
+// ub4      *blen;                                      /* output, initial blen */
+// ub4      smax;    /* input, power of two greater or equal to max hash value */
+// ub4       nkeys;                              /* number of keys being hashed */
+{
+  /*
+   * Find initial *alen, *blen
+   * Initial alen and blen values were found empirically.  Some factors:
+   *
+   * If smax<256 there is no scramble, so tab[b] needs to cover 0..smax-1.
+   *
+   * alen and blen must be powers of 2 because the values in 0..alen-1 and
+   * 0..blen-1 are produced by applying a bitmask to the initial hash function.
+   *
+   * alen must be less than smax, in fact less than nkeys, because otherwise
+   * there would often be no i such that a^scramble[i] is in 0..nkeys-1 for
+   * all the *a*s associated with a given *b*, so there would be no legal
+   * value to assign to tab[b].  This only matters when we're doing a minimal
+   * perfect hash.
+   *
+   * It takes around 800 trials to find distinct (a,b) with nkey=smax*(5/8)
+   * and alen*blen = smax*smax/32.
+   *
+   * Values of blen less than smax/4 never work, and smax/2 always works.
+   *
+   * We want blen as small as possible because it is the number of bytes in
+   * the huge array we must create for the perfect hash.
+   *
+   * When nkey <= smax*(5/8), blen=smax/4 works much more often with 
+   * alen=smax/8 than with alen=smax/4.  Above smax*(5/8), blen=smax/4
+   * doesn't seem to care whether alen=smax/8 or alen=smax/4.  I think it
+   * has something to do with 5/8 = 1/8 * 5.  For example examine 80000, 
+   * 85000, and 90000 keys with different values of alen.  This only matters
+   * if we're doing a minimal perfect hash.
+   *
+   * When alen*blen <= 1<<UB4BITS, the initial hash must produce one integer.
+   * Bigger than that it must produce two integers, which increases the
+   * cost of the hash per character hashed.
+   */
+  *alen = smax;                     /* no reason to restrict alen to smax/2 */
+  *blen = ((nkeys <= smax*0.6) ? smax/16 : 
+           (nkeys <= smax*0.8) ? smax/8 : smax/4);
+  
+  if (*alen < 1) *alen = 1;
+  if (*blen < 1) *blen = 1;
+
+#if SELOPT_DEBUG
+  fprintf(stderr, "alen %d blen %d smax %d nkeys %d\n", *alen, *blen, smax, nkeys);
+#endif
+}
+
+/* 
+** Try to find a perfect hash function.  
+** Return the successful initializer for the initial hash. 
+** Return 0 if no perfect hash could be found.
+*/
+static int findhash(bstuff **tabb, ub4 *alen, ub4 *blen, ub8 *salt, 
+                    ub4 *scramble, ub4 smax, key *keys, ub4 nkeys)
+// bstuff  **tabb;           /* output, tab[] of the perfect hash, length *blen */
+// ub4      *alen;                 /* output, 0..alen-1 is range for a of (a,b) */
+// ub4      *blen;                 /* output, 0..blen-1 is range for b of (a,b) */
+// ub4      *salt;                         /* output, initializes initial hash */
+// ub4      *scramble;                      /* input, hash = a^scramble[tab[b]] */
+// ub4      smax;                           /* input, scramble[i] in 0..smax-1 */
+// key      *keys;                                       /* input, keys to hash */
+// ub4       nkeys;                       /* input, number of keys being hashed */
+{
+  ub4 bad_initkey;                       /* how many times did initkey fail? */
+  ub4 bad_perfect;                       /* how many times did perfect fail? */
+  ub4 si;                        /* trial initializer for initial hash */
+  ub4 maxalen;
+  hstuff *tabh;                       /* table of keys indexed by hash value */
+  qstuff *tabq;    /* table of stuff indexed by queue value, used by augment */
+
+  /* guess initial values for alen and blen */
+  initalen(alen, blen, smax, nkeys);
+
+  scrambleinit(scramble, smax);
+
+  maxalen = smax;
+
+  /* allocate working memory */
+  *tabb = new bstuff[*blen];
+  tabq  = new qstuff[*blen+1];
+  tabh  = new hstuff[smax];
+
+  /* Actually find the perfect hash */
+  *salt = 0;
+  bad_initkey = 0;
+  bad_perfect = 0;
+  for (si=1; ; ++si)
+  {
+    ub4 rslinit;
+    /* Try to find distinct (A,B) for all keys */
+    *salt = si * 0x9e3779b97f4a7c13LL; /* golden ratio (arbitrary value) */
+    initnorm(keys, nkeys, *alen, *blen, smax, *salt);
+    rslinit = inittab(*tabb, *blen, keys, nkeys, FALSE);
+    if (rslinit == 0)
+    {
+      /* didn't find distinct (a,b) */
+      if (++bad_initkey >= RETRY_INITKEY)
+      {
+       /* Try to put more bits in (A,B) to make distinct (A,B) more likely */
+       if (*alen < maxalen)
+       {
+         *alen *= 2;
+       } 
+       else if (*blen < smax)
+       {
+         *blen *= 2;
+         delete[] tabq;
+         delete[] *tabb;
+         *tabb  = new bstuff[*blen];
+         tabq  = new qstuff[*blen+1];
+       }
+       bad_initkey = 0;
+       bad_perfect = 0;
+      }
+      continue;                             /* two keys have same (a,b) pair */
+    }
+
+    /* Given distinct (A,B) for all keys, build a perfect hash */
+    if (!perfect(*tabb, tabh, tabq, *blen, smax, scramble, nkeys))
+    {
+      if (++bad_perfect >= RETRY_PERFECT)
+      {
+       if (*blen < smax)
+       {
+         *blen *= 2;
+         delete[] *tabb;
+         delete[] tabq;
+         *tabb  = new bstuff[*blen];
+         tabq  = new qstuff[*blen+1];
+         --si;               /* we know this salt got distinct (A,B) */
+       }
+       else
+       {
+          return 0;
+       }
+       bad_perfect = 0;
+      }
+      continue;
+    }
+    
+    break;
+  }
+
+  /* free working memory */
+  delete[] tabh;
+  delete[] tabq;
+
+  return 1;
+}
+
+/*
+------------------------------------------------------------------------------
+Input/output type routines
+------------------------------------------------------------------------------
+*/
+
+/* get the list of keys */
+static void getkeys(key **keys, ub4 *nkeys, const string_map& strings)
+{
+  key *buf = new key[strings.size()];
+  size_t i;
+  string_map::const_iterator s;
+  for (i = 0, s = strings.begin(); s != strings.end(); ++s, ++i) {
+    key *mykey = buf+i;
+    mykey->name_k = (ub1 *)s->first;
+    mykey->len_k  = (ub4)strlen(s->first);
+  }
+  *keys = buf;
+  *nkeys = strings.size();
+}
+
+
+static perfect_hash 
+make_perfect(const string_map& strings)
+{
+  ub4       nkeys;                                         /* number of keys */
+  key      *keys;                                    /* head of list of keys */
+  bstuff   *tab;                                       /* table indexed by b */
+  ub4       smax;            /* scramble[] values in 0..smax-1, a power of 2 */
+  ub4       alen;                            /* a in 0..alen-1, a power of 2 */
+  ub4       blen;                            /* b in 0..blen-1, a power of 2 */
+  ub8       salt;                       /* a parameter to the hash function */
+  ub4       scramble[SCRAMBLE_LEN];           /* used in final hash function */
+  int ok;
+  int i;
+  perfect_hash result;
+
+  /* read in the list of keywords */
+  getkeys(&keys, &nkeys, strings);
+
+  /* find the hash */
+  smax = ((ub4)1<<log2u(nkeys));
+  ok = findhash(&tab, &alen, &blen, &salt, 
+                scramble, smax, keys, nkeys);
+  if (!ok) {
+      smax = 2 * ((ub4)1<<log2u(nkeys));
+      ok = findhash(&tab, &alen, &blen, &salt, 
+                    scramble, smax, keys, nkeys);
+  }
+  if (!ok) {
+      bzero(&result, sizeof(result));
+  } else {
+      /* build the tables */
+      result.capacity = smax;
+      result.occupied = nkeys;
+      result.shift = UB8BITS - log2u(alen);
+      result.mask = blen - 1;
+      result.salt = salt;
+      
+      result.tab = new uint8_t[blen];
+      for (i = 0; i < blen; i++) {
+          result.tab[i] = tab[i].val_b;
+      }
+      for (i = 0; i < 256; i++) {
+          result.scramble[i] = scramble[i];
+      }
+  }
+
+  delete[] keys;
+  delete[] tab;
+
+  return result;
+}
+
+// SELOPT_WRITE
+#endif
+
+// namespace objc_selopt
+};
+
+#undef S32
+#undef S64
+
+#endif
index 05d64306f8a7fe3a033fb4ec7b5665dd9084b1dc..e26825d27436b5e4aa26c9e7fc1a0cca1a1d7422 100644 (file)
 //
 // Architectures
 //
 //
 // Architectures
 //
-struct ppc
-{
-       typedef Pointer32<BigEndian>            P;
-       
-};
-
 struct x86
 {
        typedef Pointer32<LittleEndian>         P;
 struct x86
 {
        typedef Pointer32<LittleEndian>         P;
index ac882dc357d4a21dacbb5c55a25dd961a5345988..332478fa19112648dc9185bfe16b1755e5237026 100644 (file)
@@ -97,7 +97,7 @@ private:
        void                                                                            doBindDyldLazyInfo(std::vector<void*>& pointersInData);
        void                                                                            bindDyldInfoAt(uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, 
                                                                                                                                int libraryOrdinal, int64_t addend, 
        void                                                                            doBindDyldLazyInfo(std::vector<void*>& pointersInData);
        void                                                                            bindDyldInfoAt(uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, 
                                                                                                                                int libraryOrdinal, int64_t addend, 
-                                                                                                                               const char* symbolName, bool lazyPointer,
+                                                                                                                               const char* symbolName, bool lazyPointer, bool weakImport,
                                                                                                                                std::vector<void*>& pointersInData);
        pint_t                                                                          resolveUndefined(const macho_nlist<P>* undefinedSymbol);
        bool                                                                            findExportedSymbolAddress(const char* name, pint_t* result, Binder<A>** foundIn, bool* isResolverSymbol);
                                                                                                                                std::vector<void*>& pointersInData);
        pint_t                                                                          resolveUndefined(const macho_nlist<P>* undefinedSymbol);
        bool                                                                            findExportedSymbolAddress(const char* name, pint_t* result, Binder<A>** foundIn, bool* isResolverSymbol);
@@ -190,7 +190,7 @@ Binder<A>::Binder(const MachOLayoutAbstraction& layout, uint64_t dyldBaseAddress
                                fDyldInfo = (macho_dyld_info_command<P>*)cmd;
                                break;
                        case LC_RPATH:
                                fDyldInfo = (macho_dyld_info_command<P>*)cmd;
                                break;
                        case LC_RPATH:
-                               throwf("LC_RPATH not supported in dylibs in dyld shared cache");
+                               throwf("dyld shared cache does not support LC_RPATH found in %s", layout.getFilePath());
                                break;
                        default:
                                if ( cmd->cmd() & LC_REQ_DYLD )
                                break;
                        default:
                                if ( cmd->cmd() & LC_REQ_DYLD )
@@ -262,12 +262,10 @@ Binder<A>::Binder(const MachOLayoutAbstraction& layout, uint64_t dyldBaseAddress
        }
 }
 
        }
 }
 
-template <> uint8_t    Binder<ppc>::pointerRelocSize()    { return 2; }
 template <> uint8_t    Binder<x86>::pointerRelocSize()   { return 2; }
 template <> uint8_t    Binder<x86_64>::pointerRelocSize() { return 3; }
 template <> uint8_t    Binder<arm>::pointerRelocSize() { return 2; }
 
 template <> uint8_t    Binder<x86>::pointerRelocSize()   { return 2; }
 template <> uint8_t    Binder<x86_64>::pointerRelocSize() { return 3; }
 template <> uint8_t    Binder<arm>::pointerRelocSize() { return 2; }
 
-template <> uint8_t    Binder<ppc>::pointerRelocType()    { return GENERIC_RELOC_VANILLA; }
 template <> uint8_t    Binder<x86>::pointerRelocType()   { return GENERIC_RELOC_VANILLA; }
 template <> uint8_t    Binder<x86_64>::pointerRelocType() { return X86_64_RELOC_UNSIGNED; }
 template <> uint8_t    Binder<arm>::pointerRelocType() { return ARM_RELOC_VANILLA; }
 template <> uint8_t    Binder<x86>::pointerRelocType()   { return GENERIC_RELOC_VANILLA; }
 template <> uint8_t    Binder<x86_64>::pointerRelocType() { return X86_64_RELOC_UNSIGNED; }
 template <> uint8_t    Binder<arm>::pointerRelocType() { return ARM_RELOC_VANILLA; }
@@ -363,8 +361,18 @@ void Binder<A>::setDependentBinders(const Map& map)
                                                        }
                                                }
                                        }
                                                        }
                                                }
                                        }
-                                       if ( ! found )
-                                               throwf("in %s can't find dylib %s", this->getDylibID(), path);
+                                       if ( ! found ) {
+                                               if ( cmd->cmd() == LC_LOAD_WEAK_DYLIB ) {
+                                                       BinderAndReExportFlag entry;
+                                                       entry.binder = NULL;
+                                                       entry.reExport = false;
+                                                       fDependentDylibs.push_back(entry);
+                                                       break;
+                                               }
+                                               else {
+                                                       throwf("in %s can't find dylib %s", this->getDylibID(), path);
+                                               }
+                                       }
                                }
                                break;
                }
                                }
                                break;
                }
@@ -534,7 +542,7 @@ void Binder<A>::doSetUpDyldSection()
 
 template <typename A>
 void Binder<A>::bindDyldInfoAt(uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, int libraryOrdinal, 
 
 template <typename A>
 void Binder<A>::bindDyldInfoAt(uint8_t segmentIndex, uint64_t segmentOffset, uint8_t type, int libraryOrdinal, 
-                                                       int64_t addend, const char* symbolName, bool lazyPointer, std::vector<void*>& pointersInData)
+                                                       int64_t addend, const char* symbolName, bool lazyPointer, bool weakImport, std::vector<void*>& pointersInData)
 {
        //printf("%d 0x%08llX type=%d, lib=%d, addend=%lld, symbol=%s\n", segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName);
        const std::vector<MachOLayoutAbstraction::Segment>& segments = this->fLayout.getSegments();
 {
        //printf("%d 0x%08llX type=%d, lib=%d, addend=%lld, symbol=%s\n", segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName);
        const std::vector<MachOLayoutAbstraction::Segment>& segments = this->fLayout.getSegments();
@@ -561,9 +569,16 @@ void Binder<A>::bindDyldInfoAt(uint8_t segmentIndex, uint64_t segmentOffset, uin
        pint_t targetSymbolAddress;
        bool isResolverSymbol;
     Binder<A>* foundIn;
        pint_t targetSymbolAddress;
        bool isResolverSymbol;
     Binder<A>* foundIn;
-       if ( ! binder->findExportedSymbolAddress(symbolName, &targetSymbolAddress, &foundIn, &isResolverSymbol) ) 
-               throwf("could not bind symbol %s in %s expected in %s", symbolName, this->getDylibID(), binder->getDylibID());
-
+       if ( weakImport && (binder == NULL) ) {
+               targetSymbolAddress = 0;
+               foundIn = NULL;
+               isResolverSymbol = false;
+       }
+       else {
+               if ( ! binder->findExportedSymbolAddress(symbolName, &targetSymbolAddress, &foundIn, &isResolverSymbol) ) 
+                       throwf("could not bind symbol %s in %s expected in %s", symbolName, this->getDylibID(), binder->getDylibID());
+       }
+       
        // don't bind lazy pointers to resolver stubs in shared cache
        if ( lazyPointer && isResolverSymbol ) {
         if ( foundIn == this ) {
        // don't bind lazy pointers to resolver stubs in shared cache
        if ( lazyPointer && isResolverSymbol ) {
         if ( foundIn == this ) {
@@ -620,6 +635,7 @@ void Binder<A>::doBindDyldLazyInfo(std::vector<void*>& pointersInData)
        const char* symbolName = NULL;
        int libraryOrdinal = 0;
        int64_t addend = 0;
        const char* symbolName = NULL;
        int libraryOrdinal = 0;
        int64_t addend = 0;
+       bool weakImport = false;
        while ( p < end ) {
                uint8_t immediate = *p & BIND_IMMEDIATE_MASK;
                uint8_t opcode = *p & BIND_OPCODE_MASK;
        while ( p < end ) {
                uint8_t immediate = *p & BIND_IMMEDIATE_MASK;
                uint8_t opcode = *p & BIND_OPCODE_MASK;
@@ -644,6 +660,7 @@ void Binder<A>::doBindDyldLazyInfo(std::vector<void*>& pointersInData)
                                }
                                break;
                        case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
                                }
                                break;
                        case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
+                               weakImport = ( (immediate & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0 );
                                symbolName = (char*)p;
                                while (*p != '\0')
                                        ++p;
                                symbolName = (char*)p;
                                while (*p != '\0')
                                        ++p;
@@ -657,7 +674,7 @@ void Binder<A>::doBindDyldLazyInfo(std::vector<void*>& pointersInData)
                                segmentOffset = read_uleb128(p, end);
                                break;
                        case BIND_OPCODE_DO_BIND:
                                segmentOffset = read_uleb128(p, end);
                                break;
                        case BIND_OPCODE_DO_BIND:
-                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, true, pointersInData);
+                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, true, weakImport, pointersInData);
                                segmentOffset += sizeof(pint_t);
                                break;
                        case BIND_OPCODE_SET_TYPE_IMM:
                                segmentOffset += sizeof(pint_t);
                                break;
                        case BIND_OPCODE_SET_TYPE_IMM:
@@ -687,6 +704,7 @@ void Binder<A>::doBindDyldInfo(std::vector<void*>& pointersInData)
        int64_t addend = 0;
        uint32_t count;
        uint32_t skip;
        int64_t addend = 0;
        uint32_t count;
        uint32_t skip;
+       bool weakImport = false;
        bool done = false;
        while ( !done && (p < end) ) {
                uint8_t immediate = *p & BIND_IMMEDIATE_MASK;
        bool done = false;
        while ( !done && (p < end) ) {
                uint8_t immediate = *p & BIND_IMMEDIATE_MASK;
@@ -712,6 +730,7 @@ void Binder<A>::doBindDyldInfo(std::vector<void*>& pointersInData)
                                }
                                break;
                        case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
                                }
                                break;
                        case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
+                               weakImport = ( (immediate & BIND_SYMBOL_FLAGS_WEAK_IMPORT) != 0 );
                                symbolName = (char*)p;
                                while (*p != '\0')
                                        ++p;
                                symbolName = (char*)p;
                                while (*p != '\0')
                                        ++p;
@@ -731,22 +750,22 @@ void Binder<A>::doBindDyldInfo(std::vector<void*>& pointersInData)
                                segmentOffset += read_uleb128(p, end);
                                break;
                        case BIND_OPCODE_DO_BIND:
                                segmentOffset += read_uleb128(p, end);
                                break;
                        case BIND_OPCODE_DO_BIND:
-                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, pointersInData);
+                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, weakImport, pointersInData);
                                segmentOffset += sizeof(pint_t);
                                break;
                        case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
                                segmentOffset += sizeof(pint_t);
                                break;
                        case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
-                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, pointersInData);
+                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, weakImport, pointersInData);
                                segmentOffset += read_uleb128(p, end) + sizeof(pint_t);
                                break;
                        case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
                                segmentOffset += read_uleb128(p, end) + sizeof(pint_t);
                                break;
                        case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
-                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, pointersInData);
+                               bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, weakImport, pointersInData);
                                segmentOffset += immediate*sizeof(pint_t) + sizeof(pint_t);
                                break;
                        case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
                                count = read_uleb128(p, end);
                                skip = read_uleb128(p, end);
                                for (uint32_t i=0; i < count; ++i) {
                                segmentOffset += immediate*sizeof(pint_t) + sizeof(pint_t);
                                break;
                        case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
                                count = read_uleb128(p, end);
                                skip = read_uleb128(p, end);
                                for (uint32_t i=0; i < count; ++i) {
-                                       bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, pointersInData);
+                                       bindDyldInfoAt(segmentIndex, segmentOffset, type, libraryOrdinal, addend, symbolName, false, weakImport, pointersInData);
                                        segmentOffset += skip + sizeof(pint_t);
                                }
                                break;
                                        segmentOffset += skip + sizeof(pint_t);
                                }
                                break;
index 3be3fa2eb0c7d8d7fe052062f889b902a3f79f3d..6314caacedefe3951242b56fd45dfe6b82fc7ac7 100644 (file)
@@ -52,6 +52,15 @@ struct uuid_command {
 #ifndef CPU_SUBTYPE_ARM_V7
        #define CPU_SUBTYPE_ARM_V7                      ((cpu_subtype_t) 9)
 #endif
 #ifndef CPU_SUBTYPE_ARM_V7
        #define CPU_SUBTYPE_ARM_V7                      ((cpu_subtype_t) 9)
 #endif
+#ifndef CPU_SUBTYPE_ARM_V7F
+       #define CPU_SUBTYPE_ARM_V7F                     ((cpu_subtype_t) 10)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7K
+       #define CPU_SUBTYPE_ARM_V7K                     ((cpu_subtype_t) 12)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7S
+       #define CPU_SUBTYPE_ARM_V7S                     ((cpu_subtype_t) 11)
+#endif
 
 #ifndef LC_LOAD_UPWARD_DYLIB
        #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
 
 #ifndef LC_LOAD_UPWARD_DYLIB
        #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
@@ -64,6 +73,19 @@ struct uuid_command {
        #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
 #endif
 
        #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
 #endif
 
+#ifndef LC_FUNCTION_STARTS
+       #define LC_FUNCTION_STARTS 0x26
+#endif
+
+#ifndef LC_DATA_IN_CODE
+       #define LC_DATA_IN_CODE 0x29
+#endif
+
+#ifndef LC_DYLIB_CODE_SIGN_DRS
+       #define LC_DYLIB_CODE_SIGN_DRS 0x2B
+#endif
+
+
 
 #include "FileAbstraction.hpp"
 #include "Architectures.hpp"
 
 #include "FileAbstraction.hpp"
 #include "Architectures.hpp"
@@ -790,6 +812,20 @@ public:
         return NULL;
     }
 
         return NULL;
     }
 
+    const macho_load_command<P>* getLoadCommand(int query) const
+    {
+        const macho_load_command<P>* cmds = (macho_load_command<P>*)((uint8_t*)this + sizeof(macho_header<P>));
+        uint32_t cmd_count = this->ncmds();
+        const macho_load_command<P>* cmd = cmds;
+        for (uint32_t i = 0; i < cmd_count; ++i) {
+            if ( cmd->cmd() == query ) {
+                return cmd;
+            }
+            cmd = (macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
+        }
+        return NULL;
+    }
+
        typedef typename P::E           E;
 private:
        macho_header_content<P> header;
        typedef typename P::E           E;
 private:
        macho_header_content<P> header;
index e23cbac280dfc8214d6532bc2dff39783999b4d1..4d6583b6bb858f1a6623d3b230e45a082a73dffc 100644 (file)
@@ -364,9 +364,6 @@ UniversalMachOLayout::UniversalMachOLayout(const char* path, const std::set<Arch
                                        }
                                        try {
                                                switch ( OSSwapBigToHostInt32(slices[i].cputype) ) {
                                        }
                                        try {
                                                switch ( OSSwapBigToHostInt32(slices[i].cputype) ) {
-                                                       case CPU_TYPE_POWERPC:
-                                                               fLayouts.push_back(new MachOLayout<ppc>(&p[fileOffset], fileOffset, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
-                                                               break;
                                                        case CPU_TYPE_I386:
                                                                fLayouts.push_back(new MachOLayout<x86>(&p[fileOffset], fileOffset, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                                                break;
                                                        case CPU_TYPE_I386:
                                                                fLayouts.push_back(new MachOLayout<x86>(&p[fileOffset], fileOffset, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                                                break;
@@ -376,9 +373,6 @@ UniversalMachOLayout::UniversalMachOLayout(const char* path, const std::set<Arch
                                                        case CPU_TYPE_ARM:
                                                                fLayouts.push_back(new MachOLayout<arm>(&p[fileOffset], fileOffset, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                                                break;
                                                        case CPU_TYPE_ARM:
                                                                fLayouts.push_back(new MachOLayout<arm>(&p[fileOffset], fileOffset, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                                                break;
-                                                       case CPU_TYPE_POWERPC64:
-                                                               // ignore ppc64 slices
-                                                               break;
                                                        default:
                                                                throw "unknown slice in fat file";
                                                }
                                                        default:
                                                                throw "unknown slice in fat file";
                                                }
@@ -391,11 +385,7 @@ UniversalMachOLayout::UniversalMachOLayout(const char* path, const std::set<Arch
                }
                else {
                        try {
                }
                else {
                        try {
-                               if ( (OSSwapBigToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapBigToHostInt32(mh->cputype) == CPU_TYPE_POWERPC)) {
-                                       if ( requestedSlice(onlyArchs, OSSwapBigToHostInt32(mh->cputype), OSSwapBigToHostInt32(mh->cpusubtype)) ) 
-                                               fLayouts.push_back(new MachOLayout<ppc>(mh, 0, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
-                               }
-                               else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_I386)) {
+if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_I386)) {
                                        if ( requestedSlice(onlyArchs, OSSwapLittleToHostInt32(mh->cputype), OSSwapLittleToHostInt32(mh->cpusubtype)) ) 
                                                fLayouts.push_back(new MachOLayout<x86>(mh, 0, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                }
                                        if ( requestedSlice(onlyArchs, OSSwapLittleToHostInt32(mh->cputype), OSSwapLittleToHostInt32(mh->cpusubtype)) ) 
                                                fLayouts.push_back(new MachOLayout<x86>(mh, 0, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                }
@@ -407,9 +397,6 @@ UniversalMachOLayout::UniversalMachOLayout(const char* path, const std::set<Arch
                                        if ( requestedSlice(onlyArchs, OSSwapLittleToHostInt32(mh->cputype), OSSwapLittleToHostInt32(mh->cpusubtype)) ) 
                                                fLayouts.push_back(new MachOLayout<arm>(mh, 0, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                }
                                        if ( requestedSlice(onlyArchs, OSSwapLittleToHostInt32(mh->cputype), OSSwapLittleToHostInt32(mh->cpusubtype)) ) 
                                                fLayouts.push_back(new MachOLayout<arm>(mh, 0, fPath, stat_buf.st_ino, stat_buf.st_mtime, stat_buf.st_uid));
                                }
-                               else if ( (OSSwapBigToHostInt32(mh->magic) == MH_MAGIC_64) && (OSSwapBigToHostInt32(mh->cputype) == CPU_TYPE_POWERPC64)) {
-                                       // ignore ppc64 slices
-                               }
                                else {
                                        throw "unknown file format";
                                }
                                else {
                                        throw "unknown file format";
                                }
@@ -569,18 +556,11 @@ MachOLayout<A>::MachOLayout(const void* machHeader, uint64_t offset, const char*
 
 }
 
 
 }
 
-template <> cpu_type_t MachOLayout<ppc>::arch()     { return CPU_TYPE_POWERPC; }
 template <> cpu_type_t MachOLayout<x86>::arch()     { return CPU_TYPE_I386; }
 template <> cpu_type_t MachOLayout<x86_64>::arch()  { return CPU_TYPE_X86_64; }
 template <> cpu_type_t MachOLayout<arm>::arch()                { return CPU_TYPE_ARM; }
 
 
 template <> cpu_type_t MachOLayout<x86>::arch()     { return CPU_TYPE_I386; }
 template <> cpu_type_t MachOLayout<x86_64>::arch()  { return CPU_TYPE_X86_64; }
 template <> cpu_type_t MachOLayout<arm>::arch()                { return CPU_TYPE_ARM; }
 
 
-template <>
-bool MachOLayout<ppc>::isSplitSeg() const
-{
-       return ( (this->getFlags() & MH_SPLIT_SEGS) != 0 );
-}
-
 template <>
 bool MachOLayout<x86>::isSplitSeg() const
 {
 template <>
 bool MachOLayout<x86>::isSplitSeg() const
 {
index 8907aad90dda84b0b8a8c4a8f13f3b69a898c385..88c4f83d0db08ef6fab0fd6fe07f1719c73f9ccc 100644 (file)
@@ -38,7 +38,6 @@
 #include <mach-o/loader.h>
 #include <mach-o/fat.h>
 #include <mach-o/reloc.h>
 #include <mach-o/loader.h>
 #include <mach-o/fat.h>
 #include <mach-o/reloc.h>
-#include <mach-o/ppc/reloc.h>
 #include <mach-o/x86_64/reloc.h>
 #include <mach-o/arm/reloc.h>
 #include <vector>
 #include <mach-o/x86_64/reloc.h>
 #include <mach-o/arm/reloc.h>
 #include <vector>
@@ -170,7 +169,6 @@ Rebaser<A>::Rebaser(const MachOLayoutAbstraction& layout)
        fSplittingSegments = layout.hasSplitSegInfo() && this->unequalSlides();
 }
 
        fSplittingSegments = layout.hasSplitSegInfo() && this->unequalSlides();
 }
 
-template <> cpu_type_t Rebaser<ppc>::getArchitecture()    const { return CPU_TYPE_POWERPC; }
 template <> cpu_type_t Rebaser<x86>::getArchitecture()    const { return CPU_TYPE_I386; }
 template <> cpu_type_t Rebaser<x86_64>::getArchitecture() const { return CPU_TYPE_X86_64; }
 template <> cpu_type_t Rebaser<arm>::getArchitecture() const { return CPU_TYPE_ARM; }
 template <> cpu_type_t Rebaser<x86>::getArchitecture()    const { return CPU_TYPE_I386; }
 template <> cpu_type_t Rebaser<x86_64>::getArchitecture() const { return CPU_TYPE_X86_64; }
 template <> cpu_type_t Rebaser<arm>::getArchitecture() const { return CPU_TYPE_ARM; }
@@ -536,25 +534,103 @@ void Rebaser<A>::doCodeUpdate(uint8_t kind, uint64_t address, int64_t codeToData
                        value64 += codeToDataDelta;
                         A::P::E::set64(*(uint64_t*)p, value64);
                        break;
                        value64 += codeToDataDelta;
                         A::P::E::set64(*(uint64_t*)p, value64);
                        break;
-               case 3: // used only for ppc, an instruction that sets the hi16 of a register
-                       // adjust low 16 bits of instruction which contain hi16 of distance to something in DATA
-                       if ( (codeToDataDelta & 0xFFFF) != 0 )
-                               throwf("codeToDataDelta=0x%0llX is not a multiple of 64K", codeToDataDelta);
-                       p = (uint32_t*)mappedAddressForVMAddress(address);
-                       instruction = BigEndian::get32(*p);
-                       {
-                               uint16_t originalLo16 = instruction & 0x0000FFFF;
-                               uint16_t delta64Ks = codeToDataDelta >> 16;
-                               instruction = (instruction & 0xFFFF0000) | ((originalLo16+delta64Ks) & 0x0000FFFF);
-                       }
-                       BigEndian::set32(*p, instruction);
-                       break;
                case 4: // only used for i386, a reference to something in the IMPORT segment
                        p = (uint32_t*)mappedAddressForVMAddress(address);
                        value = A::P::E::get32(*p);
                        value += codeToImportDelta;
                         A::P::E::set32(*p, value);
                case 4: // only used for i386, a reference to something in the IMPORT segment
                        p = (uint32_t*)mappedAddressForVMAddress(address);
                        value = A::P::E::get32(*p);
                        value += codeToImportDelta;
                         A::P::E::set32(*p, value);
+                       break;                  
+        case 5: // used by thumb2 movw
+                       p = (uint32_t*)mappedAddressForVMAddress(address);
+                       instruction = A::P::E::get32(*p);
+                       // codeToDataDelta is always a multiple of 4096, so only top 4 bits of lo16 will ever need adjusting
+                       value = (instruction & 0x0000000F) + (codeToDataDelta >> 12);
+                       instruction = (instruction & 0xFFFFFFF0) | (value & 0x0000000F);
+                       A::P::E::set32(*p, instruction);
+                       break;
+        case 6: // used by ARM movw
+                       p = (uint32_t*)mappedAddressForVMAddress(address);
+                       instruction = A::P::E::get32(*p);
+                       // codeToDataDelta is always a multiple of 4096, so only top 4 bits of lo16 will ever need adjusting
+                       value = ((instruction & 0x000F0000) >> 16) + (codeToDataDelta >> 12);
+                       instruction = (instruction & 0xFFF0FFFF) | ((value <<16) & 0x000F0000);
+                       A::P::E::set32(*p, instruction);
                        break;
                        break;
+               case 0x10:
+               case 0x11:
+               case 0x12:
+               case 0x13:
+               case 0x14:
+               case 0x15:
+               case 0x16:
+               case 0x17:
+               case 0x18:
+               case 0x19:
+               case 0x1A:
+               case 0x1B:
+               case 0x1C:
+               case 0x1D:
+               case 0x1E:
+               case 0x1F:
+                       // used by thumb2 movt (low nibble of kind is high 4-bits of paired movw)
+                       {
+                               p = (uint32_t*)mappedAddressForVMAddress(address);
+                               instruction = A::P::E::get32(*p);
+                               // extract 16-bit value from instruction
+                               uint32_t i =    ((instruction & 0x00000400) >> 10);
+                               uint32_t imm4 =  (instruction & 0x0000000F);
+                               uint32_t imm3 = ((instruction & 0x70000000) >> 28);
+                               uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
+                               uint32_t imm16 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
+                               // combine with codeToDataDelta and kind nibble
+                               uint32_t targetValue = (imm16 << 16) | ((kind & 0xF) << 12);
+                               uint32_t newTargetValue = targetValue + codeToDataDelta;
+                               // construct new bits slices
+                               uint32_t imm4_  = (newTargetValue & 0xF0000000) >> 28;
+                               uint32_t i_             = (newTargetValue & 0x08000000) >> 27;
+                               uint32_t imm3_  = (newTargetValue & 0x07000000) >> 24;
+                               uint32_t imm8_  = (newTargetValue & 0x00FF0000) >> 16;
+                               // update instruction to match codeToDataDelta 
+                               uint32_t newInstruction = (instruction & 0x8F00FBF0) | imm4_ | (i_ << 10) | (imm3_ << 28) | (imm8_ << 16);
+                               A::P::E::set32(*p, newInstruction);
+                       }
+                       break;
+               case 0x20:
+               case 0x21:
+               case 0x22:
+               case 0x23:
+               case 0x24:
+               case 0x25:
+               case 0x26:
+               case 0x27:
+               case 0x28:
+               case 0x29:
+               case 0x2A:
+               case 0x2B:
+               case 0x2C:
+               case 0x2D:
+               case 0x2E:
+               case 0x2F:
+                       // used by arm movt (low nibble of kind is high 4-bits of paired movw)
+                       {
+                               p = (uint32_t*)mappedAddressForVMAddress(address);
+                               instruction = A::P::E::get32(*p);
+                               // extract 16-bit value from instruction
+                               uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
+                               uint32_t imm12 = (instruction & 0x00000FFF);
+                               uint32_t imm16 = (imm4 << 12) | imm12;
+                               // combine with codeToDataDelta and kind nibble
+                               uint32_t targetValue = (imm16 << 16) | ((kind & 0xF) << 12);
+                               uint32_t newTargetValue = targetValue + codeToDataDelta;
+                               // construct new bits slices
+                               uint32_t imm4_  = (newTargetValue & 0xF0000000) >> 28;
+                               uint32_t imm12_ = (newTargetValue & 0x0FFF0000) >> 16;
+                               // update instruction to match codeToDataDelta 
+                               uint32_t newInstruction = (instruction & 0xFFF0F000) | (imm4_ << 16) | imm12_;
+                               A::P::E::set32(*p, newInstruction);
+                       }
+                       break;
+               case 3: // used only for ppc, an instruction that sets the hi16 of a register
                default:
                        throwf("invalid kind=%d in split seg info", kind);
        }
                default:
                        throwf("invalid kind=%d in split seg info", kind);
        }
@@ -663,7 +739,13 @@ void Rebaser<A>::doRebase(int segIndex, uint64_t segOffset, uint8_t type, std::v
        switch ( type ) {
                case REBASE_TYPE_POINTER:
                        valueP= P::getP(*mappedAddrP);
        switch ( type ) {
                case REBASE_TYPE_POINTER:
                        valueP= P::getP(*mappedAddrP);
-                       P::setP(*mappedAddrP, valueP + this->getSlideForVMAddress(valueP));
+                       try {
+                               P::setP(*mappedAddrP, valueP + this->getSlideForVMAddress(valueP));
+                       }
+                       catch (const char* msg) {
+                               throwf("at offset=0x%08llX in seg=%s, pointer cannot be rebased because it does not point to __TEXT or __DATA. %s\n", 
+                                               segOffset, seg.name(), msg);
+                       }
                        break;
                
                case REBASE_TYPE_TEXT_ABSOLUTE32:
                        break;
                
                case REBASE_TYPE_TEXT_ABSOLUTE32:
@@ -842,27 +924,6 @@ void Rebaser<x86_64>::doLocalRelocation(const macho_relocation_info<x86_64::P>*
        }
 }
 
        }
 }
 
-template <>
-void Rebaser<ppc>::doLocalRelocation(const macho_relocation_info<P>* reloc)
-{
-       if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
-               if ( reloc->r_type() == GENERIC_RELOC_VANILLA ) {
-                       pint_t* addr = this->mappedAddressForRelocAddress(reloc->r_address());
-                       pint_t value = P::getP(*addr);
-                       P::setP(*addr, value + this->getSlideForVMAddress(value));
-               }
-       }
-       else {
-               macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
-               if ( sreloc->r_type() == PPC_RELOC_PB_LA_PTR ) {
-                       sreloc->set_r_value( sreloc->r_value() + this->getSlideForVMAddress(sreloc->r_value()) );
-               }
-               else {
-                       throw "cannot rebase final linked image with scattered relocations";
-               }
-       }
-}
-
 template <>
 void Rebaser<x86>::doLocalRelocation(const macho_relocation_info<P>* reloc)
 {
 template <>
 void Rebaser<x86>::doLocalRelocation(const macho_relocation_info<P>* reloc)
 {
@@ -972,9 +1033,6 @@ public:
                                        uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset);
                                        try {
                                                switch ( OSSwapBigToHostInt32(archs[i].cputype) ) {
                                        uint32_t fileOffset = OSSwapBigToHostInt32(archs[i].offset);
                                        try {
                                                switch ( OSSwapBigToHostInt32(archs[i].cputype) ) {
-                                                       case CPU_TYPE_POWERPC:
-                                                               fRebasers.push_back(new Rebaser<ppc>(&p[fileOffset]));
-                                                               break;
                                                        case CPU_TYPE_I386:
                                                                fRebasers.push_back(new Rebaser<x86>(&p[fileOffset]));
                                                                break;
                                                        case CPU_TYPE_I386:
                                                                fRebasers.push_back(new Rebaser<x86>(&p[fileOffset]));
                                                                break;
@@ -995,10 +1053,7 @@ public:
                        }
                        else {
                                try {
                        }
                        else {
                                try {
-                                       if ( (OSSwapBigToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapBigToHostInt32(mh->cputype) == CPU_TYPE_POWERPC)) {
-                                               fRebasers.push_back(new Rebaser<ppc>(mh));
-                                       }
-                                       else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_I386)) {
+                                       if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_I386)) {
                                                fRebasers.push_back(new Rebaser<x86>(mh));
                                        }
                                        else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC_64) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_X86_64)) {
                                                fRebasers.push_back(new Rebaser<x86>(mh));
                                        }
                                        else if ( (OSSwapLittleToHostInt32(mh->magic) == MH_MAGIC_64) && (OSSwapLittleToHostInt32(mh->cputype) == CPU_TYPE_X86_64)) {
index 43ab45a6dac98aadc0ced69e1a2880ce83eef9b9..19ee2d3f4bc08295cc6378ee1fbe73044838758c 100644 (file)
  * @APPLE_LICENSE_HEADER_END@
  */
 
  * @APPLE_LICENSE_HEADER_END@
  */
 
+#define OBJC_IMAGE_SUPPORTS_GC (1<<1)
+#define OBJC_IMAGE_REQUIRES_GC (1<<2)
+
 template <typename A>
 struct objc_image_info {
     uint32_t version;
     uint32_t flags;
 
 template <typename A>
 struct objc_image_info {
     uint32_t version;
     uint32_t flags;
 
+    uint32_t getFlags()         INLINE { return A::P::E::get32(flags); }
+    
+    bool supportsGCFlagSet()    INLINE { return getFlags() & OBJC_IMAGE_SUPPORTS_GC; }
+    bool requiresGCFlagSet()    INLINE { return getFlags() & OBJC_IMAGE_REQUIRES_GC; }
+    
     void setFlag(uint32_t bits) INLINE { uint32_t old = A::P::E::get32(flags); A::P::E::set32(flags, old | bits); }
     void setFlag(uint32_t bits) INLINE { uint32_t old = A::P::E::get32(flags); A::P::E::set32(flags, old | bits); }
-    void setSelectorsPrebound() INLINE { setFlag(1<<3); }
+    void setOptimizedByDyld() INLINE { setFlag(1<<3); }
 };
 
 template <typename A>
 };
 
 template <typename A>
@@ -221,14 +229,5 @@ public:
             uint64_t newValue = visitor.visit(oldValue);
             selrefs.set(s, newValue);
         }
             uint64_t newValue = visitor.visit(oldValue);
             selrefs.set(s, newValue);
         }
-
-        // Mark image_info
-        const macho_section<P> *imageInfoSection = 
-            header->getSection("__OBJC", "__image_info");
-        if (imageInfoSection) {
-            objc_image_info<A> *info = (objc_image_info<A> *)
-                cache->mappedAddressForVMAddress(imageInfoSection->addr());
-            info->setSelectorsPrebound();
-        }
     }
 };
     }
 };
index 9dc9b90adcad59e5de6a99df4658d0047a581f5f..41419a88300d452c965b1d706a6986b9800e987c 100644 (file)
@@ -22,6 +22,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 
  * @APPLE_LICENSE_HEADER_END@
  */
 
+#include "MachOLayout.hpp"
 #include <iterator>
 #include <deque>
 
 #include <iterator>
 #include <deque>
 
@@ -76,7 +77,7 @@ struct entsize_iterator {
     }
     
     T& operator * () { return *current; }
     }
     
     T& operator * () { return *current; }
-    const T& operator * () const { return *current; }
+    T& operator * () const { return *current; }
     T& operator -> () { return *current; }
     const T& operator -> () const { return *current; }
     
     T& operator -> () { return *current; }
     const T& operator -> () const { return *current; }
     
@@ -107,6 +108,44 @@ struct entsize_iterator {
         }
     }
 };
         }
     }
 };
+
+template <typename A> 
+class objc_header_info_t {
+
+    typedef typename A::P P;
+    typedef typename A::P::uint_t pint_t;
+
+    pint_t next;   // objc_header_info *
+    pint_t mhdr;   // mach_header or mach_header_64
+    pint_t info;   // objc_image_info *
+    pint_t fname;  // const char *
+    bool loaded; 
+    bool inSharedCache;
+    bool allClassesRealized;
+
+public:
+    objc_header_info_t(SharedCache<A>* cache, const macho_header<P>* mh) 
+        : next(0), 
+          mhdr(0), 
+          info(0), 
+          fname(0), 
+          loaded(0), 
+          allClassesRealized(0)
+    {
+        A::P::setP(mhdr, cache->VMAddressForMappedAddress(mh));
+        const macho_section<P>* sect = mh->getSection("__DATA", "__objc_imageinfo");
+        if (sect) A::P::setP(info, sect->addr());
+
+        // can't set fname because dyld sometimes edits it
+    }
+
+       void addPointers(std::vector<void*>& pointersToAdd) {
+        pointersToAdd.push_back(&mhdr);
+        if (info) pointersToAdd.push_back(&info);
+    }
+
+    uint64_t header_vmaddr() const { return mhdr; }
+};
   
 template <typename A> class objc_method_list_t;  // forward reference
 
   
 template <typename A> class objc_method_list_t;  // forward reference
 
@@ -203,15 +242,30 @@ public:
 
 template <typename A>
 class objc_ivar_t {
 
 template <typename A>
 class objc_ivar_t {
+    typedef typename A::P::uint_t pint_t;
     typename A::P::uint_t offset;  // A::P *
     typename A::P::uint_t name;    // const char *
     typename A::P::uint_t type;    // const char *
     uint32_t alignment; 
     uint32_t size;
     typename A::P::uint_t offset;  // A::P *
     typename A::P::uint_t name;    // const char *
     typename A::P::uint_t type;    // const char *
     uint32_t alignment; 
     uint32_t size;
+    
+public:
+    const char * getName(SharedCache<A> *cache) const { return (const char *)cache->mappedAddressForVMAddress(A::P::getP(name)); }
+
+    bool hasOffset() const { return A::P::getP(offset) != 0; }
+    pint_t getOffset(SharedCache<A> *cache) const { return A::P::getP(*(pint_t * const)cache->mappedAddressForVMAddress(A::P::getP(offset))); }
+    void setOffset(SharedCache<A> *cache, pint_t newOffset) { A::P::setP(*(pint_t *)cache->mappedAddressForVMAddress(A::P::getP(offset)), newOffset); }
+    
+    uint32_t getAlignment()
+    {
+        uint32_t a = A::P::E::get32(alignment);
+        return a == (uint32_t)-1 ? sizeof(typename A::P::uint_t) : 1<<a;
+    }
 };
 
 template <typename A>
 class objc_ivar_list_t {
 };
 
 template <typename A>
 class objc_ivar_list_t {
+    typedef typename A::P::uint_t pint_t;
     uint32_t entsize;
     uint32_t count;
     objc_ivar_t<A> first;
     uint32_t entsize;
     uint32_t count;
     objc_ivar_t<A> first;
@@ -228,7 +282,7 @@ public:
 
        uint32_t getEntsize() const { return A::P::E::get32(entsize); }
 
 
        uint32_t getEntsize() const { return A::P::E::get32(entsize); }
 
-    objc_ivar_t<A>& get(typename A::P::pint_t i) const { return *(objc_ivar_t<A> *)((uint8_t *)&first + i * A::P::E::get32(entsize)); }
+    objc_ivar_t<A>& get(pint_t i) const { return *(objc_ivar_t<A> *)((uint8_t *)&first + i * A::P::E::get32(entsize)); }
 
     uint32_t byteSize() const { 
         return byteSizeForCount(getCount(), getEntsize()); 
 
     uint32_t byteSize() const { 
         return byteSizeForCount(getCount(), getEntsize()); 
@@ -440,10 +494,20 @@ class objc_class_data_t {
     typename A::P::uint_t baseProperties;
 
 public:
     typename A::P::uint_t baseProperties;
 
 public:
+    bool isMetaClass() { return A::P::E::get32(flags) & 1; }
+
+    uint32_t getInstanceStart() { return A::P::E::get32(instanceStart); }
+    void setInstanceStart(uint32_t newStart) { A::P::E::set32(instanceStart, newStart); }
+    
+    uint32_t getInstanceSize() { return A::P::E::get32(instanceSize.instanceSize); }
+    void setInstanceSize(uint32_t newSiz) { A::P::E::set32(instanceSize.instanceSize, newSiz); }
+
     objc_method_list_t<A> *getMethodList(SharedCache<A>* cache) const { return (objc_method_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(baseMethods)); }
 
     objc_protocol_list_t<A> *getProtocolList(SharedCache<A>* cache) const { return (objc_protocol_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(baseProtocols)); }
 
     objc_method_list_t<A> *getMethodList(SharedCache<A>* cache) const { return (objc_method_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(baseMethods)); }
 
     objc_protocol_list_t<A> *getProtocolList(SharedCache<A>* cache) const { return (objc_protocol_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(baseProtocols)); }
 
+    objc_ivar_list_t<A> *getIvarList(SharedCache<A>* cache) const { return (objc_ivar_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(ivars)); }
+    
     objc_property_list_t<A> *getPropertyList(SharedCache<A>* cache) const { return (objc_property_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(baseProperties)); }
 
     const char * getName(SharedCache<A>* cache) const { return (const char *)cache->mappedAddressForVMAddress(A::P::getP(name)); }
     objc_property_list_t<A> *getPropertyList(SharedCache<A>* cache) const { return (objc_property_list_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(baseProperties)); }
 
     const char * getName(SharedCache<A>* cache) const { return (const char *)cache->mappedAddressForVMAddress(A::P::getP(name)); }
@@ -482,8 +546,12 @@ class objc_class_t {
     typename A::P::uint_t data;
 
 public:
     typename A::P::uint_t data;
 
 public:
+    bool isMetaClass(SharedCache<A>* cache) const { return getData(cache)->isMetaClass(); }
+
     objc_class_t<A> *getIsa(SharedCache<A> *cache) const { return (objc_class_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(isa)); }
 
     objc_class_t<A> *getIsa(SharedCache<A> *cache) const { return (objc_class_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(isa)); }
 
+    objc_class_t<A> *getSuperclass(SharedCache<A> *cache) const { return (objc_class_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(superclass)); }
+    
     objc_class_data_t<A> *getData(SharedCache<A>* cache) const { return (objc_class_data_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(data)); }
 
     objc_method_list_t<A> *getMethodList(SharedCache<A>* cache) const { return getData(cache)->getMethodList(cache); }
     objc_class_data_t<A> *getData(SharedCache<A>* cache) const { return (objc_class_data_t<A> *)cache->mappedAddressForVMAddress(A::P::getP(data)); }
 
     objc_method_list_t<A> *getMethodList(SharedCache<A>* cache) const { return getData(cache)->getMethodList(cache); }
@@ -570,6 +638,60 @@ public:
     void setName(typename A::P::uint_t newName) { A::P::setP(sel, newName); }
 };
 
     void setName(typename A::P::uint_t newName) { A::P::setP(sel, newName); }
 };
 
+// Call visitor.visitIvar() on every ivar in a given class.
+template <typename A, typename V>
+class IvarWalker {
+    typedef typename A::P P;
+    typedef typename A::P::uint_t pint_t;
+    V& ivarVisitor;
+public:
+    
+    IvarWalker(V& visitor) : ivarVisitor(visitor) { }
+    
+    void walk(SharedCache<A>* cache, const macho_header<P>* header, objc_class_t<A> *cls)
+    {
+        objc_class_data_t<A> *data = cls->getData(cache);
+        objc_ivar_list_t<A> *ivars = data->getIvarList(cache);
+        if (ivars) {
+            for (pint_t i = 0; i < ivars->getCount(); i++) {
+                objc_ivar_t<A>& ivar = ivars->get(i);
+                //fprintf(stderr, "visiting ivar: %s\n", ivar.getName(cache));
+                ivarVisitor.visitIvar(cache, header, cls, &ivar);
+            }
+        } else {
+            //fprintf(stderr, "no ivars\n");
+        }
+    }
+    
+    void visitClass(SharedCache<A>* cache, const macho_header<P>* header, objc_class_t<A> *cls)
+    {
+        walk(cache, header, cls);
+    }
+};
+
+// Call visitor.visitClass() on every class.
+template <typename A, typename V>
+class ClassWalker {
+    typedef typename A::P P;
+    typedef typename A::P::uint_t pint_t;
+    V& classVisitor;
+public:
+    
+    ClassWalker(V& visitor) : classVisitor(visitor) { }
+    
+    void walk(SharedCache<A>* cache, const macho_header<P>* header)
+    {   
+        PointerSection<A, objc_class_t<A> *> 
+        classes(cache, header, "__DATA", "__objc_classlist");
+        
+        for (pint_t i = 0; i < classes.count(); i++) {
+            objc_class_t<A> *cls = classes.get(i);
+            //fprintf(stderr, "visiting class: %s\n", cls->getName(cache));
+            classVisitor.visitClass(cache, header, cls);
+        }
+    }
+};
+
 
 // Call visitor.visitMethodList(mlist) on every method list in a header.
 template <typename A, typename V>
 
 // Call visitor.visitMethodList(mlist) on every method list in a header.
 template <typename A, typename V>
@@ -584,7 +706,7 @@ public:
     
     MethodListWalker(V& visitor) : mVisitor(visitor) { }
 
     
     MethodListWalker(V& visitor) : mVisitor(visitor) { }
 
-    void walk(SharedCache<A>* cache, const macho_header<P>* header)
+    void walk(SharedCache<A>* cache, const macho_header<P>* header, bool walkProtocols)
     {   
         // Method lists in classes
         PointerSection<A, objc_class_t<A> *> 
     {   
         // Method lists in classes
         PointerSection<A, objc_class_t<A> *> 
@@ -615,25 +737,27 @@ public:
             }
         }
 
             }
         }
 
-        // Method description lists from protocols
-        PointerSection<A, objc_protocol_t<A> *> 
-            protocols(cache, header, "__DATA", "__objc_protolist");
-        for (pint_t i = 0; i < protocols.count(); i++) {
-            objc_protocol_t<A> *proto = protocols.get(i);
-            objc_method_list_t<A> *mlist;
-            if ((mlist = proto->getInstanceMethods(cache))) {
-                mVisitor.visitMethodList(mlist);
-            }
-            if ((mlist = proto->getClassMethods(cache))) {
-                mVisitor.visitMethodList(mlist);
-            }
-            if ((mlist = proto->getOptionalInstanceMethods(cache))) {
-                mVisitor.visitMethodList(mlist);
-            }
-            if ((mlist = proto->getOptionalClassMethods(cache))) {
-                mVisitor.visitMethodList(mlist);
-            }
-        }
+               // Method description lists from protocols
+               if ( walkProtocols ) {
+                       PointerSection<A, objc_protocol_t<A> *> 
+                               protocols(cache, header, "__DATA", "__objc_protolist");
+                       for (pint_t i = 0; i < protocols.count(); i++) {
+                               objc_protocol_t<A> *proto = protocols.get(i);
+                               objc_method_list_t<A> *mlist;
+                               if ((mlist = proto->getInstanceMethods(cache))) {
+                                       mVisitor.visitMethodList(mlist);
+                               }
+                               if ((mlist = proto->getClassMethods(cache))) {
+                                       mVisitor.visitMethodList(mlist);
+                               }
+                               if ((mlist = proto->getOptionalInstanceMethods(cache))) {
+                                       mVisitor.visitMethodList(mlist);
+                               }
+                               if ((mlist = proto->getOptionalClassMethods(cache))) {
+                                       mVisitor.visitMethodList(mlist);
+                               }
+                       }
+               }
     }
 };
 
     }
 };
 
@@ -667,7 +791,7 @@ public:
     {
         // method lists of all kinds
         MethodListWalker< A, SelectorOptimizer<A,V> > mw(*this);
     {
         // method lists of all kinds
         MethodListWalker< A, SelectorOptimizer<A,V> > mw(*this);
-        mw.walk(cache, header);
+        mw.walk(cache, header, true);
         
         // @selector references
         PointerSection<A, const char *> 
         
         // @selector references
         PointerSection<A, const char *> 
@@ -687,14 +811,96 @@ public:
             pint_t newValue = mVisitor.visit(oldValue);
             msg.setName(newValue);
         }
             pint_t newValue = mVisitor.visit(oldValue);
             msg.setName(newValue);
         }
+    }
+};
 
 
-        // Mark image_info
-        const macho_section<P> *imageInfoSection = 
-            header->getSection("__DATA", "__objc_imageinfo");
+
+// Update selector references. The visitor performs recording and uniquing.
+template <typename A>
+class IvarOffsetOptimizer {
+    typedef typename A::P P;
+
+    uint32_t slide;
+    uint32_t maxAlignment;
+
+    uint32_t fOptimized;
+
+public:
+    
+    IvarOffsetOptimizer() : fOptimized(0) { }
+
+    size_t optimized() const { return fOptimized; }
+    
+    // dual purpose ivar visitor function
+    // if slide!=0 then slides the ivar by that amount, otherwise computes maxAlignment
+    void visitIvar(SharedCache<A>* cache, const macho_header<P>* /*unused, may be NULL*/, objc_class_t<A> *cls, objc_ivar_t<A> *ivar)
+    {
+        if (slide == 0) {
+            uint32_t alignment = ivar->getAlignment();
+            if (alignment > maxAlignment) maxAlignment = alignment;
+        } else {
+            // skip anonymous bitfields
+            if (ivar->hasOffset()) {
+                uint32_t oldOffset = (uint32_t)ivar->getOffset(cache);
+                ivar->setOffset(cache, oldOffset + slide);
+                fOptimized++;
+                //fprintf(stderr, "%d -> %d for %s.%s\n", oldOffset, oldOffset + slide, cls->getName(cache), ivar->getName(cache));
+            } else {
+                //fprintf(stderr, "NULL offset\n");
+            }
+        }
+    }
+    
+    // Class visitor function. Evaluates whether to slide ivars and performs slide if needed.
+    // The slide algorithm is also implemented in objc. Any changes here should be reflected there also.
+    void visitClass(SharedCache<A>* cache, const macho_header<P>* /*unused, may be NULL*/, objc_class_t<A> *cls)
+    {
+        objc_class_t<A> *super = cls->getSuperclass(cache);
+        if (super) {
+            // Recursively visit superclasses to ensure we have the correct superclass start
+            // Note that we don't need the macho_header, so just pass NULL.
+            visitClass(cache, NULL, super);
+
+            objc_class_data_t<A> *data = cls->getData(cache);
+            objc_class_data_t<A> *super_data = super->getData(cache);
+            int32_t diff = super_data->getInstanceSize() - data->getInstanceStart();
+            if (diff > 0) {
+                IvarWalker<A, IvarOffsetOptimizer<A> > ivarVisitor(*this);
+                maxAlignment = 0;
+                slide = 0;
+                
+                // This walk computes maxAlignment
+                ivarVisitor.walk(cache, NULL, cls);
+
+                // Compute a slide value that preserves that alignment
+                uint32_t alignMask = maxAlignment - 1;
+                if (diff & alignMask) diff = (diff + alignMask) & ~alignMask;
+
+                // Slide all of this class's ivars en masse
+                slide = diff;
+                if (slide != 0) {
+                    //fprintf(stderr, "Sliding ivars in %s by %u (superclass was %d, now %d)\n", cls->getName(cache), slide, data->getInstanceStart(), super_data->getInstanceSize());
+                    ivarVisitor.walk(cache, NULL, cls);
+                    data->setInstanceStart(data->getInstanceStart() + slide);
+                    data->setInstanceSize(data->getInstanceSize() + slide);
+                }
+            }
+        }
+    }
+    
+    // Enumerates objc classes in the module and performs any ivar slides
+    void optimize(SharedCache<A>* cache, const macho_header<P>* header)
+    {
+        // The slide code cannot fix up GC layout strings so skip modules that support ore require GC
+        const macho_section<P> *imageInfoSection = header->getSection("__DATA", "__objc_imageinfo");
         if (imageInfoSection) {
         if (imageInfoSection) {
-            objc_image_info<A> *info = (objc_image_info<A> *)
-                cache->mappedAddressForVMAddress(imageInfoSection->addr());
-            info->setSelectorsPrebound();
+            objc_image_info<A> *info = (objc_image_info<A> *)cache->mappedAddressForVMAddress(imageInfoSection->addr());
+            if (!info->supportsGCFlagSet() && !info->requiresGCFlagSet()) {
+                ClassWalker<A, IvarOffsetOptimizer<A> > classVisitor(*this);
+                classVisitor.walk(cache, header);
+            } else {
+                //fprintf(stderr, "GC support present - skipped module\n");
+            }
         }
     }
 };
         }
     }
 };
@@ -707,548 +913,76 @@ class MethodListSorter {
     typedef typename A::P P;
     typedef typename A::P::uint_t pint_t;
 
     typedef typename A::P P;
     typedef typename A::P::uint_t pint_t;
 
+    uint32_t fOptimized;
+
     friend class MethodListWalker<A, MethodListSorter<A> >;
     void visitMethodList(objc_method_list_t<A> *mlist)
     {
         typename objc_method_t<A>::SortBySELAddress sorter;
         std::stable_sort(mlist->begin(), mlist->end(), sorter);
         mlist->setFixedUp();
     friend class MethodListWalker<A, MethodListSorter<A> >;
     void visitMethodList(objc_method_list_t<A> *mlist)
     {
         typename objc_method_t<A>::SortBySELAddress sorter;
         std::stable_sort(mlist->begin(), mlist->end(), sorter);
         mlist->setFixedUp();
+        fOptimized++;
     }
 
 public:
     }
 
 public:
+    MethodListSorter() : fOptimized(0) { }
+
+    size_t optimized() const { return fOptimized; }
 
     void optimize(SharedCache<A>* cache, macho_header<P>* header)
     {
         MethodListWalker<A, MethodListSorter<A> > mw(*this);
 
     void optimize(SharedCache<A>* cache, macho_header<P>* header)
     {
         MethodListWalker<A, MethodListSorter<A> > mw(*this);
-        mw.walk(cache, header);
+        mw.walk(cache, header, false /* don't sort protocol method lists*/);
     }
 };
 
 
     }
 };
 
 
-// Attach categories to classes in the same framework. 
-// Merge method and protocol and property lists.
 template <typename A>
 template <typename A>
-class CategoryAttacher {
+class HeaderInfoOptimizer {
 
     typedef typename A::P P;
     typedef typename A::P::uint_t pint_t;
 
 
     typedef typename A::P P;
     typedef typename A::P::uint_t pint_t;
 
-    uint8_t *mBytes;
-    ssize_t mBytesFree;
-    ssize_t mBytesUsed;
-
-    size_t mCategoriesAttached;
+    objc_header_info_t<A>* fHinfos;
+    size_t fCount;
 
 
-    bool segmentContainsPointer(SharedCache<A>* cache, 
-                                const macho_segment_command<P>* seg, void *ptr)
-    {
-        if (!seg) return false;
-        void *start = (void*)
-            cache->mappedAddressForVMAddress(seg->vmaddr());
-        void *end   = (uint8_t *)start + seg->filesize();
-        return (ptr >= start  &&  ptr < end);
-    }
+public:
+    HeaderInfoOptimizer() : fHinfos(0), fCount(0) { }
 
 
-    bool headerContainsPointer(SharedCache<A>* cache, 
-                               macho_header<P>* header, void *ptr)
+    const char *init(size_t count, uint8_t*& buf, size_t& bufSize)
     {
     {
-        return 
-            segmentContainsPointer(cache, header->getSegment("__DATA"), ptr) ||
-            segmentContainsPointer(cache, header->getSegment("__TEXT"), ptr) ||
-            segmentContainsPointer(cache, header->getSegment("__OBJC"), ptr);
-    }
-
-    struct pointer_hash {
-        size_t operator () (void* ptr) const { 
-            return __gnu_cxx::hash<long>()((long)ptr); 
-        }
-    };
-
-    typedef std::deque<objc_category_t<A>*> CategoryList;
-    typedef std::vector<uint64_t> CategoryRefs;
-
-    struct ClassChanges {
-        CategoryList categories;
-        CategoryRefs catrefs;
-        
-        objc_method_list_t<A>* instanceMethods;
-        objc_method_list_t<A>* classMethods;
-        objc_protocol_list_t<A>* protocols;
-        objc_property_list_t<A>* instanceProperties;
-
-        ClassChanges() 
-            : instanceMethods(NULL), classMethods(NULL), 
-              protocols(NULL), instanceProperties(NULL)
-        { }
-
-        ~ClassChanges() { 
-            if (instanceMethods) delete instanceMethods;
-            if (classMethods) delete classMethods;
-            if (protocols) delete protocols;
-            if (instanceProperties) delete instanceProperties;
-        }
-    };
-
-    typedef __gnu_cxx::hash_map<objc_class_t<A>*, ClassChanges, pointer_hash> ClassMap;
-
-    class RangeArray {
-        typedef std::pair<uint8_t*,uint32_t> Range;
-        std::deque<Range> ranges;
+        if (count == 0) return NULL;
 
 
-        class SizeFits {
-        private:
-            uint32_t mSize;
-        public:
-            SizeFits(uint32_t size) : mSize(size) { } 
-            bool operator() (const Range& r) { 
-                return r.second >= mSize;
-            }
-        };
-
-        struct AddressComp {
-            bool operator() (const Range& lhs, const Range& rhs) {
-                return (lhs.first < rhs.first);
-            }
-        };
-    public:
-        RangeArray() { }
-        void add(void* p, uint32_t size) {
-            add(Range((uint8_t *)p, size));
+        if (bufSize < 2*sizeof(uint32_t) + count*sizeof(objc_header_info_t<A>)) {
+            return "libobjc's read/write section is too small (metadata not optimized)";
         }
         }
-        void add(const Range& r) {
-            // find insertion point
-            std::deque<Range>::iterator iter;
-            iter = upper_bound(ranges.begin(), ranges.end(), r, AddressComp());
-            // coalesce
-            // fixme doesn't fully coalesce if new range exactly fills a gap
-            if (iter != ranges.begin()) {
-                std::deque<Range>::iterator prev = iter - 1;
-                if ((*prev).first + (*prev).second == r.first) {
-                    (*prev).second += r.second;
-                    return;
-                }
-            }
-            if (iter != ranges.end()  &&  iter+1 != ranges.end()) {
-                std::deque<Range>::iterator next = iter + 1;
-                if (r.first + r.second == (*next).first) {
-                    (*next).second += r.second;
-                    (*next).first = r.first;
-                    return;
-                }
-            }
-            ranges.insert(iter, r);
-        }
-
-        uint8_t* remove(uint32_t size) {
-            // first-fit search
-            // this saves 50-75% of space overhead; 
-            // a better algorithm might do better
-
-            std::deque<Range>::iterator iter;
-            iter = find_if(ranges.begin(), ranges.end(), SizeFits(size));
-            if (iter == ranges.end()) {
-                return NULL;
-            }
 
 
-            Range& found = *iter;
-            uint8_t *result = found.first;
-            if (found.second > size) {
-                // keep leftovers
-                found.first += size;
-                found.second -= size;
-            } else {
-                ranges.erase(iter);
-            }
+        uint32_t *buf32 = (uint32_t *)buf;
+        A::P::E::set32(buf32[0], count);
+        A::P::E::set32(buf32[1], sizeof(objc_header_info_t<A>));
+        fHinfos = (objc_header_info_t<A>*)(buf32+2);
 
 
-            return result;
-        }
-    };
+        size_t total = sizeof(uint32_t) + count*sizeof(objc_header_info_t<A>);
+        buf += total;
+        bufSize -= total;
 
 
-    void copyMethods(typename objc_method_list_t<A>::method_iterator& dst, 
-                     const objc_method_list_t<A>* srcList)
-    {
-        objc_method_list_t<A>::method_iterator::
-            overwrite(dst, srcList);
+        return NULL;
     }
 
     }
 
-    void copyProperties(typename objc_property_list_t<A>::property_iterator& dst, 
-                        const objc_property_list_t<A>* srcList)
-    {
-        objc_property_list_t<A>::property_iterator::
-            overwrite(dst, srcList);
+    void update(SharedCache<A>* cache, const macho_header<P>* mh, std::vector<void*>& pointersInData)
+    { 
+        objc_header_info_t<A>* hi = new(&fHinfos[fCount++]) objc_header_info_t<A>(cache, mh);
+        hi->addPointers(pointersInData);
     }
 
     }
 
-    void copyProtocols(objc_protocol_list_t<A>* dst, pint_t& dstIndex,
-                       const objc_protocol_list_t<A>* src)
+    objc_header_info_t<A>* hinfoForHeader(SharedCache<A>* cache, const macho_header<P>* mh)
     {
     {
-        dst->overwrite(dstIndex, src);
-    }
-
-       class InSet
-       {
-       public:
-               InSet(std::set<void*>& deadPointers) : _deadPointers(deadPointers) {}
-
-               bool operator()(void* ptr) const {
-                       return ( _deadPointers.count(ptr) != 0 );
-               }
-
-       private:
-               std::set<void*>& _deadPointers;
-       };
-
-public:
-
-    CategoryAttacher(uint8_t *bytes, ssize_t bytesFree) 
-        : mBytes(bytes), mBytesFree(bytesFree)
-        , mBytesUsed(0), mCategoriesAttached(0) 
-    { }
-
-    size_t count() const { return mCategoriesAttached; }
-
-    const char *optimize(SharedCache<A>* cache, macho_header<P>* header, std::vector<void*>& pointersInData)
-    {
-        // Build class=>cateories mapping.
-        // Disregard target classes that aren't in this binary.
-
-        ClassMap map;
-
-               PointerSection<A, objc_category_t<A> *> 
-            nlcatsect(cache, header, "__DATA", "__objc_nlcatlist");
-        PointerSection<A, objc_category_t<A> *> 
-            catsect(cache, header, "__DATA", "__objc_catlist");
-        for (pint_t i = 0; i < catsect.count(); i++) {
-            objc_category_t<A> *cat = catsect.get(i);
-            objc_class_t<A> *cls = cat->getClass(cache);
-            if (!cls) continue;
-            if (!headerContainsPointer(cache, header, cls)) continue;
-                       if ( nlcatsect.count() !=0 ) {
-                               // don't optimize categories also in __objc_nlcatlist
-                               bool alsoInNlcatlist = false;
-                               for (pint_t nli = 0; nli < nlcatsect.count(); nli++) {
-                                       if ( nlcatsect.get(nli) == cat ) {
-                                               //fprintf(stderr, "skipping cat in __objc_nlcatlist for mh=%p\n", header);
-                                               alsoInNlcatlist = true;
-                                               break;
-                                       }
-                               }
-                               if ( alsoInNlcatlist ) 
-                                       continue;
-                       }
-
-            // The LAST category found is the FIRST to be processed later.
-            map[cls].categories.push_front(cat);
-
-            // We don't care about the category reference order.
-            map[cls].catrefs.push_back(i);
-        }
-
-        if (map.size() == 0) {
-            // No attachable categories.
-            return NULL;
-        }
-
-        // Process each class.
-        // Each class is all-or-nothing: either all of its categories 
-        // are attached successfully, or none of them are. This preserves 
-        // cache validity if we run out of space for more reallocations.
-
-        // unusedMemory stores memory ranges evacuated by now-unused metadata.
-        // It is available for re-use by other newly-added metadata.
-        // fixme could packing algorithm be improved?
-        RangeArray unusedMemory;
-
-        ssize_t reserve = 0;
-
-        // First: build new aggregated lists on the heap.
-        // Require enough space in mBytes for all of it.
-
-               std::set<void*> pointersToRemove;
-        for (typename ClassMap::iterator i = map.begin(); 
-             i != map.end(); 
-             ++i) 
-        {
-            objc_class_t<A>* cls = i->first;
-            objc_class_t<A>* meta = cls->getIsa(cache);
-            ClassChanges& changes = i->second;
-            CategoryList& cats = changes.categories;
-
-            // Count memory needed for all categories on this class.
-
-            uint32_t methodEntsize = 0;
-            uint32_t propertyEntsize = 0;
-            objc_method_list_t<A>* mlist;
-            objc_property_list_t<A>* proplist;
-            objc_protocol_list_t<A>* protolist;
-            uint32_t instanceMethodsCount = 0;
-            uint32_t classMethodsCount = 0;
-            uint32_t instancePropertyCount = 0;
-            pint_t protocolCount = 0;
-            bool addedInstanceMethods = false;
-            bool addedClassMethods = false;
-            bool addedInstanceProperties = false;
-            bool addedProtocols = false;
-
-            mlist = cls->getMethodList(cache);
-            if (mlist) {
-                instanceMethodsCount = mlist->getCount();
-                methodEntsize = 
-                    std::max(methodEntsize, mlist->getEntsize());
-            }
-
-            mlist = meta->getMethodList(cache);
-            if (mlist) {
-                classMethodsCount = mlist->getCount();
-                methodEntsize = 
-                    std::max(methodEntsize, mlist->getEntsize());
-            }
-
-            proplist = cls->getPropertyList(cache);
-            if (proplist) {
-                instancePropertyCount = proplist->getCount();
-                propertyEntsize = 
-                    std::max(propertyEntsize, proplist->getEntsize());
-            }
-
-            protolist = cls->getProtocolList(cache);
-            if (protolist) {
-                protocolCount = protolist->getCount();
-            }
-
-            typename CategoryList::iterator j;
-            for (j = cats.begin(); j != cats.end(); ++j) {
-                objc_category_t<A>* cat = *j;
-
-                mlist = cat->getInstanceMethods(cache);
-                if (mlist  &&  mlist->getCount() > 0) {
-                    addedInstanceMethods = true;
-                    instanceMethodsCount += mlist->getCount();
-                    methodEntsize = 
-                        std::max(methodEntsize, mlist->getEntsize());
-                }
-
-                mlist = cat->getClassMethods(cache);
-                if (mlist  &&  mlist->getCount() > 0) {
-                    addedClassMethods = true;
-                    classMethodsCount += mlist->getCount();
-                    methodEntsize = 
-                        std::max(methodEntsize, mlist->getEntsize());
-                }
-
-                proplist = cat->getInstanceProperties(cache);
-                if (proplist  &&  proplist->getCount() > 0) {
-                    addedInstanceProperties = true;
-                    instancePropertyCount += proplist->getCount();
-                    propertyEntsize = 
-                        std::max(propertyEntsize, proplist->getEntsize());
-                }
-
-                protolist = cat->getProtocols(cache);
-                if (protolist  &&  protolist->getCount() > 0) {
-                    addedProtocols = true;
-                    protocolCount += protolist->getCount();
-                }
-            }
-
-            // Allocate memory for aggregated lists. 
-            // Reserve the same amount of space from mBytes.
-
-            if (addedInstanceMethods) {
-                changes.instanceMethods = objc_method_list_t<A>::newMethodList(instanceMethodsCount, methodEntsize);
-                reserve = P::round_up(reserve + changes.instanceMethods->byteSize());
-            }
-            if (addedClassMethods) {
-                changes.classMethods = objc_method_list_t<A>::newMethodList(classMethodsCount, methodEntsize);
-                reserve = P::round_up(reserve + changes.classMethods->byteSize());
-            }
-            if (addedInstanceProperties) {
-                changes.instanceProperties = objc_property_list_t<A>::newPropertyList(instancePropertyCount, propertyEntsize);
-                reserve = P::round_up(reserve + changes.instanceProperties->byteSize());
-            }
-            if (addedProtocols) {
-                changes.protocols = objc_protocol_list_t<A>::newProtocolList(protocolCount);
-                reserve = P::round_up(reserve + changes.protocols->byteSize());
-            }
-
-                       // Merge. The LAST category's contents ends up FIRST in each list.
-                       // The aggregated lists are not sorted; a future pass does that.
-
-            typename objc_method_list_t<A>::method_iterator newInstanceMethods;
-            typename objc_method_list_t<A>::method_iterator newClassMethods;
-            typename objc_property_list_t<A>::property_iterator newInstanceProperties;
-            pint_t newProtocolIndex;
-
-            if (addedInstanceMethods) {
-                newInstanceMethods = changes.instanceMethods->begin();
-            }
-            if (addedClassMethods) {
-                newClassMethods = changes.classMethods->begin();
-            }
-            if (addedInstanceProperties) {
-                newInstanceProperties = changes.instanceProperties->begin();
-            }
-            if (addedProtocols) {
-                newProtocolIndex = 0;
-            }
-            
-            for (j = cats.begin(); j != cats.end(); ++j) {
-                objc_category_t<A>* cat = *j;
-
-                mlist = cat->getInstanceMethods(cache);
-                if (mlist) {
-                    copyMethods(newInstanceMethods, mlist);
-                                       mlist->getPointers(pointersToRemove);
-                    unusedMemory.add(mlist, mlist->byteSize());
-                }
-
-                mlist = cat->getClassMethods(cache);
-                if (mlist) {
-                    copyMethods(newClassMethods, mlist);
-                                       mlist->getPointers(pointersToRemove);
-                                       unusedMemory.add(mlist, mlist->byteSize());
-                }
-
-                proplist = cat->getInstanceProperties(cache);
-                if (proplist) {
-                    copyProperties(newInstanceProperties, proplist);
-                                       proplist->getPointers(pointersToRemove);
-                                       unusedMemory.add(proplist, proplist->byteSize());
-                }
-
-                protolist = cat->getProtocols(cache);
-                if (protolist) {
-                    copyProtocols(changes.protocols, newProtocolIndex, protolist);
-                                       protolist->getPointers(pointersToRemove);
-                                       unusedMemory.add(protolist, protolist->byteSize());
-                }
-
-                               cat->getPointers(pointersToRemove);
-                               unusedMemory.add(cat, sizeof(*cat));                
-            }
-
-            if (addedInstanceMethods && (mlist = cls->getMethodList(cache))) {
-                copyMethods(newInstanceMethods, mlist);
-                               mlist->getPointers(pointersToRemove);
-                               unusedMemory.add(mlist, mlist->byteSize());
-            }
-            if (addedClassMethods && (mlist = meta->getMethodList(cache))) {
-                copyMethods(newClassMethods, mlist);
-                               mlist->getPointers(pointersToRemove);
-                unusedMemory.add(mlist, mlist->byteSize());
-            }
-            if (addedInstanceProperties && (proplist = cls->getPropertyList(cache))) {
-                copyProperties(newInstanceProperties, proplist);
-                               proplist->getPointers(pointersToRemove);
-                               unusedMemory.add(proplist, proplist->byteSize());
-            }
-            if (addedProtocols && (protolist = cls->getProtocolList(cache))) {
-                copyProtocols(changes.protocols, newProtocolIndex, protolist);
-                               protolist->getPointers(pointersToRemove);
-                unusedMemory.add(protolist, protolist->byteSize());
-            }
+        // fixme could be binary search
+        pint_t mh_vmaddr = cache->VMAddressForMappedAddress(mh);
+        for (size_t i = 0; i < fCount; i++) {
+            objc_header_info_t<A>* hi = &fHinfos[i];
+            if (hi->header_vmaddr() == mh_vmaddr) return hi;
         }
         }
-
-               if (reserve > mBytesFree) {
-                       return "insufficient space for category data (metadata not optimized)";
-               }
-
-               // update cache slide info and remove areas now longer containing pointers
-               //fprintf(stderr, "found %lu pointers in objc structures being moved\n", pointersToRemove.size());
-               pointersInData.erase(std::remove_if(pointersInData.begin(), pointersInData.end(), InSet(pointersToRemove)), pointersInData.end());
-               
-
-               // All lists are now built.
-        // mBytes is big enough to hold everything if necessary.
-        // Everything in unusedMemory is now available for re-use.
-        // The original metadata is still untouched.
-
-        // Second: write lists into mBytes and unusedMemory, 
-        // then disconnect categories.
-
-        for (typename ClassMap::iterator i = map.begin(); 
-             i != map.end(); 
-             ++i) 
-        {
-            objc_class_t<A>* cls = i->first;
-            objc_class_t<A>* meta = cls->getIsa(cache);
-            ClassChanges& changes = i->second;
-
-            // Write lists.
-            
-            if (changes.instanceMethods) {
-                uint8_t *bytes;
-                uint32_t size = changes.instanceMethods->byteSize();
-                if (! (bytes = unusedMemory.remove(size))) {
-                    bytes = mBytes + mBytesUsed;
-                    mBytesFree -= size;
-                    mBytesUsed += size;
-                }
-                memcpy(bytes, changes.instanceMethods, size);
-                               objc_method_list_t<A>::addPointers(bytes, pointersInData);
-                               cls->setMethodList(cache, (objc_method_list_t<A> *)bytes);
-                               cls->addMethodListPointer(cache, pointersInData);
-            }
-            
-            if (changes.classMethods) {
-                uint8_t *bytes;
-                uint32_t size = changes.classMethods->byteSize();
-                if (! (bytes = unusedMemory.remove(size))) {
-                    bytes = mBytes + mBytesUsed;
-                    mBytesFree -= size;
-                    mBytesUsed += size;
-                }
-                memcpy(bytes, changes.classMethods, size);
-                               objc_method_list_t<A>::addPointers(bytes, pointersInData);
-                               meta->setMethodList(cache, (objc_method_list_t<A> *)bytes);
-                               meta->addMethodListPointer(cache, pointersInData);
-            }
-            
-            if (changes.instanceProperties) {
-                uint8_t *bytes;
-                uint32_t size = changes.instanceProperties->byteSize();
-                if (! (bytes = unusedMemory.remove(size))) {
-                    bytes = mBytes + mBytesUsed;
-                    mBytesFree -= size;
-                    mBytesUsed += size;
-                }
-                memcpy(bytes, changes.instanceProperties, size);
-                               objc_property_list_t<A>::addPointers(bytes, pointersInData);
-                cls->setPropertyList(cache, (objc_property_list_t<A> *)bytes);
-                               cls->addPropertyListPointer(cache, pointersInData);
-          }
-
-            if (changes.protocols) {
-                uint8_t *bytes;
-                uint32_t size = changes.protocols->byteSize();
-                if (! (bytes = unusedMemory.remove(size))) {
-                    bytes = mBytes + mBytesUsed;
-                    mBytesFree -= size;
-                    mBytesUsed += size;
-                }
-                memcpy(bytes, changes.protocols, size);
-                cls->setProtocolList(cache, (objc_protocol_list_t<A> *)bytes);
-                               objc_protocol_list_t<A>::addPointers(bytes, pointersInData);
-                               cls->addProtocolListPointer(cache, pointersInData);
-                               meta->setProtocolList(cache, (objc_protocol_list_t<A> *)bytes);
-                               meta->addProtocolListPointer(cache, pointersInData);
-          }
-
-            // Disavow all knowledge of the categories.
-
-            for (typename CategoryRefs::iterator j = changes.catrefs.begin();
-                 j != changes.catrefs.end();
-                 ++j)
-            {
-                catsect.set(*j, 0);
-            }
-
-            mCategoriesAttached += changes.categories.size();
-        }
-
-        catsect.removeNulls();
-
         return NULL;
     }
         return NULL;
     }
-
-    ssize_t bytesUsed() { return mBytesUsed; }
 };
 };
index b86b3665b1115944bdc9466a17201cd3e65617c4..c94cbe0e645c4e4adef03d605763507b58075c51 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
  *
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
  *
- * Copyright (c) 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -85,6 +85,8 @@ int optimize_linkedit(macho_header<typename A::P>* mh, const void* mapped_cache,
        macho_segment_command<P>* linkEditSegCmd = NULL;
        macho_symtab_command<P>* symtab = NULL;
        macho_dysymtab_command<P>*      dynamicSymTab = NULL;
        macho_segment_command<P>* linkEditSegCmd = NULL;
        macho_symtab_command<P>* symtab = NULL;
        macho_dysymtab_command<P>*      dynamicSymTab = NULL;
+       macho_linkedit_data_command<P>* functionStarts = NULL;
+       macho_linkedit_data_command<P>* dataInCode = NULL;
        for (uint32_t i = 0; i < cmd_count; ++i) {
                if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
                        // update segment/section file offsets
        for (uint32_t i = 0; i < cmd_count; ++i) {
                if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
                        // update segment/section file offsets
@@ -121,6 +123,12 @@ int optimize_linkedit(macho_header<typename A::P>* mh, const void* mapped_cache,
                else if ( cmd->cmd() == LC_DYSYMTAB ) {
                        dynamicSymTab = (macho_dysymtab_command<P>*)cmd;
                }
                else if ( cmd->cmd() == LC_DYSYMTAB ) {
                        dynamicSymTab = (macho_dysymtab_command<P>*)cmd;
                }
+               else if ( cmd->cmd() == LC_FUNCTION_STARTS ) {
+                       functionStarts = (macho_linkedit_data_command<P>*)cmd;
+               }
+               else if ( cmd->cmd() == LC_DATA_IN_CODE ) {
+                       dataInCode = (macho_linkedit_data_command<P>*)cmd;
+               }
                cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
        }
        
                cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
        }
        
@@ -137,8 +145,23 @@ int optimize_linkedit(macho_header<typename A::P>* mh, const void* mapped_cache,
                fprintf(stderr, "LC_DYSYMTAB not found\n");
                return -1;
        }
                fprintf(stderr, "LC_DYSYMTAB not found\n");
                return -1;
        }
+
+       const uint32_t newFunctionStartsOffset = linkEditSegCmd->fileoff();
+       uint32_t functionStartsSize = 0;
+       if ( functionStarts != NULL ) {
+               // copy function starts from original cache file to new mapped dylib file
+               functionStartsSize = functionStarts->datasize();
+               memcpy((char*)mh + newFunctionStartsOffset, (char*)mapped_cache + functionStarts->dataoff(), functionStartsSize);
+       }
+       const uint32_t newDataInCodeOffset = (newFunctionStartsOffset + functionStartsSize + sizeof(pint_t) - 1) & (-sizeof(pint_t)); // pointer align
+       uint32_t dataInCodeSize = 0;
+       if ( dataInCode != NULL ) {
+               // copy data-in-code info from original cache file to new mapped dylib file
+               dataInCodeSize = dataInCode->datasize();
+               memcpy((char*)mh + newDataInCodeOffset, (char*)mapped_cache + dataInCode->dataoff(), dataInCodeSize);
+       }
        // copy symbol entries and strings from original cache file to new mapped dylib file
        // copy symbol entries and strings from original cache file to new mapped dylib file
-       const uint32_t newSymTabOffset = linkEditSegCmd->fileoff();
+       const uint32_t newSymTabOffset = (newDataInCodeOffset + dataInCodeSize + sizeof(pint_t) - 1) & (-sizeof(pint_t)); // pointer align
        const uint32_t newIndSymTabOffset = newSymTabOffset + symtab->nsyms()*sizeof(macho_nlist<P>);
        const uint32_t newStringPoolOffset = newIndSymTabOffset + dynamicSymTab->nindirectsyms()*sizeof(uint32_t);
        macho_nlist<P>* const newSymTabStart = (macho_nlist<P>*)(((uint8_t*)mh) + newSymTabOffset);
        const uint32_t newIndSymTabOffset = newSymTabOffset + symtab->nsyms()*sizeof(macho_nlist<P>);
        const uint32_t newStringPoolOffset = newIndSymTabOffset + dynamicSymTab->nindirectsyms()*sizeof(uint32_t);
        macho_nlist<P>* const newSymTabStart = (macho_nlist<P>*)(((uint8_t*)mh) + newSymTabOffset);
@@ -165,6 +188,14 @@ int optimize_linkedit(macho_header<typename A::P>* mh, const void* mapped_cache,
        memcpy(newIndSymTab, mergedIndSymTab, dynamicSymTab->nindirectsyms()*sizeof(uint32_t));
        
        // update load commands
        memcpy(newIndSymTab, mergedIndSymTab, dynamicSymTab->nindirectsyms()*sizeof(uint32_t));
        
        // update load commands
+       if ( functionStarts != NULL ) {
+               functionStarts->set_dataoff(newFunctionStartsOffset);
+               functionStarts->set_datasize(functionStartsSize);
+       }
+       if ( dataInCode != NULL ) {
+               dataInCode->set_dataoff(newDataInCodeOffset);
+               dataInCode->set_datasize(dataInCodeSize);
+       }
        symtab->set_symoff(newSymTabOffset);
        symtab->set_stroff(newStringPoolOffset);
        symtab->set_strsize(poolOffset);
        symtab->set_symoff(newSymTabOffset);
        symtab->set_stroff(newStringPoolOffset);
        symtab->set_strsize(poolOffset);
@@ -290,7 +321,7 @@ size_t dylib_maker(const void* mapped_cache, std::vector<uint8_t> &dylib_data, c
 } 
 
 
 } 
 
 
-extern int dyld_shared_cache_extract_dylibs_progress(const char* shared_cache_file_path, const char* extraction_root_path,
+int dyld_shared_cache_extract_dylibs_progress(const char* shared_cache_file_path, const char* extraction_root_path,
                                                                                                        void (^progress)(unsigned current, unsigned total))
 {
        struct stat statbuf;
                                                                                                        void (^progress)(unsigned current, unsigned total))
 {
        struct stat statbuf;
@@ -319,14 +350,14 @@ extern int dyld_shared_cache_extract_dylibs_progress(const char* shared_cache_fi
                dylib_create_func = dylib_maker<x86>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1  x86_64") == 0 ) 
                dylib_create_func = dylib_maker<x86_64>;
                dylib_create_func = dylib_maker<x86>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1  x86_64") == 0 ) 
                dylib_create_func = dylib_maker<x86_64>;
-       else if ( strcmp((char*)mapped_cache, "dyld_v1     ppc") == 0 ) 
-               dylib_create_func = dylib_maker<ppc>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1   armv5") == 0 ) 
                dylib_create_func = dylib_maker<arm>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1   armv6") == 0 ) 
                dylib_create_func = dylib_maker<arm>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1   armv7") == 0 ) 
                dylib_create_func = dylib_maker<arm>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1   armv5") == 0 ) 
                dylib_create_func = dylib_maker<arm>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1   armv6") == 0 ) 
                dylib_create_func = dylib_maker<arm>;
        else if ( strcmp((char*)mapped_cache, "dyld_v1   armv7") == 0 ) 
                dylib_create_func = dylib_maker<arm>;
+       else if ( strncmp((char*)mapped_cache, "dyld_v1  armv7", 14) == 0 ) 
+               dylib_create_func = dylib_maker<arm>;
        else {
                fprintf(stderr, "Error: unrecognized dyld shared cache magic.\n");
         munmap(mapped_cache, statbuf.st_size);
        else {
                fprintf(stderr, "Error: unrecognized dyld shared cache magic.\n");
         munmap(mapped_cache, statbuf.st_size);
@@ -343,7 +374,7 @@ extern int dyld_shared_cache_extract_dylibs_progress(const char* shared_cache_fi
 
        // for each dylib instantiate a dylib file
     dispatch_group_t        group               = dispatch_group_create();
 
        // for each dylib instantiate a dylib file
     dispatch_group_t        group               = dispatch_group_create();
-    dispatch_semaphore_t    sema                = dispatch_semaphore_create(4);
+    dispatch_semaphore_t    sema                = dispatch_semaphore_create(2);
     dispatch_queue_t        process_queue       = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
     dispatch_queue_t        writer_queue        = dispatch_queue_create("dyld writer queue", 0);
     
     dispatch_queue_t        process_queue       = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
     dispatch_queue_t        writer_queue        = dispatch_queue_create("dyld writer queue", 0);
     
@@ -351,8 +382,8 @@ extern int dyld_shared_cache_extract_dylibs_progress(const char* shared_cache_fi
        __block unsigned        count               = 0;
     
        for ( NameToSegments::iterator it = map.begin(); it != map.end(); ++it) {
        __block unsigned        count               = 0;
     
        for ( NameToSegments::iterator it = map.begin(); it != map.end(); ++it) {
+        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
         dispatch_group_async(group, process_queue, ^{
         dispatch_group_async(group, process_queue, ^{
-            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
             
             char    dylib_path[PATH_MAX];
             strcpy(dylib_path, extraction_root_path);
             
             char    dylib_path[PATH_MAX];
             strcpy(dylib_path, extraction_root_path);
@@ -426,18 +457,35 @@ int dyld_shared_cache_extract_dylibs(const char* shared_cache_file_path, const c
 
 
 #if 0 
 
 
 #if 0 
+
+typedef int (*extractor_proc)(const char* shared_cache_file_path, const char* extraction_root_path,
+                                                                                                       void (^progress)(unsigned current, unsigned total));
+
 int main(int argc, const char* argv[])
 {
        if ( argc != 3 ) {
                fprintf(stderr, "usage: dsc_extractor <path-to-cache-file> <path-to-device-dir>\n");
                return 1;
        }
 int main(int argc, const char* argv[])
 {
        if ( argc != 3 ) {
                fprintf(stderr, "usage: dsc_extractor <path-to-cache-file> <path-to-device-dir>\n");
                return 1;
        }
-               
-       int result = dyld_shared_cache_extract_dylibs_progress(argv[1], argv[2], ^(unsigned c, unsigned total) { printf("%d/%d\n", c, total); } );
+       
+       void* handle = dlopen("/Developer/Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle", RTLD_LAZY);
+       if ( handle == NULL ) {
+               fprintf(stderr, "dsc_extractor.bundle could not be loaded\n");
+               return 1;
+       }
+       
+       extractor_proc proc = (extractor_proc)dlsym(handle, "dyld_shared_cache_extract_dylibs_progress");
+       if ( proc == NULL ) {
+               fprintf(stderr, "dsc_extractor.bundle did not have dyld_shared_cache_extract_dylibs_progress symbol\n");
+               return 1;
+       }
+       
+       int result = (*proc)(argv[1], argv[2], ^(unsigned c, unsigned total) { printf("%d/%d\n", c, total); } );
        fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n", result);
        return 0;
 }
 #endif
 
        fprintf(stderr, "dyld_shared_cache_extract_dylibs_progress() => %d\n", result);
        return 0;
 }
 #endif
 
-
 
 
index 9b5cac4f962f40a9a0d55a25e8db002949f9a2b9..50ff8c9ad5a521b9accecc155ace7a1a0eb41b41 100644 (file)
@@ -125,14 +125,14 @@ int dyld_shared_cache_iterate_segments_with_slide(const void* shared_cache_file,
                        return dyld::walkImages<x86>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1  x86_64") == 0 ) 
                        return dyld::walkImages<x86_64>(cache, callback);
                        return dyld::walkImages<x86>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1  x86_64") == 0 ) 
                        return dyld::walkImages<x86_64>(cache, callback);
-       else if ( strcmp((char*)cache, "dyld_v1     ppc") == 0 ) 
-                       return dyld::walkImages<ppc>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1   armv5") == 0 ) 
                        return dyld::walkImages<arm>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1   armv6") == 0 ) 
                        return dyld::walkImages<arm>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1   armv7") == 0 ) 
                        return dyld::walkImages<arm>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1   armv5") == 0 ) 
                        return dyld::walkImages<arm>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1   armv6") == 0 ) 
                        return dyld::walkImages<arm>(cache, callback);
        else if ( strcmp((char*)cache, "dyld_v1   armv7") == 0 ) 
                        return dyld::walkImages<arm>(cache, callback);
+       else if ( strncmp((char*)cache, "dyld_v1  armv7", 14) == 0 ) 
+                       return dyld::walkImages<arm>(cache, callback);
        else
                return -1;
 }
        else
                return -1;
 }
diff --git a/launch-cache/dsc_slider.cpp b/launch-cache/dsc_slider.cpp
deleted file mode 100644 (file)
index d11f46a..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
- *
- * Copyright (c) 2010 Apple 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 <stdio.h>
-#include <stdarg.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <Availability.h>
-
-#define NO_ULEB 1
-#include "dyld_cache_format.h"
-#include "Architectures.hpp"
-#include "MachOFileAbstraction.hpp"
-#include "CacheFileAbstraction.hpp"
-
-#include "dsc_slider.h"
-
-int update_dyld_shared_cache_load_address(const char* path, void (*logProc)(const char* format, ...) )
-{
-       int fd = open(path, O_RDONLY, 0);
-       if ( fd == -1 ) {
-               (*logProc)("open(%s) failed, errno=%d\n", path, errno);
-               return -1;
-       }
-       (void)fcntl(fd, F_NOCACHE, 1); // tell kernel to not cache file content
-
-       uint8_t buffer[4096];
-       if ( read(fd, buffer, 4096) != 4096 ) {
-               (*logProc)("read(%s) failed, errno=%d\n", path, errno);
-               close(fd);
-               return -1;
-       }
-       bool has64BitPointers = false;
-       bool isBigEndian = false;
-       uint64_t startReadOnlySharedRegion = 0;
-       uint64_t endReadOnlySharedRegion = 0;
-       uint64_t startReadWriteSharedRegion = 0;
-       uint64_t endReadWriteSharedRegion = 0;
-       if ( strcmp((char*)buffer, "dyld_v1    i386") == 0 ) {
-               has64BitPointers = false;
-               isBigEndian = false;
-       }
-       else if ( strcmp((char*)buffer, "dyld_v1  x86_64") == 0 ) {
-               has64BitPointers = true;
-               isBigEndian = false;
-               startReadOnlySharedRegion  = 0x7FFF80000000LL;
-               endReadOnlySharedRegion    = 0x7FFFC0000000LL;
-               startReadWriteSharedRegion = 0x7FFF70000000LL;
-               endReadWriteSharedRegion   = 0x7FFF80000000LL;
-       }
-       else if ( strcmp((char*)buffer, "dyld_v1     ppc") == 0 ) {
-               has64BitPointers = false;
-               isBigEndian = true;
-       }
-       else if ( strcmp((char*)buffer, "dyld_v1   armv5") == 0 ) {
-               has64BitPointers = false;
-               isBigEndian = false;
-               startReadOnlySharedRegion  = 0x30000000LL;
-               endReadOnlySharedRegion    = 0x3E000000LL;
-               startReadWriteSharedRegion = 0x3E000000LL;
-               endReadWriteSharedRegion   = 0x40000000LL;
-       }
-       else if ( strcmp((char*)buffer, "dyld_v1   armv6") == 0 ) {
-               has64BitPointers = false;
-               isBigEndian = false;
-               startReadOnlySharedRegion  = 0x30000000LL;
-               endReadOnlySharedRegion    = 0x3E000000LL;
-               startReadWriteSharedRegion = 0x3E000000LL;
-               endReadWriteSharedRegion   = 0x40000000LL;
-       }
-       else if ( strcmp((char*)buffer, "dyld_v1   armv7") == 0 ) {
-               has64BitPointers = false;
-               isBigEndian = false;
-               startReadOnlySharedRegion  = 0x30000000LL;
-               endReadOnlySharedRegion    = 0x3E000000LL;
-               startReadWriteSharedRegion = 0x3E000000LL;
-               endReadWriteSharedRegion   = 0x40000000LL;
-       }
-       else {
-               (*logProc)("file %s is not a known dyld shared cache file\n", path);
-               close(fd);
-               return -1;
-       }
-#if __BIG_ENDIAN__ 
-       bool swap = !isBigEndian;
-#else
-       bool swap = isBigEndian;
-#endif
-       
-       const dyld_cache_header* header = (dyld_cache_header*)buffer;
-       uint32_t mappingOffset = swap ? OSSwapInt32(header->mappingOffset) : header->mappingOffset;
-       if ( mappingOffset < 0x48 ) {
-               (*logProc)("dyld shared cache file %s is old format\n", path);
-               close(fd);
-               return -1;
-       }
-
-       uint32_t mappingCount = swap ? OSSwapInt32(header->mappingCount) : header->mappingCount;
-       if ( mappingCount != 3 ) {
-               (*logProc)("dyld shared cache file %s has wrong mapping count\n", path);
-               close(fd);
-               return -1;
-       }
-
-       uint64_t slidePointersOffset = swap ? OSSwapInt64(header->slidePointersOffset) : header->slidePointersOffset;
-       uint64_t slidePointersSize = swap ? OSSwapInt64(header->slidePointersSize) : header->slidePointersSize;
-       if ( (slidePointersOffset == 0) || (slidePointersSize == 0) ) {
-               (*logProc)("dyld shared cache file %s is missing slide information\n", path);
-               close(fd);
-               return -1;
-       }
-       
-       // read slide info
-       void* slideInfo = malloc(slidePointersSize);
-       if ( slideInfo == NULL ) {
-               (*logProc)("malloc(%llu) failed\n", slidePointersSize);
-               close(fd);
-               return -1;
-       }
-       int64_t amountRead = pread(fd, slideInfo, slidePointersSize, slidePointersOffset);
-       if ( amountRead != (int64_t)slidePointersSize ) {
-               (*logProc)("slide info pread(fd, buf, %llu, %llu) failed\n", slidePointersSize, slidePointersOffset);
-               close(fd);
-               return -1;
-       }
-
-       // read all DATA 
-       const dyld_cache_mapping_info* mappings = (dyld_cache_mapping_info*)&buffer[mappingOffset];
-       uint64_t dataFileOffset = swap ? OSSwapInt64(mappings[1].fileOffset) : mappings[1].fileOffset;
-       uint64_t dataSize = swap ? OSSwapInt64(mappings[1].size) : mappings[1].size;
-       uint8_t* data = (uint8_t*)malloc(dataSize);
-       amountRead = pread(fd, data, dataSize, dataFileOffset);
-       if ( amountRead != (int64_t)dataSize ) {
-               (*logProc)("data pread(fd, buf, %llu, %llu) failed\n", data, dataSize);
-               close(fd);
-               return -1;
-       }
-       
-       // close read-only file
-       close(fd);
-       
-       // extract current slide
-       uint64_t headerDataUses;
-       if ( has64BitPointers ) {
-               headerDataUses = *((uint64_t*)data);
-               if ( swap ) 
-                       headerDataUses = OSSwapInt64(headerDataUses);
-       }
-       else {
-               uint32_t temp = *((uint32_t*)data);
-               if ( swap ) 
-                       temp = OSSwapInt32(temp);
-               headerDataUses = temp;
-       }
-       uint64_t textAddress = swap ? OSSwapInt64(mappings[0].address) : mappings[0].address;
-       uint32_t currentSlide = headerDataUses - textAddress;
-       (*logProc)("currentSlide=0x%08X\n", currentSlide);
-       
-       // find read-only space
-       uint64_t linkeditAddress = swap ? OSSwapInt64(mappings[2].address) : mappings[2].address;
-       uint64_t linkeditSize = swap ? OSSwapInt64(mappings[2].size) : mappings[2].size;
-       uint64_t linkeditEnd = linkeditAddress + linkeditSize;
-       uint64_t roSpace = endReadOnlySharedRegion - linkeditEnd;
-       (*logProc)("ro space=0x%08llX\n", roSpace);
-       
-       // find read-write space
-       uint64_t dataAddress = swap ? OSSwapInt64(mappings[1].address) : mappings[1].address;
-       uint64_t dataEnd = dataAddress + dataSize;
-       uint64_t rwSpace = endReadWriteSharedRegion - dataEnd;
-       (*logProc)("rw space=0x%08llX\n", rwSpace);
-       
-       // choose new random slide
-       uint32_t slideSpace = rwSpace;
-       if ( roSpace < rwSpace )
-               slideSpace = roSpace;
-       uint32_t newSlide = (arc4random() % slideSpace) & (-4096);
-       (*logProc)("newSlide=0x%08X\n", newSlide);
-       int32_t slideAdjustment = newSlide - currentSlide;
-       
-       // update DATA with slide info
-       uint64_t offsetInCacheFile = 0;
-       const uint8_t* infoStart = (uint8_t*)slideInfo;
-       const uint8_t* infoEnd = infoStart + slidePointersSize;
-       for(const uint8_t* p = infoStart; (*p != 0) && (p < infoEnd); ) {
-               uint64_t delta = 0;
-               uint32_t shift = 0;
-               bool more = true;
-               do {
-                       uint8_t byte = *p++;
-                       delta |= ((byte & 0x7F) << shift);
-                       shift += 7;
-                       if ( byte < 0x80 ) {
-                               offsetInCacheFile += delta;
-                               // verify in DATA range
-                               if ( (offsetInCacheFile < dataFileOffset) || (offsetInCacheFile > (dataFileOffset+dataSize)) ) {
-                                       (*logProc)("pointer offset 0x%llX outside DATA range\n", offsetInCacheFile);
-                                       return -1;
-                               }
-                               uint32_t offsetInData = offsetInCacheFile - dataFileOffset;
-                               if ( has64BitPointers ) {
-                                       uint64_t value64 = *((uint64_t*)(&data[offsetInData]));
-                                       if ( swap ) 
-                                               value64 = OSSwapInt64(value64);
-                                       value64 += slideAdjustment;
-                                       if ( swap ) 
-                                               value64 = OSSwapInt64(value64);
-                                       *((uint64_t*)(&data[offsetInData])) = value64;
-                               }
-                               else {
-                                       uint64_t value32 = *((uint32_t*)(&data[offsetInData]));
-                                       if ( swap ) 
-                                               value32 = OSSwapInt32(value32);
-                                       value32 += slideAdjustment;
-                                       if ( swap ) 
-                                               value32 = OSSwapInt32(value32);
-                                       *((uint32_t*)(&data[offsetInData])) = value32;
-                               }
-                               //(*logProc)("update pointer at offset 0x%08X", offsetInData);
-                               more = false;
-                       }
-               } while (more);
-       }
-       free(slideInfo);
-       slideInfo = NULL;
-       
-       // re-open cache file and overwrite DATA range
-       fd = open(path, O_RDWR, 0);
-       if ( fd == -1 ) {
-               (*logProc)("open(%s) failed, errno=%d\n", path, errno);
-               return -1;
-       }
-       (void)fcntl(fd, F_NOCACHE, 1); // tell kernel to not cache file content
-       uint64_t amountWrote = pwrite(fd, data, dataSize, dataFileOffset);
-       if ( amountWrote != dataSize ) {
-               (*logProc)("data pwrite(fd, buf, %llu, %llu) failed\n", data, dataSize);
-               close(fd);
-               return -1;
-       }
-       close(fd);
-       
-       // re-open and re-read to verify write
-       fd = open(path, O_RDONLY, 0);
-       if ( fd == -1 ) {
-               (*logProc)("verify open(%s) failed, errno=%d\n", path, errno);
-               return -1;
-       }
-       (void)fcntl(fd, F_NOCACHE, 1); // tell kernel to not cache file content
-       uint8_t* dataVerify = (uint8_t*)malloc(dataSize);
-       amountRead = pread(fd, dataVerify, dataSize, dataFileOffset);
-       if ( amountRead != (int64_t)dataSize ) {
-               (*logProc)("verify data pread(fd, buf, %llu, %llu) failed\n", data, dataSize);
-               close(fd);
-               return -1;
-       }
-       close(fd);
-       if ( memcmp(data, dataVerify, dataSize) != 0 ) {
-               (*logProc)("data update verification failed\n");
-               return -1;
-       }
-       free(data);
-       free(dataVerify);
-
-       
-       // success
-       return 0;
-}
-
-
-#if 0
-static void logger(const char* format, ...)
-{
-       va_list list;
-       va_start(list, format);
-       fprintf(stderr, "error: ");
-       vfprintf(stderr, format, list);
-}
-
-
-int main(int argc, const char* argv[])
-{
-       return update_dyld_shared_cache_load_address(argv[1], logger);
-}
-#endif
-
-
diff --git a/launch-cache/dsc_slider.h b/launch-cache/dsc_slider.h
deleted file mode 100644 (file)
index 4979562..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 
- *
- * Copyright (c) 2010 Apple 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>
-
-#ifdef __cplusplus
-extern "C" {
-#endif 
-
-//
-// This function is called with a path to a dyld shared cache file.  It will update the shared cache file 
-// in place.  The update randomizes the load address when the shared cache file is later used by dyld.
-//
-// On success, the return value is zero.  
-// On failure the return value is non-zero and an explanation error was written to the logProc callback.
-//
-extern int update_dyld_shared_cache_load_address(const char* path, void (*logProc)(const char* format, ...) );
-
-
-#ifdef __cplusplus
-}
-#endif 
index 42a1a139155e60e2c5f53b753b5a18a13b232ba7..70d897cb7e7f9ed165239e13a1934e8426872b6c 100644 (file)
@@ -31,7 +31,7 @@
 
 struct dyld_cache_header
 {
 
 struct dyld_cache_header
 {
-       char            magic[16];                              // e.g. "dyld_v0     ppc"
+       char            magic[16];                              // e.g. "dyld_v0    i386"
        uint32_t        mappingOffset;                  // file offset to first dyld_cache_mapping_info
        uint32_t        mappingCount;                   // number of dyld_cache_mapping_info entries
        uint32_t        imagesOffset;                   // file offset to first dyld_cache_image_info
        uint32_t        mappingOffset;                  // file offset to first dyld_cache_mapping_info
        uint32_t        mappingCount;                   // number of dyld_cache_mapping_info entries
        uint32_t        imagesOffset;                   // file offset to first dyld_cache_image_info
index d82674af33f90c4d1d27355287993101a190e443..b0b69182cc1aee5591472dc1889cbb78939f5c51 100644 (file)
@@ -78,14 +78,16 @@ static const char* default_shared_cache_path() {
        return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "i386";
 #elif __x86_64__ 
        return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "x86_64";
        return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "i386";
 #elif __x86_64__ 
        return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "x86_64";
-#elif __ppc__ 
-       return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "rosetta";
 #elif __ARM_ARCH_5TEJ__ 
        return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv5";
 #elif __ARM_ARCH_6K__ 
        return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv6";
 #elif __ARM_ARCH_7A__ 
        return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv7";
 #elif __ARM_ARCH_5TEJ__ 
        return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv5";
 #elif __ARM_ARCH_6K__ 
        return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv6";
 #elif __ARM_ARCH_7A__ 
        return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv7";
+#elif __ARM_ARCH_7F__ 
+       return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv7f";
+#elif __ARM_ARCH_7K__ 
+       return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME "armv7k";
 #else
        #error unsupported architecture
 #endif
 #else
        #error unsupported architecture
 #endif
@@ -137,14 +139,17 @@ void list_dependencies(const char *dylib, void *headerAddr, uint8_t print_dylib_
                        uint32_t current_vers = dylib_cmd->current_version();
                        
             if (print_dylib_versions) {
                        uint32_t current_vers = dylib_cmd->current_version();
                        
             if (print_dylib_versions) {
-                printf("\t%s (compatibility version %u.%u.%u, current version %u.%u.%u)\n", 
-                       name, 
+                printf("\t%s", name);
+                if ( compat_vers != 0xFFFFFFFF )
+                    printf("(compatibility version %u.%u.%u, current version %u.%u.%u)\n", 
                        (compat_vers >> 16),
                        (compat_vers >> 8) & 0xff,
                        (compat_vers) & 0xff,
                        (current_vers >> 16),
                        (current_vers >> 8) & 0xff,
                        (current_vers) & 0xff);
                        (compat_vers >> 16),
                        (compat_vers >> 8) & 0xff,
                        (compat_vers) & 0xff,
                        (current_vers >> 16),
                        (current_vers >> 8) & 0xff,
                        (current_vers) & 0xff);
+                else
+                    printf("\n");
             } else {
                 printf("\t%s\n", name);
             }                  
             } else {
                 printf("\t%s\n", name);
             }                  
@@ -417,7 +422,9 @@ int main (int argc, char **argv) {
                const dyldCacheHeader<LittleEndian>* header = (dyldCacheHeader<LittleEndian>*)mapped_cache;
                if (   (strcmp(header->magic(), "dyld_v1  x86_64") != 0)
                        && (strcmp(header->magic(), "dyld_v1   armv6") != 0)
                const dyldCacheHeader<LittleEndian>* header = (dyldCacheHeader<LittleEndian>*)mapped_cache;
                if (   (strcmp(header->magic(), "dyld_v1  x86_64") != 0)
                        && (strcmp(header->magic(), "dyld_v1   armv6") != 0)
-                       && (strcmp(header->magic(), "dyld_v1   armv7") != 0) ) {
+                       && (strcmp(header->magic(), "dyld_v1   armv7") != 0) 
+                       && (strcmp(header->magic(), "dyld_v1  armv7f") != 0) 
+                       && (strcmp(header->magic(), "dyld_v1  armv7k") != 0) ) {
                        fprintf(stderr, "Error: unrecognized dyld shared cache magic or arch does not support sliding\n");
                        exit(1);
                }
                        fprintf(stderr, "Error: unrecognized dyld shared cache magic or arch does not support sliding\n");
                        exit(1);
                }
@@ -449,14 +456,16 @@ int main (int argc, char **argv) {
                        callback = segment_callback<x86>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1  x86_64") == 0 ) 
                        callback = segment_callback<x86_64>;
                        callback = segment_callback<x86>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1  x86_64") == 0 ) 
                        callback = segment_callback<x86_64>;
-               else if ( strcmp((char*)mapped_cache, "dyld_v1     ppc") == 0 ) 
-                       callback = segment_callback<ppc>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1   armv5") == 0 ) 
                        callback = segment_callback<arm>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1   armv6") == 0 ) 
                        callback = segment_callback<arm>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1   armv7") == 0 ) 
                        callback = segment_callback<arm>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1   armv5") == 0 ) 
                        callback = segment_callback<arm>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1   armv6") == 0 ) 
                        callback = segment_callback<arm>;
                else if ( strcmp((char*)mapped_cache, "dyld_v1   armv7") == 0 ) 
                        callback = segment_callback<arm>;
+               else if ( strcmp((char*)mapped_cache, "dyld_v1  armv7f") == 0 ) 
+                       callback = segment_callback<arm>;
+               else if ( strcmp((char*)mapped_cache, "dyld_v1  armv7k") == 0 ) 
+                       callback = segment_callback<arm>;
                else {
                        fprintf(stderr, "Error: unrecognized dyld shared cache magic.\n");
                        exit(1);
                else {
                        fprintf(stderr, "Error: unrecognized dyld shared cache magic.\n");
                        exit(1);
index c7a3874b9a11d379d092e722768eca189bea818b..ac9cc1ccc006a8be19b2a00e3d8b5e5dda11bb25 100644 (file)
@@ -59,9 +59,9 @@
 #include "CacheFileAbstraction.hpp"
 
 #define SELOPT_WRITE
 #include "CacheFileAbstraction.hpp"
 
 #define SELOPT_WRITE
-#include <objc/objc-selopt.h>
+#include "objc-shared-cache.h"
 
 
-#define FIRST_DYLIB_TEXT_OFFSET 0x5000
+#define FIRST_DYLIB_TEXT_OFFSET 0x7000
 #define FIRST_DYLIB_DATA_OFFSET 0x1000
 
 #ifndef LC_FUNCTION_STARTS
 #define FIRST_DYLIB_DATA_OFFSET 0x1000
 
 #ifndef LC_FUNCTION_STARTS
@@ -109,7 +109,8 @@ public:
        static void                     addRoot(const char* vpath, const std::set<ArchPair>& archs);
        static void                     findSharedDylibs(ArchPair ap);
        static ArchGraph*       graphForArchPair(ArchPair ap) { return fgPerArchGraph[ap]; }
        static void                     addRoot(const char* vpath, const std::set<ArchPair>& archs);
        static void                     findSharedDylibs(ArchPair ap);
        static ArchGraph*       graphForArchPair(ArchPair ap) { return fgPerArchGraph[ap]; }
-       static void                     setFileSystemRoot(const char* root, bool usesOverlay) { fgFileSystemRoot = root; fgUsesOverlay = usesOverlay; }
+       static void                     setFileSystemRoot(const char* root) { fgFileSystemRoot = root; }
+       static void                     setFileSystemOverlay(const char* overlay) { fgFileSystemOverlay = overlay; }
        static const char*      archName(ArchPair ap);
        
        ArchPair                                                                                        getArchPair() { return fArchPair; }
        static const char*      archName(ArchPair ap);
        
        ArchPair                                                                                        getArchPair() { return fArchPair; }
@@ -151,7 +152,7 @@ private:
 
        static std::map<ArchPair, ArchGraph*>   fgPerArchGraph;
        static const char*                                              fgFileSystemRoot;
 
        static std::map<ArchPair, ArchGraph*>   fgPerArchGraph;
        static const char*                                              fgFileSystemRoot;
-       static bool                                                             fgUsesOverlay;
+       static const char*                                              fgFileSystemOverlay;
        
        ArchPair                                                                        fArchPair;
        std::set<DependencyNode*>                                       fRoots;
        
        ArchPair                                                                        fArchPair;
        std::set<DependencyNode*>                                       fRoots;
@@ -161,7 +162,7 @@ private:
 };
 std::map<ArchPair, ArchGraph*>         ArchGraph::fgPerArchGraph;
 const char*                                                    ArchGraph::fgFileSystemRoot = "";
 };
 std::map<ArchPair, ArchGraph*>         ArchGraph::fgPerArchGraph;
 const char*                                                    ArchGraph::fgFileSystemRoot = "";
-bool                                                           ArchGraph::fgUsesOverlay = false;
+const char*                                                    ArchGraph::fgFileSystemOverlay = "";
 
 void ArchGraph::addArchPair(ArchPair ap)
 {
 
 void ArchGraph::addArchPair(ArchPair ap)
 {
@@ -171,28 +172,30 @@ void ArchGraph::addArchPair(ArchPair ap)
 
 void ArchGraph::addRoot(const char* vpath, const std::set<ArchPair>& onlyArchs)
 {
 
 void ArchGraph::addRoot(const char* vpath, const std::set<ArchPair>& onlyArchs)
 {
-       char completePath[strlen(fgFileSystemRoot)+strlen(vpath)+2];
+       //fprintf(stderr, "addRoot(%s)\n", vpath);
+       char completePath[MAXPATHLEN];
        const char* path = NULL;
        const char* path = NULL;
-       if ( strlen(fgFileSystemRoot) == 0 ) {
-               path = vpath;
+       // check -overlay path first
+       if ( fgFileSystemOverlay[0] != '\0' ) {
+               strcpy(completePath, fgFileSystemOverlay);
+               strcat(completePath, vpath);    // assumes vpath starts with '/'
+               struct stat stat_buf;
+               if ( stat(completePath, &stat_buf) == 0 )
+                       path = completePath;
        }
        }
-       else {
+       // if not found in overlay, check for -root
+       if ( (path == NULL) && (fgFileSystemRoot[0] != '\0') ) {
                strcpy(completePath, fgFileSystemRoot);
                strcat(completePath, vpath);    // assumes vpath starts with '/'
                strcpy(completePath, fgFileSystemRoot);
                strcat(completePath, vpath);    // assumes vpath starts with '/'
-               if ( fgUsesOverlay ) {
-                       // using -overlay means if /overlay/usr/lib exists use it, otherwise use original path
-                       struct stat stat_buf;
-                       if ( stat(completePath, &stat_buf) == 0 )
-                               path = completePath;
-                       else
-                               path = vpath;
-               }
-               else {
-                       // using -root means alway redirect /usr/lib to /rootpath/usr/lib
+               struct stat stat_buf;
+               if ( stat(completePath, &stat_buf) == 0 )
                        path = completePath;
                        path = completePath;
-               }
        }
        }
+       if ( path == NULL ) 
+               path = vpath;
+       
        try {
        try {
+               //fprintf(stderr, "    UniversalMachOLayout::find(%s)\n", path);
                const UniversalMachOLayout& uni = UniversalMachOLayout::find(path, &onlyArchs);
                for(std::set<ArchPair>::iterator ait = onlyArchs.begin(); ait != onlyArchs.end(); ++ait) {
                        try {
                const UniversalMachOLayout& uni = UniversalMachOLayout::find(path, &onlyArchs);
                for(std::set<ArchPair>::iterator ait = onlyArchs.begin(); ait != onlyArchs.end(); ++ait) {
                        try {
@@ -229,54 +232,59 @@ void ArchGraph::addRoot(const char* path, const MachOLayoutAbstraction* layout)
                node->markNeededByRoot(NULL);
 }
 
                node->markNeededByRoot(NULL);
 }
 
-// a virtual path does not have the fgFileSystemRoot prefix
 // a virtual path does not have the fgFileSystemRoot prefix
 ArchGraph::DependencyNode* ArchGraph::getNodeForVirtualPath(const char* vpath)
 {
 // a virtual path does not have the fgFileSystemRoot prefix
 ArchGraph::DependencyNode* ArchGraph::getNodeForVirtualPath(const char* vpath)
 {
-       if ( fgFileSystemRoot == NULL ) {
-               return this->getNode(vpath);
-       }
-       else {
-               char completePath[strlen(fgFileSystemRoot)+strlen(vpath)+2];
-               strcpy(completePath, fgFileSystemRoot);
+       //fprintf(stderr, "getNodeForVirtualPath(%s)\n", vpath);
+       char completePath[MAXPATHLEN];
+       if ( fgFileSystemOverlay[0] != '\0' ) {
+               // using -overlay means if /overlay/path/dylib exists use it, otherwise use /path/dylib
+               strcpy(completePath, fgFileSystemOverlay);
                strcat(completePath, vpath);    // assumes vpath starts with '/'
                strcat(completePath, vpath);    // assumes vpath starts with '/'
-               if ( fgUsesOverlay ) {
-                       // using -overlay means if /overlay/path/dylib exists use it, otherwise use /path/dylib
-                       struct stat stat_buf;
-                       if ( stat(completePath, &stat_buf) == 0 )
-                               return this->getNode(completePath);
-                       else {
-                               // <rdar://problem/9279770> support when install name is a symlink
-                               if ( (lstat(vpath, &stat_buf) == 0) && S_ISLNK(stat_buf.st_mode) ) {
-                                       // requested path did not exist in /overlay, but leaf of path is a symlink in /
-                                       char pathInSymLink[MAXPATHLEN];
-                                       size_t res = readlink(vpath, pathInSymLink, sizeof(pathInSymLink));
-                                       if ( res != -1 ) {
-                                               pathInSymLink[res] = '\0';
-                                               if ( pathInSymLink[0] != '/' ) {
-                                                       char symFullPath[MAXPATHLEN];
-                                                       strcpy(symFullPath, vpath);
-                                                       char* lastSlash = strrchr(symFullPath, '/');
-                                                       if ( lastSlash != NULL ) {
-                                                               strcpy(lastSlash+1, pathInSymLink);
-                                                               // (re)try looking for what symlink points to, but in /overlay
-                                                               return this->getNodeForVirtualPath(symFullPath);
-                                                       }
-                                               } 
-                                       }
+               struct stat stat_buf;
+               if ( stat(completePath, &stat_buf) == 0 )
+                       return this->getNode(completePath);
+               else {
+                       // <rdar://problem/9279770> support when install name is a symlink
+                       const char* pathToSymlink = vpath;
+                       if ( fgFileSystemRoot[0] != '\0' ) {
+                               strcpy(completePath, fgFileSystemRoot);
+                               strcat(completePath, vpath);
+                               pathToSymlink = completePath;
+                       }
+                       if ( (lstat(pathToSymlink, &stat_buf) == 0) && S_ISLNK(stat_buf.st_mode) ) {
+                               // requested path did not exist in /overlay, but leaf of path is a symlink in /
+                               char pathInSymLink[MAXPATHLEN];
+                               size_t res = readlink(pathToSymlink, pathInSymLink, sizeof(pathInSymLink));
+                               if ( res != -1 ) {
+                                       pathInSymLink[res] = '\0';
+                                       if ( pathInSymLink[0] != '/' ) {
+                                               char symFullPath[MAXPATHLEN];
+                                               strcpy(symFullPath, vpath);
+                                               char* lastSlash = strrchr(symFullPath, '/');
+                                               if ( lastSlash != NULL ) {
+                                                       strcpy(lastSlash+1, pathInSymLink);
+                                                       // (re)try looking for what symlink points to, but in /overlay
+                                                       return this->getNodeForVirtualPath(symFullPath);
+                                               }
+                                       } 
                                }
                                }
-                               return this->getNode(vpath);
                        }
                }
                        }
                }
-               else {
-                       // using -root means always use /rootpath/usr/lib
-                       return this->getNode(completePath);
-               }
        }
        }
+       if ( fgFileSystemRoot[0] != '\0' ) {
+               // using -root means always use /rootpath/usr/lib
+               strcpy(completePath, fgFileSystemRoot);
+               strcat(completePath, vpath);    // assumes vpath starts with '/'
+               return this->getNode(completePath);
+       }
+       // not found in -overlay or -root not used
+       return this->getNode(vpath);
 }
 
 ArchGraph::DependencyNode* ArchGraph::getNode(const char* path)
 {
 }
 
 ArchGraph::DependencyNode* ArchGraph::getNode(const char* path)
 {
+       //fprintf(stderr, "getNode(%s)\n", path);
        // look up supplied path to see if node already exists
        PathToNode::iterator pos = fNodes.find(path);
        if ( pos != fNodes.end() )
        // look up supplied path to see if node already exists
        PathToNode::iterator pos = fNodes.find(path);
        if ( pos != fNodes.end() )
@@ -328,9 +336,13 @@ ArchGraph::DependencyNode* ArchGraph::getNode(const char* path)
                        fNodes[node->getLayout()->getID().name] = node;
                // update fAliasesMap with symlinks found
                const char* aliasPath = realPath;
                        fNodes[node->getLayout()->getID().name] = node;
                // update fAliasesMap with symlinks found
                const char* aliasPath = realPath;
-               if ( (fgFileSystemRoot != NULL) && (strncmp(realPath, fgFileSystemRoot, strlen(fgFileSystemRoot)) == 0) ) {
+               if ( (fgFileSystemRoot != NULL) && (fgFileSystemRoot[0] != '\0') && (strncmp(realPath, fgFileSystemRoot, strlen(fgFileSystemRoot)) == 0) ) {
                        aliasPath = &realPath[strlen(fgFileSystemRoot)];
                }
                        aliasPath = &realPath[strlen(fgFileSystemRoot)];
                }
+               // <rdar://problem/11192810> Too many aliases in -overlay mode
+               if ( (fgFileSystemOverlay != NULL) && (fgFileSystemOverlay[0] != '\0') && (strncmp(realPath, fgFileSystemOverlay, strlen(fgFileSystemOverlay)) == 0) ) {
+                       aliasPath = &realPath[strlen(fgFileSystemOverlay)];
+               }
                if ( fAliasesMap.find(aliasPath) == fAliasesMap.end() ) {
                        if ( strcmp(aliasPath, node->getLayout()->getID().name) != 0 ) {
                                fAliasesMap[strdup(aliasPath)] = node->getLayout()->getID().name;
                if ( fAliasesMap.find(aliasPath) == fAliasesMap.end() ) {
                        if ( strcmp(aliasPath, node->getLayout()->getID().name) != 0 ) {
                                fAliasesMap[strdup(aliasPath)] = node->getLayout()->getID().name;
@@ -402,7 +414,7 @@ void ArchGraph::DependencyNode::loadDependencies(const MachOLayoutAbstraction* m
                                        fDependsOn.insert(fGraph->getNodeForVirtualPath(dependentPath));
                        }
                        catch (const char* msg) {
                                        fDependsOn.insert(fGraph->getNodeForVirtualPath(dependentPath));
                        }
                        catch (const char* msg) {
-                               if ( it->weakImport && ! fLayout->hasSplitSegInfo() ) {
+                               if ( it->weakImport || ! fLayout->hasSplitSegInfo() ) {
                                        // ok to ignore missing weak imported dylibs from things that are
                                        // not going to be in the dyld shared cache
                                }
                                        // ok to ignore missing weak imported dylibs from things that are
                                        // not going to be in the dyld shared cache
                                }
@@ -476,8 +488,6 @@ void ArchGraph::findSharedDylibs(ArchPair ap)
 const char*    ArchGraph::archName(ArchPair ap)
 {
        switch ( ap.arch ) {
 const char*    ArchGraph::archName(ArchPair ap)
 {
        switch ( ap.arch ) {
-               case CPU_TYPE_POWERPC:
-                       return "ppc";
                case CPU_TYPE_I386:
                        return "i386";
                case CPU_TYPE_X86_64:
                case CPU_TYPE_I386:
                        return "i386";
                case CPU_TYPE_X86_64:
@@ -494,6 +504,10 @@ const char*        ArchGraph::archName(ArchPair ap)
                                        return "arm-xscale";
                                case CPU_SUBTYPE_ARM_V7:
                                        return "armv7";
                                        return "arm-xscale";
                                case CPU_SUBTYPE_ARM_V7:
                                        return "armv7";
+                               case CPU_SUBTYPE_ARM_V7F:
+                                       return "armv7f";
+                               case CPU_SUBTYPE_ARM_V7K:
+                                       return "armv7k";
                                default:
                                        return "arm";
                        }
                                default:
                                        return "arm";
                        }
@@ -554,6 +568,9 @@ bool ArchGraph::canBeShared(const MachOLayoutAbstraction* layout, ArchPair ap, c
                                if ( nodes.find(realPath) != nodes.end() )
                                        continue;
                        }
                                if ( nodes.find(realPath) != nodes.end() )
                                        continue;
                        }
+                       // handle weak imported dylibs not found
+                       if ( dit->weakImport )
+                               continue;
                        shareableMap[layout] = false;
                        char* msg;
                        asprintf(&msg, "can't put %s in shared cache because it depends on %s which can't be found", layout->getID().name, dit->name);
                        shareableMap[layout] = false;
                        char* msg;
                        asprintf(&msg, "can't put %s in shared cache because it depends on %s which can't be found", layout->getID().name, dit->name);
@@ -582,8 +599,9 @@ template <typename A>
 class SharedCache
 {
 public:
 class SharedCache
 {
 public:
-                                                       SharedCache(ArchGraph* graph, const char* rootPath, const char* cacheDir, bool alphaSort, bool verify, bool optimize, bool overlay, uint64_t dyldBaseAddress);
-       bool                                    update(bool usesOverlay, bool force, bool optimize, bool deleteExistingFirst, int archIndex, 
+                                                       SharedCache(ArchGraph* graph, const char* rootPath, const char* overlayPath, const char* cacheDir, bool explicitCacheDir,
+                                                                                       bool alphaSort, bool verify, bool optimize, uint64_t dyldBaseAddress);
+       bool                                    update(bool force, bool optimize, bool deleteExistingFirst, int archIndex, 
                                                                                int archCount, bool keepSignatures);
        static const char*              cacheFileSuffix(bool optimized, const char* archName);
 
                                                                                int archCount, bool keepSignatures);
        static const char*              cacheFileSuffix(bool optimized, const char* archName);
 
@@ -595,6 +613,8 @@ public:
        uint64_t                                cacheFileOffsetForVMAddress(uint64_t addr) const;
        uint64_t                                VMAddressForCacheFileOffset(uint64_t addr) const;
 
        uint64_t                                cacheFileOffsetForVMAddress(uint64_t addr) const;
        uint64_t                                VMAddressForCacheFileOffset(uint64_t addr) const;
 
+       static const char*              archName();
+
 private:
        typedef typename A::P                   P;
     typedef typename A::P::E           E;
 private:
        typedef typename A::P                   P;
     typedef typename A::P::E           E;
@@ -607,7 +627,6 @@ private:
 
        static void                             getSharedCacheBasAddresses(cpu_type_t arch, uint64_t* baseReadOnly, uint64_t* baseWritable);
        static cpu_type_t               arch();
 
        static void                             getSharedCacheBasAddresses(cpu_type_t arch, uint64_t* baseReadOnly, uint64_t* baseWritable);
        static cpu_type_t               arch();
-       static const char*              archName();
        static uint64_t                 sharedRegionReadOnlyStartAddress();
        static uint64_t                 sharedRegionWritableStartAddress();
        static uint64_t                 sharedRegionReadOnlySize();
        static uint64_t                 sharedRegionReadOnlyStartAddress();
        static uint64_t                 sharedRegionWritableStartAddress();
        static uint64_t                 sharedRegionReadOnlySize();
@@ -627,6 +646,12 @@ private:
                bool operator()(const LayoutInfo& left, const LayoutInfo& right) 
                                { return (strcmp(left.layout->getID().name, right.layout->getID().name) < 0); }
        };
                bool operator()(const LayoutInfo& left, const LayoutInfo& right) 
                                { return (strcmp(left.layout->getID().name, right.layout->getID().name) < 0); }
        };
+       
+       struct ByAddressSorter {
+               bool operator()(const LayoutInfo& left, const LayoutInfo& right) { 
+                       return (left.layout->getSegments()[0].newAddress() < right.layout->getSegments()[0].newAddress()); 
+               }
+       };
 
     struct ByCStringSectionSizeSorter {
         bool operator()(const LayoutInfo& left, const LayoutInfo& right) {
 
     struct ByCStringSectionSizeSorter {
         bool operator()(const LayoutInfo& left, const LayoutInfo& right) {
@@ -690,6 +715,8 @@ private:
        uint32_t                                                        fSizeOfOldStringPoolInCombinedLinkedit;
        uint32_t                                                        fOffsetOfFunctionStartsInCombinedLinkedit;
        uint32_t                                                        fSizeOfFunctionStartsInCombinedLinkedit;
        uint32_t                                                        fSizeOfOldStringPoolInCombinedLinkedit;
        uint32_t                                                        fOffsetOfFunctionStartsInCombinedLinkedit;
        uint32_t                                                        fSizeOfFunctionStartsInCombinedLinkedit;
+       uint32_t                                                        fOffsetOfDataInCodeInCombinedLinkedit;
+       uint32_t                                                        fSizeOfDataInCodeInCombinedLinkedit;
        uint32_t                                                        fLinkEditsTotalOptimizedSize;
 };
 
        uint32_t                                                        fLinkEditsTotalOptimizedSize;
 };
 
@@ -783,44 +810,37 @@ public:
 
 
        
 
 
        
-template <>     cpu_type_t     SharedCache<ppc>::arch()        { return CPU_TYPE_POWERPC; }
 template <>     cpu_type_t     SharedCache<x86>::arch()        { return CPU_TYPE_I386; }
 template <>     cpu_type_t     SharedCache<x86_64>::arch()     { return CPU_TYPE_X86_64; }
 template <>     cpu_type_t     SharedCache<arm>::arch()        { return CPU_TYPE_ARM; }
 
 template <>     cpu_type_t     SharedCache<x86>::arch()        { return CPU_TYPE_I386; }
 template <>     cpu_type_t     SharedCache<x86_64>::arch()     { return CPU_TYPE_X86_64; }
 template <>     cpu_type_t     SharedCache<arm>::arch()        { return CPU_TYPE_ARM; }
 
-template <>     uint64_t       SharedCache<ppc>::sharedRegionReadOnlyStartAddress()    { return 0x90000000; }
 template <>     uint64_t       SharedCache<x86>::sharedRegionReadOnlyStartAddress()    { return 0x90000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionReadOnlyStartAddress() { return 0x7FFF80000000LL; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionReadOnlyStartAddress()    { return 0x30000000; }
 
 template <>     uint64_t       SharedCache<x86>::sharedRegionReadOnlyStartAddress()    { return 0x90000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionReadOnlyStartAddress() { return 0x7FFF80000000LL; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionReadOnlyStartAddress()    { return 0x30000000; }
 
-template <>     uint64_t       SharedCache<ppc>::sharedRegionWritableStartAddress()    { return 0xA0000000; }
 template <>     uint64_t       SharedCache<x86>::sharedRegionWritableStartAddress()    { return 0xAC000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionWritableStartAddress() { return 0x7FFF70000000LL; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionWritableStartAddress()    { return 0x3E000000; }
 
 template <>     uint64_t       SharedCache<x86>::sharedRegionWritableStartAddress()    { return 0xAC000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionWritableStartAddress() { return 0x7FFF70000000LL; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionWritableStartAddress()    { return 0x3E000000; }
 
-template <>     uint64_t       SharedCache<ppc>::sharedRegionReadOnlySize()                    { return 0x10000000; }
 template <>     uint64_t       SharedCache<x86>::sharedRegionReadOnlySize()                    { return 0x1C000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionReadOnlySize()                 { return 0x40000000; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionReadOnlySize()                    { return 0x0E000000; }
 
 template <>     uint64_t       SharedCache<x86>::sharedRegionReadOnlySize()                    { return 0x1C000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionReadOnlySize()                 { return 0x40000000; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionReadOnlySize()                    { return 0x0E000000; }
 
-template <>     uint64_t       SharedCache<ppc>::sharedRegionWritableSize()                    { return 0x10000000; }
 template <>     uint64_t       SharedCache<x86>::sharedRegionWritableSize()                    { return 0x04000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionWritableSize()                 { return 0x10000000; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionWritableSize()                    { return 0x02000000; }
 
 
 template <>     uint64_t       SharedCache<x86>::sharedRegionWritableSize()                    { return 0x04000000; }
 template <>     uint64_t       SharedCache<x86_64>::sharedRegionWritableSize()                 { return 0x10000000; }
 template <>     uint64_t       SharedCache<arm>::sharedRegionWritableSize()                    { return 0x02000000; }
 
 
-template <>     const char*    SharedCache<ppc>::archName()    { return "ppc"; }
 template <>     const char*    SharedCache<x86>::archName()    { return "i386"; }
 template <>     const char*    SharedCache<x86_64>::archName() { return "x86_64"; }
 template <>     const char*    SharedCache<arm>::archName()    { return "arm"; }
 
 template <>     const char*    SharedCache<x86>::archName()    { return "i386"; }
 template <>     const char*    SharedCache<x86_64>::archName() { return "x86_64"; }
 template <>     const char*    SharedCache<arm>::archName()    { return "arm"; }
 
-template <>     const char*    SharedCache<ppc>::cacheFileSuffix(bool optimized, const char*)  { return optimized ? "ppc" : "rosetta"; }
 template <>     const char*    SharedCache<x86>::cacheFileSuffix(bool, const char* archName)   { return archName; }
 template <>     const char*    SharedCache<x86_64>::cacheFileSuffix(bool, const char* archName){ return archName; }
 template <>     const char*    SharedCache<arm>::cacheFileSuffix(bool, const char* archName)   { return archName; }
 
 template <typename A>
 template <>     const char*    SharedCache<x86>::cacheFileSuffix(bool, const char* archName)   { return archName; }
 template <>     const char*    SharedCache<x86_64>::cacheFileSuffix(bool, const char* archName){ return archName; }
 template <>     const char*    SharedCache<arm>::cacheFileSuffix(bool, const char* archName)   { return archName; }
 
 template <typename A>
-SharedCache<A>::SharedCache(ArchGraph* graph, const char* rootPath, const char* cacheDir, bool alphaSort, bool verify, bool optimize, bool overlay, uint64_t dyldBaseAddress) 
+SharedCache<A>::SharedCache(ArchGraph* graph, const char* rootPath, const char* overlayPath, const char* cacheDir, bool explicitCacheDir, bool alphaSort, bool verify, bool optimize, uint64_t dyldBaseAddress) 
   : fArchGraph(graph), fVerify(verify), fExistingIsNotUpToDate(true), 
        fCacheFileInFinalLocation(rootPath[0] == '\0'), fCacheFilePath(NULL),
        fExistingCacheForVerification(NULL), fDyldBaseAddress(dyldBaseAddress),
   : fArchGraph(graph), fVerify(verify), fExistingIsNotUpToDate(true), 
        fCacheFileInFinalLocation(rootPath[0] == '\0'), fCacheFilePath(NULL),
        fExistingCacheForVerification(NULL), fDyldBaseAddress(dyldBaseAddress),
@@ -830,7 +850,8 @@ SharedCache<A>::SharedCache(ArchGraph* graph, const char* rootPath, const char*
        fOffsetOfOldExternalRelocationsInCombinedLinkedit(0), fSizeOfOldExternalRelocationsInCombinedLinkedit(0),
        fOffsetOfOldIndirectSymbolsInCombinedLinkedit(0), fSizeOfOldIndirectSymbolsInCombinedLinkedit(0),
        fOffsetOfOldStringPoolInCombinedLinkedit(0), fSizeOfOldStringPoolInCombinedLinkedit(0),
        fOffsetOfOldExternalRelocationsInCombinedLinkedit(0), fSizeOfOldExternalRelocationsInCombinedLinkedit(0),
        fOffsetOfOldIndirectSymbolsInCombinedLinkedit(0), fSizeOfOldIndirectSymbolsInCombinedLinkedit(0),
        fOffsetOfOldStringPoolInCombinedLinkedit(0), fSizeOfOldStringPoolInCombinedLinkedit(0),
-       fOffsetOfFunctionStartsInCombinedLinkedit(0), fSizeOfFunctionStartsInCombinedLinkedit(0)
+       fOffsetOfFunctionStartsInCombinedLinkedit(0), fSizeOfFunctionStartsInCombinedLinkedit(0),
+       fOffsetOfDataInCodeInCombinedLinkedit(0), fSizeOfDataInCodeInCombinedLinkedit(0)
 {
        if ( fArchGraph->getArchPair().arch != arch() )
                throwf("SharedCache object is wrong architecture: 0x%08X vs 0x%08X", fArchGraph->getArchPair().arch, arch());
 {
        if ( fArchGraph->getArchPair().arch != arch() )
                throwf("SharedCache object is wrong architecture: 0x%08X vs 0x%08X", fArchGraph->getArchPair().arch, arch());
@@ -857,29 +878,50 @@ SharedCache<A>::SharedCache(ArchGraph* graph, const char* rootPath, const char*
        }
 
        // create path to cache file
        }
 
        // create path to cache file
-       char cachePathNonOverlay[1024];
-       strcpy(cachePathNonOverlay, cacheDir);
-       if ( cachePathNonOverlay[strlen(cachePathNonOverlay)-1] != '/' )
-               strcat(cachePathNonOverlay, "/");
-       strcat(cachePathNonOverlay, DYLD_SHARED_CACHE_BASE_NAME);
-       strcat(cachePathNonOverlay, cacheFileSuffix(optimize, fArchGraph->archName()));
-       char cachePath[1024];
-       strcpy(cachePath, rootPath);
-       strcat(cachePath, "/");
-       strcat(cachePath, cachePathNonOverlay);
-       if ( !overlay && (rootPath[0] != '\0') )
-               fCacheFilePath = strdup(cachePathNonOverlay);
-       else
+       char cachePathCanonical[MAXPATHLEN];
+       strcpy(cachePathCanonical, cacheDir);
+       if ( cachePathCanonical[strlen(cachePathCanonical)-1] != '/' )
+               strcat(cachePathCanonical, "/");
+       strcat(cachePathCanonical, DYLD_SHARED_CACHE_BASE_NAME);
+       strcat(cachePathCanonical, cacheFileSuffix(optimize, fArchGraph->archName()));
+       char cachePath[MAXPATHLEN];
+       if ( explicitCacheDir ) {
+               fCacheFilePath = strdup(cachePathCanonical);
+       }
+       else if ( overlayPath[0] != '\0' ) {
+               strcpy(cachePath, overlayPath);
+               strcat(cachePath, "/");
+               strcat(cachePath, cachePathCanonical);
+               fCacheFilePath = strdup(cachePath);
+       }
+       else if ( rootPath[0] != '\0' ) {
+               strcpy(cachePath, rootPath);
+               strcat(cachePath, "/");
+               strcat(cachePath, cachePathCanonical);
                fCacheFilePath = strdup(cachePath);
                fCacheFilePath = strdup(cachePath);
-       if ( overlay ) {
+       }
+       else {
+               fCacheFilePath = strdup(cachePathCanonical);
+       }
+       if ( overlayPath[0] != '\0' ) {
                // in overlay mode if there already is a cache file in the overlay
                // in overlay mode if there already is a cache file in the overlay
-               // check if it is up to date.  If there is no file, check if
-               // the one in the boot volume is up to date.
+               // check if it is up to date.  
                struct stat stat_buf;
                struct stat stat_buf;
-               if ( stat(fCacheFilePath, &stat_buf) == 0 ) 
+               if ( stat(fCacheFilePath, &stat_buf) == 0 ) {
                        fExistingIsNotUpToDate = this->notUpToDate(fCacheFilePath, aliasCount);
                        fExistingIsNotUpToDate = this->notUpToDate(fCacheFilePath, aliasCount);
-               else
-                       fExistingIsNotUpToDate = this->notUpToDate(cachePathNonOverlay, aliasCount);
+               }
+               else if ( rootPath[0] != '\0' ) {
+                       // using -root and -overlay, but no cache file in overlay, check one in -root
+                       char cachePathRoot[MAXPATHLEN];
+                       strcpy(cachePathRoot, rootPath);
+                       strcat(cachePathRoot, "/");
+                       strcat(cachePathRoot, cachePathCanonical);
+                       fExistingIsNotUpToDate = this->notUpToDate(cachePathRoot, aliasCount);
+               }
+               else {
+                       // uisng -overlay, but no cache file in overlay, check one in boot volume
+                       fExistingIsNotUpToDate = this->notUpToDate(cachePathCanonical, aliasCount);
+               }
        }
        else {
                fExistingIsNotUpToDate = this->notUpToDate(fCacheFilePath, aliasCount);
        }
        else {
                fExistingIsNotUpToDate = this->notUpToDate(fCacheFilePath, aliasCount);
@@ -955,13 +997,6 @@ uint64_t SharedCache<A>::getWritableSegmentNewAddress(uint64_t proposedNewAddres
        return proposedNewAddress;
 }
 
        return proposedNewAddress;
 }
 
-template <>
-uint64_t SharedCache<ppc>::getWritableSegmentNewAddress(uint64_t proposedNewAddress, uint64_t originalAddress, uint64_t executableSlide)
-{
-       // for ppc writable segments can only move in increments of 64K (so only hi16 instruction needs to be modified)
-       return (((executableSlide & 0x000000000000F000ULL) - ((proposedNewAddress - originalAddress) & 0x000000000000F000ULL)) & 0x000000000000F000ULL) + proposedNewAddress;
-}
-
 
 template <typename A>
 void SharedCache<A>::assignNewBaseAddresses(bool verify)
 
 template <typename A>
 void SharedCache<A>::assignNewBaseAddresses(bool verify)
@@ -1012,7 +1047,6 @@ void SharedCache<A>::assignNewBaseAddresses(bool verify)
                                }
                                else {
                                        // __DATA segment
                                }
                                else {
                                        // __DATA segment
-                                       // for ppc, writable segments have to move in 64K increments
                                        if (  it->layout->hasSplitSegInfo() ) {
                                                if ( executableSegment == NULL )
                                                        throwf("first segment in dylib is not executable for %s", it->layout->getID().name);
                                        if (  it->layout->hasSplitSegInfo() ) {
                                                if ( executableSegment == NULL )
                                                        throwf("first segment in dylib is not executable for %s", it->layout->getID().name);
@@ -1296,7 +1330,7 @@ bool SharedCache<A>::notUpToDate(const char* path, unsigned int aliasCount)
        (void)fcntl(fd, F_NOCACHE, 1);
     ssize_t readResult = pread(fd, mappingAddr, cacheFileSize, 0);
     if ( readResult != cacheFileSize )
        (void)fcntl(fd, F_NOCACHE, 1);
     ssize_t readResult = pread(fd, mappingAddr, cacheFileSize, 0);
     if ( readResult != cacheFileSize )
-        throw "can't read existing cache file";
+        throwf("can't read all of existing cache file (%lu of %u): %s", readResult, cacheFileSize, path);
        ::close(fd);
 
        // validate it
        ::close(fd);
 
        // validate it
@@ -1403,6 +1437,7 @@ public:
                void                                                            copyExternalRelocations(uint32_t& offset);
                void                                                            copyIndirectSymbolTable(uint32_t& offset);
                void                                                            copyFunctionStarts(uint32_t& offset);
                void                                                            copyExternalRelocations(uint32_t& offset);
                void                                                            copyIndirectSymbolTable(uint32_t& offset);
                void                                                            copyFunctionStarts(uint32_t& offset);
+               void                                                            copyDataInCode(uint32_t& offset);
                void                                                            updateLoadCommands(uint64_t newVMAddress, uint64_t size, uint32_t stringPoolOffset, 
                                                                                                                                uint32_t linkEditsFileOffset, bool keepSignatures);
        
                void                                                            updateLoadCommands(uint64_t newVMAddress, uint64_t size, uint32_t stringPoolOffset, 
                                                                                                                                uint32_t linkEditsFileOffset, bool keepSignatures);
        
@@ -1422,6 +1457,7 @@ private:
        macho_dyld_info_command<P>*                                     fDyldInfo;
        macho_dysymtab_command<P>*                                      fDynamicSymbolTable;
        macho_linkedit_data_command<P>*                         fFunctionStarts;
        macho_dyld_info_command<P>*                                     fDyldInfo;
        macho_dysymtab_command<P>*                                      fDynamicSymbolTable;
        macho_linkedit_data_command<P>*                         fFunctionStarts;
+       macho_linkedit_data_command<P>*                         fDataInCode;
        macho_symtab_command<P>*                                        fSymbolTableLoadCommand;
        const macho_nlist<P>*                                           fSymbolTable;
        const char*                                                                     fStrings;
        macho_symtab_command<P>*                                        fSymbolTableLoadCommand;
        const macho_nlist<P>*                                           fSymbolTable;
        const char*                                                                     fStrings;
@@ -1445,6 +1481,7 @@ private:
        uint32_t                                                                        fExternalRelocationsOffsetIntoNewLinkEdit;
        uint32_t                                                                        fIndirectSymbolTableOffsetInfoNewLinkEdit;
        uint32_t                                                                        fFunctionStartsOffsetInNewLinkEdit;
        uint32_t                                                                        fExternalRelocationsOffsetIntoNewLinkEdit;
        uint32_t                                                                        fIndirectSymbolTableOffsetInfoNewLinkEdit;
        uint32_t                                                                        fFunctionStartsOffsetInNewLinkEdit;
+       uint32_t                                                                        fDataInCodeOffsetInNewLinkEdit;
 };
 
 
 };
 
 
@@ -1452,7 +1489,8 @@ private:
 template <typename A>
 LinkEditOptimizer<A>::LinkEditOptimizer(const MachOLayoutAbstraction& layout, const SharedCache<A>& sharedCache, uint8_t* newLinkEdit, StringPool& stringPool)
  :     fSharedCache(sharedCache), fLayout(layout), fLinkEditBase(NULL), fNewLinkEditStart(newLinkEdit), fDyldInfo(NULL),
 template <typename A>
 LinkEditOptimizer<A>::LinkEditOptimizer(const MachOLayoutAbstraction& layout, const SharedCache<A>& sharedCache, uint8_t* newLinkEdit, StringPool& stringPool)
  :     fSharedCache(sharedCache), fLayout(layout), fLinkEditBase(NULL), fNewLinkEditStart(newLinkEdit), fDyldInfo(NULL),
-       fDynamicSymbolTable(NULL), fFunctionStarts(NULL), fSymbolTableLoadCommand(NULL), fSymbolTable(NULL), fStrings(NULL), fNewStringPool(stringPool),
+       fDynamicSymbolTable(NULL), fFunctionStarts(NULL), fDataInCode(NULL), 
+       fSymbolTableLoadCommand(NULL), fSymbolTable(NULL), fStrings(NULL), fNewStringPool(stringPool),
        fBindInfoOffsetIntoNewLinkEdit(0), fBindInfoSizeInNewLinkEdit(0),
        fWeakBindInfoOffsetIntoNewLinkEdit(0), fWeakBindInfoSizeInNewLinkEdit(0),
        fLazyBindInfoOffsetIntoNewLinkEdit(0), fLazyBindInfoSizeInNewLinkEdit(0),
        fBindInfoOffsetIntoNewLinkEdit(0), fBindInfoSizeInNewLinkEdit(0),
        fWeakBindInfoOffsetIntoNewLinkEdit(0), fWeakBindInfoSizeInNewLinkEdit(0),
        fLazyBindInfoOffsetIntoNewLinkEdit(0), fLazyBindInfoSizeInNewLinkEdit(0),
@@ -1462,7 +1500,7 @@ LinkEditOptimizer<A>::LinkEditOptimizer(const MachOLayoutAbstraction& layout, co
        fExportedSymbolsStartIndexInNewLinkEdit(0), fExportedSymbolsCountInNewLinkEdit(0),
        fImportSymbolsStartIndexInNewLinkEdit(0), fImportedSymbolsCountInNewLinkEdit(0),
        fExternalRelocationsOffsetIntoNewLinkEdit(0), fIndirectSymbolTableOffsetInfoNewLinkEdit(0),
        fExportedSymbolsStartIndexInNewLinkEdit(0), fExportedSymbolsCountInNewLinkEdit(0),
        fImportSymbolsStartIndexInNewLinkEdit(0), fImportedSymbolsCountInNewLinkEdit(0),
        fExternalRelocationsOffsetIntoNewLinkEdit(0), fIndirectSymbolTableOffsetInfoNewLinkEdit(0),
-       fFunctionStartsOffsetInNewLinkEdit(0)
+       fFunctionStartsOffsetInNewLinkEdit(0), fDataInCodeOffsetInNewLinkEdit(0)
        
 {
        fHeader = (const macho_header<P>*)fLayout.getSegments()[0].mappedAddress();
        
 {
        fHeader = (const macho_header<P>*)fLayout.getSegments()[0].mappedAddress();
@@ -1497,6 +1535,8 @@ LinkEditOptimizer<A>::LinkEditOptimizer(const MachOLayoutAbstraction& layout, co
                                break;
                        case LC_FUNCTION_STARTS:
                                fFunctionStarts = (macho_linkedit_data_command<P>*)cmd;
                                break;
                        case LC_FUNCTION_STARTS:
                                fFunctionStarts = (macho_linkedit_data_command<P>*)cmd;
+                       case LC_DATA_IN_CODE:
+                               fDataInCode = (macho_linkedit_data_command<P>*)cmd;
                                break;
                }
                cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
                                break;
                }
                cmd = (const macho_load_command<P>*)(((uint8_t*)cmd)+cmd->cmdsize());
@@ -1674,6 +1714,17 @@ void LinkEditOptimizer<A>::copyFunctionStarts(uint32_t& offset)
        }
 }
 
        }
 }
 
+template <typename A>
+void LinkEditOptimizer<A>::copyDataInCode(uint32_t& offset)
+{      
+       if ( fDataInCode != NULL ) {
+               fDataInCodeOffsetInNewLinkEdit = offset;
+               memcpy(&fNewLinkEditStart[offset], &fLinkEditBase[fDataInCode->dataoff()], fDataInCode->datasize());
+               offset += fDataInCode->datasize();
+       }
+}
+
+
 template <typename A>
 void LinkEditOptimizer<A>::copyIndirectSymbolTable(uint32_t& offset)
 {      
 template <typename A>
 void LinkEditOptimizer<A>::copyIndirectSymbolTable(uint32_t& offset)
 {      
@@ -1772,6 +1823,10 @@ void LinkEditOptimizer<A>::updateLoadCommands(uint64_t newVMAddress, uint64_t si
        if ( fFunctionStarts != NULL ) {
                fFunctionStarts->set_dataoff(linkEditsFileOffset+fFunctionStartsOffsetInNewLinkEdit);
        }
        if ( fFunctionStarts != NULL ) {
                fFunctionStarts->set_dataoff(linkEditsFileOffset+fFunctionStartsOffsetInNewLinkEdit);
        }
+       // update data-in-code info
+       if ( fDataInCode != NULL ) {
+               fDataInCode->set_dataoff(linkEditsFileOffset+fDataInCodeOffsetInNewLinkEdit);
+       }
        
        // now remove load commands no longer needed
        const macho_load_command<P>* srcCmd = cmds;
        
        // now remove load commands no longer needed
        const macho_load_command<P>* srcCmd = cmds;
@@ -1781,6 +1836,7 @@ void LinkEditOptimizer<A>::updateLoadCommands(uint64_t newVMAddress, uint64_t si
                uint32_t cmdSize = srcCmd->cmdsize();
                switch ( srcCmd->cmd() ) {
                        case LC_SEGMENT_SPLIT_INFO:
                uint32_t cmdSize = srcCmd->cmdsize();
                switch ( srcCmd->cmd() ) {
                        case LC_SEGMENT_SPLIT_INFO:
+                       case LC_DYLIB_CODE_SIGN_DRS:
                                // don't copy
                                break;
                        case LC_CODE_SIGNATURE:
                                // don't copy
                                break;
                        case LC_CODE_SIGNATURE:
@@ -1882,6 +1938,13 @@ uint8_t* SharedCache<A>::optimizeLINKEDIT(bool keepSignatures)
        }
        fSizeOfFunctionStartsInCombinedLinkedit = offset - fOffsetOfFunctionStartsInCombinedLinkedit;
 
        }
        fSizeOfFunctionStartsInCombinedLinkedit = offset - fOffsetOfFunctionStartsInCombinedLinkedit;
 
+       // copy data-in-code info
+       fOffsetOfDataInCodeInCombinedLinkedit = offset;
+       for(typename std::vector<LinkEditOptimizer<A>*>::iterator it = optimizers.begin(); it != optimizers.end(); ++it) {
+               (*it)->copyDataInCode(offset);
+       }
+       fSizeOfDataInCodeInCombinedLinkedit = offset - fOffsetOfDataInCodeInCombinedLinkedit;
+
        // copy indirect symbol tables
        fOffsetOfOldIndirectSymbolsInCombinedLinkedit = offset;
        for(typename std::vector<LinkEditOptimizer<A>*>::iterator it = optimizers.begin(); it != optimizers.end(); ++it) {
        // copy indirect symbol tables
        fOffsetOfOldIndirectSymbolsInCombinedLinkedit = offset;
        for(typename std::vector<LinkEditOptimizer<A>*>::iterator it = optimizers.begin(); it != optimizers.end(); ++it) {
@@ -1932,7 +1995,6 @@ uint8_t* SharedCache<A>::optimizeLINKEDIT(bool keepSignatures)
 }
 
 
 }
 
 
-
 template <typename A>
 class ObjCSelectorUniquer
 {
 template <typename A>
 class ObjCSelectorUniquer
 {
@@ -1966,16 +2028,73 @@ public:
     size_t count() const { return fCount; }
 };
 
     size_t count() const { return fCount; }
 };
 
+
+template <typename A>
+class ClassListBuilder
+{
+private:
+    typedef typename A::P P;
+
+    objc_opt::string_map fClassNames;
+    objc_opt::class_map fClasses;
+    size_t fCount;
+    HeaderInfoOptimizer<A>& fHinfos;
+
+public:
+
+    ClassListBuilder(HeaderInfoOptimizer<A>& hinfos)
+        : fClassNames()
+        , fClasses()
+        , fCount(0)
+        , fHinfos(hinfos)
+    { }
+
+    void visitClass(SharedCache<A>* cache, 
+                    const macho_header<P>* header,
+                    objc_class_t<A>* cls) 
+    {
+        if (cls->isMetaClass(cache)) return;
+
+        const char *name = cls->getName(cache);
+        uint64_t name_vmaddr = cache->VMAddressForMappedAddress(name);
+        uint64_t cls_vmaddr = cache->VMAddressForMappedAddress(cls);
+        uint64_t hinfo_vmaddr = cache->VMAddressForMappedAddress(fHinfos.hinfoForHeader(cache, header));
+        fClassNames.insert(objc_opt::string_map::value_type(name, name_vmaddr));
+        fClasses.insert(objc_opt::class_map::value_type(name, std::pair<uint64_t, uint64_t>(cls_vmaddr, hinfo_vmaddr)));
+        fCount++;
+    }
+
+    objc_opt::string_map& classNames() { 
+        return fClassNames;
+    }
+
+    objc_opt::class_map& classes() { 
+        return fClasses;
+    }
+
+    size_t count() const { return fCount; }
+};
+
+
+static int percent(size_t num, size_t denom) {
+    if (denom) return (int)(num / (double)denom * 100);
+    else return 100;
+}
+
 template <typename A>
 void SharedCache<A>::optimizeObjC(std::vector<void*>& pointersInData)
 {
     const char *err;
 template <typename A>
 void SharedCache<A>::optimizeObjC(std::vector<void*>& pointersInData)
 {
     const char *err;
-    size_t headerSize = sizeof(objc_opt::objc_opt_t);
 
     if ( verbose ) {
         fprintf(stderr, "update_dyld_shared_cache: for %s, optimizing objc metadata\n", archName());
     }
 
 
     if ( verbose ) {
         fprintf(stderr, "update_dyld_shared_cache: for %s, optimizing objc metadata\n", archName());
     }
 
+    size_t headerSize = P::round_up(sizeof(objc_opt::objc_opt_t));
+    if (headerSize != sizeof(objc_opt::objc_opt_t)) {
+               warn(archName(), "libobjc's optimization structure size is wrong (metadata not optimized)");
+    }
+
     // Find libobjc's empty sections to fill in
     const macho_section<P> *optROSection = NULL;
     const macho_section<P> *optRWSection = NULL;
     // Find libobjc's empty sections to fill in
     const macho_section<P> *optROSection = NULL;
     const macho_section<P> *optRWSection = NULL;
@@ -1983,9 +2102,6 @@ void SharedCache<A>::optimizeObjC(std::vector<void*>& pointersInData)
         if ( strstr(it->layout->getFilePath(), "libobjc") != NULL ) {
                        const macho_header<P>* mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
                        optROSection = mh->getSection("__TEXT", "__objc_opt_ro");
         if ( strstr(it->layout->getFilePath(), "libobjc") != NULL ) {
                        const macho_header<P>* mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
                        optROSection = mh->getSection("__TEXT", "__objc_opt_ro");
-                       // __objc_selopt is old name for __objc_opt_ro
-                       if ( optROSection == NULL )
-                               optROSection = mh->getSection("__TEXT", "__objc_selopt");
                        optRWSection = mh->getSection("__DATA", "__objc_opt_rw");
                        break;
                }
                        optRWSection = mh->getSection("__DATA", "__objc_opt_rw");
                        break;
                }
@@ -1996,17 +2112,62 @@ void SharedCache<A>::optimizeObjC(std::vector<void*>& pointersInData)
                return;
        }
        
                return;
        }
        
-       objc_opt::objc_opt_t* optROHeader = (objc_opt::objc_opt_t*)mappedAddressForVMAddress(optROSection->addr());
-       if (optROSection->size() < headerSize) {
+       if ( optRWSection == NULL ) {
+               warn(archName(), "libobjc's read/write section missing (metadata not optimized)");
+               return;
+       }
+
+       uint8_t* optROData = (uint8_t*)mappedAddressForVMAddress(optROSection->addr());
+    size_t optRORemaining = optROSection->size();
+
+       uint8_t* optRWData = (uint8_t*)mappedAddressForVMAddress(optRWSection->addr());
+    size_t optRWRemaining = optRWSection->size();
+       
+       if (optRORemaining < headerSize) {
                warn(archName(), "libobjc's read-only section is too small (metadata not optimized)");
                return;
        }
                warn(archName(), "libobjc's read-only section is too small (metadata not optimized)");
                return;
        }
+       objc_opt::objc_opt_t* optROHeader = (objc_opt::objc_opt_t *)optROData;
+    optROData += headerSize;
+    optRORemaining -= headerSize;
 
        if (E::get32(optROHeader->version) != objc_opt::VERSION) {
                warn(archName(), "libobjc's read-only section version is unrecognized (metadata not optimized)");
                return;
        }
 
 
        if (E::get32(optROHeader->version) != objc_opt::VERSION) {
                warn(archName(), "libobjc's read-only section version is unrecognized (metadata not optimized)");
                return;
        }
 
+    // Write nothing to optROHeader until everything else is written.
+    // If something fails below, libobjc will not use the section.
+
+    // Find objc-containing dylibs
+    std::vector<LayoutInfo> objcDylibs;
+    for(typename std::vector<LayoutInfo>::const_iterator it = fDylibs.begin(); it != fDylibs.end(); ++it) {
+        macho_header<P> *mh = (macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
+        if (mh->getSection("__DATA", "__objc_imageinfo")  ||  mh->getSegment("__OBJC")) {
+            objcDylibs.push_back(*it);
+        }
+    }
+
+    // Build image list
+
+    // This is SAFE: the binaries themselves are unmodified.
+
+    std::vector<LayoutInfo> addressSortedDylibs = objcDylibs;
+    std::sort(addressSortedDylibs.begin(), addressSortedDylibs.end(), ByAddressSorter());
+
+    uint64_t hinfoVMAddr = optRWSection->addr() + optRWSection->size() - optRWRemaining;
+    HeaderInfoOptimizer<A> hinfoOptimizer;
+    err = hinfoOptimizer.init(objcDylibs.size(), optRWData, optRWRemaining);
+    if (err) {
+               warn(archName(), err);
+               return;
+    }
+    for(typename std::vector<LayoutInfo>::const_iterator it = addressSortedDylibs.begin(); it != addressSortedDylibs.end(); ++it) {
+        const macho_header<P> *mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
+        hinfoOptimizer.update(this, mh, pointersInData);
+    }
+
+
     // Update selector references and build selector list
 
     // This is SAFE: if we run out of room for the selector table, 
     // Update selector references and build selector list
 
     // This is SAFE: if we run out of room for the selector table, 
@@ -2015,102 +2176,128 @@ void SharedCache<A>::optimizeObjC(std::vector<void*>& pointersInData)
     // Heuristic: choose selectors from libraries with more cstring data first.
     // This tries to localize selector cstring memory.
     ObjCSelectorUniquer<A> uniq(this);
     // Heuristic: choose selectors from libraries with more cstring data first.
     // This tries to localize selector cstring memory.
     ObjCSelectorUniquer<A> uniq(this);
-    std::vector<LayoutInfo> sortedDylibs = fDylibs;
-    std::sort(sortedDylibs.begin(), sortedDylibs.end(), ByCStringSectionSizeSorter());
+    std::vector<LayoutInfo> sizeSortedDylibs = objcDylibs;
+    std::sort(sizeSortedDylibs.begin(), sizeSortedDylibs.end(), ByCStringSectionSizeSorter());
 
     SelectorOptimizer<A, ObjCSelectorUniquer<A> > selOptimizer(uniq);
 
     SelectorOptimizer<A, ObjCSelectorUniquer<A> > selOptimizer(uniq);
-       for(typename std::vector<LayoutInfo>::const_iterator it = sortedDylibs.begin(); it != sortedDylibs.end(); ++it) {
+       for(typename std::vector<LayoutInfo>::const_iterator it = sizeSortedDylibs.begin(); it != sizeSortedDylibs.end(); ++it) {
         const macho_header<P> *mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
         LegacySelectorUpdater<A, ObjCSelectorUniquer<A> >::update(this, mh, uniq);
         selOptimizer.optimize(this, mh);
        }
 
         const macho_header<P> *mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
         LegacySelectorUpdater<A, ObjCSelectorUniquer<A> >::update(this, mh, uniq);
         selOptimizer.optimize(this, mh);
        }
 
-    if ( verbose ) {
-        fprintf(stderr, "update_dyld_shared_cache: for %s, found %zu unique objc selectors\n", archName(), uniq.strings().size());
+    uint64_t seloptVMAddr = optROSection->addr() + optROSection->size() - optRORemaining;
+    objc_opt::objc_selopt_t *selopt = new(optROData) objc_opt::objc_selopt_t;
+    err = selopt->write(seloptVMAddr, optRORemaining, uniq.strings());
+    if (err) {
+        warn(archName(), err);
+        return;
     }
     }
+    optROData += selopt->size();
+    optRORemaining -= selopt->size();
+    selopt->byteswap(E::little_endian), selopt = NULL;
 
 
-    // Write selector table in read-only data.
-    size_t selTableOffset = P::round_up(headerSize);
-    size_t selTableSize;
-    objc_opt::objc_selopt_t *seloptData = (objc_opt::objc_selopt_t *)
-        mappedAddressForVMAddress(optROSection->addr() + selTableOffset);
-    err = objc_opt::write_selopt(seloptData, 
-                                 optROSection->addr() + selTableOffset, 
-                                 optROSection->size() - selTableOffset, 
-                                 uniq.strings(), 
-                                 E::little_endian, &selTableSize);
+
+    // Build class table.
+
+    // This is SAFE: the binaries themselves are unmodified.
+
+    ClassListBuilder<A> classes(hinfoOptimizer);
+    ClassWalker< A, ClassListBuilder<A> > classWalker(classes);
+       for(typename std::vector<LayoutInfo>::const_iterator it = sizeSortedDylibs.begin(); it != sizeSortedDylibs.end(); ++it) {
+        const macho_header<P> *mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
+        classWalker.walk(this, mh);
+       }
+
+    uint64_t clsoptVMAddr = optROSection->addr() + optROSection->size() - optRORemaining;
+    objc_opt::objc_clsopt_t *clsopt = new(optROData) objc_opt::objc_clsopt_t;
+    err = clsopt->write(clsoptVMAddr, optRORemaining, 
+                        classes.classNames(), classes.classes(), verbose);
     if (err) {
         warn(archName(), err);
         return;
     }
     if (err) {
         warn(archName(), err);
         return;
     }
+    optROData += clsopt->size();
+    optRORemaining -= clsopt->size();
+    size_t duplicateCount = clsopt->duplicateCount();
+    clsopt->byteswap(E::little_endian), clsopt = NULL;
+
+
+    // Sort method lists.
+
+    // This is SAFE: modified binaries are still usable as unsorted lists.
+    // This must be done AFTER uniquing selectors.
+
+    MethodListSorter<A> methodSorter;
+    for(typename std::vector<LayoutInfo>::const_iterator it = sizeSortedDylibs.begin(); it != sizeSortedDylibs.end(); ++it) {
+        macho_header<P> *mh = (macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
+        methodSorter.optimize(this, mh);
+    }
+
+
+    // Repair ivar offsets.
+
+    // This is SAFE: the runtime always validates ivar offsets at runtime.
+
+    IvarOffsetOptimizer<A> ivarOffsetOptimizer;
+       for(typename std::vector<LayoutInfo>::const_iterator it = sizeSortedDylibs.begin(); it != sizeSortedDylibs.end(); ++it) {
+        const macho_header<P> *mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
+        ivarOffsetOptimizer.optimize(this, mh);
+       }
+    
+
+    // Success. Mark dylibs as optimized.
+       for(typename std::vector<LayoutInfo>::const_iterator it = sizeSortedDylibs.begin(); it != sizeSortedDylibs.end(); ++it) {
+        const macho_header<P> *mh = (const macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
+        const macho_section<P> *imageInfoSection;
+        imageInfoSection = mh->getSection("__DATA", "__objc_imageinfo");
+        if (!imageInfoSection) {
+            imageInfoSection = mh->getSection("__OBJC", "__image_info");
+        }
+        if (imageInfoSection) {
+            objc_image_info<A> *info = (objc_image_info<A> *)
+                mappedAddressForVMAddress(imageInfoSection->addr());
+            info->setOptimizedByDyld();
+        }
+    }
+
+
+    // Success. Update RO header last.
+    E::set32(optROHeader->selopt_offset, seloptVMAddr - optROSection->addr());
+    E::set32(optROHeader->clsopt_offset, clsoptVMAddr - optROSection->addr());
+    E::set32(optROHeader->headeropt_offset, hinfoVMAddr - optROSection->addr());
 
     if ( verbose ) {
 
     if ( verbose ) {
-        size_t totalSize = headerSize + selTableSize;
+        size_t roSize = optROSection->size() - optRORemaining;
+        size_t rwSize = optRWSection->size() - optRWRemaining;
         fprintf(stderr, "update_dyld_shared_cache: for %s, %zu/%llu bytes "
                 "(%d%%) used in libobjc read-only optimization section\n", 
         fprintf(stderr, "update_dyld_shared_cache: for %s, %zu/%llu bytes "
                 "(%d%%) used in libobjc read-only optimization section\n", 
-                archName(), totalSize, optROSection->size(), 
-                (int)(totalSize / (double)optROSection->size() * 100));
+                archName(), roSize, optROSection->size(), 
+                percent(roSize, optROSection->size()));
+        fprintf(stderr, "update_dyld_shared_cache: for %s, %zu/%llu bytes "
+                "(%d%%) used in libobjc read/write optimization section\n", 
+                archName(), rwSize, optRWSection->size(), 
+                percent(rwSize, optRWSection->size()));
+        fprintf(stderr, "update_dyld_shared_cache: for %s, "
+                "uniqued %zu selectors\n", 
+                archName(), uniq.strings().size());
         fprintf(stderr, "update_dyld_shared_cache: for %s, "
                 "updated %zu selector references\n", 
                 archName(), uniq.count());
         fprintf(stderr, "update_dyld_shared_cache: for %s, "
                 "updated %zu selector references\n", 
                 archName(), uniq.count());
+        fprintf(stderr, "update_dyld_shared_cache: for %s, "
+                "updated %zu ivar offsets\n", 
+                archName(), ivarOffsetOptimizer.optimized());
+        fprintf(stderr, "update_dyld_shared_cache: for %s, "
+                "sorted %zu method lists\n", 
+                archName(), methodSorter.optimized());
+        fprintf(stderr, "update_dyld_shared_cache: for %s, "
+                "recorded %zu classes (%zu duplicates)\n", 
+                archName(), classes.classNames().size(), duplicateCount);
         fprintf(stderr, "update_dyld_shared_cache: for %s, "
                 "wrote objc metadata optimization version %d\n", 
                 archName(), objc_opt::VERSION);
     }
 
         fprintf(stderr, "update_dyld_shared_cache: for %s, "
                 "wrote objc metadata optimization version %d\n", 
                 archName(), objc_opt::VERSION);
     }
 
-       // if r/w section exists in libojc attempt to optimize categories into classes
-       if ( optRWSection != NULL ) {
-               // Attach categories to classes in the same framework. 
-               // Build aggregated (but unsorted) method lists in read-write data.
-
-               // This is SAFE: if we run out of room while attaching categories in 
-               // a binary then previously-edited binaries are still valid. (This assumes 
-               // each binary is processed all-or-nothing, which CategoryAttacher does.)
-               // This must be done AFTER uniquing selectors.
-               // This must be done BEFORE sorting method lists.
-               
-               size_t categoryOffset = 0;
-               uint8_t *categoryData = (uint8_t*)mappedAddressForVMAddress(optRWSection->addr() + categoryOffset);
-               CategoryAttacher<A> categoryAttacher(categoryData, optRWSection->size() - categoryOffset);
-               for(typename std::vector<LayoutInfo>::const_iterator it = sortedDylibs.begin(); it != sortedDylibs.end(); ++it) {
-                       macho_header<P> *mh = (macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
-                       err = categoryAttacher.optimize(this, mh, pointersInData);
-                       if (err) {
-                               warn(archName(), err);
-                               return;
-                       }
-               }    
-               size_t categorySize = categoryAttacher.bytesUsed();
-
-
-               // Sort method lists.
-               
-               // This is SAFE: modified binaries are still usable as unsorted lists.
-               // This must be done AFTER uniquing selectors.
-               // This must be done AFTER attaching categories.
-
-               MethodListSorter<A> methodSorter;
-               for(typename std::vector<LayoutInfo>::const_iterator it = sortedDylibs.begin(); it != sortedDylibs.end(); ++it) {
-                       macho_header<P> *mh = (macho_header<P>*)(*it->layout).getSegments()[0].mappedAddress();
-                       methodSorter.optimize(this, mh);
-               }
-
-               if ( verbose ) {
-                       size_t totalRWSize = categorySize;
-                       fprintf(stderr, "update_dyld_shared_cache: for %s, %zu/%llu bytes "
-                "(%d%%) used in libobjc read-write optimization section\n", 
-                archName(), totalRWSize, optRWSection->size(), 
-                (int)(totalRWSize / (double)optRWSection->size() * 100));
-                       fprintf(stderr, "update_dyld_shared_cache: for %s, "
-                "attached %zu categories (%zd bytes used)\n", 
-                archName(), categoryAttacher.count(), 
-                categoryAttacher.bytesUsed());
-               }
-       }
-
-    // Success. Update RO header last
-    E::set32(optROHeader->selopt_offset, headerSize);
-
     return;
 }
 
     return;
 }
 
@@ -2132,12 +2319,11 @@ static void cleanup(int sig)
 template <>     bool   SharedCache<x86_64>::addCacheSlideInfo(){ return true; }
 template <>     bool   SharedCache<arm>::addCacheSlideInfo()   { return true; }
 template <>     bool   SharedCache<x86>::addCacheSlideInfo()   { return false; }
 template <>     bool   SharedCache<x86_64>::addCacheSlideInfo(){ return true; }
 template <>     bool   SharedCache<arm>::addCacheSlideInfo()   { return true; }
 template <>     bool   SharedCache<x86>::addCacheSlideInfo()   { return false; }
-template <>     bool   SharedCache<ppc>::addCacheSlideInfo()   { return false; }
 
 
 
 template <typename A>
 
 
 
 template <typename A>
-bool SharedCache<A>::update(bool usesOverlay, bool force, bool optimize, bool deleteExistingFirst, int archIndex,
+bool SharedCache<A>::update(bool force, bool optimize, bool deleteExistingFirst, int archIndex,
                                                                int archCount, bool keepSignatures)
 {
        bool didUpdate = false;
                                                                int archCount, bool keepSignatures)
 {
        bool didUpdate = false;
@@ -2243,7 +2429,7 @@ bool SharedCache<A>::update(bool usesOverlay, bool force, bool optimize, bool de
                                        throwf("file modified during cache creation: %s", path);
 
                                if ( verbose )
                                        throwf("file modified during cache creation: %s", path);
 
                                if ( verbose )
-                                       fprintf(stderr, "update_dyld_shared_cache: copying %s to cache\n", it->layout->getID().name);
+                                       fprintf(stderr, "update_dyld_shared_cache: copying %s to cache\n", it->layout->getFilePath());
                                try {
                                        const std::vector<MachOLayoutAbstraction::Segment>& segs = it->layout->getSegments();
                                        for (int i=0; i < segs.size(); ++i) {
                                try {
                                        const std::vector<MachOLayoutAbstraction::Segment>& segs = it->layout->getSegments();
                                        for (int i=0; i < segs.size(); ++i) {
@@ -2556,7 +2742,7 @@ bool SharedCache<A>::update(bool usesOverlay, bool force, bool optimize, bool de
 
                                // write out cache file
                                if ( verbose )
 
                                // write out cache file
                                if ( verbose )
-                                       fprintf(stderr, "update_dyld_shared_cache: writing cache to disk\n");
+                                       fprintf(stderr, "update_dyld_shared_cache: writing cache to disk: %s\n", tempCachePath);
                                if ( ::pwrite(fd, inMemoryCache, cacheFileSize, 0) != cacheFileSize )
                                        throwf("write() failure creating cache file, errno=%d", errno);
                                if ( progress ) {
                                if ( ::pwrite(fd, inMemoryCache, cacheFileSize, 0) != cacheFileSize )
                                        throwf("write() failure creating cache file, errno=%d", errno);
                                if ( progress ) {
@@ -2594,6 +2780,8 @@ bool SharedCache<A>::update(bool usesOverlay, bool force, bool optimize, bool de
                                }
                                
                                // move new cache file to correct location for use after reboot
                                }
                                
                                // move new cache file to correct location for use after reboot
+                               if ( verbose )
+                                       fprintf(stderr, "update_dyld_shared_cache: atomically moving cache file into place: %s\n", fCacheFilePath);
                                result = ::rename(tempCachePath, fCacheFilePath);
                                if ( result != 0 ) 
                                        throwf("can't swap newly create dyld shared cache file: rename(%s,%s) returned errno=%d", tempCachePath, fCacheFilePath, errno);
                                result = ::rename(tempCachePath, fCacheFilePath);
                                if ( result != 0 ) 
                                        throwf("can't swap newly create dyld shared cache file: rename(%s,%s) returned errno=%d", tempCachePath, fCacheFilePath, errno);
@@ -2661,6 +2849,11 @@ bool SharedCache<A>::update(bool usesOverlay, bool force, bool optimize, bool de
                                                                fSizeOfFunctionStartsInCombinedLinkedit/1024,
                                                                fLinkEditsStartAddress+fOffsetOfFunctionStartsInCombinedLinkedit,
                                                                fLinkEditsStartAddress+fOffsetOfFunctionStartsInCombinedLinkedit+fSizeOfFunctionStartsInCombinedLinkedit);                              
                                                                fSizeOfFunctionStartsInCombinedLinkedit/1024,
                                                                fLinkEditsStartAddress+fOffsetOfFunctionStartsInCombinedLinkedit,
                                                                fLinkEditsStartAddress+fOffsetOfFunctionStartsInCombinedLinkedit+fSizeOfFunctionStartsInCombinedLinkedit);                              
+                                       if ( fSizeOfDataInCodeInCombinedLinkedit != 0 )
+                                               fprintf(fmap, "linkedit   %4uKB 0x%0llX -> 0x%0llX non-dyld data-in-code info size\n",          
+                                                               fSizeOfDataInCodeInCombinedLinkedit/1024,
+                                                               fLinkEditsStartAddress+fOffsetOfDataInCodeInCombinedLinkedit,
+                                                               fLinkEditsStartAddress+fOffsetOfDataInCodeInCombinedLinkedit+fSizeOfDataInCodeInCombinedLinkedit);                              
                                        if ( fSizeOfOldExternalRelocationsInCombinedLinkedit != 0 )
                                                fprintf(fmap, "linkedit   %4uKB 0x%0llX -> 0x%0llX non-dyld external relocs size\n",            
                                                                fSizeOfOldExternalRelocationsInCombinedLinkedit/1024,
                                        if ( fSizeOfOldExternalRelocationsInCombinedLinkedit != 0 )
                                                fprintf(fmap, "linkedit   %4uKB 0x%0llX -> 0x%0llX non-dyld external relocs size\n",            
                                                                fSizeOfOldExternalRelocationsInCombinedLinkedit/1024,
@@ -2795,10 +2988,11 @@ static void parsePathsFile(const char* filePath, std::vector<const char*>& paths
 
 
 
 
 
 
-static void setSharedDylibs(const char* rootPath, bool usesOverlay, const std::set<ArchPair>& onlyArchs, std::vector<const char*> rootsPaths)
+static void setSharedDylibs(const char* rootPath, const char* overlayPath, const std::set<ArchPair>& onlyArchs, std::vector<const char*> rootsPaths)
 {
        // set file system root
 {
        // set file system root
-       ArchGraph::setFileSystemRoot(rootPath, usesOverlay);
+       ArchGraph::setFileSystemRoot(rootPath);
+       ArchGraph::setFileSystemOverlay(overlayPath);
 
        // initialize all architectures requested
        for(std::set<ArchPair>::iterator a = onlyArchs.begin(); a != onlyArchs.end(); ++a)
 
        // initialize all architectures requested
        for(std::set<ArchPair>::iterator a = onlyArchs.begin(); a != onlyArchs.end(); ++a)
@@ -2814,12 +3008,11 @@ static void setSharedDylibs(const char* rootPath, bool usesOverlay, const std::s
 }
 
 
 }
 
 
-static void scanForSharedDylibs(const char* rootPath, bool usesOverlay, const char* dirOfPathFiles, const std::set<ArchPair>& onlyArchs)
+static void scanForSharedDylibs(const char* rootPath, const char* overlayPath, const char* dirOfPathFiles, const std::set<ArchPair>& onlyArchs)
 {
        char rootDirOfPathFiles[strlen(rootPath)+strlen(dirOfPathFiles)+2];
 {
        char rootDirOfPathFiles[strlen(rootPath)+strlen(dirOfPathFiles)+2];
-       // in -overlay mode, still look for roots in /var/db/dyld
        // in -root mode, look for roots in /rootpath/var/db/dyld
        // in -root mode, look for roots in /rootpath/var/db/dyld
-       if ( !usesOverlay && (strlen(rootPath) != 0) ) {
+       if ( rootPath[0] != '\0' ) {
                strcpy(rootDirOfPathFiles, rootPath);
                strcat(rootDirOfPathFiles, dirOfPathFiles);
                dirOfPathFiles = rootDirOfPathFiles;
                strcpy(rootDirOfPathFiles, rootPath);
                strcat(rootDirOfPathFiles, dirOfPathFiles);
                dirOfPathFiles = rootDirOfPathFiles;
@@ -2860,14 +3053,14 @@ static void scanForSharedDylibs(const char* rootPath, bool usesOverlay, const ch
        
        if ( rootsPaths.size() == 0 )
                fprintf(stderr, "update_dyld_shared_cache: warning, no entries found in shared_region_roots\n");
        
        if ( rootsPaths.size() == 0 )
                fprintf(stderr, "update_dyld_shared_cache: warning, no entries found in shared_region_roots\n");
-       setSharedDylibs(rootPath, usesOverlay, onlyArchs, rootsPaths);
+       setSharedDylibs(rootPath, overlayPath, onlyArchs, rootsPaths);
 }
 
 }
 
-static void setSharedDylibs(const char* rootPath, bool usesOverlay, const char* pathsFile, const std::set<ArchPair>& onlyArchs)
+static void setSharedDylibs(const char* rootPath, const char* overlayPath, const char* pathsFile, const std::set<ArchPair>& onlyArchs)
 {
        std::vector<const char*> rootsPaths;
        parsePathsFile(pathsFile, rootsPaths);
 {
        std::vector<const char*> rootsPaths;
        parsePathsFile(pathsFile, rootsPaths);
-       setSharedDylibs(rootPath, usesOverlay, onlyArchs, rootsPaths);
+       setSharedDylibs(rootPath, overlayPath, onlyArchs, rootsPaths);
 }
 
 
 }
 
 
@@ -2914,7 +3107,7 @@ static void deleteOrphanTempCacheFiles()
 
 
 
 
 
 
-static bool updateSharedeCacheFile(const char* rootPath, bool usesOverlay, const char* cacheDir, const std::set<ArchPair>& onlyArchs, 
+static bool updateSharedeCacheFile(const char* rootPath, const char* overlayPath, const char* cacheDir, bool explicitCacheDir, const std::set<ArchPair>& onlyArchs, 
                                                                        bool force, bool alphaSort, bool optimize, bool deleteExistingFirst, bool verify, bool keepSignatures)
 {
        bool didUpdate = false;
                                                                        bool force, bool alphaSort, bool optimize, bool deleteExistingFirst, bool verify, bool keepSignatures)
 {
        bool didUpdate = false;
@@ -2940,34 +3133,22 @@ static bool updateSharedeCacheFile(const char* rootPath, bool usesOverlay, const
                else
                        fprintf(stderr, "update_dyld_shared_cache: warning, dyld not available for specified architectures\n");
                switch ( a->arch ) {
                else
                        fprintf(stderr, "update_dyld_shared_cache: warning, dyld not available for specified architectures\n");
                switch ( a->arch ) {
-                       case CPU_TYPE_POWERPC:
-                               {
-               #if __i386__ || __x86_64__
-                                       // <rdar://problem/5217377> Rosetta does not work with optimized dyld shared cache
-                                       SharedCache<ppc> cache(ArchGraph::graphForArchPair(*a), rootPath, cacheDir, alphaSort, verify, false, usesOverlay, dyldBaseAddress);
-                                       didUpdate |= cache.update(usesOverlay, force, false, deleteExistingFirst, index, archCount, keepSignatures);
-               #else
-                                       SharedCache<ppc> cache(ArchGraph::graphForArchPair(*a), rootPath, cacheDir, alphaSort, verify, optimize, usesOverlay, dyldBaseAddress);
-                                       didUpdate |= cache.update(usesOverlay, force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
-               #endif
-                               }
-                               break;
                        case CPU_TYPE_I386:
                                {
                        case CPU_TYPE_I386:
                                {
-                                       SharedCache<x86> cache(ArchGraph::graphForArchPair(*a), rootPath, cacheDir, alphaSort, verify, optimize, usesOverlay, dyldBaseAddress);
-                                       didUpdate |= cache.update(usesOverlay, force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
+                                       SharedCache<x86> cache(ArchGraph::graphForArchPair(*a), rootPath, overlayPath, cacheDir, explicitCacheDir, alphaSort, verify, optimize, dyldBaseAddress);
+                                       didUpdate |= cache.update(force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
                                }
                                break;
                        case CPU_TYPE_X86_64:
                                {
                                }
                                break;
                        case CPU_TYPE_X86_64:
                                {
-                                       SharedCache<x86_64> cache(ArchGraph::graphForArchPair(*a), rootPath, cacheDir, alphaSort, verify, optimize, usesOverlay, dyldBaseAddress);
-                                       didUpdate |= cache.update(usesOverlay, force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
+                                       SharedCache<x86_64> cache(ArchGraph::graphForArchPair(*a), rootPath, overlayPath, cacheDir, explicitCacheDir, alphaSort, verify, optimize, dyldBaseAddress);
+                                       didUpdate |= cache.update(force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
                                }
                                break;
                        case CPU_TYPE_ARM:
                                {
                                }
                                break;
                        case CPU_TYPE_ARM:
                                {
-                                       SharedCache<arm> cache(ArchGraph::graphForArchPair(*a), rootPath, cacheDir, alphaSort, verify, optimize, usesOverlay, dyldBaseAddress);
-                                       didUpdate |= cache.update(usesOverlay, force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
+                                       SharedCache<arm> cache(ArchGraph::graphForArchPair(*a), rootPath, overlayPath, cacheDir, explicitCacheDir, alphaSort, verify, optimize, dyldBaseAddress);
+                                       didUpdate |= cache.update(force, optimize, deleteExistingFirst, index, archCount, keepSignatures);
                                }
                                break;
                }
                                }
                                break;
                }
@@ -2990,14 +3171,14 @@ int main(int argc, const char* argv[])
 {
        std::set<ArchPair> onlyArchs;
        const char* rootPath = "";
 {
        std::set<ArchPair> onlyArchs;
        const char* rootPath = "";
+       const char* overlayPath = "";
        const char* dylibListFile = NULL;
        bool force = false;
        bool alphaSort = false;
        bool optimize = true;
        const char* dylibListFile = NULL;
        bool force = false;
        bool alphaSort = false;
        bool optimize = true;
-       bool hasRoot = false;
-       bool hasOverlay = false;
        bool verify = false;
        bool keepSignatures = false;
        bool verify = false;
        bool keepSignatures = false;
+       bool explicitCacheDir = false;
        const char* cacheDir = NULL;
        
        try {
        const char* cacheDir = NULL;
        
        try {
@@ -3035,31 +3216,24 @@ int main(int argc, const char* argv[])
                                                throw "-dylib_list missing path argument";
                                }
                                else if ( (strcmp(arg, "-root") == 0) || (strcmp(arg, "--root") == 0) ) {
                                                throw "-dylib_list missing path argument";
                                }
                                else if ( (strcmp(arg, "-root") == 0) || (strcmp(arg, "--root") == 0) ) {
-                                       if ( hasOverlay )
-                                               throw "cannot use both -root and -overlay";
                                        rootPath = argv[++i];
                                        if ( rootPath == NULL )
                                                throw "-root missing path argument";
                                        rootPath = argv[++i];
                                        if ( rootPath == NULL )
                                                throw "-root missing path argument";
-                                       hasRoot = true;
                                }
                                else if ( strcmp(arg, "-overlay") == 0 ) {
                                }
                                else if ( strcmp(arg, "-overlay") == 0 ) {
-                                       if ( hasRoot )
-                                               throw "cannot use both -root and -overlay";
-                                       rootPath = argv[++i];
-                                       if ( rootPath == NULL )
-                                               throw "-root missing path argument";
-                                       hasOverlay = true;
+                                       overlayPath = argv[++i];
+                                       if ( overlayPath == NULL )
+                                               throw "-overlay missing path argument";
                                }
                                else if ( strcmp(arg, "-cache_dir") == 0 ) {
                                        cacheDir = argv[++i];
                                        if ( cacheDir == NULL )
                                                throw "-cache_dir missing path argument";
                                }
                                else if ( strcmp(arg, "-cache_dir") == 0 ) {
                                        cacheDir = argv[++i];
                                        if ( cacheDir == NULL )
                                                throw "-cache_dir missing path argument";
+                                       explicitCacheDir = true;
                                }
                                else if ( strcmp(arg, "-arch") == 0 ) {
                                        const char* arch = argv[++i];
                                }
                                else if ( strcmp(arg, "-arch") == 0 ) {
                                        const char* arch = argv[++i];
-                                       if ( strcmp(arch, "ppc") == 0 ) 
-                                               onlyArchs.insert(ArchPair(CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL));
-                                       else if ( strcmp(arch, "i386") == 0 )
+                                       if ( strcmp(arch, "i386") == 0 )
                                                onlyArchs.insert(ArchPair(CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL));
                                        else if ( strcmp(arch, "x86_64") == 0 )
                                                onlyArchs.insert(ArchPair(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL));
                                                onlyArchs.insert(ArchPair(CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL));
                                        else if ( strcmp(arch, "x86_64") == 0 )
                                                onlyArchs.insert(ArchPair(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL));
@@ -3071,13 +3245,14 @@ int main(int argc, const char* argv[])
                                                onlyArchs.insert(ArchPair(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6));
                                        else if ( strcmp(arch, "armv7") == 0 )
                                                onlyArchs.insert(ArchPair(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7));
                                                onlyArchs.insert(ArchPair(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6));
                                        else if ( strcmp(arch, "armv7") == 0 )
                                                onlyArchs.insert(ArchPair(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7));
+                                       else if ( strcmp(arch, "armv7f") == 0 )
+                                               onlyArchs.insert(ArchPair(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7F));
+                                       else if ( strcmp(arch, "armv7k") == 0 )
+                                               onlyArchs.insert(ArchPair(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K));
                                        else 
                                                throwf("unknown architecture %s", arch);
                                }
                                else if ( strcmp(arg, "-universal_boot") == 0 ) {
                                        else 
                                                throwf("unknown architecture %s", arch);
                                }
                                else if ( strcmp(arg, "-universal_boot") == 0 ) {
-                       #if __ppc__
-                                       throwf("universal_boot option can only be used on Intel machines");
-                       #endif
                                        onlyArchs.insert(ArchPair(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL));
                                        onlyArchs.insert(ArchPair(CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL));
                                }
                                        onlyArchs.insert(ArchPair(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL));
                                        onlyArchs.insert(ArchPair(CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL));
                                }
@@ -3092,7 +3267,7 @@ int main(int argc, const char* argv[])
                        }
                }
                                
                        }
                }
                                
-               // strip tailing slashes on -root or -overlay
+               // strip tailing slashes on -root 
                // make it a real path so as to not make all dylibs look like symlink aliases
                if ( rootPath[0] != '\0' ) {
                        char realRootPath[MAXPATHLEN];
                // make it a real path so as to not make all dylibs look like symlink aliases
                if ( rootPath[0] != '\0' ) {
                        char realRootPath[MAXPATHLEN];
@@ -3101,16 +3276,18 @@ int main(int argc, const char* argv[])
                        rootPath = strdup(realRootPath);
                }
                
                        rootPath = strdup(realRootPath);
                }
                
-               // set location to write cache dir
-               if ( cacheDir == NULL ) {
-                       if ( (rootPath[0] == '\0') || hasOverlay ) {
-                               cacheDir =  (iPhoneOS ? IPHONE_DYLD_SHARED_CACHE_DIR : MACOSX_DYLD_SHARED_CACHE_DIR);
-                       }
-                       else {
-                               asprintf((char**)&cacheDir, "%s/%s", rootPath, (iPhoneOS ? IPHONE_DYLD_SHARED_CACHE_DIR : MACOSX_DYLD_SHARED_CACHE_DIR));
-                       }
+               // strip tailing slashes on -overlay
+               if ( overlayPath[0] != '\0' ) {
+                       char realOverlayPath[MAXPATHLEN];
+                       if ( realpath(overlayPath, realOverlayPath) == NULL )
+                               throwf("realpath() failed on %s\n", overlayPath);
+                       overlayPath = strdup(realOverlayPath);
                }
 
                }
 
+               // set default location to write cache dir
+               if ( cacheDir == NULL ) 
+                       cacheDir = (iPhoneOS ? IPHONE_DYLD_SHARED_CACHE_DIR : MACOSX_DYLD_SHARED_CACHE_DIR);
+
                // if no restrictions specified, use architectures that work on this machine
                if ( onlyArchs.size() == 0 ) {
                        if ( iPhoneOS ) {
                // if no restrictions specified, use architectures that work on this machine
                if ( onlyArchs.size() == 0 ) {
                        if ( iPhoneOS ) {
@@ -3122,19 +3299,6 @@ int main(int argc, const char* argv[])
                                size_t len = sizeof(int);
                        #if __i386__ || __x86_64__
                                onlyArchs.insert(ArchPair(CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL));
                                size_t len = sizeof(int);
                        #if __i386__ || __x86_64__
                                onlyArchs.insert(ArchPair(CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL));
-                               // check rosetta is installed
-                               char rosettaPath[1024];
-                               strlcpy(rosettaPath, rootPath, 1024);
-                               strlcat(rosettaPath, "/usr/libexec/oah/translate", 1024);
-                               struct stat stat_buf;
-                               if ( stat(rosettaPath, &stat_buf) == 0 ) {
-                                       onlyArchs.insert(ArchPair(CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL));
-                               }
-                               else if ( hasOverlay ) {
-                                       // in overlay mode, rosetta may be installed on base system, but is not in update root
-                                       if ( stat("/usr/libexec/oah/translate", &stat_buf) == 0 ) 
-                                               onlyArchs.insert(ArchPair(CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL));
-                               }
                                // check system is capable of running 64-bit programs
                                if ( (sysctlbyname("hw.optional.x86_64", &available, &len, NULL, 0) == 0) && available )
                                        onlyArchs.insert(ArchPair(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL));
                                // check system is capable of running 64-bit programs
                                if ( (sysctlbyname("hw.optional.x86_64", &available, &len, NULL, 0) == 0) && available )
                                        onlyArchs.insert(ArchPair(CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL));
@@ -3149,10 +3313,10 @@ int main(int argc, const char* argv[])
                
                // build list of shared dylibs
                if ( dylibListFile != NULL )
                
                // build list of shared dylibs
                if ( dylibListFile != NULL )
-                       setSharedDylibs(rootPath, hasOverlay, dylibListFile, onlyArchs);
+                       setSharedDylibs(rootPath, overlayPath, dylibListFile, onlyArchs);
                else
                else
-                       scanForSharedDylibs(rootPath, hasOverlay, "/var/db/dyld/shared_region_roots/", onlyArchs);
-               updateSharedeCacheFile(rootPath, hasOverlay, cacheDir, onlyArchs, force, alphaSort, optimize, 
+                       scanForSharedDylibs(rootPath, overlayPath, "/var/db/dyld/shared_region_roots/", onlyArchs);
+               updateSharedeCacheFile(rootPath, overlayPath, cacheDir, explicitCacheDir, onlyArchs, force, alphaSort, optimize, 
                                                                false, verify, keepSignatures);
        }
        catch (const char* msg) {
                                                                false, verify, keepSignatures);
        }
        catch (const char* msg) {
index 3b0e8242155f1c6829f64b00821761a329866ddc..58b22829d8b5bb5fe507f715e2d2f96964f7373a 100644 (file)
@@ -64,7 +64,7 @@ uintptr_t                                                             ImageLoader::fgNextPIEDylibAddress = 0;
 
 
 ImageLoader::ImageLoader(const char* path, unsigned int libCount)
 
 
 ImageLoader::ImageLoader(const char* path, unsigned int libCount)
-       : fPath(path), fDevice(0), fInode(0), fLastModified(0), 
+       : fPath(path), fRealPath(NULL), fDevice(0), fInode(0), fLastModified(0), 
        fPathHash(0), fDlopenReferenceCount(0), fStaticReferenceCount(0),
        fDynamicReferenceCount(0), fDynamicReferences(NULL), fInitializerRecursiveLock(NULL), 
        fDepth(0), fLoadOrder(fgLoadOrdinal++), fState(0), fLibraryCount(libCount), 
        fPathHash(0), fDlopenReferenceCount(0), fStaticReferenceCount(0),
        fDynamicReferenceCount(0), fDynamicReferences(NULL), fInitializerRecursiveLock(NULL), 
        fDepth(0), fLoadOrder(fgLoadOrdinal++), fState(0), fLibraryCount(libCount), 
@@ -72,7 +72,8 @@ ImageLoader::ImageLoader(const char* path, unsigned int libCount)
        fHideSymbols(false), fMatchByInstallName(false),
        fInterposed(false), fRegisteredDOF(false), fAllLazyPointersBound(false), 
     fBeingRemoved(false), fAddFuncNotified(false),
        fHideSymbols(false), fMatchByInstallName(false),
        fInterposed(false), fRegisteredDOF(false), fAllLazyPointersBound(false), 
     fBeingRemoved(false), fAddFuncNotified(false),
-       fPathOwnedByImage(false), fWeakSymbolsBound(false)
+       fPathOwnedByImage(false), fIsReferencedDownward(false), 
+       fIsReferencedUpward(false), fWeakSymbolsBound(false)
 {
        if ( fPath != NULL )
                fPathHash = hash(fPath);
 {
        if ( fPath != NULL )
                fPathHash = hash(fPath);
@@ -96,6 +97,8 @@ void ImageLoader::deleteImage(ImageLoader* image)
 
 ImageLoader::~ImageLoader()
 {
 
 ImageLoader::~ImageLoader()
 {
+       if ( fRealPath != NULL ) 
+               delete [] fRealPath;
        if ( fPathOwnedByImage && (fPath != NULL) ) 
                delete [] fPath;
        if ( fDynamicReferences != NULL ) {
        if ( fPathOwnedByImage && (fPath != NULL) ) 
                delete [] fPath;
        if ( fDynamicReferences != NULL ) {
@@ -166,6 +169,7 @@ void ImageLoader::setPath(const char* path)
        strcpy((char*)fPath, path);
        fPathOwnedByImage = true;  // delete fPath when this image is destructed
        fPathHash = hash(fPath);
        strcpy((char*)fPath, path);
        fPathOwnedByImage = true;  // delete fPath when this image is destructed
        fPathHash = hash(fPath);
+       fRealPath = NULL;
 }
 
 void ImageLoader::setPathUnowned(const char* path)
 }
 
 void ImageLoader::setPathUnowned(const char* path)
@@ -178,6 +182,21 @@ void ImageLoader::setPathUnowned(const char* path)
        fPathHash = hash(fPath);
 }
 
        fPathHash = hash(fPath);
 }
 
+void ImageLoader::setPaths(const char* path, const char* realPath)
+{
+       this->setPath(path);
+       fRealPath = new char[strlen(realPath)+1];
+       strcpy((char*)fRealPath, realPath);
+}
+
+const char* ImageLoader::getRealPath() const 
+{ 
+       if ( fRealPath != NULL ) 
+               return fRealPath;
+       else
+               return fPath; 
+}
+
 
 uint32_t ImageLoader::hash(const char* path)
 {
 
 uint32_t ImageLoader::hash(const char* path)
 {
@@ -243,8 +262,6 @@ time_t ImageLoader::lastModified() const
 
 bool ImageLoader::containsAddress(const void* addr) const
 {
 
 bool ImageLoader::containsAddress(const void* addr) const
 {
-       if ( ! this->isLinked() )
-               return false;
        for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
                const uint8_t* start = (const uint8_t*)segActualLoadAddress(i);
                const uint8_t* end = (const uint8_t*)segActualEndAddress(i);
        for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
                const uint8_t* start = (const uint8_t*)segActualLoadAddress(i);
                const uint8_t* end = (const uint8_t*)segActualEndAddress(i);
@@ -301,7 +318,6 @@ const ImageLoader::Symbol* ImageLoader::findExportedSymbolInDependentImagesExcep
                        const ImageLoader** dsiStart, const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const
 {
        const ImageLoader::Symbol* sym;
                        const ImageLoader** dsiStart, const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const
 {
        const ImageLoader::Symbol* sym;
-       
        // search self
        if ( notInImgageList(this, dsiStart, dsiCur) ) {
                sym = this->findExportedSymbol(name, false, foundIn);
        // search self
        if ( notInImgageList(this, dsiStart, dsiCur) ) {
                sym = this->findExportedSymbol(name, false, foundIn);
@@ -481,7 +497,7 @@ unsigned int ImageLoader::recursiveUpdateDepth(unsigned int maxDepth)
                unsigned int minDependentDepth = maxDepth;
                for(unsigned int i=0; i < libraryCount(); ++i) {
                        ImageLoader* dependentImage = libImage(i);
                unsigned int minDependentDepth = maxDepth;
                for(unsigned int i=0; i < libraryCount(); ++i) {
                        ImageLoader* dependentImage = libImage(i);
-                       if ( dependentImage != NULL ) {
+                       if ( (dependentImage != NULL) && !libIsUpward(i) ) {
                                unsigned int d = dependentImage->recursiveUpdateDepth(maxDepth);
                                if ( d < minDependentDepth )
                                        minDependentDepth = d;
                                unsigned int d = dependentImage->recursiveUpdateDepth(maxDepth);
                                if ( d < minDependentDepth )
                                        minDependentDepth = d;
@@ -538,8 +554,13 @@ void ImageLoader::recursiveLoadLibraries(const LinkContext& context, bool prefli
                                }
                                if ( fNeverUnload )
                                        dependentLib->setNeverUnload();
                                }
                                if ( fNeverUnload )
                                        dependentLib->setNeverUnload();
-                               if ( ! requiredLibInfo.upward )
+                               if ( requiredLibInfo.upward ) {
+                                       dependentLib->fIsReferencedUpward = true;
+                               }
+                               else { 
                                        dependentLib->fStaticReferenceCount += 1;
                                        dependentLib->fStaticReferenceCount += 1;
+                                       dependentLib->fIsReferencedDownward = true;
+                               }
                                LibraryInfo actualInfo = dependentLib->doGetLibraryInfo();
                                depLibReRequired = requiredLibInfo.required;
                                depLibCheckSumsMatch = ( actualInfo.checksum == requiredLibInfo.info.checksum );
                                LibraryInfo actualInfo = dependentLib->doGetLibraryInfo();
                                depLibReRequired = requiredLibInfo.required;
                                depLibCheckSumsMatch = ( actualInfo.checksum == requiredLibInfo.info.checksum );
@@ -549,7 +570,8 @@ void ImageLoader::recursiveLoadLibraries(const LinkContext& context, bool prefli
                                        depLibReExported = dependentLib->isSubframeworkOf(context, this) || this->hasSubLibrary(context, dependentLib);
                                }
                                // check found library version is compatible
                                        depLibReExported = dependentLib->isSubframeworkOf(context, this) || this->hasSubLibrary(context, dependentLib);
                                }
                                // check found library version is compatible
-                               if ( actualInfo.minVersion < requiredLibInfo.info.minVersion ) {
+                               // <rdar://problem/89200806> 0xFFFFFFFF is wildcard that matches any version
+                               if ( (requiredLibInfo.info.minVersion != 0xFFFFFFFF) && (actualInfo.minVersion < requiredLibInfo.info.minVersion) ) {
                                        // record values for possible use by CrashReporter or Finder
                                        dyld::throwf("Incompatible library version: %s requires version %d.%d.%d or later, but %s provides version %d.%d.%d",
                                                        this->getShortName(), requiredLibInfo.info.minVersion >> 16, (requiredLibInfo.info.minVersion >> 8) & 0xff, requiredLibInfo.info.minVersion & 0xff,
                                        // record values for possible use by CrashReporter or Finder
                                        dyld::throwf("Incompatible library version: %s requires version %d.%d.%d or later, but %s provides version %d.%d.%d",
                                                        this->getShortName(), requiredLibInfo.info.minVersion >> 16, (requiredLibInfo.info.minVersion >> 8) & 0xff, requiredLibInfo.info.minVersion & 0xff,
@@ -582,7 +604,7 @@ void ImageLoader::recursiveLoadLibraries(const LinkContext& context, bool prefli
                                                (*context.setErrorStrings)(dyld_error_kind_dylib_wrong_arch, this->getPath(), requiredLibInfo.name, NULL);
                                        else
                                                (*context.setErrorStrings)(dyld_error_kind_dylib_missing, this->getPath(), requiredLibInfo.name, NULL);
                                                (*context.setErrorStrings)(dyld_error_kind_dylib_wrong_arch, this->getPath(), requiredLibInfo.name, NULL);
                                        else
                                                (*context.setErrorStrings)(dyld_error_kind_dylib_missing, this->getPath(), requiredLibInfo.name, NULL);
-                                       dyld::throwf("Library not loaded: %s\n  Referenced from: %s\n  Reason: %s", requiredLibInfo.name, this->getPath(), msg);
+                                       dyld::throwf("Library not loaded: %s\n  Referenced from: %s\n  Reason: %s", requiredLibInfo.name, this->getRealPath(), msg);
                                }
                                // ok if weak library not found
                                dependentLib = NULL;
                                }
                                // ok if weak library not found
                                dependentLib = NULL;
@@ -872,20 +894,25 @@ void ImageLoader::recursiveInitialization(const LinkContext& context, mach_port_
                // break cycles
                fState = dyld_image_state_dependents_initialized-1;
                try {
                // break cycles
                fState = dyld_image_state_dependents_initialized-1;
                try {
+                       bool hasUpwards = false;
                        // initialize lower level libraries first
                        for(unsigned int i=0; i < libraryCount(); ++i) {
                                ImageLoader* dependentImage = libImage(i);
                        // initialize lower level libraries first
                        for(unsigned int i=0; i < libraryCount(); ++i) {
                                ImageLoader* dependentImage = libImage(i);
-                               if ( dependentImage != NULL )
-                               // don't try to initialize stuff "above" me
-                               if ( (dependentImage != NULL) && (dependentImage->fDepth >= fDepth) && !libIsUpward(i) )
-                                       dependentImage->recursiveInitialization(context, this_thread, timingInfo);
+                               if ( dependentImage != NULL ) {
+                                       // don't try to initialize stuff "above" me
+                                       bool isUpward = libIsUpward(i);
+                                       if ( (dependentImage->fDepth >= fDepth) && !isUpward ) {
+                                               dependentImage->recursiveInitialization(context, this_thread, timingInfo);
+                                       }
+                                       hasUpwards |= isUpward;
+                }
                        }
                        
                        // record termination order
                        if ( this->needsTermination() )
                                context.terminationRecorder(this);
                        
                        }
                        
                        // record termination order
                        if ( this->needsTermination() )
                                context.terminationRecorder(this);
                        
-                       // let objc know we are about to initalize this image
+                       // let objc know we are about to initialize this image
                        uint64_t t1 = mach_absolute_time();
                        fState = dyld_image_state_dependents_initialized;
                        oldState = fState;
                        uint64_t t1 = mach_absolute_time();
                        fState = dyld_image_state_dependents_initialized;
                        oldState = fState;
@@ -894,7 +921,19 @@ void ImageLoader::recursiveInitialization(const LinkContext& context, mach_port_
                        // initialize this image
                        bool hasInitializers = this->doInitialization(context);
                        
                        // initialize this image
                        bool hasInitializers = this->doInitialization(context);
                        
-                       // let anyone know we finished initalizing this image
+                       // <rdar://problem/10491874> initialize any upward depedencies
+                       if ( hasUpwards ) {
+                               for(unsigned int i=0; i < libraryCount(); ++i) {
+                                       ImageLoader* dependentImage = libImage(i);
+                                       // <rdar://problem/10643239> ObjC CG hang
+                                       // only init upward lib here if lib is not downwardly referenced somewhere 
+                                       if ( (dependentImage != NULL) && libIsUpward(i) && !dependentImage->isReferencedDownward() ) {
+                                               dependentImage->recursiveInitialization(context, this_thread, timingInfo);
+                                       }
+                               }
+                       }
+            
+                       // let anyone know we finished initializing this image
                        fState = dyld_image_state_initialized;
                        oldState = fState;
                        context.notifySingle(dyld_image_state_initialized, this);
                        fState = dyld_image_state_initialized;
                        oldState = fState;
                        context.notifySingle(dyld_image_state_initialized, this);
index 582e60c0e1961f805130dd6e0a753e84caffc623..83bc1fe03788655a1926e970c1025db4727edb83 100644 (file)
 #elif __x86_64__
        #define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64
        #define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64
 #elif __x86_64__
        #define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64
        #define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64
-#elif __ppc__
-       #define SHARED_REGION_BASE SHARED_REGION_BASE_PPC
-       #define SHARED_REGION_SIZE SHARED_REGION_SIZE_PPC
-#elif __ppc64__
-       #define SHARED_REGION_BASE SHARED_REGION_BASE_PPC64
-       #define SHARED_REGION_SIZE SHARED_REGION_SIZE_PPC64
 #elif __arm__
        #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM
        #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM
 #elif __arm__
        #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM
        #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM
        #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
 #endif
 
        #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
 #endif
 
+#ifndef LC_MAIN
+       #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
+       struct entry_point_command {
+               uint32_t  cmd;  /* LC_MAIN only used in MH_EXECUTE filetypes */
+               uint32_t  cmdsize;      /* 24 */
+               uint64_t  entryoff;     /* file (__TEXT) offset of main() */
+               uint64_t  stacksize;/* if not zero, initial stack size */
+       };
+#endif
 
 #define SPLIT_SEG_SHARED_REGION_SUPPORT __arm__
 
 #define SPLIT_SEG_SHARED_REGION_SUPPORT __arm__
-#define SPLIT_SEG_DYLIB_SUPPORT (__ppc__ || __i386__ || __arm__)
-#define PREBOUND_IMAGE_SUPPORT (__ppc__ || __i386__ || __arm__)
-#define TEXT_RELOC_SUPPORT (__ppc__ || __i386__ || __arm__)
-#define DYLD_SHARED_CACHE_SUPPORT (__ppc__ || __i386__ || __ppc64__ || __x86_64__ || __arm__)
-#define SUPPORT_OLD_CRT_INITIALIZATION (__ppc__ || __i386__)
+#define SPLIT_SEG_DYLIB_SUPPORT (__i386__ || __arm__)
+#define PREBOUND_IMAGE_SUPPORT (__i386__ || __arm__)
+#define TEXT_RELOC_SUPPORT (__i386__ || __arm__)
+#define DYLD_SHARED_CACHE_SUPPORT (__i386__ ||  __x86_64__ || __arm__)
+#define SUPPORT_OLD_CRT_INITIALIZATION (__i386__)
 #define SUPPORT_LC_DYLD_ENVIRONMENT  (__i386__ || __x86_64__)
 #define SUPPORT_VERSIONED_PATHS  (__i386__ || __x86_64__)
 #if __IPHONE_OS_VERSION_MIN_REQUIRED
 #define SUPPORT_LC_DYLD_ENVIRONMENT  (__i386__ || __x86_64__)
 #define SUPPORT_VERSIONED_PATHS  (__i386__ || __x86_64__)
 #if __IPHONE_OS_VERSION_MIN_REQUIRED
@@ -89,7 +92,7 @@
        #define CORESYMBOLICATION_SUPPORT   (__i386__ || __x86_64__)
 #endif
 #if __arm__
        #define CORESYMBOLICATION_SUPPORT   (__i386__ || __x86_64__)
 #endif
 #if __arm__
-       #define INITIAL_IMAGE_COUNT 100
+       #define INITIAL_IMAGE_COUNT 256
 #else
        #define INITIAL_IMAGE_COUNT 200
 #endif
 #else
        #define INITIAL_IMAGE_COUNT 200
 #endif
@@ -187,6 +190,7 @@ public:
                void                    (*removeImage)(ImageLoader* image);
                void                    (*registerDOFs)(const std::vector<DOFInfo>& dofs);
                void                    (*clearAllDepths)();
                void                    (*removeImage)(ImageLoader* image);
                void                    (*registerDOFs)(const std::vector<DOFInfo>& dofs);
                void                    (*clearAllDepths)();
+               void                    (*printAllDepths)();
                unsigned int    (*imageCount)();
                void                    (*setNewProgramVars)(const ProgramVars&);
                bool                    (*inSharedCache)(const char* path);
                unsigned int    (*imageCount)();
                void                    (*setNewProgramVars)(const ProgramVars&);
                bool                    (*inSharedCache)(const char* path);
@@ -285,6 +289,9 @@ public:
 
        uint32_t                                                        getPathHash() const { return fPathHash; }
 
 
        uint32_t                                                        getPathHash() const { return fPathHash; }
 
+                                                                               // get the "real" path for this image (e.g. no @rpath)
+       const char*                                                     getRealPath() 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;
 
                                                                                // get path this image is intended to be placed on disk or NULL if no preferred install location
        virtual const char*                                     getInstallPath() const = 0;
 
@@ -325,7 +332,10 @@ public:
                                                                                // st_mtime from stat() on file
        time_t                                                          lastModified() const;
 
                                                                                // st_mtime from stat() on file
        time_t                                                          lastModified() const;
 
-                                                                               // only valid for main executables, returns a pointer its entry point
+                                                                               // only valid for main executables, returns a pointer its entry point from LC_UNIXTHREAD
+       virtual void*                                           getThreadPC() const = 0;
+       
+                                                                               // only valid for main executables, returns a pointer its main from LC_<MAIN
        virtual void*                                           getMain() const = 0;
        
                                                                                // dyld API's require each image to have an associated mach_header
        virtual void*                                           getMain() const = 0;
        
                                                                                // dyld API's require each image to have an associated mach_header
@@ -478,7 +488,11 @@ public:
        bool                                                            neverUnload() const { return fNeverUnload; }
 
        void                                                            setNeverUnload() { fNeverUnload = true; fLeaveMapped = true; }
        bool                                                            neverUnload() const { return fNeverUnload; }
 
        void                                                            setNeverUnload() { fNeverUnload = true; fLeaveMapped = true; }
+       
+       bool                                                            isReferencedDownward() { return fIsReferencedDownward; }
 
 
+       bool                                                            isReferencedUpward() { return fIsReferencedUpward; }
+       
                                                                                // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
        static void                                                     printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo);
                                
                                                                                // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
        static void                                                     printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo);
                                
@@ -490,10 +504,12 @@ public:
                                                                                // used instead of directly deleting image
        static void                                                     deleteImage(ImageLoader*);
                
                                                                                // used instead of directly deleting image
        static void                                                     deleteImage(ImageLoader*);
                
-                       void                                            setPath(const char* path);      // only called for images created from memory
+                       void                                            setPath(const char* path);
+                       void                                            setPaths(const char* path, const char* realPath);
                        void                                            setPathUnowned(const char* path);
                                                
                        void                                            clearDepth() { fDepth = 0; }
                        void                                            setPathUnowned(const char* path);
                                                
                        void                                            clearDepth() { fDepth = 0; }
+                       int                                                     getDepth() { return fDepth; }
                        
                        void                                            setBeingRemoved() { fBeingRemoved = true; }
                        bool                                            isBeingRemoved() const { return fBeingRemoved; }
                        
                        void                                            setBeingRemoved() { fBeingRemoved = true; }
                        bool                                            isBeingRemoved() const { return fBeingRemoved; }
@@ -638,6 +654,7 @@ protected:
        static uint64_t                         fgTotalInitTime;
        static std::vector<InterposeTuple>      fgInterposingTuples;
        const char*                                     fPath;
        static uint64_t                         fgTotalInitTime;
        static std::vector<InterposeTuple>      fgInterposingTuples;
        const char*                                     fPath;
+       const char*                                     fRealPath;
        dev_t                                           fDevice;
        ino_t                                           fInode;
        time_t                                          fLastModified;
        dev_t                                           fDevice;
        ino_t                                           fInode;
        time_t                                          fLastModified;
@@ -677,6 +694,8 @@ private:
                                                                fBeingRemoved : 1,
                                                                fAddFuncNotified : 1,
                                                                fPathOwnedByImage : 1,
                                                                fBeingRemoved : 1,
                                                                fAddFuncNotified : 1,
                                                                fPathOwnedByImage : 1,
+                                                               fIsReferencedDownward : 1,
+                                                               fIsReferencedUpward : 1,
                                                                fWeakSymbolsBound : 1;
 
        static uint16_t                         fgLoadOrdinal;
                                                                fWeakSymbolsBound : 1;
 
        static uint16_t                         fgLoadOrdinal;
index b068b7a03779efb0bfba4f7c656c5076d002f071..3a8ad7d17e2096b3266d9ee15df7223e026c2c8c 100644 (file)
@@ -88,7 +88,7 @@ ImageLoaderMachO::ImageLoaderMachO(const macho_header* mh, const char* path, uns
        fReadOnlyImportSegment(false),
 #endif
        fHasSubLibraries(false), fHasSubUmbrella(false), fInUmbrella(false), fHasDOFSections(false), fHasDashInit(false),
        fReadOnlyImportSegment(false),
 #endif
        fHasSubLibraries(false), fHasSubUmbrella(false), fInUmbrella(false), fHasDOFSections(false), fHasDashInit(false),
-       fHasInitializers(false), fHasTerminators(false), fGoodFirstSegment(false), fRegisteredAsRequiresCoalescing(false)
+       fHasInitializers(false), fHasTerminators(false), fRegisteredAsRequiresCoalescing(false)
 {
        fIsSplitSeg = ((mh->flags & MH_SPLIT_SEGS) != 0);        
 
 {
        fIsSplitSeg = ((mh->flags & MH_SPLIT_SEGS) != 0);        
 
@@ -121,10 +121,14 @@ void ImageLoaderMachO::sniffLoadCommands(const macho_header* mh, const char* pat
        *segCount = 0;
        *libCount = 0;
        *codeSigCmd = NULL;
        *segCount = 0;
        *libCount = 0;
        *codeSigCmd = NULL;
+       struct macho_segment_command* segCmd;
+#if CODESIGNING_SUPPORT
+       bool foundLoadCommandSegment = false;
+#endif
        const uint32_t cmd_count = mh->ncmds;
        const uint32_t cmd_count = mh->ncmds;
-       const struct load_command* const cmds    = (struct load_command*)(((uint8_t*)mh) + sizeof(macho_header));
+       const struct load_command* const startCmds    = (struct load_command*)(((uint8_t*)mh) + sizeof(macho_header));
        const struct load_command* const endCmds = (struct load_command*)(((uint8_t*)mh) + sizeof(macho_header) + mh->sizeofcmds);
        const struct load_command* const endCmds = (struct load_command*)(((uint8_t*)mh) + sizeof(macho_header) + mh->sizeofcmds);
-       const struct load_command* cmd = cmds;
+       const struct load_command* cmd = startCmds;
        for (uint32_t i = 0; i < cmd_count; ++i) {
                switch (cmd->cmd) {
                        case LC_DYLD_INFO:
        for (uint32_t i = 0; i < cmd_count; ++i) {
                switch (cmd->cmd) {
                        case LC_DYLD_INFO:
@@ -132,9 +136,20 @@ void ImageLoaderMachO::sniffLoadCommands(const macho_header* mh, const char* pat
                                *compressed = true;
                                break;
                        case LC_SEGMENT_COMMAND:
                                *compressed = true;
                                break;
                        case LC_SEGMENT_COMMAND:
+                               segCmd = (struct macho_segment_command*)cmd;
                                // ignore zero-sized segments
                                // ignore zero-sized segments
-                               if ( ((struct macho_segment_command*)cmd)->vmsize != 0 )
+                               if ( segCmd->vmsize != 0 )
                                        *segCount += 1;
                                        *segCount += 1;
+#if CODESIGNING_SUPPORT
+                               // <rdar://problem/7942521> all load commands must be in an executable segment
+                               if ( (segCmd->fileoff < mh->sizeofcmds) && (segCmd->filesize != 0) ) {
+                                       if ( (segCmd->fileoff != 0) || (segCmd->filesize < (mh->sizeofcmds+sizeof(macho_header))) ) 
+                                               dyld::throwf("malformed mach-o image: segment %s does not span all load commands", segCmd->segname); 
+                                       if ( segCmd->initprot != (VM_PROT_READ | VM_PROT_EXECUTE) ) 
+                                               dyld::throwf("malformed mach-o image: load commands found in segment %s with wrong permissions", segCmd->segname); 
+                                       foundLoadCommandSegment = true;
+                               }
+#endif         
                                break;
                        case LC_LOAD_DYLIB:
                        case LC_LOAD_WEAK_DYLIB:
                                break;
                        case LC_LOAD_DYLIB:
                        case LC_LOAD_WEAK_DYLIB:
@@ -148,11 +163,17 @@ void ImageLoaderMachO::sniffLoadCommands(const macho_header* mh, const char* pat
                }
                uint32_t cmdLength = cmd->cmdsize;
                cmd = (const struct load_command*)(((char*)cmd)+cmdLength);
                }
                uint32_t cmdLength = cmd->cmdsize;
                cmd = (const struct load_command*)(((char*)cmd)+cmdLength);
-               if ( cmd > endCmds ) {
+               if ( (cmd > endCmds) || (cmd < startCmds) ) {
                        dyld::throwf("malformed mach-o image: load command #%d length (%u) would exceed sizeofcmds (%u) in %s", 
                                                        i, cmdLength, mh->sizeofcmds, path);
                }
        }
                        dyld::throwf("malformed mach-o image: load command #%d length (%u) would exceed sizeofcmds (%u) in %s", 
                                                        i, cmdLength, mh->sizeofcmds, path);
                }
        }
+       
+#if CODESIGNING_SUPPORT
+       if ( ! foundLoadCommandSegment )
+               throw "load commands not in a segment";
+#endif
+               
        // fSegmentsArrayCount is only 8-bits
        if ( *segCount > 255 )
                dyld::throwf("malformed mach-o image: more than 255 segments in %s", path);
        // fSegmentsArrayCount is only 8-bits
        if ( *segCount > 255 )
                dyld::throwf("malformed mach-o image: more than 255 segments in %s", path);
@@ -287,6 +308,8 @@ void ImageLoaderMachO::parseLoadCmds()
        const dyld_info_command* dyldInfo = NULL;
        const macho_nlist* symbolTable = NULL;
        const char* symbolTableStrings = NULL;
        const dyld_info_command* dyldInfo = NULL;
        const macho_nlist* symbolTable = NULL;
        const char* symbolTableStrings = NULL;
+       const struct load_command* firstUnknownCmd = NULL;
+       const struct version_min_command* minOSVersionCmd = NULL;
        const dysymtab_command* dynSymbolTable = NULL;
        const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
        const dysymtab_command* dynSymbolTable = NULL;
        const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
@@ -352,14 +375,34 @@ void ImageLoaderMachO::parseLoadCmds()
                        case LC_LOAD_WEAK_DYLIB:
                    case LC_REEXPORT_DYLIB:
                        case LC_LOAD_UPWARD_DYLIB:
                        case LC_LOAD_WEAK_DYLIB:
                    case LC_REEXPORT_DYLIB:
                        case LC_LOAD_UPWARD_DYLIB:
+                       case LC_MAIN:
                                // do nothing, just prevent LC_REQ_DYLD exception from occuring
                                break;
                                // do nothing, just prevent LC_REQ_DYLD exception from occuring
                                break;
+                       case LC_VERSION_MIN_MACOSX:
+                       case LC_VERSION_MIN_IPHONEOS:
+                               minOSVersionCmd = (version_min_command*)cmd;
+                               break;
                        default:
                        default:
-                               if ( (cmd->cmd & LC_REQ_DYLD) != 0 )
-                                       dyld::throwf("unknown required load command 0x%08X", cmd->cmd);
+                               if ( (cmd->cmd & LC_REQ_DYLD) != 0 ) {
+                                       if ( firstUnknownCmd == NULL )
+                                               firstUnknownCmd = cmd;
+                               }
+                               break;
                }
                cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
        }
                }
                cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
        }
+       if ( firstUnknownCmd != NULL ) {
+               if ( minOSVersionCmd != NULL )  {
+                       dyld::throwf("cannot load '%s' because it was built for OS version %u.%u (load command 0x%08X is unknown)", 
+                                                this->getShortName(),
+                                                minOSVersionCmd->version >> 16, ((minOSVersionCmd->version >> 8) & 0xff), 
+                                                firstUnknownCmd->cmd);
+               }
+               else {
+                       dyld::throwf("cannot load '%s' (load command 0x%08X is unknown)", this->getShortName(), firstUnknownCmd->cmd);
+               }
+       }
+       
        
        if ( dyldInfo != NULL )
                this->setDyldInfo(dyldInfo);
        
        if ( dyldInfo != NULL )
                this->setDyldInfo(dyldInfo);
@@ -673,11 +716,6 @@ const char* ImageLoaderMachO::getInstallPath() const
 void ImageLoaderMachO::registerInterposing()
 {
        // mach-o files advertise interposing by having a __DATA __interpose section
 void ImageLoaderMachO::registerInterposing()
 {
        // mach-o files advertise interposing by having a __DATA __interpose section
-       uintptr_t textStart = this->segActualLoadAddress(0);
-       uintptr_t textEnd = this->segActualEndAddress(0);
-       // <rdar://problem/8268602> verify that the first segment load command is for a read-only segment
-       if ( ! fGoodFirstSegment )
-               return;
        struct InterposeData { uintptr_t replacement; uintptr_t replacee; };
        const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
        struct InterposeData { uintptr_t replacement; uintptr_t replacee; };
        const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
@@ -699,7 +737,7 @@ void ImageLoaderMachO::registerInterposing()
                                                                tuple.replacementImage  = this;
                                                                tuple.replacee                  = interposeArray[i].replacee;
                                                                // <rdar://problem/7937695> verify that replacement is in this image
                                                                tuple.replacementImage  = this;
                                                                tuple.replacee                  = interposeArray[i].replacee;
                                                                // <rdar://problem/7937695> verify that replacement is in this image
-                                                               if ( (tuple.replacement >= textStart) && (tuple.replacement < textEnd) ) {
+                                                               if ( this->containsAddress((void*)tuple.replacement) ) {
                                                                        for (std::vector<InterposeTuple>::iterator it=fgInterposingTuples.begin(); it != fgInterposingTuples.end(); it++) {
                                                                                if ( it->replacee == tuple.replacee ) {
                                                                                        tuple.replacee = it->replacement;
                                                                        for (std::vector<InterposeTuple>::iterator it=fgInterposingTuples.begin(); it != fgInterposingTuples.end(); it++) {
                                                                                if ( it->replacee == tuple.replacee ) {
                                                                                        tuple.replacee = it->replacement;
@@ -717,6 +755,26 @@ void ImageLoaderMachO::registerInterposing()
        }
 }
 
        }
 }
 
+void* ImageLoaderMachO::getThreadPC() 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 (uint32_t i = 0; i < cmd_count; ++i) {
+               if ( cmd->cmd == LC_MAIN ) {
+                       entry_point_command* mainCmd = (entry_point_command*)cmd;
+                       void* entry = (void*)(mainCmd->entryoff + (char*)fMachOData);
+                       // <rdar://problem/8543820&9228031> verify entry point is in image
+                       if ( this->containsAddress(entry) )
+                               return entry;
+                       else
+                               throw "LC_MAIN entryoff is out of range";
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+       return NULL;
+}
+
 
 void* ImageLoaderMachO::getMain() const
 {
 
 void* ImageLoaderMachO::getMain() const
 {
@@ -727,30 +785,28 @@ void* ImageLoaderMachO::getMain() const
                switch (cmd->cmd) {
                        case LC_UNIXTHREAD:
                        {
                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 + fSlide);
-                       #elif __ppc64__
-                               const ppc_thread_state64_t* registers = (ppc_thread_state64_t*)(((char*)cmd) + 16);
-                               return (void*)(registers->srr0 + fSlide);
-                       #elif __i386__
+                       #if __i386__
                                const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
                                const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
-                               return (void*)(registers->eip + fSlide);
+                               void* entry = (void*)(registers->eip + fSlide);
                        #elif __x86_64__
                                const x86_thread_state64_t* registers = (x86_thread_state64_t*)(((char*)cmd) + 16);
                        #elif __x86_64__
                                const x86_thread_state64_t* registers = (x86_thread_state64_t*)(((char*)cmd) + 16);
-                               return (void*)(registers->rip + fSlide);
+                               void* entry = (void*)(registers->rip + fSlide);
                        #elif __arm__
                                const arm_thread_state_t* registers = (arm_thread_state_t*)(((char*)cmd) + 16);
                        #elif __arm__
                                const arm_thread_state_t* registers = (arm_thread_state_t*)(((char*)cmd) + 16);
-                               return (void*)(registers->__pc + fSlide);
+                               void* entry = (void*)(registers->__pc + fSlide);
                        #else
                                #warning need processor specific code
                        #endif
                        #else
                                #warning need processor specific code
                        #endif
+                               // <rdar://problem/8543820&9228031> verify entry point is in image
+                               if ( this->containsAddress(entry) ) {
+                                       return entry;
+                               }
                        }
                        break;
                }
                cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
        }
                        }
                        break;
                }
                cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
        }
-       return NULL;
+       throw "no valid entry point";
 }
 
 bool ImageLoaderMachO::needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh)
 }
 
 bool ImageLoaderMachO::needsAddedLibSystemDepency(unsigned int libCount, const macho_header* mh)
@@ -1306,9 +1362,7 @@ uintptr_t ImageLoaderMachO::bindLocation(const LinkContext& context, uintptr_t l
 
 #if SUPPORT_OLD_CRT_INITIALIZATION
 // first 16 bytes of "start" in crt1.o
 
 #if SUPPORT_OLD_CRT_INITIALIZATION
 // first 16 bytes of "start" in crt1.o
-#if __ppc__
-       static uint32_t sStandardEntryPointInstructions[4] = { 0x7c3a0b78, 0x3821fffc, 0x54210034, 0x38000000 };
-#elif __i386__
+#if __i386__
        static uint8_t sStandardEntryPointInstructions[16] = { 0x6a, 0x00, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0x8b, 0x5d, 0x04, 0x89, 0x5c, 0x24 };
 #endif
 #endif
        static uint8_t sStandardEntryPointInstructions[16] = { 0x6a, 0x00, 0x89, 0xe5, 0x83, 0xe4, 0xf0, 0x83, 0xec, 0x10, 0x8b, 0x5d, 0x04, 0x89, 0x5c, 0x24 };
 #endif
 #endif
@@ -1331,11 +1385,10 @@ void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext& context)
        const uint32_t cmd_count = mh->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
        const struct load_command* cmd;
        const uint32_t cmd_count = mh->ncmds;
        const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
        const struct load_command* cmd;
-       // set up __dyld section
-       // optimizations:
-       //   1) do nothing if image is in dyld shared cache and dyld loaded at same address as when cache built
-       //       2) first read __dyld value, if already correct don't write, this prevents dirtying a page
-       if ( !fInSharedCache || !context.dyldLoadedAtSameAddressNeededBySharedCache ) {
+       // There used to be some optimizations to skip this section scan, but we need to handle the 
+       // __dyld section in libdyld.dylib, so everything needs to be scanned for now.
+       // <rdar://problem/10910062> CrashTracer: 1,295 crashes in bash at bash: getenv
+       if ( true ) {
                cmd = cmds;
                for (uint32_t i = 0; i < cmd_count; ++i) {
                        if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
                cmd = cmds;
                for (uint32_t i = 0; i < cmd_count; ++i) {
                        if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
@@ -1377,6 +1430,16 @@ void ImageLoaderMachO::setupLazyPointerHandler(const LinkContext& context)
                                #endif
                                                                }
                                                        }
                                #endif
                                                                }
                                                        }
+                                                       else if ( mh->filetype == MH_DYLIB ) {
+                                                               const char* installPath = this->getInstallPath();
+                                                               if ( (installPath != NULL) && (strncmp(installPath, "/usr/lib/", 9) == 0) ) {
+                                                                       if ( sect->size > offsetof(DATAdyld, vars) ) {
+                                                                               // use ProgramVars from libdyld.dylib but tweak mh field to correct value
+                                                                               dd->vars.mh = context.mainExecutable->machHeader();
+                                                                               context.setNewProgramVars(dd->vars);
+                                                                       }
+                                                               }
+                                                       }
                                                }
                                                else if ( (strcmp(sect->sectname, "__program_vars" ) == 0) && (mh->filetype == MH_EXECUTE) ) {
                                                        // this is a Mac OS X 10.6 or later main executable 
                                                }
                                                else if ( (strcmp(sect->sectname, "__program_vars" ) == 0) && (mh->filetype == MH_EXECUTE) ) {
                                                        // this is a Mac OS X 10.6 or later main executable 
@@ -1451,16 +1514,6 @@ bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const
 void ImageLoaderMachO::doImageInit(const LinkContext& context)
 {
        if ( fHasDashInit ) {
 void ImageLoaderMachO::doImageInit(const LinkContext& context)
 {
        if ( fHasDashInit ) {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED   
-               // <rdar://problem/8543820> verify initializers are in first segment for dylibs
-               if ( this->isDylib() && !fGoodFirstSegment ) {
-                       if ( context.verboseInit )
-                               dyld::log("dyld: ignoring -init in %s\n", this->getPath());
-                       return;
-               }
-               uintptr_t textStart = this->segActualLoadAddress(0);
-               uintptr_t textEnd = this->segActualEndAddress(0);
-#endif
                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 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;
@@ -1468,20 +1521,13 @@ void ImageLoaderMachO::doImageInit(const LinkContext& context)
                        switch (cmd->cmd) {
                                case LC_ROUTINES_COMMAND:
                                        Initializer func = (Initializer)(((struct macho_routines_command*)cmd)->init_address + fSlide);
                        switch (cmd->cmd) {
                                case LC_ROUTINES_COMMAND:
                                        Initializer func = (Initializer)(((struct macho_routines_command*)cmd)->init_address + fSlide);
-#if __IPHONE_OS_VERSION_MIN_REQUIRED   
-                                       // <rdar://problem/8543820> verify initializers are in first segment for dylibs
-                                       if ( this->isDylib() && (((uintptr_t)func >= textEnd) || ((uintptr_t)func < textStart)) ) {
-                                               if ( context.verboseInit )
-                                                       dyld::log("dyld: ignoring out of bounds initializer function %p in %s\n", func, this->getPath());
-                                       }
-                                       else {
-#endif
-                                               if ( context.verboseInit )
-                                                       dyld::log("dyld: calling -init function 0x%p in %s\n", func, this->getPath());
-                                               func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
-#if __IPHONE_OS_VERSION_MIN_REQUIRED   
+                                       // <rdar://problem/8543820&9228031> verify initializers are in image
+                                       if ( ! this->containsAddress((void*)func) ) {
+                                               dyld::throwf("initializer function %p not in mapped image for %s\n", func, this->getPath());
                                        }
                                        }
-#endif
+                                       if ( context.verboseInit )
+                                               dyld::log("dyld: calling -init function 0x%p in %s\n", func, this->getPath());
+                                       func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
                                        break;
                        }
                        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
                                        break;
                        }
                        cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
@@ -1492,16 +1538,6 @@ void ImageLoaderMachO::doImageInit(const LinkContext& context)
 void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)
 {
        if ( fHasInitializers ) {
 void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)
 {
        if ( fHasInitializers ) {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED   
-               // <rdar://problem/8543820> verify initializers are in first segment for dylibs
-               if ( this->isDylib() && !fGoodFirstSegment ) {
-                       if ( context.verboseInit )
-                               dyld::log("dyld: ignoring all initializers in %s\n", this->getPath());
-                       return;
-               }
-               uintptr_t textStart = this->segActualLoadAddress(0);
-               uintptr_t textEnd = this->segActualEndAddress(0);
-#endif
                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 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;
@@ -1517,20 +1553,13 @@ void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)
                                                const uint32_t count = sect->size / sizeof(uintptr_t);
                                                for (uint32_t i=0; i < count; ++i) {
                                                        Initializer func = inits[i];
                                                const uint32_t count = sect->size / sizeof(uintptr_t);
                                                for (uint32_t i=0; i < count; ++i) {
                                                        Initializer func = inits[i];
-#if __IPHONE_OS_VERSION_MIN_REQUIRED   
-                                                       // <rdar://problem/8543820> verify initializers are in first segment for dylibs
-                                                       if ( this->isDylib() && (((uintptr_t)func >= textEnd) || ((uintptr_t)func < textStart)) ) {
-                                                               if ( context.verboseInit )
-                                                                       dyld::log("dyld: ignoring out of bounds initializer function %p in %s\n", func, this->getPath());
+                                                       // <rdar://problem/8543820&9228031> verify initializers are in image
+                                                       if ( ! this->containsAddress((void*)func) ) {
+                                                               dyld::throwf("initializer function %p not in mapped image for %s\n", func, this->getPath());
                                                        }
                                                        }
-                                                       else {
-#endif                                         
-                                                               if ( context.verboseInit )
-                                                                       dyld::log("dyld: calling initializer function %p in %s\n", func, this->getPath());
-                                                               func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
-#if __IPHONE_OS_VERSION_MIN_REQUIRED   
-                                                       }
-#endif
+                                                       if ( context.verboseInit )
+                                                               dyld::log("dyld: calling initializer function %p in %s\n", func, this->getPath());
+                                                       func(context.argc, context.argv, context.envp, context.apple, &context.programVars);
                                                }
                                        }
                                }
                                                }
                                        }
                                }
@@ -1620,6 +1649,10 @@ void ImageLoaderMachO::doTermination(const LinkContext& context)
                                                const uint32_t count = sect->size / sizeof(uintptr_t);
                                                for (uint32_t i=count; i > 0; --i) {
                                                        Terminator func = terms[i-1];
                                                const uint32_t count = sect->size / sizeof(uintptr_t);
                                                for (uint32_t i=count; i > 0; --i) {
                                                        Terminator func = terms[i-1];
+                                                       // <rdar://problem/8543820&9228031> verify terminators are in image
+                                                       if ( ! this->containsAddress((void*)func) ) {
+                                                               dyld::throwf("termination function %p not in mapped image for %s\n", func, this->getPath());
+                                                       }
                                                        if ( context.verboseInit )
                                                                dyld::log("dyld: calling termination function %p in %s\n", func, this->getPath());
                                                        func();
                                                        if ( context.verboseInit )
                                                                dyld::log("dyld: calling termination function %p in %s\n", func, this->getPath());
                                                        func();
@@ -1726,24 +1759,11 @@ void ImageLoaderMachO::mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInF
        intptr_t slide = this->assignSegmentAddresses(context);
        if ( context.verboseMapping )
                dyld::log("dyld: Mapping %s\n", this->getPath());
        intptr_t slide = this->assignSegmentAddresses(context);
        if ( context.verboseMapping )
                dyld::log("dyld: Mapping %s\n", this->getPath());
-       // <rdar://problem/8268602> verify that the first segment load command is for a r-x segment
-       // that starts at begining of file and is larger than all load commands
-       uintptr_t firstSegMappedStart = segPreferredLoadAddress(0) + slide;
-       uintptr_t firstSegMappedEnd = firstSegMappedStart + this->segSize(0);
-       if ( (this->segLoadCommand(0)->initprot == (VM_PROT_EXECUTE|VM_PROT_READ)) 
-               && (this->segFileOffset(0) == 0) 
-               && (this->segFileSize(0) != 0) 
-               && (this->segSize(0) > ((macho_header*)fMachOData)->sizeofcmds) ) {
-                       fGoodFirstSegment = true;
-       }
        // map in all segments
        for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
                vm_offset_t fileOffset = segFileOffset(i) + offsetInFat;
                vm_size_t size = segFileSize(i);
                uintptr_t requestedLoadAddress = segPreferredLoadAddress(i) + slide;
        // map in all segments
        for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
                vm_offset_t fileOffset = segFileOffset(i) + offsetInFat;
                vm_size_t size = segFileSize(i);
                uintptr_t requestedLoadAddress = segPreferredLoadAddress(i) + slide;
-               // <rdar://problem/8268602> verify other segments map after first
-               if ( (i != 0) && (requestedLoadAddress < firstSegMappedEnd) )
-                       fGoodFirstSegment = false;
                int protection = 0;
                if ( !segUnaccessible(i) ) {
                        // If has text-relocs, don't set x-bit initially.
                int protection = 0;
                if ( !segUnaccessible(i) ) {
                        // If has text-relocs, don't set x-bit initially.
index a2b657a9c554aa9b426daf5202cf732030f9f7c2..c3e192bb7ff06b531dfe72c7522c2d906029d56c 100644 (file)
@@ -50,6 +50,7 @@ public:
        bool                                                            inSharedCache() const { return fInSharedCache; }
        const char*                                                     getInstallPath() const;
        virtual void*                                           getMain() const;
        bool                                                            inSharedCache() const { return fInSharedCache; }
        const char*                                                     getInstallPath() const;
        virtual void*                                           getMain() const;
+       virtual void*                                           getThreadPC() const;
        virtual const struct mach_header*   machHeader() const;
        virtual uintptr_t                                       getSlide() const;
        virtual const void*                                     getEnd() const;
        virtual const struct mach_header*   machHeader() const;
        virtual uintptr_t                                       getSlide() const;
        virtual const void*                                     getEnd() const;
@@ -218,7 +219,6 @@ protected:
                                                                                        fHasDashInit : 1,
                                                                                        fHasInitializers : 1,
                                                                                        fHasTerminators : 1,
                                                                                        fHasDashInit : 1,
                                                                                        fHasInitializers : 1,
                                                                                        fHasTerminators : 1,
-                                                                                       fGoodFirstSegment : 1,
                                                                                        fRegisteredAsRequiresCoalescing : 1;    // <rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount
                                                                                        
                                                                                        
                                                                                        fRegisteredAsRequiresCoalescing : 1;    // <rdar://problem/7886402> Loading MH_DYLIB_STUB causing coalescable miscount
                                                                                        
                                                                                        
index 33b055d94bee273ef19a8d5c9a851f3de26d7171..2d0cf1b20904aaafb4247bccd55bc28779529d36 100644 (file)
@@ -44,9 +44,6 @@
 #include <libkern/OSAtomic.h>
 #include <libkern/OSCacheControl.h>
 
 #include <libkern/OSAtomic.h>
 #include <libkern/OSCacheControl.h>
 
-#if __ppc__ || __ppc64__
-       #include <mach-o/ppc/reloc.h>
-#endif
 #if __x86_64__
        #include <mach-o/x86_64/reloc.h>
 #endif
 #if __x86_64__
        #include <mach-o/x86_64/reloc.h>
 #endif
 #include "ImageLoaderMachOClassic.h"
 #include "mach-o/dyld_images.h"
 
 #include "ImageLoaderMachOClassic.h"
 #include "mach-o/dyld_images.h"
 
-// optimize strcmp for ppc
-#if __ppc__
-       #include <ppc_intrinsics.h>
-#else
-       #define astrcmp(a,b) strcmp(a,b)
-#endif
-
-
 // in dyldStartup.s
 extern "C" void fast_stub_binding_helper_interface();
 
 // in dyldStartup.s
 extern "C" void fast_stub_binding_helper_interface();
 
@@ -163,11 +152,12 @@ ImageLoaderMachOClassic* ImageLoaderMachOClassic::instantiateFromFile(const char
                const char* installName = image->getInstallPath();
                if ( (installName != NULL) && (strcmp(installName, path) == 0) && (path[0] == '/') )
                        image->setPathUnowned(installName);
                const char* installName = image->getInstallPath();
                if ( (installName != NULL) && (strcmp(installName, path) == 0) && (path[0] == '/') )
                        image->setPathUnowned(installName);
-               else if ( path[0] != '/' ) {
+               else if ( (path[0] != '/') || (strstr(path, "../") != NULL) ) {
+                       // rdar://problem/10733082 Fix up @path based paths during introspection
                        // rdar://problem/5135363 turn relative paths into absolute paths so gdb, Symbolication can later find them
                        char realPath[MAXPATHLEN];
                        // rdar://problem/5135363 turn relative paths into absolute paths so gdb, Symbolication can later find them
                        char realPath[MAXPATHLEN];
-                       if ( realpath(path, realPath) != NULL )
-                               image->setPath(realPath);
+                       if ( fcntl(fd, F_GETPATH, realPath) == 0 ) 
+                               image->setPaths(path, realPath);
                        else
                                image->setPath(path);
                }
                        else
                                image->setPath(path);
                }
@@ -729,33 +719,6 @@ uintptr_t ImageLoaderMachOClassic::getRelocBase()
 }
 
 
 }
 
 
-#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);
-       //dyld::log("dyld: ppc fixup %0p type %d from 0x%08X to 0x%08X\n", locationToFix, relocationType, before, after);
-}
-#endif
-
 #if PREBOUND_IMAGE_SUPPORT
 void ImageLoaderMachOClassic::resetPreboundLazyPointers(const LinkContext& context)
 {
 #if PREBOUND_IMAGE_SUPPORT
 void ImageLoaderMachOClassic::resetPreboundLazyPointers(const LinkContext& context)
 {
@@ -770,11 +733,6 @@ void ImageLoaderMachOClassic::resetPreboundLazyPointers(const LinkContext& conte
                        if (sreloc->r_length == RELOC_SIZE) {
                                uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
                                switch(sreloc->r_type) {
                        if (sreloc->r_length == RELOC_SIZE) {
                                uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
                                switch(sreloc->r_type) {
-               #if __ppc__ 
-                                       case PPC_RELOC_PB_LA_PTR:
-                                               *locationToFix = sreloc->r_value + slide;
-                                               break;
-               #endif
                #if __i386__
                                        case GENERIC_RELOC_PB_LA_PTR:
                                                *locationToFix = sreloc->r_value + slide;
                #if __i386__
                                        case GENERIC_RELOC_PB_LA_PTR:
                                                *locationToFix = sreloc->r_value + slide;
@@ -809,6 +767,7 @@ void ImageLoaderMachOClassic::rebase(const LinkContext& context)
        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) {
        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) {
+               uintptr_t rebaseAddr;
                try {
        #if LINKEDIT_USAGE_DEBUG
                        noteAccessedLinkEditAddress(reloc);
                try {
        #if LINKEDIT_USAGE_DEBUG
                        noteAccessedLinkEditAddress(reloc);
@@ -823,7 +782,12 @@ void ImageLoaderMachOClassic::rebase(const LinkContext& context)
                                throw "bad local relocation pc_rel";
                        if ( reloc->r_extern != 0 ) 
                                throw "extern relocation found with local relocations";
                                throw "bad local relocation pc_rel";
                        if ( reloc->r_extern != 0 ) 
                                throw "extern relocation found with local relocations";
-                       *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
+                       rebaseAddr = reloc->r_address + relocBase;
+                       if ( ! this->containsAddress((void*)rebaseAddr) )
+                               dyld::throwf("local reloc %p not in mapped image\n", (void*)rebaseAddr);
+                       *((uintptr_t*)rebaseAddr) += slide;
+                       if ( context.verboseRebase )
+                               dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), rebaseAddr, slide);
                #else   
                        if ( (reloc->r_address & R_SCATTERED) == 0 ) {
                                if ( reloc->r_symbolnum == R_ABS ) {
                #else   
                        if ( (reloc->r_address & R_SCATTERED) == 0 ) {
                                if ( reloc->r_symbolnum == R_ABS ) {
@@ -832,17 +796,13 @@ void ImageLoaderMachOClassic::rebase(const LinkContext& context)
                                else if (reloc->r_length == RELOC_SIZE) {
                                        switch(reloc->r_type) {
                                                case GENERIC_RELOC_VANILLA:
                                else if (reloc->r_length == RELOC_SIZE) {
                                        switch(reloc->r_type) {
                                                case GENERIC_RELOC_VANILLA:
-                                                       *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
+                                                       rebaseAddr = reloc->r_address + relocBase;
+                                                       if ( ! this->containsAddress((void*)rebaseAddr) )
+                                                               dyld::throwf("local reloc %p not in mapped image\n", (void*)rebaseAddr);
+                                                       *((uintptr_t*)rebaseAddr) += slide;
+                                                       if ( context.verboseRebase )
+                                                               dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), rebaseAddr, slide);
                                                        break;
                                                        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";
                                        }
                                                default:
                                                        throw "unknown local relocation type";
                                        }
@@ -857,26 +817,13 @@ void ImageLoaderMachOClassic::rebase(const LinkContext& context)
                                        uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
                                        switch(sreloc->r_type) {
                                                case GENERIC_RELOC_VANILLA:
                                        uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
                                        switch(sreloc->r_type) {
                                                case GENERIC_RELOC_VANILLA:
+                                                       if ( ! this->containsAddress((void*)locationToFix) ) 
+                                                               dyld::throwf("local scattered reloc %p not in mapped image\n", locationToFix);
                                                        *locationToFix += slide;
                                                        *locationToFix += slide;
+                                                       if ( context.verboseRebase )
+                                                               dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), (uintptr_t)locationToFix, slide);
                                                        break;
                                                        break;
-                       #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;
-                                               case PPC_RELOC_PB_LA_PTR:
-                                                       // do nothing
-                                                       break;
-                       #elif __ppc64__
-                                               case PPC_RELOC_PB_LA_PTR:
-                                                       // needed for compatibility with ppc64 binaries built with the first ld64
-                                                       // which used PPC_RELOC_PB_LA_PTR relocs instead of GENERIC_RELOC_VANILLA for lazy pointers
-                                                       *locationToFix += slide;
-                                                       break;
-                       #elif __i386__
+                       #if __i386__
                                                case GENERIC_RELOC_PB_LA_PTR:
                                                        // do nothing
                                                        break;
                                                case GENERIC_RELOC_PB_LA_PTR:
                                                        // do nothing
                                                        break;
@@ -932,7 +879,7 @@ const struct macho_nlist* ImageLoaderMachOClassic::binarySearchWithToc(const cha
                noteAccessedLinkEditAddress(pivot);
                noteAccessedLinkEditAddress(pivotStr);
 #endif
                noteAccessedLinkEditAddress(pivot);
                noteAccessedLinkEditAddress(pivotStr);
 #endif
-               int cmp = astrcmp(key, pivotStr);
+               int cmp = strcmp(key, pivotStr);
                if ( cmp == 0 )
                        return pivot;
                if ( cmp > 0 ) {
                if ( cmp == 0 )
                        return pivot;
                if ( cmp > 0 ) {
@@ -964,7 +911,7 @@ const struct macho_nlist* ImageLoaderMachOClassic::binarySearch(const char* key,
                noteAccessedLinkEditAddress(pivot);
                noteAccessedLinkEditAddress(pivotStr);
 #endif
                noteAccessedLinkEditAddress(pivot);
                noteAccessedLinkEditAddress(pivotStr);
 #endif
-               int cmp = astrcmp(key, pivotStr);
+               int cmp = strcmp(key, pivotStr);
                if ( cmp == 0 )
                        return pivot;
                if ( cmp > 0 ) {
                if ( cmp == 0 )
                        return pivot;
                if ( cmp > 0 ) {
@@ -1266,6 +1213,8 @@ void ImageLoaderMachOClassic::doBindExternalRelocations(const LinkContext& conte
                                        {
                                                const struct macho_nlist* undefinedSymbol = &fSymbolTable[reloc->r_symbolnum];
                                                uintptr_t* location = ((uintptr_t*)(reloc->r_address + relocBase));
                                        {
                                                const struct macho_nlist* undefinedSymbol = &fSymbolTable[reloc->r_symbolnum];
                                                uintptr_t* location = ((uintptr_t*)(reloc->r_address + relocBase));
+                                               if ( ! this->containsAddress((void*)location) )
+                                                       dyld::throwf("external reloc %p not in mapped image %s\n", (void*)location, this->getPath());
                                                uintptr_t value = *location;
                                                bool symbolAddrCached = true;
                                        #if __i386__
                                                uintptr_t value = *location;
                                                bool symbolAddrCached = true;
                                        #if __i386__
index dda3e8af74dfc2c370bea6c486f717287066d5c8..2d0cca2446e7b5c99aa47090af30f3a03a50d380 100644 (file)
@@ -87,7 +87,7 @@ static intptr_t read_sleb128(const uint8_t*& p, const uint8_t* end)
                if (p == end)
                        throw "malformed sleb128";
                byte = *p++;
                if (p == end)
                        throw "malformed sleb128";
                byte = *p++;
-               result |= ((byte & 0x7f) << bit);
+               result |= (((int64_t)(byte & 0x7f)) << bit);
                bit += 7;
        } while (byte & 0x80);
        // sign extend negative numbers
                bit += 7;
        } while (byte & 0x80);
        // sign extend negative numbers
@@ -161,11 +161,12 @@ ImageLoaderMachOCompressed* ImageLoaderMachOCompressed::instantiateFromFile(cons
                else if ( (installName != NULL) && (strcmp(path, "/usr/lib/libgcc_s.1.dylib") == 0) && (strcmp(installName, "/usr/lib/libSystem.B.dylib") == 0) )
                        image->setPathUnowned("/usr/lib/libSystem.B.dylib");
 #endif
                else if ( (installName != NULL) && (strcmp(path, "/usr/lib/libgcc_s.1.dylib") == 0) && (strcmp(installName, "/usr/lib/libSystem.B.dylib") == 0) )
                        image->setPathUnowned("/usr/lib/libSystem.B.dylib");
 #endif
-               else if ( path[0] != '/' ) {
+               else if ( (path[0] != '/') || (strstr(path, "../") != NULL) ) {
+                       // rdar://problem/10733082 Fix up @rpath based paths during introspection
                        // rdar://problem/5135363 turn relative paths into absolute paths so gdb, Symbolication can later find them
                        char realPath[MAXPATHLEN];
                        // rdar://problem/5135363 turn relative paths into absolute paths so gdb, Symbolication can later find them
                        char realPath[MAXPATHLEN];
-                       if ( realpath(path, realPath) != NULL )
-                               image->setPath(realPath);
+                       if ( fcntl(fd, F_GETPATH, realPath) == 0 ) 
+                               image->setPaths(path, realPath);
                        else
                                image->setPath(path);
                }
                        else
                                image->setPath(path);
                }
@@ -204,7 +205,6 @@ ImageLoaderMachOCompressed* ImageLoaderMachOCompressed::instantiateFromCache(con
 
                // remember this is from shared cache and cannot be unloaded
                image->fInSharedCache = true;
 
                // remember this is from shared cache and cannot be unloaded
                image->fInSharedCache = true;
-               image->fGoodFirstSegment = true;
                image->setNeverUnload();
                image->setSlide(slide);
 
                image->setNeverUnload();
                image->setSlide(slide);
 
@@ -393,6 +393,9 @@ void ImageLoaderMachOCompressed::markLINKEDIT(const LinkContext& context, int ad
 
 void ImageLoaderMachOCompressed::rebaseAt(const LinkContext& context, uintptr_t addr, uintptr_t slide, uint8_t type)
 {
 
 void ImageLoaderMachOCompressed::rebaseAt(const LinkContext& context, uintptr_t addr, uintptr_t slide, uint8_t type)
 {
+       if ( context.verboseRebase ) {
+               dyld::log("dyld: rebase: %s:*0x%08lX += 0x%08lX\n", this->getShortName(), (uintptr_t)addr, slide);
+       }
        //dyld::log("0x%08lX type=%d\n", addr, type);
        uintptr_t* locationToFix = (uintptr_t*)addr;
        switch (type) {
        //dyld::log("0x%08lX type=%d\n", addr, type);
        uintptr_t* locationToFix = (uintptr_t*)addr;
        switch (type) {
@@ -637,7 +640,18 @@ uintptr_t ImageLoaderMachOCompressed::exportedSymbolAddress(const LinkContext& c
        if ( (flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_REGULAR ) {
                if ( runResolver && (flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) ) {
                        // this node has a stub and resolver, run the resolver to get target address
        if ( (flags & EXPORT_SYMBOL_FLAGS_KIND_MASK) == EXPORT_SYMBOL_FLAGS_KIND_REGULAR ) {
                if ( runResolver && (flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) ) {
                        // this node has a stub and resolver, run the resolver to get target address
-                       read_uleb128(exportNode, exportTrieEnd); // skip over stub
+                       uintptr_t stub = read_uleb128(exportNode, exportTrieEnd) + (uintptr_t)fMachOData; // skip over stub
+                       // <rdar://problem/10657737> interposing dylibs have the stub address as their replacee
+                       for (std::vector<InterposeTuple>::iterator it=fgInterposingTuples.begin(); it != fgInterposingTuples.end(); it++) {
+                               // replace all references to 'replacee' with 'replacement'
+                               if ( stub == it->replacee ) {
+                                       if ( context.verboseInterposing ) {
+                                               dyld::log("dyld interposing: lazy replace 0x%lX with 0x%lX from %s\n", 
+                                                                 it->replacee, it->replacement, this->getPath());
+                                       }
+                                       return it->replacement;
+                               }
+                       }
                        typedef uintptr_t (*ResolverProc)(void);
                        ResolverProc resolver = (ResolverProc)(read_uleb128(exportNode, exportTrieEnd) + (uintptr_t)fMachOData);
                        uintptr_t result = (*resolver)();
                        typedef uintptr_t (*ResolverProc)(void);
                        ResolverProc resolver = (ResolverProc)(read_uleb128(exportNode, exportTrieEnd) + (uintptr_t)fMachOData);
                        uintptr_t result = (*resolver)();
index 31265a9b7bad6c984fd1d600658aeec4b90a78e4..6854ef51f92ec64e809ef04a361c0112b0672774 100644 (file)
 #ifndef CPU_SUBTYPE_ARM_V7
        #define CPU_SUBTYPE_ARM_V7                      ((cpu_subtype_t) 9)
 #endif
 #ifndef CPU_SUBTYPE_ARM_V7
        #define CPU_SUBTYPE_ARM_V7                      ((cpu_subtype_t) 9)
 #endif
+#ifndef CPU_SUBTYPE_ARM_V7F
+       #define CPU_SUBTYPE_ARM_V7F                     ((cpu_subtype_t) 10)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7S
+       #define CPU_SUBTYPE_ARM_V7S                     ((cpu_subtype_t) 11)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7K
+       #define CPU_SUBTYPE_ARM_V7K                     ((cpu_subtype_t) 12)
+#endif
 #ifndef LC_DYLD_ENVIRONMENT
        #define LC_DYLD_ENVIRONMENT                     0x27
 #endif
 #ifndef LC_DYLD_ENVIRONMENT
        #define LC_DYLD_ENVIRONMENT                     0x27
 #endif
@@ -91,8 +100,8 @@ extern "C" char *                    _simple_string(_SIMPLE_STRING __b);
 
 
 
 
 
 
-// 32-bit ppc and ARM are the only architecture that use cpu-sub-types
-#define CPU_SUBTYPES_SUPPORTED __ppc__ || __arm__
+// ARM is the only architecture that use cpu-sub-types
+#define CPU_SUBTYPES_SUPPORTED  __arm__
 
 
 
 
 
 
@@ -113,6 +122,8 @@ extern "C" {
 // implemented in dyldStartup.s for CrashReporter
 extern "C" void dyld_fatal_error(const char* errString) __attribute__((noreturn));
 
 // implemented in dyldStartup.s for CrashReporter
 extern "C" void dyld_fatal_error(const char* errString) __attribute__((noreturn));
 
+// magic linker symbol for start of dyld binary
+extern "C" void* __dso_handle;
 
 
 //
 
 
 //
@@ -175,6 +186,8 @@ typedef std::vector<dyld_image_state_change_handler> StateHandlers;
 struct RegisteredDOF { const mach_header* mh; int registrationID; };
 struct DylibOverride { const char* installName; const char* override; };
 
 struct RegisteredDOF { const mach_header* mh; int registrationID; };
 struct DylibOverride { const char* installName; const char* override; };
 
+enum RestrictedReason { restrictedNot, restrictedBySetGUid, restrictedBySegment, restrictedByEntitlements };
+       
 // all global state
 static const char*                                     sExecPath = NULL;
 static const macho_header*                     sMainExecutableMachHeader = NULL;
 // all global state
 static const char*                                     sExecPath = NULL;
 static const macho_header*                     sMainExecutableMachHeader = NULL;
@@ -184,6 +197,7 @@ static cpu_subtype_t                                sHostCPUsubtype;
 #endif
 static ImageLoader*                                    sMainExecutable = NULL;
 static bool                                                    sProcessIsRestricted = false;
 #endif
 static ImageLoader*                                    sMainExecutable = NULL;
 static bool                                                    sProcessIsRestricted = false;
+static RestrictedReason                        sRestrictedReason = restrictedNot;
 static unsigned int                                    sInsertedDylibCount = 0;
 static std::vector<ImageLoader*>       sAllImages;
 static std::vector<ImageLoader*>       sImageRoots;
 static unsigned int                                    sInsertedDylibCount = 0;
 static std::vector<ImageLoader*>       sAllImages;
 static std::vector<ImageLoader*>       sImageRoots;
@@ -334,6 +348,7 @@ void throwf(const char* format, ...)
 
 
 //#define ALTERNATIVE_LOGFILE "/dev/console"
 
 
 //#define ALTERNATIVE_LOGFILE "/dev/console"
+
 static int sLogfile = STDERR_FILENO;
 
 #if LOG_BINDINGS
 static int sLogfile = STDERR_FILENO;
 
 #if LOG_BINDINGS
@@ -429,19 +444,8 @@ FileOpener::~FileOpener()
 }
 
 
 }
 
 
-// forward declaration
-#if __ppc__ || __i386__
-bool isRosetta();
-#endif
-
-
 static void    registerDOFs(const std::vector<ImageLoader::DOFInfo>& dofs)
 {
 static void    registerDOFs(const std::vector<ImageLoader::DOFInfo>& dofs)
 {
-#if __ppc__
-       // can't dtrace a program running emulated under rosetta rdar://problem/5179640
-       if ( isRosetta() )
-               return;
-#endif
        const unsigned int dofSectionCount = dofs.size();
        if ( !sEnv.DYLD_DISABLE_DOFS && (dofSectionCount != 0) ) {
                int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
        const unsigned int dofSectionCount = dofs.size();
        if ( !sEnv.DYLD_DISABLE_DOFS && (dofSectionCount != 0) ) {
                int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
@@ -560,7 +564,7 @@ static void notifySingle(dyld_image_states state, const ImageLoader* image)
        if ( handlers != NULL ) {
                dyld_image_info info;
                info.imageLoadAddress   = image->machHeader();
        if ( handlers != NULL ) {
                dyld_image_info info;
                info.imageLoadAddress   = image->machHeader();
-               info.imageFilePath              = image->getPath();
+               info.imageFilePath              = image->getRealPath();
                info.imageFileModDate   = image->lastModified();
                for (std::vector<dyld_image_state_change_handler>::iterator it = handlers->begin(); it != handlers->end(); ++it) {
                        const char* result = (*it)(state, 1, &info);
                info.imageFileModDate   = image->lastModified();
                for (std::vector<dyld_image_state_change_handler>::iterator it = handlers->begin(); it != handlers->end(); ++it) {
                        const char* result = (*it)(state, 1, &info);
@@ -616,7 +620,7 @@ void syncAllImages()
                dyld_image_info info;
                ImageLoader* image = *it;
                info.imageLoadAddress = image->machHeader();
                dyld_image_info info;
                ImageLoader* image = *it;
                info.imageLoadAddress = image->machHeader();
-               info.imageFilePath = image->getPath();
+               info.imageFilePath = image->getRealPath();
                info.imageFileModDate = image->lastModified();
                // add to all_image_infos if not already there
                bool found = false;
                info.imageFileModDate = image->lastModified();
                // add to all_image_infos if not already there
                bool found = false;
@@ -676,7 +680,7 @@ static void notifyBatchPartial(dyld_image_states state, bool orLater, dyld_image
                                ImageLoader* image = images[i];
                                //dyld::log("  state=%d, name=%s\n", state, image->getPath());
                                p->imageLoadAddress = image->machHeader();
                                ImageLoader* image = images[i];
                                //dyld::log("  state=%d, name=%s\n", state, image->getPath());
                                p->imageLoadAddress = image->machHeader();
-                               p->imageFilePath = image->getPath();
+                               p->imageFilePath = image->getRealPath();
                                p->imageFileModDate = image->lastModified();
                                // special case for add_image hook
                                if ( state == dyld_image_state_bound )
                                p->imageFileModDate = image->lastModified();
                                // special case for add_image hook
                                if ( state == dyld_image_state_bound )
@@ -758,6 +762,13 @@ static void clearAllDepths()
                (*it)->clearDepth();
 }
 
                (*it)->clearDepth();
 }
 
+static void printAllDepths()
+{
+       for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++)
+               dyld::log("%03d %s\n",  (*it)->getDepth(), (*it)->getShortName());
+}
+
+
 static unsigned int imageCount()
 {
        return sAllImages.size();
 static unsigned int imageCount()
 {
        return sAllImages.size();
@@ -949,16 +960,23 @@ ImageLoader* mainExecutable()
 
 void runTerminators(void* extra)
 {
 
 void runTerminators(void* extra)
 {
-       const unsigned int imageCount = sImageFilesNeedingTermination.size();
-       for(unsigned int i=imageCount; i > 0; --i){
-               ImageLoader* image = sImageFilesNeedingTermination[i-1];
-               image->doTermination(gLinkContext);
+       try {
+               const unsigned int imageCount = sImageFilesNeedingTermination.size();
+               for(unsigned int i=imageCount; i > 0; --i){
+                       ImageLoader* image = sImageFilesNeedingTermination[i-1];
+                       image->doTermination(gLinkContext);
+               }
+               sImageFilesNeedingTermination.clear();
+               notifyBatch(dyld_image_state_terminated);
+       }
+       catch (const char* msg) {
+               halt(msg);
        }
        }
-       sImageFilesNeedingTermination.clear();
-       notifyBatch(dyld_image_state_terminated);
 }
 
 
 }
 
 
+#if SUPPORT_VERSIONED_PATHS
+
 // forward reference
 static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* version, char* installName);
 
 // forward reference
 static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* version, char* installName);
 
@@ -1068,6 +1086,8 @@ static void checkFrameworkOverridesInDir(const char* dirPath)
                closedir(dirp);
        }
 }
                closedir(dirp);
        }
 }
+#endif // SUPPORT_VERSIONED_PATHS
+
 
 //
 // Turns a colon separated list of strings into a NULL terminated array 
 
 //
 // Turns a colon separated list of strings into a NULL terminated array 
@@ -1480,6 +1500,22 @@ static void pruneEnvironmentVariables(const char* envp[], const char*** applep)
                }
        }
        *d++ = NULL;
                }
        }
        *d++ = NULL;
+       if ( removedCount != 0 ) {
+               dyld::log("dyld: DYLD_ environment variables being ignored because ");
+               switch (sRestrictedReason) {
+                       case restrictedNot:
+                               break;
+                       case restrictedBySetGUid:
+                               dyld::log("main executable (%s) is setuid or setgid\n", sExecPath);
+                               break;
+                       case restrictedBySegment:
+                               dyld::log("main executable (%s) has __RESTRICT/__restrict section\n", sExecPath);
+                               break;
+                       case restrictedByEntitlements:
+                               dyld::log("main executable (%s) is code signed with entitlements\n", sExecPath);
+                               break;
+               }
+       }
        
        // slide apple parameters
        if ( removedCount > 0 ) {
        
        // slide apple parameters
        if ( removedCount > 0 ) {
@@ -1562,6 +1598,15 @@ static void getHostInfo()
 #elif __ARM_ARCH_6K__
        sHostCPU                = CPU_TYPE_ARM;
        sHostCPUsubtype = CPU_SUBTYPE_ARM_V6;
 #elif __ARM_ARCH_6K__
        sHostCPU                = CPU_TYPE_ARM;
        sHostCPUsubtype = CPU_SUBTYPE_ARM_V6;
+#elif __ARM_ARCH_7F__
+       sHostCPU                = CPU_TYPE_ARM;
+       sHostCPUsubtype = CPU_SUBTYPE_ARM_V7F;
+#elif __ARM_ARCH_7S__
+       sHostCPU                = CPU_TYPE_ARM;
+       sHostCPUsubtype = CPU_SUBTYPE_ARM_V7S;
+#elif __ARM_ARCH_7K__
+       sHostCPU                = CPU_TYPE_ARM;
+       sHostCPUsubtype = CPU_SUBTYPE_ARM_V7K;
 #else
        struct host_basic_info info;
        mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
 #else
        struct host_basic_info info;
        mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
@@ -1742,31 +1787,19 @@ const cpu_subtype_t CPU_SUBTYPE_END_OF_LIST = -1;
 //
 
 
 //
 
 
-#if __ppc__
-//      
-//     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 }
-};
-#endif
-
-
 #if __arm__
 //      
 //     ARM sub-type lists
 //
 #if __arm__
 //      
 //     ARM sub-type lists
 //
-const int kARM_RowCount = 5;
-static const cpu_subtype_t kARM[kARM_RowCount][6] = { 
+const int kARM_RowCount = 8;
+static const cpu_subtype_t kARM[kARM_RowCount][9] = { 
+
+       // armv7f can run: v7f, v7, v6, v5, and v4
+       {  CPU_SUBTYPE_ARM_V7F, CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
+
+       // armv7k can run: v7k, v6, v5, and v4
+       {  CPU_SUBTYPE_ARM_V7K, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
+
        // armv7 can run: v7, v6, v5, and v4
        {  CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
        
        // armv7 can run: v7, v6, v5, and v4
        {  CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
        
@@ -1789,14 +1822,6 @@ static const cpu_subtype_t kARM[kARM_RowCount][6] = {
 static const cpu_subtype_t* findCPUSubtypeList(cpu_type_t cpu, cpu_subtype_t subtype)
 {
        switch (cpu) {
 static const cpu_subtype_t* findCPUSubtypeList(cpu_type_t cpu, cpu_subtype_t subtype)
 {
        switch (cpu) {
-#if __ppc__
-               case CPU_TYPE_POWERPC:
-                       for (int i=0; i < kPPC_RowCount ; ++i) {
-                               if ( kPPC32[i][0] == subtype )
-                                       return kPPC32[i];
-                       }
-                       break;
-#endif
 #if __arm__
                case CPU_TYPE_ARM:
                        for (int i=0; i < kARM_RowCount ; ++i) {
 #if __arm__
                case CPU_TYPE_ARM:
                        for (int i=0; i < kARM_RowCount ; ++i) {
@@ -1851,15 +1876,6 @@ static bool fatFindRunsOnAllCPUs(cpu_type_t cpu, const fat_header* fh, uint64_t*
        for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
                if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu) {
                        switch (cpu) {
        for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
                if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu) {
                        switch (cpu) {
-#if __ppc__
-                               case CPU_TYPE_POWERPC:
-                                       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;
-#endif
 #if __arm__
                                case CPU_TYPE_ARM:
                                        if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_ARM_ALL ) {
 #if __arm__
                                case CPU_TYPE_ARM:
                                        if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_ARM_ALL ) {
@@ -1952,12 +1968,6 @@ bool isCompatibleMachO(const uint8_t* firstPage, const char* path)
                        
                        // cpu type has no ordered list of subtypes
                        switch (mh->cputype) {
                        
                        // cpu type has no ordered list of subtypes
                        switch (mh->cputype) {
-                               case CPU_TYPE_POWERPC:
-                                       // allow _ALL to be used by any client
-                                       if ( mh->cpusubtype == CPU_SUBTYPE_POWERPC_ALL ) 
-                                               return true;
-                                       break;
-                               case CPU_TYPE_POWERPC64:
                                case CPU_TYPE_I386:
                                case CPU_TYPE_X86_64:
                                        // subtypes are not used or these architectures
                                case CPU_TYPE_I386:
                                case CPU_TYPE_X86_64:
                                        // subtypes are not used or these architectures
@@ -2257,6 +2267,7 @@ static ImageLoader* loadPhase5stat(const char* path, const LoadContext& context,
 {
        ImageLoader* image = NULL;
        *imageFound = false;
 {
        ImageLoader* image = NULL;
        *imageFound = false;
+       *statErrNo = 0;
        if ( stat(path, stat_buf) == 0 ) {
                // in case image was renamed or found via symlinks, check for inode match
                image = findLoadedImage(*stat_buf);
        if ( stat(path, stat_buf) == 0 ) {
                // in case image was renamed or found via symlinks, check for inode match
                image = findLoadedImage(*stat_buf);
@@ -2304,7 +2315,7 @@ static ImageLoader* loadPhase5load(const char* path, const char* orgPath, const
                // see if this image in the cache was already loaded via a different path
                for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); ++it) {
                        ImageLoader* anImage = *it;
                // see if this image in the cache was already loaded via a different path
                for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); ++it) {
                        ImageLoader* anImage = *it;
-                       if ( anImage->machHeader() == mhInCache )
+                       if ( (const macho_header*)anImage->machHeader() == mhInCache )
                                return anImage;
                }
                // do nothing if not already loaded and if RTLD_NOLOAD 
                                return anImage;
                }
                // do nothing if not already loaded and if RTLD_NOLOAD 
@@ -2329,7 +2340,7 @@ static ImageLoader* loadPhase5load(const char* path, const char* orgPath, const
                return image;
 #endif
        // just return NULL if file not found, but record any other errors
                return image;
 #endif
        // just return NULL if file not found, but record any other errors
-       if ( statErrNo != ENOENT ) {
+       if ( (statErrNo != ENOENT) && (statErrNo != 0) ) {
                exceptions->push_back(dyld::mkstringf("%s: stat() failed with errno=%d", path, statErrNo));
        }
        return NULL;
                exceptions->push_back(dyld::mkstringf("%s: stat() failed with errno=%d", path, statErrNo));
        }
        return NULL;
@@ -2711,20 +2722,11 @@ ImageLoader* load(const char* path, const LoadContext& context)
 
 
 
 
 
 
-
 #if DYLD_SHARED_CACHE_SUPPORT
 
 
 
 #if DYLD_SHARED_CACHE_SUPPORT
 
 
 
-
-#if __ppc__
-       #define ARCH_NAME                       "ppc"
-       #define ARCH_NAME_ROSETTA       "rosetta"
-       #define ARCH_CACHE_MAGIC        "dyld_v1     ppc"
-#elif __ppc64__
-       #define ARCH_NAME                       "ppc64"
-       #define ARCH_CACHE_MAGIC        "dyld_v1   ppc64"
-#elif __i386__
+#if __i386__
        #define ARCH_NAME                       "i386"
        #define ARCH_CACHE_MAGIC        "dyld_v1    i386"
 #elif __x86_64__
        #define ARCH_NAME                       "i386"
        #define ARCH_CACHE_MAGIC        "dyld_v1    i386"
 #elif __x86_64__
@@ -2741,6 +2743,14 @@ ImageLoader* load(const char* path, const LoadContext& context)
 #elif __ARM_ARCH_6K__
        #define ARCH_NAME                       "armv6"
        #define ARCH_CACHE_MAGIC        "dyld_v1   armv6"
 #elif __ARM_ARCH_6K__
        #define ARCH_NAME                       "armv6"
        #define ARCH_CACHE_MAGIC        "dyld_v1   armv6"
+#elif __ARM_ARCH_7F__
+       #define ARCH_NAME                       "armv7f"
+       #define ARCH_CACHE_MAGIC        "dyld_v1  armv7f"
+       #define SHARED_REGION_READ_ONLY_START   0x30000000
+       #define SHARED_REGION_READ_ONLY_END     0x3E000000
+       #define SHARED_REGION_WRITABLE_START    0x3E000000
+       #define SHARED_REGION_WRITABLE_END      0x40000000
+       #define SLIDEABLE_CACHE_SUPPORT             1
 #elif __ARM_ARCH_7A__
        #define ARCH_NAME                       "armv7"
        #define ARCH_CACHE_MAGIC        "dyld_v1   armv7"
 #elif __ARM_ARCH_7A__
        #define ARCH_NAME                       "armv7"
        #define ARCH_CACHE_MAGIC        "dyld_v1   armv7"
@@ -2749,12 +2759,20 @@ ImageLoader* load(const char* path, const LoadContext& context)
        #define SHARED_REGION_WRITABLE_START    0x3E000000
        #define SHARED_REGION_WRITABLE_END      0x40000000
        #define SLIDEABLE_CACHE_SUPPORT             1
        #define SHARED_REGION_WRITABLE_START    0x3E000000
        #define SHARED_REGION_WRITABLE_END      0x40000000
        #define SLIDEABLE_CACHE_SUPPORT             1
+#elif __ARM_ARCH_7K__
+       #define ARCH_NAME                       "armv7k"
+       #define ARCH_CACHE_MAGIC        "dyld_v1  armv7k"
+       #define SHARED_REGION_READ_ONLY_START   0x30000000
+       #define SHARED_REGION_READ_ONLY_END     0x3E000000
+       #define SHARED_REGION_WRITABLE_START    0x3E000000
+       #define SHARED_REGION_WRITABLE_END      0x40000000
+       #define SLIDEABLE_CACHE_SUPPORT             1
 #endif
 
 
 static int __attribute__((noinline)) _shared_region_check_np(uint64_t* start_address)
 {
 #endif
 
 
 static int __attribute__((noinline)) _shared_region_check_np(uint64_t* start_address)
 {
-       if ( (gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion) ) 
+       if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion ) 
                return syscall(294, start_address);
        return -1;
 }
                return syscall(294, start_address);
        return -1;
 }
@@ -2775,7 +2793,7 @@ static int __attribute__((noinline)) _shared_region_map_and_slide_np(int fd, uin
                        dyld::log("dyld: code signature for shared cache failed with errno=%d\n", errno);
        }
 #endif
                        dyld::log("dyld: code signature for shared cache failed with errno=%d\n", errno);
        }
 #endif
-       if ( (gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion) ) {
+       if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion ) {
                return syscall(438, fd, count, mappings, slide, slideInfo, slideInfoSize);
        }
 
                return syscall(438, fd, count, mappings, slide, slideInfo, slideInfoSize);
        }
 
@@ -2861,13 +2879,7 @@ int openSharedCacheFile()
        char path[1024];
        strcpy(path, sSharedCacheDir);
        strcat(path, "/");
        char path[1024];
        strcpy(path, sSharedCacheDir);
        strcat(path, "/");
-#if __ppc__
-       // rosetta cannot handle optimized _ppc cache, so it use _rosetta cache instead, rdar://problem/5495438
-    if ( isRosetta() )
-               strcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_ROSETTA);
-    else
-#endif
-               strcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME);
+       strcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME);
        return ::open(path, O_RDONLY);
 }
 
        return ::open(path, O_RDONLY);
 }
 
@@ -3158,8 +3170,7 @@ static void mapSharedCache()
                // check for file that enables dyld shared cache dylibs to be overridden
                struct stat enableStatBuf;
                sDylibsOverrideCache = ( ::stat(IPHONE_DYLD_SHARED_CACHE_DIR "enable-dylibs-to-override-cache", &enableStatBuf) == 0 );
                // check for file that enables dyld shared cache dylibs to be overridden
                struct stat enableStatBuf;
                sDylibsOverrideCache = ( ::stat(IPHONE_DYLD_SHARED_CACHE_DIR "enable-dylibs-to-override-cache", &enableStatBuf) == 0 );
-#endif         
-
+#endif 
        }
 }
 #endif // #if DYLD_SHARED_CACHE_SUPPORT
        }
 }
 #endif // #if DYLD_SHARED_CACHE_SUPPORT
@@ -3475,14 +3486,19 @@ void registerImageStateSingleChangeHandler(dyld_image_states state, dyld_image_s
        // add to list of handlers
        std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sSingleHandlers);
        if ( handlers != NULL ) {
        // add to list of handlers
        std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sSingleHandlers);
        if ( handlers != NULL ) {
-               handlers->push_back(handler);
+        // <rdar://problem/10332417> need updateAllImages() to be last in dyld_image_state_mapped list
+        // so that if ObjC adds a handler that prevents a load, it happens before the gdb list is updated
+        if ( state == dyld_image_state_mapped )
+            handlers->insert(handlers->begin(), handler);
+        else
+            handlers->push_back(handler);
 
                // call callback with all existing images
                for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
                        ImageLoader* image = *it;
                        dyld_image_info  info;
                        info.imageLoadAddress   = image->machHeader();
 
                // call callback with all existing images
                for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
                        ImageLoader* image = *it;
                        dyld_image_info  info;
                        info.imageLoadAddress   = image->machHeader();
-                       info.imageFilePath              = image->getPath();
+                       info.imageFilePath              = image->getRealPath();
                        info.imageFileModDate   = image->lastModified();
                        // should only call handler if state == image->state
                        if ( image->getState() == state )
                        info.imageFileModDate   = image->lastModified();
                        // should only call handler if state == image->state
                        if ( image->getState() == state )
@@ -3557,6 +3573,7 @@ static void setContext(const macho_header* mainExecutableMH, int argc, const cha
        gLinkContext.removeImage                        = &removeImage;
        gLinkContext.registerDOFs                       = &registerDOFs;
        gLinkContext.clearAllDepths                     = &clearAllDepths;
        gLinkContext.removeImage                        = &removeImage;
        gLinkContext.registerDOFs                       = &registerDOFs;
        gLinkContext.clearAllDepths                     = &clearAllDepths;
+       gLinkContext.printAllDepths                     = &printAllDepths;
        gLinkContext.imageCount                         = &imageCount;
        gLinkContext.setNewProgramVars          = &setNewProgramVars;
 #if DYLD_SHARED_CACHE_SUPPORT
        gLinkContext.imageCount                         = &imageCount;
        gLinkContext.setNewProgramVars          = &setNewProgramVars;
 #if DYLD_SHARED_CACHE_SUPPORT
@@ -3583,21 +3600,6 @@ static void setContext(const macho_header* mainExecutableMH, int argc, const cha
        gLinkContext.sharedRegionMode           = ImageLoader::kUseSharedRegion;
 }
 
        gLinkContext.sharedRegionMode           = ImageLoader::kUseSharedRegion;
 }
 
-#if __ppc__ || __i386__
-bool isRosetta()
-{
-       int mib[] = { CTL_KERN, KERN_CLASSIC, getpid() };
-       int is_classic = 0;
-       size_t len = sizeof(int);
-       int ret = sysctl(mib, 3, &is_classic, &len, NULL, 0);
-       if ((ret != -1) && is_classic) {
-               // we're running under Rosetta 
-               return true;
-       }
-       return false;
-}
-#endif
-
 
 #if __LP64__
        #define LC_SEGMENT_COMMAND              LC_SEGMENT_64
 
 #if __LP64__
        #define LC_SEGMENT_COMMAND              LC_SEGMENT_64
@@ -3644,7 +3646,7 @@ static bool hasRestrictedSegment(const macho_header* mh)
        return false;
 }
 
        return false;
 }
 
-
+#if SUPPORT_VERSIONED_PATHS
 //
 // Peeks at a dylib file and returns its current_version and install_name.
 // Returns false on error.
 //
 // Peeks at a dylib file and returns its current_version and install_name.
 // Returns false on error.
@@ -3706,7 +3708,8 @@ static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* versi
        
        return false;
 }
        
        return false;
 }
-                                                               
+#endif // SUPPORT_VERSIONED_PATHS
+                                               
 #if 0
 static void printAllImages()
 {
 #if 0
 static void printAllImages()
 {
@@ -3758,8 +3761,14 @@ void garbageCollectImages()
                for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
                        ImageLoader* image = *it;
                        if ( (image->referenceCount() == 0) && !image->neverUnload() && !image->isBeingRemoved() ) {
                for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
                        ImageLoader* image = *it;
                        if ( (image->referenceCount() == 0) && !image->neverUnload() && !image->isBeingRemoved() ) {
+                               if ( image->isReferencedUpward() ) {
+                                       // temp hack for rdar://problem/10973109
+                                       // if an image is upwardly referenced, we really need to scan all images 
+                                       // to see if any are still using it.
+                                       continue;
+                               }
                                try {
                                try {
-                                       //dyld::log("garbageCollectImages: deleting %s\n", image->getPath());
+                                       //dyld::log("garbageCollectImages: deleting %p %s\n", image, image->getPath());
                                        image->setBeingRemoved();
                                        removeImage(image);
                                        ImageLoader::deleteImage(image);
                                        image->setBeingRemoved();
                                        removeImage(image);
                                        ImageLoader::deleteImage(image);
@@ -3828,14 +3837,18 @@ static void loadInsertedDylib(const char* path)
 static bool processRestricted(const macho_header* mainExecutableMH)
 {
     // all processes with setuid or setgid bit set are restricted
 static bool processRestricted(const macho_header* mainExecutableMH)
 {
     // all processes with setuid or setgid bit set are restricted
-    if ( issetugid() )
-        return true;
-        
-       if ( hasRestrictedSegment(mainExecutableMH) && (geteuid() != 0) ) {
+    if ( issetugid() ) {
+               sRestrictedReason = restrictedBySetGUid;
+               return true;
+       }
+               
+       const uid_t euid = geteuid();
+       if ( (euid != 0) && hasRestrictedSegment(mainExecutableMH) ) {
                // existence of __RESTRICT/__restrict section make process restricted
                // existence of __RESTRICT/__restrict section make process restricted
+               sRestrictedReason = restrictedBySegment;
                return true;
        }
                return true;
        }
-    
+       
 #if __MAC_OS_X_VERSION_MIN_REQUIRED    
     // ask kernel if code signature of program makes it restricted
     uint32_t flags;
 #if __MAC_OS_X_VERSION_MIN_REQUIRED    
     // ask kernel if code signature of program makes it restricted
     uint32_t flags;
@@ -3844,14 +3857,42 @@ static bool processRestricted(const macho_header* mainExecutableMH)
                 CS_OPS_STATUS,
                 &flags,
                 sizeof(flags)) != -1) {
                 CS_OPS_STATUS,
                 &flags,
                 sizeof(flags)) != -1) {
-        if (flags & CS_RESTRICT)
-            return true;
+        if (flags & CS_RESTRICT) {
+                       sRestrictedReason = restrictedByEntitlements;
+                       return true;
+               }
     }
 #endif
     return false;
 }
 
 
     }
 #endif
     return false;
 }
 
 
+
+
+// <rdar://problem/10583252> Add dyld to uuidArray to enable symbolication of stackshots
+static void addDyldImageToUUIDList()
+{
+       const struct macho_header* mh = (macho_header*)&__dso_handle;
+       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_UUID: {
+                               uuid_command* uc = (uuid_command*)cmd;
+                               dyld_uuid_info info;
+                               info.imageLoadAddress = (mach_header*)mh;
+                               memcpy(info.imageUUID, uc->uuid, 16);
+                               addNonSharedCacheImageUUID(info);
+                               return;
+                       }
+               }
+               cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+       }
+}
+
+
+
 //
 // Entry point for dyld.  The kernel loads dyld and jumps to __dyld_start which
 // sets up some registers and call this function.
 //
 // Entry point for dyld.  The kernel loads dyld and jumps to __dyld_start which
 // sets up some registers and call this function.
@@ -3859,8 +3900,11 @@ static bool processRestricted(const macho_header* mainExecutableMH)
 // Returns address of main() in target program which __dyld_start jumps to
 //
 uintptr_t
 // Returns address of main() in target program which __dyld_start jumps to
 //
 uintptr_t
-_main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int argc, const char* argv[], const char* envp[], const char* apple[])
+_main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, 
+               int argc, const char* argv[], const char* envp[], const char* apple[], 
+               uintptr_t* startGlue)
 {      
 {      
+       uintptr_t result = 0;
        CRSetCrashLogMessage("dyld: launch started");
 #ifdef ALTERNATIVE_LOGFILE
        sLogfile = open(ALTERNATIVE_LOGFILE, O_WRONLY | O_CREAT | O_APPEND);
        CRSetCrashLogMessage("dyld: launch started");
 #ifdef ALTERNATIVE_LOGFILE
        sLogfile = open(ALTERNATIVE_LOGFILE, O_WRONLY | O_CREAT | O_APPEND);
@@ -3894,16 +3938,6 @@ _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int a
        // Pickup the pointer to the exec path.
        sExecPath = apple[0];
        bool ignoreEnvironmentVariables = false;
        // Pickup the pointer to the exec path.
        sExecPath = apple[0];
        bool ignoreEnvironmentVariables = false;
-#if __i386__
-       if ( isRosetta() ) {
-               // under Rosetta (x86 side)
-               // When a 32-bit ppc program is run under emulation on an Intel processor,
-               // we want any i386 dylibs (e.g. any used by Rosetta) to not load in the shared region
-               // because the shared region is being used by ppc dylibs
-               gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
-               ignoreEnvironmentVariables = true;
-       }
-#endif
        if ( sExecPath[0] != '/' ) {
                // have relative path, use cwd to make absolute
                char cwdbuff[MAXPATHLEN];
        if ( sExecPath[0] != '/' ) {
                // have relative path, use cwd to make absolute
                char cwdbuff[MAXPATHLEN];
@@ -3916,7 +3950,6 @@ _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int a
                        sExecPath = s;
                }
        }
                        sExecPath = s;
                }
        }
-       uintptr_t result = 0;
        sMainExecutableMachHeader = mainExecutableMH;
     sProcessIsRestricted = processRestricted(mainExecutableMH);
     if ( sProcessIsRestricted ) {
        sMainExecutableMachHeader = mainExecutableMH;
     sProcessIsRestricted = processRestricted(mainExecutableMH);
     if ( sProcessIsRestricted ) {
@@ -3954,6 +3987,8 @@ _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int a
 #endif
        
        try {
 #endif
        
        try {
+               // add dyld itself to UUID list
+               addDyldImageToUUIDList();
                CRSetCrashLogMessage("dyld: launch, loading dependent libraries");
                // instantiate ImageLoader for main executable
                sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);
                CRSetCrashLogMessage("dyld: launch, loading dependent libraries");
                // instantiate ImageLoader for main executable
                sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);
@@ -3983,7 +4018,6 @@ _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int a
                        gLinkContext.bindFlat = true;
                        gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
                }
                        gLinkContext.bindFlat = true;
                        gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
                }
-               result = (uintptr_t)sMainExecutable->getMain();
 
                // link any inserted libraries
                // do this after linking main executable so that any dylibs pulled in by inserted 
 
                // link any inserted libraries
                // do this after linking main executable so that any dylibs pulled in by inserted 
@@ -4001,8 +4035,25 @@ _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int a
        #if SUPPORT_OLD_CRT_INITIALIZATION
                // Old way is to run initializers via a callback from crt1.o
                if ( ! gRunInitializersOldWay ) 
        #if SUPPORT_OLD_CRT_INITIALIZATION
                // Old way is to run initializers via a callback from crt1.o
                if ( ! gRunInitializersOldWay ) 
+                       initializeMainExecutable(); 
+       #else
+               // run all initializers
+               initializeMainExecutable(); 
        #endif
        #endif
-               initializeMainExecutable(); // run all initializers
+               // find entry point for main executable
+               result = (uintptr_t)sMainExecutable->getThreadPC();
+               if ( result != 0 ) {
+                       // main executable uses LC_MAIN, needs to return to glue in libdyld.dylib
+                       if ( (gLibSystemHelpers != NULL) && (gLibSystemHelpers->version >= 9) )
+                               *startGlue = (uintptr_t)gLibSystemHelpers->startGlueToCallExit;
+                       else
+                               halt("libdyld.dylib support not present for LC_MAIN");
+               }
+               else {
+                       // main executable uses LC_UNIXTHREAD, dyld needs to let "start" in program set up for main()
+                       result = (uintptr_t)sMainExecutable->getMain();
+                       *startGlue = NULL;
+               }
        }
        catch(const char* message) {
                syncAllImages();
        }
        catch(const char* message) {
                syncAllImages();
index 9ad1ef8b7ea139da70dff3a0ca3cfc497e507a17..19b4431c14d4c1406ac051afa7f136bd288ea3ac 100644 (file)
@@ -88,7 +88,8 @@ namespace dyld {
        extern void                                     removeImage(ImageLoader* image);
        extern ImageLoader*                     cloneImage(ImageLoader* image);
        extern void                                     forEachImageDo( void (*)(ImageLoader*, void*), void*);
        extern void                                     removeImage(ImageLoader* image);
        extern ImageLoader*                     cloneImage(ImageLoader* image);
        extern void                                     forEachImageDo( void (*)(ImageLoader*, void*), void*);
-       extern uintptr_t                        _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int argc, const char* argv[], const char* envp[], const char* apple[]);
+       extern uintptr_t                        _main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int argc, const char* argv[], const char* envp[], 
+                                                                               const char* apple[], uintptr_t* startGlue);
        extern void                                     halt(const char* message)  __attribute__((noreturn));
        extern void                                     setErrorMessage(const char* msg);
        extern const char*                      getErrorMessage();
        extern void                                     halt(const char* message)  __attribute__((noreturn));
        extern void                                     setErrorMessage(const char* msg);
        extern const char*                      getErrorMessage();
index 0d0dbc73219f89599803fd302cf72cd1cf03f989..d00118448979ebf78a5f29f40c18910f38131eb7 100644 (file)
@@ -80,8 +80,7 @@ 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
 // 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 (__ppc__ || __i386__)
-
+#define OLD_LIBSYSTEM_SUPPORT (__i386__)
 
 // The following functions have no prototype in any header.  They are special cases
 // where _dyld_func_lookup() is used directly.
 
 // The following functions have no prototype in any header.  They are special cases
 // where _dyld_func_lookup() is used directly.
@@ -334,7 +333,7 @@ const char* _dyld_get_image_name(uint32_t image_index)
                dyld::log("%s(%u)\n", __func__, image_index);
        ImageLoader* image = dyld::getIndexedImage(image_index);
        if ( image != NULL )
                dyld::log("%s(%u)\n", __func__, image_index);
        ImageLoader* image = dyld::getIndexedImage(image_index);
        if ( image != NULL )
-               return image->getPath();
+               return image->getRealPath();
        else
                return NULL;
 }
        else
                return NULL;
 }
@@ -582,7 +581,7 @@ const struct mach_header* NSAddImage(const char* path, uint32_t 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 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|NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) == 0 );
+       const bool abortOnError = ( (options & (NSADDIMAGE_OPTION_RETURN_ON_ERROR|NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED)) == 0 );
        void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
        return addImage(callerAddress, path, search, dontLoad, matchInstallName, abortOnError);
 }
        void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
        return addImage(callerAddress, path, search, dontLoad, matchInstallName, abortOnError);
 }
@@ -1188,8 +1187,6 @@ void _dyld_fork_child()
        dyld_all_image_infos.systemOrderFlag = 0;
 }
 
        dyld_all_image_infos.systemOrderFlag = 0;
 }
 
-
-
 typedef void (*MonitorProc)(char *lowpc, char *highpc);
 
 static void monInitCallback(ImageLoader* image, void* userData)
 typedef void (*MonitorProc)(char *lowpc, char *highpc);
 
 static void monInitCallback(ImageLoader* image, void* userData)
@@ -1584,7 +1581,7 @@ int dladdr(const void* address, Dl_info* info)
        CRSetCrashLogMessage("dyld: in dladdr()");
        ImageLoader* image = dyld::findImageContainingAddress(address);
        if ( image != NULL ) {
        CRSetCrashLogMessage("dyld: in dladdr()");
        ImageLoader* image = dyld::findImageContainingAddress(address);
        if ( image != NULL ) {
-               info->dli_fname = image->getPath();
+               info->dli_fname = image->getRealPath();
                info->dli_fbase = (void*)image->machHeader();
                if ( address == info->dli_fbase ) {
                        // special case lookup of header
                info->dli_fbase = (void*)image->machHeader();
                if ( address == info->dli_fbase ) {
                        // special case lookup of header
@@ -1595,6 +1592,13 @@ int dladdr(const void* address, Dl_info* info)
                }
                // find closest symbol in the image
                info->dli_sname = image->findClosestSymbol(address, (const void**)&info->dli_saddr);
                }
                // find closest symbol in the image
                info->dli_sname = image->findClosestSymbol(address, (const void**)&info->dli_saddr);
+               // never return the mach_header symbol
+               if ( info->dli_saddr == info->dli_fbase ) {
+                       info->dli_sname = NULL;
+                       info->dli_saddr = NULL;
+                       CRSetCrashLogMessage(NULL);
+                       return 1; // success
+               }
                if ( info->dli_sname != NULL ) {
                        if ( info->dli_sname[0] == '_' )
                                info->dli_sname = info->dli_sname +1; // strip off leading underscore
                if ( info->dli_sname != NULL ) {
                        if ( info->dli_sname[0] == '_' )
                                info->dli_sname = info->dli_sname +1; // strip off leading underscore
@@ -1675,15 +1679,7 @@ void* dlsym(void* handle, const char* symbolName)
        
        // magic "search what I would see" handle
        if ( handle == RTLD_NEXT ) {
        
        // magic "search what I would see" handle
        if ( handle == RTLD_NEXT ) {
-#if __ppc__
-               // <rdar://problem/7628929> work around for llvmgcc bug
-               void* fa = __builtin_frame_address(0);
-               fa = *(void**)fa;
-               fa = *(void**)fa;
-               void* callerAddress = *((void**)(((int)fa)+8));
-#else  
                void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
                void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
-#endif
                ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
                sym = callerImage->findExportedSymbolInDependentImages(underscoredName, dyld::gLinkContext, &image); // don't search image, but do search what it links against
                if ( sym != NULL ) {
                ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
                sym = callerImage->findExportedSymbolInDependentImages(underscoredName, dyld::gLinkContext, &image); // don't search image, but do search what it links against
                if ( sym != NULL ) {
@@ -1782,7 +1778,7 @@ const char* dyld_image_path_containing_address(const void* address)
 
        ImageLoader* image = dyld::findImageContainingAddress(address);
        if ( image != NULL )
 
        ImageLoader* image = dyld::findImageContainingAddress(address);
        if ( image != NULL )
-               return image->getPath();
+               return image->getRealPath();
        return NULL;
 }
 
        return NULL;
 }
 
index cb99cdd75564ebfde28062a1c3884bb3439efe76..0417585d684bfd9da642327b3246ac3b6e6f5eaf 100644 (file)
 extern "C" int  __cxa_atexit(void (*func)(void *), void *arg, void *dso);
 extern "C" void __cxa_finalize(const void *dso);
 
 extern "C" int  __cxa_atexit(void (*func)(void *), void *arg, void *dso);
 extern "C" void __cxa_finalize(const void *dso);
 
+
+#ifndef LC_VERSION_MIN_MACOSX
+       #define LC_VERSION_MIN_MACOSX 0x24
+       struct version_min_command {
+               uint32_t        cmd;            /* LC_VERSION_MIN_MACOSX or
+                                          LC_VERSION_MIN_IPHONEOS  */
+               uint32_t        cmdsize;        /* sizeof(struct min_version_command) */
+               uint32_t        version;        /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+               uint32_t        sdk;            /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+       };
+#endif
+
+#ifndef LC_VERSION_MIN_IPHONEOS
+       #define LC_VERSION_MIN_IPHONEOS 0x25
+#endif
+
+
 #ifndef LC_LOAD_UPWARD_DYLIB
        #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
 #endif
 
 #ifndef LC_LOAD_UPWARD_DYLIB
        #define LC_LOAD_UPWARD_DYLIB (0x23|LC_REQ_DYLD) /* load of dylib whose initializers run later */
 #endif
 
-#define DYLD_SHARED_CACHE_SUPPORT (__ppc__ || __i386__ || __ppc64__ || __x86_64__ || __arm__)
+#define DYLD_SHARED_CACHE_SUPPORT (__i386__ || __x86_64__ || __arm__)
 
 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
 #if __IPHONE_OS_VERSION_MIN_REQUIRED   
 
 // deprecated APIs are still availble on Mac OS X, but not on iPhone OS
 #if __IPHONE_OS_VERSION_MIN_REQUIRED   
@@ -406,6 +423,119 @@ const char* libraryName)
        return(-1);
 }
 
        return(-1);
 }
 
+
+/*
+ * Returns the sdk version (encode as nibble XXXX.YY.ZZ) the
+ * specified binary was built against.
+ *
+ * First looks for LC_VERSION_MIN_MACOSX/LC_VERSION_MIN_IPHONEOS
+ * in binary and if sdk field is not zero, return that value.
+ * Otherwise, looks for the libSystem.B.dylib the binary linked
+ * against and uses a table to convert that to an sdk version.
+ */
+uint32_t dyld_get_sdk_version(const mach_header* mh)
+{
+#if __LP64__
+       const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header_64));
+#else
+       const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header));
+#endif
+       const version_min_command* versCmd;
+       const dylib_command* dylibCmd;
+       const load_command* cmd = cmds;
+       uint32_t libSystemVers = 0;
+       for(uint32_t i = 0; i < mh->ncmds; ++i) {
+               switch ( cmd->cmd ) { 
+                       case LC_VERSION_MIN_MACOSX:
+                       case LC_VERSION_MIN_IPHONEOS:
+                               versCmd = (version_min_command*)cmd;
+                               if ( versCmd->sdk != 0 )
+                                       return versCmd->sdk;    // found explicit SDK version
+                               break;
+                       case LC_LOAD_DYLIB:
+                       case LC_LOAD_WEAK_DYLIB:
+                       case LC_LOAD_UPWARD_DYLIB:
+                               dylibCmd = (dylib_command*)cmd;
+                               if ( strcmp((char*)dylibCmd + dylibCmd->dylib.name.offset, "/usr/lib/libSystem.B.dylib") == 0 )
+                                       libSystemVers = dylibCmd->dylib.current_version;
+                               else if ( strcmp((char*)dylibCmd + dylibCmd->dylib.name.offset, "/usr/lib/libSystem.dylib") == 0 )
+                                       return 0x00040000; // all iOS simulator have same libSystem.dylib version
+                               break;
+               }
+           cmd = (load_command*)((char *)cmd + cmd->cmdsize);
+       }
+       
+       if ( libSystemVers != 0 ) {
+               // found linked libSystem.B.dylib version linked against
+#if __IPHONE_OS_VERSION_MIN_REQUIRED
+               // convert libSystem.B.dylib version to iOS sdk version
+               if ( libSystemVers < 0x006F0010 )       // libSystem 111.0.16 in 3.0
+                       return 0x00020000;              // 2.0  
+               else if ( libSystemVers < 0x006F0201 )  // libSystem 111.2.1 in 3.1
+                       return 0x00030000;              // 3.0  
+               else if ( libSystemVers < 0x007D020B )  // libSystem 125.2.11 in 4.0
+                       return 0x00030100;              // 3.1  
+               else if ( libSystemVers < 0x007D0400 )  // libSystem 125.4 in 4.1 and in 4.2
+                       return 0x00040000;              // 4.0  
+               else if ( libSystemVers < 0x009F0000 )  // libSystem 159 in 4.3
+                       return 0x00040100;              // 4.1  
+               else if ( libSystemVers < 0x00A10000 )  // libSystem 161 in 5.0
+                       return 0x00040300;              // 4.3  
+               else
+                       return 0x00050000;
+#else
+               // convert libSystem.B.dylib version to MacOSX sdk version
+               if ( libSystemVers < 0x006F0000 )       // libSystem 111 in 10.5
+                       return 0x000A0400;              // 10.4  
+               else if ( libSystemVers < 0x007B0000 )  // libSystem 123 in 10.6
+                       return 0x000A0500;              // 10.5  
+               else if ( libSystemVers < 0x009F0000 )  // libSystem 159 in 10.7
+                       return 0x000A0600;              // 10.6  
+               else if ( libSystemVers < 0x00A10000 )  // libSystem 161 in 10.8
+                       return 0x000A0700;              // 10.7  
+               else 
+                       return 0x000A0800;              // 10.8  
+#endif
+       }
+       
+       return 0;
+}
+
+uint32_t dyld_get_program_sdk_version()
+{
+       return dyld_get_sdk_version((mach_header*)_NSGetMachExecuteHeader());
+}
+
+
+uint32_t dyld_get_min_os_version(const struct mach_header* mh)
+{
+#if __LP64__
+       const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header_64));
+#else
+       const load_command* cmds = (load_command*)((char *)mh + sizeof(mach_header));
+#endif
+       const version_min_command* versCmd;
+       const load_command* cmd = cmds;
+       for(uint32_t i = 0; i < mh->ncmds; ++i) {
+               switch ( cmd->cmd ) { 
+                       case LC_VERSION_MIN_MACOSX:
+                       case LC_VERSION_MIN_IPHONEOS:
+                               versCmd = (version_min_command*)cmd;
+                               return versCmd->version;        // found explicit min OS version
+                               break;
+               }
+           cmd = (load_command*)((char *)cmd + cmd->cmdsize);
+       }
+       return 0;
+}
+
+
+uint32_t dyld_get_program_min_os_version()
+{
+       return dyld_get_min_os_version((mach_header*)_NSGetMachExecuteHeader());
+}
+
+
 #if DEPRECATED_APIS_SUPPORTED
 /*
  * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
 #if DEPRECATED_APIS_SUPPORTED
 /*
  * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
@@ -1075,9 +1205,10 @@ static void shared_cache_out_of_date()
 }
 #endif // DYLD_SHARED_CACHE_SUPPORT
 
 }
 #endif // DYLD_SHARED_CACHE_SUPPORT
 
+extern void* start;
 
 // the table passed to dyld containing thread helpers
 
 // the table passed to dyld containing thread helpers
-static dyld::LibSystemHelpers sHelpers = { 8, &dyldGlobalLockAcquire, &dyldGlobalLockRelease,  
+static dyld::LibSystemHelpers sHelpers = { 9, &dyldGlobalLockAcquire, &dyldGlobalLockRelease,  
                                                                        &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit,
                                                #if DYLD_SHARED_CACHE_SUPPORT
                                                                        &shared_cache_missing, &shared_cache_out_of_date,
                                                                        &getPerThreadBufferFor_dlerror, &malloc, &free, &__cxa_atexit,
                                                #if DYLD_SHARED_CACHE_SUPPORT
                                                                        &shared_cache_missing, &shared_cache_out_of_date,
@@ -1088,7 +1219,8 @@ static dyld::LibSystemHelpers sHelpers = { 8, &dyldGlobalLockAcquire, &dyldGloba
                                                                        &pthread_key_create, &pthread_setspecific,
                                                                        &malloc_size,
                                                                        &pthread_getspecific,
                                                                        &pthread_key_create, &pthread_setspecific,
                                                                        &malloc_size,
                                                                        &pthread_getspecific,
-                                                                       &__cxa_finalize};
+                                                                       &__cxa_finalize,
+                                                                       &start};
 
 
 //
 
 
 //
index cff7dbe7474d1d66e7e49d162bed3384b295d2b9..2520f8fac505943c64dcc6ef06bfae082b20fe38 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2004-2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -96,51 +96,31 @@ char* __cxa_get_globals_fast()
 
 
 
 
 
 
-#if __x86_64__ || __i386__ || __ppc__
+#if !__arm__
 //
 //
-//  The intel/ppc versions of dyld uses zero-cost exceptions which are handled by
+//  The intel versions of dyld uses zero-cost exceptions which are handled by
 //  linking with a special copy of libunwind.a
 //
 
 //  linking with a special copy of libunwind.a
 //
 
-static struct dyld_unwind_sections     sDyldInfo;
-static void*                                           sDyldTextEnd;
+extern void*  ehStart  __asm("section$start$__TEXT$__eh_frame");
+extern void*  ehEnd    __asm("section$end$__TEXT$__eh_frame");
+extern void*  uwStart  __asm("section$start$__TEXT$__unwind_info");
+extern void*  uwEnd    __asm("section$end$__TEXT$__unwind_info");
 
 
-// called by dyldStartup.s very early
-void dyld_exceptions_init(struct mach_header* mh, intptr_t slide)
-{
-       // record location of unwind sections in dyld itself
-    sDyldInfo.mh = mh;    
-       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, "__TEXT") == 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, "__eh_frame") == 0 ) {
-                                               sDyldInfo.dwarf_section = (void*)(sect[j].addr + slide);
-                                               sDyldInfo.dwarf_section_length = sect[j].size;
-                                       }
-                                       else if ( strcmp(sect[j].sectname, "__unwind_info") == 0 ) {
-                                               sDyldInfo.compact_unwind_section = (void*)(sect[j].addr + slide);
-                                               sDyldInfo.compact_unwind_section_length = sect[j].size;
-                                       }
-                               }
-                               sDyldTextEnd = (void*)(seg->vmaddr + seg->vmsize + slide);
-                   }
-               }
-           cmd = (struct load_command*)( (char*)cmd + cmd->cmdsize );
-       }
-}
+extern void*  textStart __asm("section$start$__TEXT$__text");
+extern void*  textEnd   __asm("section$end$__TEXT$__text");
 
 
-// called by libuwind code to find unwind information in dyld
+extern void* __dso_handle;
+
+// called by libuwind code to find unwind information sections in dyld
 bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
 {
 bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
 {
-       if ( ((void*)sDyldInfo.mh < addr) && (addr < sDyldTextEnd) ) { 
-               *info = sDyldInfo;
+       if ( ((void*)&textStart < addr) && (addr < (void*)&textEnd) ) { 
+        info->mh = (struct mach_header*)&__dso_handle;
+        info->dwarf_section = &ehStart;
+        info->dwarf_section_length = ((char*)&ehEnd - (char*)&ehStart);
+        info->compact_unwind_section = &uwStart;
+        info->compact_unwind_section_length = ((char*)&uwEnd - (char*)&uwStart);
                return true;
        }
        else {
                return true;
        }
        else {
@@ -148,13 +128,7 @@ bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
        }
 }
 
        }
 }
 
-#if __ppc__
-       // the ppc version of _Znwm in libstdc++.a uses keymgr
-       // need to override that
-       void* _Znwm(size_t size) { return malloc(size); }
-#endif
-
-#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
+#endif // !__arm__
 
 
 #if __arm__
 
 
 #if __arm__
@@ -166,13 +140,6 @@ struct _Unwind_FunctionContext
 
 };
 
 
 };
 
-//
-//  The ARM of dyld use SL-LJ based exception handling
-//  which does not require any initialization until libSystem is initialized.
-//
-void dyld_exceptions_init(struct mach_header *mh, uintptr_t slide)
-{
-}
 
 static pthread_key_t                                           sThreadChainKey = 0; 
 static struct _Unwind_FunctionContext*         sStaticThreadChain = NULL; 
 
 static pthread_key_t                                           sThreadChainKey = 0; 
 static struct _Unwind_FunctionContext*         sStaticThreadChain = NULL; 
index e40b1e84c7159a986ca3651a5cf20af8f0e0bee2..a1266d7f68cf221e276d40c86aa737911abcd23c 100644 (file)
@@ -31,9 +31,6 @@
 #include <mach-o/loader.h>
 #include <mach-o/ldsyms.h>
 #include <mach-o/reloc.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
 #if __x86_64__
        #include <mach-o/x86_64/reloc.h>
 #endif
 #if __x86_64__
        #include <mach-o/x86_64/reloc.h>
 #endif
@@ -192,10 +189,6 @@ static void rebaseDyld(const struct macho_header* mh, intptr_t slide)
        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) {
        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 __ppc__ || __ppc64__ || __i36__
-               if ( (reloc->r_address & R_SCATTERED) != 0 )
-                       throw "scattered relocation in dyld";
-       #endif
                if ( reloc->r_length != RELOC_SIZE ) 
                        throw "relocation in dyld has wrong size";
 
                if ( reloc->r_length != RELOC_SIZE ) 
                        throw "relocation in dyld has wrong size";
 
@@ -208,7 +201,6 @@ static void rebaseDyld(const struct macho_header* mh, intptr_t slide)
 }
 
 
 }
 
 
-extern "C" void dyld_exceptions_init(const struct macho_header*, uintptr_t slide); // in dyldExceptions.cpp
 extern "C" void mach_init();
 
 //
 extern "C" void mach_init();
 
 //
@@ -228,7 +220,8 @@ extern "C" {
 //  In dyld we have to do this manually.
 //
 uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* argv[], 
 //  In dyld we have to do this manually.
 //
 uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* argv[], 
-                                                               intptr_t slide, const struct macho_header* dyldsMachHeader)
+                               intptr_t slide, const struct macho_header* dyldsMachHeader,
+                               uintptr_t* startGlue)
 {
        // 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 kernel had to slide dyld, we need to fix up load sensitive locations
        // we have to do this before using any global variables
@@ -242,9 +235,6 @@ uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char*
        _pthread_keys_init();
 #endif
 
        _pthread_keys_init();
 #endif
 
-       // enable C++ exceptions to work inside dyld
-       dyld_exceptions_init(dyldsMachHeader, slide);
-       
        // allow dyld to use mach messaging
        mach_init();
 
        // allow dyld to use mach messaging
        mach_init();
 
@@ -261,7 +251,7 @@ uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char*
                
        // now that we are done bootstrapping dyld, call dyld's main
        uintptr_t appsSlide = slideOfMainExecutable(appsMachHeader);
                
        // now that we are done bootstrapping dyld, call dyld's main
        uintptr_t appsSlide = slideOfMainExecutable(appsMachHeader);
-       return dyld::_main(appsMachHeader, appsSlide, argc, argv, envp, apple);
+       return dyld::_main(appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue);
 }
 
 
 }
 
 
index bbd8b01389693dfb44b648e7c34de566cebb1536..0fdda05463285b194576c80ccd81c375c4f0576d 100644 (file)
  */
 
 #include <Availability.h>
  */
 
 #include <Availability.h>
+#include <stddef.h>
 
 //
 // This is the temporary private interface between libSystem.B.dylib and dyld
 //
 
 
 //
 // This is the temporary private interface between libSystem.B.dylib and dyld
 //
 
+
+int          NXArgc = 0;
+const char** NXArgv = NULL;
+const char** environ = NULL;
+const char*  __progname = NULL;
+
+
+
 //
 // Long ago, the compiler driver added -ldylib1.o to every dylib which caused a
 // __DATA,__dyld section to be added every dylib.  The new LINKEDIT format no longer requires
 //
 // Long ago, the compiler driver added -ldylib1.o to every dylib which caused a
 // __DATA,__dyld section to be added every dylib.  The new LINKEDIT format no longer requires
 // to some sort of vtable based interface, libdyld still needs a __DATA,__dyld section.
 // The code below adds that section.
 //
 // to some sort of vtable based interface, libdyld still needs a __DATA,__dyld section.
 // The code below adds that section.
 //
-struct __DATA__dyld { long lazy; int (*lookup)(const char*, void**); };
+struct __DATA__dyld { 
+       long                    lazy; 
+       int                             (*lookup)(const char*, void**);
+       // ProgramVars
+       const void*             mh;
+       int*                    NXArgcPtr;
+       const char***   NXArgvPtr;
+       const char***   environPtr;
+       const char**    __prognamePtr;
+};
 
 
-static volatile struct __DATA__dyld  myDyldSection __attribute__ ((section ("__DATA,__dyld"))) = { 0, 0 };
+static volatile struct __DATA__dyld  myDyldSection __attribute__ ((section ("__DATA,__dyld"))) 
+       = { 0, 0, NULL, &NXArgc, &NXArgv, &environ, &__progname };
 
 #if __arm__ && __MAC_OS_X_VERSION_MIN_REQUIRED
 // <rdar://problem/8755380>
 
 #if __arm__ && __MAC_OS_X_VERSION_MIN_REQUIRED
 // <rdar://problem/8755380>
@@ -54,5 +73,3 @@ int _dyld_func_lookup(const char* dyld_func_name, void **address)
 }
 
 
 }
 
 
-
-
index 874c49782eec0fe0e0c3daf4295bb4bdb69c34f7..9a5fd6085c8e95d4ce5363e769fcca37d1393602 100644 (file)
@@ -61,6 +61,8 @@ namespace dyld {
                void*           (*pthread_getspecific)(pthread_key_t);
                // added in version 8
                void            (*cxa_finalize)(const void*);
                void*           (*pthread_getspecific)(pthread_key_t);
                // added in version 8
                void            (*cxa_finalize)(const void*);
+               // added in version 9
+               void*           startGlueToCallExit;
        };
 #if __cplusplus
 };
        };
 #if __cplusplus
 };
index cf296ef3c69d0ec9fd43b55a805d2ebc5fbcbabf..11c8f1ff123e5a5606aa2e6aebaf11caf70a6686 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 1999-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -21,7 +21,7 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 /*
  * @APPLE_LICENSE_HEADER_END@
  */
 /*
- * C runtime startup for i386 and ppc interface to the dynamic linker.
+ * C runtime startup for 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.
  *
  * 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.
  *
@@ -111,37 +111,57 @@ _offset_to_dyld_all_image_infos:
        .align  4, 0x90
        .globl __dyld_start
 __dyld_start:
        .align  4, 0x90
        .globl __dyld_start
 __dyld_start:
+       popl    %edx            # edx = mh of app
        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
        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
+       subl    $32,%esp        # room for locals and outgoing parameters
        
        
-       # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
-       subl    $12,%esp
        call    L__dyld_start_picbase
 L__dyld_start_picbase: 
        popl    %ebx            # set %ebx to runtime value of picbase
        call    L__dyld_start_picbase
 L__dyld_start_picbase: 
        popl    %ebx            # set %ebx to runtime value of picbase
+
        movl    Lmh-L__dyld_start_picbase(%ebx), %ecx # ecx = prefered load address
        movl    __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
        subl    %eax, %ebx      # ebx = slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
        addl    %ebx, %ecx      # ecx = actual load address
        movl    Lmh-L__dyld_start_picbase(%ebx), %ecx # ecx = prefered load address
        movl    __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
        subl    %eax, %ebx      # ebx = slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
        addl    %ebx, %ecx      # ecx = actual load address
-       pushl   %ecx            # param5 = actual load address
-       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    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_     
-
-       # clean up stack and jump to result
+       # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
+       movl    %edx,(%esp)     # param1 = app_mh
+       movl    4(%ebp),%eax    
+       movl    %eax,4(%esp)    # param2 = argc
+       lea     8(%ebp),%eax    
+       movl    %eax,8(%esp)    # param3 = argv
+       movl    %ebx,12(%esp)   # param4 = slide
+       movl    %ecx,16(%esp)   # param5 = actual load address
+       lea     28(%esp),%eax
+       movl    %eax,20(%esp)   # param6 = &startGlue
+       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm   
+       movl    28(%esp),%edx
+       cmpl    $0,%edx
+       jne     Lnew
+
+       # clean up stack and jump to "start" in main executable
        movl    %ebp,%esp       # restore the unaligned stack pointer
        movl    %ebp,%esp       # restore the unaligned stack pointer
-       addl    $8,%esp         # remove the mh argument, and debugger end
-                               #  frame marker
+       addl    $4,%esp         # remove debugger end frame marker
        movl    $0,%ebp         # restore ebp back to zero
        jmp     *%eax           # jump to the entry point
 
        movl    $0,%ebp         # restore ebp back to zero
        jmp     *%eax           # jump to the entry point
 
-
+       # LC_MAIN case, set up stack for call to main() 
+Lnew:  movl    4(%ebp),%ebx
+       movl    %ebx,(%esp)     # main param1 = argc
+       leal    8(%ebp),%ecx
+       movl    %ecx,4(%esp)    # main param2 = argv
+       leal    0x4(%ecx,%ebx,4),%ebx
+       movl    %ebx,8(%esp)    # main param3 = env
+Lapple:        movl    (%ebx),%ecx     # look for NULL ending env[] array
+       add     $4,%ebx
+       testl   %ecx,%ecx
+       jne     Lapple          # once found, next pointer is "apple" parameter now in %ebx
+       movl    %ebx,12(%esp)   # main param4 = apple
+       pushl   %edx            # simulate return address into _start in libdyld
+       jmp     *%eax           # jump to main(argc,argv,env,apple) with return address set to _start
+       
+       
        .globl dyld_stub_binding_helper
 dyld_stub_binding_helper:
        hlt
        .globl dyld_stub_binding_helper
 dyld_stub_binding_helper:
        hlt
@@ -182,105 +202,50 @@ _offset_to_dyld_all_image_infos:
        .align 2,0x90
        .globl __dyld_start
 __dyld_start:
        .align 2,0x90
        .globl __dyld_start
 __dyld_start:
+       popq    %rdi            # param1 = mh of app
        pushq   $0              # push a zero for debugger end of frames marker
        movq    %rsp,%rbp       # pointer to base of kernel frame
        andq    $-16,%rsp       # force SSE alignment
        pushq   $0              # push a zero for debugger end of frames marker
        movq    %rsp,%rbp       # pointer to base of kernel frame
        andq    $-16,%rsp       # force SSE alignment
+       subq    $16,%rsp        # room for local variables
        
        
-       # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
-       movq    8(%rbp),%rdi    # param1 = mh into %rdi
-       movl    16(%rbp),%esi   # param2 = argc into %esi
-       leaq    24(%rbp),%rdx   # param3 = &argv[0] into %rdx
+       # call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
+       movl    8(%rbp),%esi    # param2 = argc into %esi
+       leaq    16(%rbp),%rdx   # param3 = &argv[0] into %rdx
        movq    __dyld_start_static(%rip), %r8
        leaq    __dyld_start(%rip), %rcx
        subq     %r8, %rcx      # param4 = slide into %rcx
        leaq    ___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
        movq    __dyld_start_static(%rip), %r8
        leaq    __dyld_start(%rip), %rcx
        subq     %r8, %rcx      # param4 = slide into %rcx
        leaq    ___dso_handle(%rip),%r8 # param5 = dyldsMachHeader
-       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_     
+       leaq    -8(%rbp),%r9
+       call    __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
+       movq    -8(%rbp),%rdi
+       cmpq    $0,%rdi
+       jne     Lnew
 
 
-       # clean up stack and jump to result
+       # clean up stack and jump to "start" in main executable
        movq    %rbp,%rsp       # restore the unaligned stack pointer
        movq    %rbp,%rsp       # restore the unaligned stack pointer
-       addq    $16,%rsp        # remove the mh argument, and debugger end frame marker
+       addq    $8,%rsp         # remove the mh argument, and debugger end frame marker
        movq    $0,%rbp         # restore ebp back to zero
        jmp     *%rax           # jump to the entry point
        
        movq    $0,%rbp         # restore ebp back to zero
        jmp     *%rax           # jump to the entry point
        
+       # LC_MAIN case, set up stack for call to main() 
+Lnew:  addq    $16,%rsp        # remove local variables
+       pushq   %rdi            # simulate return address into _start in libdyld
+       movq    8(%rbp),%rdi    # main param1 = argc into %rdi
+       leaq    16(%rbp),%rsi   # main param2 = &argv[0] into %rsi
+       leaq    0x8(%rsi,%rdi,8),%rdx # main param3 = &env[0] into %rdx
+       movq    %rdx,%rcx
+Lapple: movq   (%rcx),%r8
+       add     $8,%rcx
+       testq   %r8,%r8         # look for NULL ending env[] array
+       jne     Lapple          # main param4 = apple into %rcx
+       jmp     *%rax           # jump to main(argc,argv,env,apple) with return address set to _start
+       
 #endif /* __x86_64__ */
 
 
 #endif /* __x86_64__ */
 
 
-#if __ppc__ || __ppc64__
-#include <architecture/ppc/mode_independent_asm.h>
-
-       .data
-       .align 2
-__dyld_start_static_picbase: 
-       .g_long     L__dyld_start_picbase
-Lmh:   .g_long     ___dso_handle
-
-#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
-       nop 
-_offset_to_dyld_all_image_infos:
-       .long   _dyld_all_image_infos - . + 0x1010 
-       .long   0
-       # space for future stable entry points
-       .space  16
-       
-       
-       .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, dyld_mh)
-       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
-       addis   r7,r31,ha16(Lmh-L__dyld_start_picbase)
-       lg      r7,lo16(Lmh-L__dyld_start_picbase)(r7)
-       add     r7,r6,r7        ; r7 = dyld_mh
-       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_     
-       
-       ; 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__ */
 
 #if __arm__
 
 #if __arm__
+       .syntax unified
        .data
        .align 2
 __dyld_start_static_picbase: 
        .data
        .align 2
 __dyld_start_static_picbase: 
@@ -318,10 +283,10 @@ ___dso_handle:    .long 0
        .align 2
 __dyld_start:
        mov     r8, sp          // save stack pointer
        .align 2
 __dyld_start:
        mov     r8, sp          // save stack pointer
-       sub     sp, #8          // make room for outgoing dyld_mh parameter
+       sub     sp, #16         // make room for outgoing parameters
        bic     sp, sp, #7      // force 8-byte alignment
 
        bic     sp, sp, #7      // force 8-byte alignment
 
-       // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh)
+       // call dyldbootstrap::start(app_mh, argc, argv, slide, dyld_mh, &startGlue)
 
        ldr     r3, L__dyld_start_picbase_ptr
 L__dyld_start_picbase:
 
        ldr     r3, L__dyld_start_picbase_ptr
 L__dyld_start_picbase:
@@ -334,15 +299,33 @@ L__dyld_start_picbase:
        add     r2, r8, #8      // r2 = argv
 
        ldr     r4, Lmh
        add     r2, r8, #8      // r2 = argv
 
        ldr     r4, Lmh
-L3:    add     r4, r4, pc      // r4 = dyld_mh
-       str     r4, [sp, #0]
-       
-       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_
+L3:    add     r4, r4, pc      
+       str     r4, [sp, #0]    // [sp] = dyld_mh
+       add     r4, sp, #12
+       str     r4, [sp, #4]    // [sp+4] = &startGlue
        
        
-       // clean up stack and jump to result
+       bl      __ZN13dyldbootstrap5startEPK12macho_headeriPPKclS2_Pm
+       ldr     r5, [sp, #12]
+       cmp     r5, #0
+       bne     Lnew
+       
+       // traditional case, clean up stack and jump to result
        add     sp, r8, #4      // remove the mach_header argument.
        bx      r0              // jump to the program's entry point
 
        add     sp, r8, #4      // remove the mach_header argument.
        bx      r0              // jump to the program's entry point
 
+       // LC_MAIN case, set up stack for call to main()
+Lnew:  mov     lr, r5              // simulate return address into _start in libdyld
+       mov     r5, r0              // save address of main() for later use
+       ldr     r0, [r8, #4]        // main param1 = argc
+       add     r1, r8, #8          // main param2 = argv
+       add     r2, r1, r0, lsl #2  
+       add     r2, r2, #4          // main param3 = &env[0]
+       mov     r3, r2
+Lapple:        ldr     r4, [r3]
+       add     r3, #4
+       cmp     r4, #0
+       bne     Lapple              // main param4 = apple
+       bx      r5
 
        .align 2
 L__dyld_start_picbase_ptr:
 
        .align 2
 L__dyld_start_picbase_ptr:
@@ -380,7 +363,7 @@ L_end:
        .align 2
        .globl  _dyld_fatal_error
 _dyld_fatal_error:
        .align 2
        .globl  _dyld_fatal_error
 _dyld_fatal_error:
-#if __ppc__ || __ppc64__ || __arm__
+#if __arm__
     trap
     nop
 #elif __x86_64__ || __i386__
     trap
     nop
 #elif __x86_64__ || __i386__
index 9db993f5f5c33bc3ce7ea6e74f8fa6dd27a0dc48..8132b2ce07bca95c22890cef8c2bae7a423baaa2 100644 (file)
 
 int dummy_dyld_symbol = 1;
 
 
 int dummy_dyld_symbol = 1;
 
-#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"
-#include "mach-o/dyld_priv.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 slide
-static ptrdiff_t slideForHeader(task_port_t target_task, const struct mach_header* otherAddressHeader)
-{
-       ptrdiff_t result = 0;
-       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) {
-                                       result = (uintptr_t)mh - (uintptr_t)sgp->vmaddr;
-                                       break;
-                               }
-                       }
-                       sgp = (const struct segment_command *)((char *)sgp + sgp->cmdsize);
-               }
-               free((void*)mh);
-       }
-       return result;  
-}
-
-
-/*
- * _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
index 9f65555d059b406708411b6756ece73421e4aba7..9ccc656f5e6934277db350a1f0fc5ce1f742d3eb 100644 (file)
@@ -25,6 +25,7 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 #include <time.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <time.h>
 #include <unistd.h>
 #include <stdarg.h>
@@ -240,10 +241,8 @@ char* mach_error_type(mach_error_t err)
 
 // _pthread_reap_thread calls fprintf(stderr). 
 // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL
 
 // _pthread_reap_thread calls fprintf(stderr). 
 // We map fprint to _simple_vdprintf and ignore FILE* stream, so ok for it to be NULL
-#if !__ppc__
 FILE* __stderrp = NULL;
 FILE* __stdoutp = NULL;
 FILE* __stderrp = NULL;
 FILE* __stdoutp = NULL;
-#endif
 
 // work with c++abi.a
 void (*__cxa_terminate_handler)() = _ZSt9terminatev;
 
 // work with c++abi.a
 void (*__cxa_terminate_handler)() = _ZSt9terminatev;
@@ -261,3 +260,20 @@ void __cxa_bad_typeid()
 {
        _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
 }
 {
        _ZN4dyld4haltEPKc("__cxa_bad_typeid()");
 }
+
+// to work with libc++
+void _ZNKSt3__120__vector_base_commonILb1EE20__throw_length_errorEv()
+{
+       _ZN4dyld4haltEPKc("std::vector<>::_throw_length_error()");
+}
+
+// libc.a sometimes missing memset
+#undef memset
+void* memset(void* b, int c, size_t len)
+{
+       uint8_t* p = (uint8_t*)b;
+       for(size_t i=len; i > 0; --i)
+               *p++ = c;
+       return b;
+}
+
diff --git a/src/start_glue.s b/src/start_glue.s
new file mode 100644 (file)
index 0000000..4ccfd39
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011 Apple 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__
+
+    .align 2
+    .globl _start
+    .private_extern _start
+start:
+       nop             # <rdar://problem/10753356> backtraces of LC_MAIN binaries don't end in "start"
+_start:
+       movl    %eax,(%esp)         # pass result from main() to exit() 
+       call    _exit
+       hlt
+
+#endif /* __i386__ */
+
+
+#if __x86_64__
+
+    .align 2
+    .globl _start
+    .private_extern _start
+start:
+       nop             # <rdar://problem/10753356> backtraces of LC_MAIN binaries don't end in "start"
+_start:
+       movl    %eax,%edi           # pass result from main() to exit() 
+       call    _exit
+       hlt
+
+#endif
+
+
+#if __arm__
+    .align 2
+    .globl _start
+    .private_extern _start
+start:
+       nop                                     // <rdar://problem/10753356> backtraces of LC_MAIN binaries don't end in "start"
+_start:
+       bl      _exit                   // result in r0 already in param reg r0
+       trap
+#endif /* __arm__ */
+
index aec491f6f4486a4c8aad2e27afed330ce1871689..843347563f632caab32fab64675297c08ad3ac9a 100644 (file)
@@ -180,71 +180,6 @@ _stub_binding_helper_interface:
 #endif
 
 
 #endif
 
 
-#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__ */
-
 #if __arm__
 /*
  * This is the interface for the stub_binding_helper for ARM:
 #if __arm__
 /*
  * This is the interface for the stub_binding_helper for ARM:
index 21415cd18a812c65dd1b72c2f5eddb26af34cec0..d6d19fcfd59c5a978b18bb0365083e7b6b3e5bdd 100755 (executable)
@@ -17,9 +17,9 @@ echo "#!/bin/sh" > /var/root/testing/run-all-tests
 chmod +x /var/root/testing/run-all-tests
 
 # do every combination of OS version and architectures
 chmod +x /var/root/testing/run-all-tests
 
 # do every combination of OS version and architectures
-for os in "4.3" "3.0" 
+for os in "6.0" "3.0" 
 do
 do
-       for arch in armv6 thumb armv7 thumb2
+       for arch in armv7 armv6 thumb
        do
                # make copy of tests
                cp -r ${TEST_CASE_DIR}/../../unit-tests  /var/root/testing/unit-tests-${arch}-${os}
        do
                # make copy of tests
                cp -r ${TEST_CASE_DIR}/../../unit-tests  /var/root/testing/unit-tests-${arch}-${os}
index 461ebb0f2602c95d504660588e6c1e2e4ccd703e..ba256c883b0b31727dc890e0800dacb5d56f64b2 100644 (file)
@@ -6,28 +6,29 @@ SHELL = /bin/sh
 OS_NAME ?= MacOSX
 ifeq "$(OS_NAME)" "iPhoneOS"
        OS_VERSION ?= 3.1
 OS_NAME ?= MacOSX
 ifeq "$(OS_NAME)" "iPhoneOS"
        OS_VERSION ?= 3.1
-       ifeq "$(OS_VERSION)" "4.3"
-               OS_BAROLO_FEATURES = 1
+       ifeq "$(findstring -$(OS_VERSION)-,-3.0-3.1-3.2-4.0-4.1-4.2-4.3-)" ""
+               OS_LION_FEATURES = 1
        endif
        endif
-       ARCH ?= armv6
-       VALID_ARCHS ?= armv6
+       ARCH ?= armv7
+       VALID_ARCHS ?= armv7
 else
        OS_VERSION ?= 10.7
 else
        OS_VERSION ?= 10.7
-       ifeq "$(OS_VERSION)" "10.7"
-               OS_BAROLO_FEATURES = 1
+       ifeq "$(findstring -$(OS_VERSION)-,-10.4-10.5-10.6-)" ""
+               OS_LION_FEATURES = 1
        endif
        endif
-       ARCH ?= $(shell arch)
+       ARCH ?= x86_64
        VALID_ARCHS ?= "i386 x86_64"
 endif
 
        VALID_ARCHS ?= "i386 x86_64"
 endif
 
+IOSROOT        = 
+
 ifeq "$(OS_NAME)" "iPhoneOS"
 ifeq "$(OS_NAME)" "iPhoneOS"
-       CC                      = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch ${ARCH} -miphoneos-version-min=$(OS_VERSION) -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.Internal.sdk
-       CXX                     = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++-4.2 -arch ${ARCH} -miphoneos-version-min=$(OS_VERSION) -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.Internal.sdk
-#      CC                      = gcc-4.2 -arch ${ARCH} -miphoneos-version-min=$(OS_VERSION)
-#      CXX                     = g++-4.2 -arch ${ARCH} -miphoneos-version-min=$(OS_VERSION)
+       IOSROOT         = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.Internal.sdk
+       CC                      = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cc -arch ${ARCH} -miphoneos-version-min=$(OS_VERSION) -isysroot $(IOSROOT)
+       CXX                     = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/c++ -arch ${ARCH} -miphoneos-version-min=$(OS_VERSION) -isysroot $(IOSROOT)
 else
 else
-       CC                      = gcc-4.2 -arch ${ARCH} -mmacosx-version-min=$(OS_VERSION)
-       CXX                     = g++-4.2 -arch ${ARCH} -mmacosx-version-min=$(OS_VERSION)
+       CC                      = cc -arch ${ARCH} -mmacosx-version-min=$(OS_VERSION)
+       CXX                     = c++ -arch ${ARCH} -mmacosx-version-min=$(OS_VERSION)
 endif
 
 CCFLAGS                = -Wall -std=c99
 endif
 
 CCFLAGS                = -Wall -std=c99
index 91659ba8c6b82369bc42497441a1eefd17036ff9..ceb2106175320b8adf5a54df3f1bd86d91b23c8f 100755 (executable)
@@ -8,7 +8,7 @@ CRSTATE=`defaults read com.apple.CrashReporter DialogType`
 defaults write com.apple.CrashReporter DialogType basic
 
 # run test targeting different OS versions
 defaults write com.apple.CrashReporter DialogType basic
 
 # run test targeting different OS versions
-for OSVERSION in 10.7 10.6 10.5 10.4
+for OSVERSION in 10.8 10.7 10.6 10.5 10.4
 do 
        echo ""
        echo " * * * Running all unit tests i386 built for $OSVERSION * * *"
 do 
        echo ""
        echo " * * * Running all unit tests i386 built for $OSVERSION * * *"
index a903b04b7af5f87d08bf09d77ae989c26cd38043..224d93e8527e7a64f070ef5878d9d8b5daea06bd 100644 (file)
@@ -34,12 +34,14 @@ extern int foo();
 
 int main(int argc, const char* argv[])
 {
 
 int main(int argc, const char* argv[])
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
+#endif
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
index 36bf14e786f65b382f80283425ffaeccb7bf68dc..5c0374b60e36fa06f432aa008b7cf3d15c85387e 100644 (file)
@@ -25,9 +25,21 @@ include ${TESTROOT}/include/common.makefile
 
 PWD = $(shell pwd)
 
 
 PWD = $(shell pwd)
 
-all-check: all check
+ifeq "$(OS_NAME)" "iPhoneOS"
+       CHECK = check-ios
+else
+       CHECK = check-macosx
+endif
 
 
-check:
+
+all-check: all $(CHECK)
+
+check: $(CHECK)
+
+check-ios:
+       ./main 10
+
+check-macosx:
        ./main 10
        export DYLD_VERSIONED_FRAMEWORK_PATH="${PWD}/alt11" && ./main 11
        export DYLD_VERSIONED_FRAMEWORK_PATH="${PWD}/alt9" && ./main 10
        ./main 10
        export DYLD_VERSIONED_FRAMEWORK_PATH="${PWD}/alt11" && ./main 11
        export DYLD_VERSIONED_FRAMEWORK_PATH="${PWD}/alt9" && ./main 10
index a903b04b7af5f87d08bf09d77ae989c26cd38043..2815ba1fc4a15c334671077aec18bb5957a04351 100644 (file)
@@ -34,13 +34,15 @@ extern int foo();
 
 int main(int argc, const char* argv[])
 {
 
 int main(int argc, const char* argv[])
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
-               FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
+               FAIL("DYLD_VERSIONED_FRAMEWORK_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
        else
-               PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
+#endif
+               PASS("DYLD_VERSIONED_FRAMEWORK_PATH-basic");
                
        return EXIT_SUCCESS;
 }
                
        return EXIT_SUCCESS;
 }
index 2be1439c6a46c8a120534bb694682c121dae936c..788e74af44df5e610f57dc2a0360d32d94fb00e7 100644 (file)
@@ -25,9 +25,20 @@ include ${TESTROOT}/include/common.makefile
 
 PWD = $(shell pwd)
 
 
 PWD = $(shell pwd)
 
+ifeq "$(OS_NAME)" "iPhoneOS"
+       CHECK = check-ios
+else
+       CHECK = check-macosx
+endif
+
 all-check: all check
 
 all-check: all check
 
-check:
+check: $(CHECK)
+
+check-ios:
+       ./main 10
+
+check-macosx:
        ./main 10
        export DYLD_VERSIONED_LIBRARY_PATH="${PWD}/alt11" && ./main 11
        export DYLD_VERSIONED_LIBRARY_PATH="${PWD}/alt9" && ./main 10
        ./main 10
        export DYLD_VERSIONED_LIBRARY_PATH="${PWD}/alt11" && ./main 11
        export DYLD_VERSIONED_LIBRARY_PATH="${PWD}/alt9" && ./main 10
index a903b04b7af5f87d08bf09d77ae989c26cd38043..224d93e8527e7a64f070ef5878d9d8b5daea06bd 100644 (file)
@@ -34,12 +34,14 @@ extern int foo();
 
 int main(int argc, const char* argv[])
 {
 
 int main(int argc, const char* argv[])
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
+#endif
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
index a903b04b7af5f87d08bf09d77ae989c26cd38043..224d93e8527e7a64f070ef5878d9d8b5daea06bd 100644 (file)
@@ -34,12 +34,14 @@ extern int foo();
 
 int main(int argc, const char* argv[])
 {
 
 int main(int argc, const char* argv[])
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
+#endif
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
index a903b04b7af5f87d08bf09d77ae989c26cd38043..224d93e8527e7a64f070ef5878d9d8b5daea06bd 100644 (file)
@@ -34,12 +34,14 @@ extern int foo();
 
 int main(int argc, const char* argv[])
 {
 
 int main(int argc, const char* argv[])
 {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
        int expectedResult = atoi(argv[1]);
        int actualResult = foo();
        //fprintf(stderr, "foo() returned %d, expected %d\n", actualResult, expectedResult);
        if ( actualResult != expectedResult )
                FAIL("DYLD_VERSIONED_LIBRARY_PATH-basic using wrong dylib. foo() returned %d, expected %d", actualResult, expectedResult);
        else
+#endif
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
                PASS("DYLD_VERSIONED_LIBRARY_PATH-basic");
                
        return EXIT_SUCCESS;
index 006adaa4e6fd94610d157bb4317dd643028dae6f..72b371028e2a70052d0aabe43d5286945af6275d 100644 (file)
@@ -38,6 +38,13 @@ const char* pc   = &c;
 const char* pd_2 = &d - 2;
 const char* pb2  = &b + 2;
 
 const char* pd_2 = &d - 2;
 const char* pb2  = &b + 2;
 
+const char* pd_1234567890 = &d - 1234567890;
+const char* pd1234567890  = &d + 1234567890;
+
+#if __LP64__
+const char* pd_12345678901234 = &d - 12345678901234;
+const char* pd12345678901234  = &d + 12345678901234;
+#endif
 
 int main()
 {
 
 int main()
 {
@@ -56,6 +63,28 @@ int main()
                return 0;
        }
        
                return 0;
        }
        
+       if (pd_1234567890[1234567890] != 13 ) {
+               FAIL("addend: pd_1234567890[1234567890] != 13");
+               return 0;
+       }
+       
+       if (pd1234567890[-1234567890] != 13 ) {
+               FAIL("addend: pd1234567890[-1234567890] != 13");
+               return 0;
+       }
+       
+#if __LP64__
+       if (pd_12345678901234[12345678901234] != 13 ) {
+               FAIL("addend: pd_12345678901234[12345678901234] != 13");
+               return 0;
+       }
+       
+       if (pd12345678901234[-12345678901234] != 13 ) {
+               FAIL("addend: pd12345678901234[-12345678901234] != 13");
+               return 0;
+       }
+#endif 
+       
        PASS("addend");
        return 0;
 }
        PASS("addend");
        return 0;
 }
index 687eea699d8a9073c8862adc9cce9e5e576322a7..e87cda5f81b5ac85327d8ef2ea883ba9d3b005bd 100644 (file)
@@ -1,5 +1,5 @@
 ##
 ##
-# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2005-2011 Apple Inc. All rights reserved.
 #
 # @APPLE_LICENSE_HEADER_START@
 # 
 #
 # @APPLE_LICENSE_HEADER_START@
 # 
@@ -23,7 +23,7 @@
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
-FATFLAGS = `lipo -detailed_info /usr/lib/libSystem.B.dylib | grep architecture | sed -e 's/architecture/-arch/'`
+FATFLAGS = $(shell lipo -detailed_info $(IOSROOT)/usr/lib/libSystem.B.dylib | grep architecture | sed -e 's/architecture/-arch/')
 
 all-check: all check
 
 
 all-check: all check
 
@@ -36,7 +36,9 @@ main : main.c
        ${CC} ${CCFLAGS}  -Wno-deprecated-declarations -I${TESTROOT}/include -o main main.c
 
 test.bundle : bundle.c
        ${CC} ${CCFLAGS}  -Wno-deprecated-declarations -I${TESTROOT}/include -o main main.c
 
 test.bundle : bundle.c
-       gcc ${FATFLAGS} -bundle -o test.bundle bundle.c
+       echo ${IOSROOT}
+       echo $(IOSROOT)
+       ${CC} ${FATFLAGS} -bundle -o test.bundle bundle.c
 
 clean:
        ${RM} ${RMFLAGS} *~ main test.bundle
 
 clean:
        ${RM} ${RMFLAGS} *~ main test.bundle
index 938ea758f3d4d96c739419d51519ca5e363ebf27..56690a786c53faa33a1f158f8d5feffb444b2317 100644 (file)
@@ -28,5 +28,5 @@ static int mydata[10];
 
 bool checkdata()
 {
 
 bool checkdata()
 {
-       return ( mydata[10] == 0 );
+       return ( mydata[9] == 0 );
 }
 }
index 78e43d593663fc35b4fde857c2818ec099639454..bc160be597304c3f323ed2db1376709f49910975 100644 (file)
@@ -23,6 +23,9 @@
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
+SHELL = bash # use bash shell so we can redirect just stderr
+
+
 #
 # verify that apple[0] parameter is correct by comparing to argv[1]
 #
 #
 # verify that apple[0] parameter is correct by comparing to argv[1]
 #
@@ -34,7 +37,7 @@ check:
        ./main.stripped ./main.stripped
        `pwd`/main `pwd`/main
        `pwd`/main.stripped `pwd`/main.stripped
        ./main.stripped ./main.stripped
        `pwd`/main `pwd`/main
        `pwd`/main.stripped `pwd`/main.stripped
-       export DYLD_LIBRARY_PATH=. && export DYLD_FRAMEWORK_PATH=. && ./main-setuid ./main-setuid
+       export DYLD_LIBRARY_PATH=. && export DYLD_FRAMEWORK_PATH=. && ./main-setuid ./main-setuid 2>/dev/null
 
 all: main  main.stripped main-setuid
 
 
 all: main  main.stripped main-setuid
 
index 0d888ad0dda43e3a636d75a6398c8998f326c9d2..8a56fd87a9d27046301920e2ae031ae53d7308f7 100644 (file)
@@ -71,9 +71,9 @@ main(int argc, const char* argv[], const char* env[], const char* apple[])
        }
                
        if ( strcmp(apple[0], argv[1]) == 0 )
        }
                
        if ( strcmp(apple[0], argv[1]) == 0 )
-               PASS("crt-apple %s", argv[0]);
+               PASS("crt-apple %s", apple[0]);
        else
        else
-               FAIL("crt-apple %s", argv[0]);
+               FAIL("crt-apple %s", apple[0]);
                
        return EXIT_SUCCESS;
 }
                
        return EXIT_SUCCESS;
 }
index ee12f105146b48667b67772d81ed3b223d8e75bf..7bb8ddc395aa144319b49846c0c06f3bdb82a56c 100644 (file)
@@ -37,7 +37,7 @@ check:
 all: main
 
 main: main.c
 all: main
 
 main: main.c
-       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main mystart.s main.c -e _mystart
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main mystart.s main.c -e _mystart -Wl,-no_new_main
 
 
 clean:
 
 
 clean:
index a95e0b511824da84125229e77e559f1634e8419f..c507706d66d05875fb77e7c9dcf213b417799705 100644 (file)
@@ -6,6 +6,7 @@
 
 
        .text
 
 
        .text
+       .align 2
        .globl _mystart
 _mystart:
 #if __i386__ 
        .globl _mystart
 _mystart:
 #if __i386__ 
diff --git a/unit-tests/test-cases/dlopen_preflight-cycle/Makefile b/unit-tests/test-cases/dlopen_preflight-cycle/Makefile
new file mode 100644 (file)
index 0000000..2123b40
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2011 Apple 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
+
+all-check: all check
+
+check:
+       ./main
+
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c 
+       ${CC} ${CCFLAGS} -dynamiclib -I${TESTROOT}/include -o libbar.dylib bar.c 
+       ${CC} ${CCFLAGS} -dynamiclib -I${TESTROOT}/include -o libbaz.dylib baz.c -Wl,-upward_library,libbar.dylib
+       ${CC} ${CCFLAGS} -dynamiclib -I${TESTROOT}/include -o libbar.dylib bar.c  libbaz.dylib
+       ${CC} ${CCFLAGS} -dynamiclib -I${TESTROOT}/include -o libfoo.dylib foo.c libbar.dylib  
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libbaz.dylib libbar.dylib libfoo.dylib 
+
diff --git a/unit-tests/test-cases/dlopen_preflight-cycle/bar.c b/unit-tests/test-cases/dlopen_preflight-cycle/bar.c
new file mode 100644 (file)
index 0000000..63c34e0
--- /dev/null
@@ -0,0 +1,2 @@
+
+int bar = 10;
diff --git a/unit-tests/test-cases/dlopen_preflight-cycle/baz.c b/unit-tests/test-cases/dlopen_preflight-cycle/baz.c
new file mode 100644 (file)
index 0000000..256a0e3
--- /dev/null
@@ -0,0 +1 @@
+void baz() {}
diff --git a/unit-tests/test-cases/dlopen_preflight-cycle/foo.c b/unit-tests/test-cases/dlopen_preflight-cycle/foo.c
new file mode 100644 (file)
index 0000000..6924ac6
--- /dev/null
@@ -0,0 +1,3 @@
+
+void foo() {}
+
diff --git a/unit-tests/test-cases/dlopen_preflight-cycle/main.c b/unit-tests/test-cases/dlopen_preflight-cycle/main.c
new file mode 100644 (file)
index 0000000..af5caec
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011 Apple 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
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <stdbool.h>
+#include <string.h>
+#include <mach-o/dyld.h>  
+#include <mach-o/dyld_priv.h>  
+#include <dlfcn.h>  
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int main(int argc, const char* argv[])
+{
+       if ( ! dlopen_preflight("libfoo.dylib") ) {
+               FAIL("dlopen_preflight-cycle libfoo.dylib should not be loadable");
+               return EXIT_SUCCESS;
+       }
+
+       void* handle = dlopen("libbar.dylib", RTLD_NOLOAD);
+       if ( handle != NULL ) {
+               FAIL("dlopen_preflight-cycle libbar.dylib was left loaded by dlopen_preflight()");
+               return EXIT_SUCCESS;
+       }
+       
+       handle = dlopen("libbaz.dylib", RTLD_NOLOAD);
+       if ( handle != NULL ) {
+               FAIL("dlopen_preflight-cycle libbaz.dylib was left loaded by dlopen_preflight()");
+               return EXIT_SUCCESS;
+       }
+
+       handle = dlopen("libfoo.dylib", RTLD_NOLOAD);
+       if ( handle != NULL ) {
+               FAIL("dlopen_preflight-cycle libfoo.dylib was left loaded by dlopen_preflight()");
+               return EXIT_SUCCESS;
+       }
+
+       PASS("dlopen_preflight-cycle");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/dyld-slide/Makefile b/unit-tests/test-cases/dyld-slide/Makefile
deleted file mode 100644 (file)
index aa3debf..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-##
-# Copyright (c) 2005-2009 Apple 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
-
-STACK_BASE = 0x8fe01000
-STACK_SIZE = 0x00100000
-
-ifeq "armv6" "$(ARCH)"
-       STACK_BASE = 0x2fe01000
-       STACK_SIZE = 0x00100000
-endif
-ifeq "armv7" "$(ARCH)"
-       STACK_BASE = 0x2fe01000
-       STACK_SIZE = 0x00100000
-endif
-ifeq "ppc64" "$(ARCH)"
-       STACK_BASE = 0x7fff5ff00000
-       STACK_SIZE = 0x00400000
-endif
-ifeq "x86_64" "$(ARCH)"
-       STACK_BASE = 0x7fff5ff00000
-       STACK_SIZE = 0x00400000
-endif
-
-
-
-all-check: all check
-
-check:
-       ${TESTROOT}/bin/exit-zero-pass.pl "dyld did slide" "dyld did not slide" ./main
-
-all:
-       ${CC} ${CCFLAGS} -Wno-deprecated-declarations -I${TESTROOT}/include -o main main.c -Wl,-stack_addr,${STACK_BASE} -Wl,-stack_size,${STACK_SIZE}
-
-clean:
-       ${RM} ${RMFLAGS} main
diff --git a/unit-tests/test-cases/dyld-slide/main.c b/unit-tests/test-cases/dyld-slide/main.c
deleted file mode 100644 (file)
index a689f63..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2005-2009 Apple 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 <dlfcn.h>
-#include <mach-o/dyld_priv.h>
-
-#include "test.h"
-
-//
-// This builds an executable that is just big enough to force dyld to slide a bit
-//
-#if __arm__
-       #define ARRAY_SIZE  66582528
-#else
-       #define ARRAY_SIZE 335400000
-#endif
-
-//int bigarray1[ARRAY_SIZE];
-
-int
-main()
-{
-       // call a dyld function that will execute lots of code and bus error dyld was not slid
-       dlsym(RTLD_DEFAULT, "foobar");
-
-       return EXIT_SUCCESS;
-}
-
-
index f0ea7791a905a2818cc4dec56bcf879b1801dc16..351769ade4e45506648ee73f69b123e61ffc838a 100644 (file)
@@ -31,6 +31,8 @@
 ///  main links directly against one libfoo.dylib and indirectly through libbar.dylib with the other.
 ///
 
 ///  main links directly against one libfoo.dylib and indirectly through libbar.dylib with the other.
 ///
 
+extern int foo();
+extern int bar();
 
 int main(int argc, const char* argv[])
 {
 
 int main(int argc, const char* argv[])
 {
diff --git a/unit-tests/test-cases/image-state-deny-all_image_infos/Makefile b/unit-tests/test-cases/image-state-deny-all_image_infos/Makefile
new file mode 100644 (file)
index 0000000..56dd654
--- /dev/null
@@ -0,0 +1,41 @@
+##
+# Copyright (c) 2011 Apple 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
+
+all-check: all check
+
+check:
+       ./main
+
+all: main bar.bundle
+
+main: main.c
+       ${CC} ${CCFLAGS} -Wno-deprecated-declarations  -I${TESTROOT}/include -o main main.c 
+
+bar.bundle: bar.c
+       ${CC} ${CCFLAGS} -bundle -I${TESTROOT}/include -o bar.bundle bar.c  
+
+clean:
+       ${RM} ${RMFLAGS} *~ main bar.bundle
+
diff --git a/unit-tests/test-cases/image-state-deny-all_image_infos/bar.c b/unit-tests/test-cases/image-state-deny-all_image_infos/bar.c
new file mode 100644 (file)
index 0000000..e425999
--- /dev/null
@@ -0,0 +1 @@
+void bar() {}
diff --git a/unit-tests/test-cases/image-state-deny-all_image_infos/main.c b/unit-tests/test-cases/image-state-deny-all_image_infos/main.c
new file mode 100644 (file)
index 0000000..ed4b56c
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <stdbool.h>
+#include <string.h>
+#include <mach-o/dyld.h>  
+#include <mach-o/dyld_images.h>
+#include <mach-o/dyld_priv.h>  
+#include <dlfcn.h>  
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+//
+// By returning a string, we prevent that image from loading.
+// We just prevent any image with "bar" in its name from loading.
+//
+
+
+static const char* singleMappedHandler(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[])
+{
+       //fprintf(stderr, "single mapped: %s\n", info[0].imageFilePath);
+       if ( strstr(info[0].imageFilePath, "bar") != NULL )
+               return "can't load bar";
+       return NULL;
+}
+
+
+static void load(const char* name)
+{
+       void* handle = dlopen(name, RTLD_LAZY);
+       if ( handle != NULL ) {
+               FAIL("image-state-deny-all_image_infos: dlopen(%s) should have failed", name);
+               exit(0);
+       }
+}
+
+
+int main(int argc, const char* argv[])
+{
+       // tell dyld we want to know when images are mapped
+       dyld_register_image_state_change_handler(dyld_image_state_mapped, false, singleMappedHandler);
+       
+    const struct dyld_all_image_infos* infos = _dyld_get_all_image_infos();
+    const uint32_t initialCount = infos->infoArrayCount;
+    
+       load("bar.bundle");
+
+    if ( infos->infoArrayCount != initialCount ){
+               FAIL("image-state-deny-all_image_infos: infoArrayCount should not have changed");
+               exit(0);
+       }
+
+    //for (int i=0; i < infos->infoArrayCount; ++i)
+    //    printf("mh=%p, path=%s\n", infos->infoArray[i].imageLoadAddress, infos->infoArray[i].imageFilePath); 
+       
+       PASS("image-state-deny-all_image_infos");
+               
+       return EXIT_SUCCESS;
+}
index 28b4c8e65e192fbfd52272376301090425fa8fa0..204744edc04fadd177c9644e3aa818454fa398a3 100644 (file)
@@ -22,6 +22,7 @@
  */
 #include <stdlib.h>
 #include <mach-o/dyld.h>
  */
 #include <stdlib.h>
 #include <mach-o/dyld.h>
+#include <dlfcn.h>
 
 #include "test.h"
 
 
 #include "test.h"
 
index aa3576533c261447cb10520fa690a80052877deb..42f9e422aa7897314937b792562b24ab2d56bfe7 100644 (file)
@@ -26,7 +26,7 @@ include ${TESTROOT}/include/common.makefile
 all-check: all check
 
 check:
 all-check: all check
 
 check:
-       ./main 
+       ${PASS_IFF_FAILURE} ./main 
        
 all:
        ${CC} ${CCFLAGS} -I${TESTROOT}/include bar.c -dynamiclib -o libbar.dylib
        
 all:
        ${CC} ${CCFLAGS} -I${TESTROOT}/include bar.c -dynamiclib -o libbar.dylib
index f466342a153d76b0d9880dcac03f02123f2fee5a..bd4a512b0aed4f7fdb74b68137e145101125c90a 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -30,13 +30,9 @@ extern int bar;
 int
 main()
 {
 int
 main()
 {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
        if ( bar == 1 )
                FAIL("initializer-bounds-check, out of bounds initializer called");
        else
                PASS("initializer-bounds-check");
        if ( bar == 1 )
                FAIL("initializer-bounds-check, out of bounds initializer called");
        else
                PASS("initializer-bounds-check");
-#else
-               PASS("initializer-bounds-check");
-#endif
   return EXIT_SUCCESS;
 }
   return EXIT_SUCCESS;
 }
index b270917c5e946eb36af4dd643dde5050a180f948..c06cad5f7f5324eaa8e2c13fcfcc9668f1cf16c7 100644 (file)
@@ -23,6 +23,8 @@
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
+SHELL = bash # use bash shell so we can redirect just stderr
+
 PWD = `pwd`
 
 ifeq "$(OS_NAME)" "iPhoneOS"
 PWD = `pwd`
 
 ifeq "$(OS_NAME)" "iPhoneOS"
@@ -34,7 +36,7 @@ endif
 all-check: all check
 
 check:
 all-check: all check
 
 check:
-       ${RUN_AS_USER} $(PWD)/main-with-env
+       ${RUN_AS_USER} $(PWD)/main-with-env insert-libraries-with-suid 2>/dev/null
 
 all: main
 
 
 all: main
 
index 192b3b6dc4f912500549a88240ff121cf79f1a76..93ef8980e8ec34ad752531f6e3dcd66593113a53 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2005-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <string.h>
 #include <dlfcn.h>
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <string.h>
 #include <dlfcn.h>
+#include <stdbool.h>
 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
+extern bool allocationSeen(void* p);
+typedef bool (*seenProc)(void*);
 
 int main()
 {
 
 int main()
 {
-       const char* x = strdup("123");
-  
-       if ( (strcmp(&x[-16], "hello") == 0) )
+       void* x = strdup("123");
+       
+       seenProc seen = (seenProc)dlsym(RTLD_DEFAULT, "allocationSeen");
+       
+       if ( (seen != NULL) && (*seen)(x) )
                PASS("interpose-basic-shared-cache");
        else
                FAIL("interpose-basic-shared-cache");
                PASS("interpose-basic-shared-cache");
        else
                FAIL("interpose-basic-shared-cache");
index 9afe7f15bd865d2a29c99d170bf6ddf83dd22edb..bca0938823d2b1e8b85e66a79cd04f7ea35e9092 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2005-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2005-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  */
 
 #include <stdlib.h>
  */
 
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <string.h>
+#include <stdbool.h>
 #include <mach-o/dyld-interposing.h>
 #include <mach-o/dyld-interposing.h>
+#include <malloc/malloc.h>
 
 
-// return blocks that have preceeding 16-bytes filled with "hello"
+static void* seenAllocations[128];
+static int seenAllocationIndex = 0;
+
+// record each malloc result in a ring buffer
 void* my_malloc(size_t size)
 {
 void* my_malloc(size_t size)
 {
-       char* x = malloc(size+16);
-       strcpy(x, "hello");
-       return &x[16];
+       char* x = malloc(size);
+       seenAllocations[seenAllocationIndex++] = x;
+       seenAllocationIndex = (seenAllocationIndex & 127); //wrap around
+       return x;
 }
 
 DYLD_INTERPOSE(my_malloc, malloc)
 }
 
 DYLD_INTERPOSE(my_malloc, malloc)
+
+bool allocationSeen(void* p)
+{
+       for(int i=0; i < 127; ++i) {
+               if ( seenAllocations[i] == p )
+                       return true;
+       }
+       return false;
+}
+
+
+
diff --git a/unit-tests/test-cases/loader_path-symlink/Makefile b/unit-tests/test-cases/loader_path-symlink/Makefile
new file mode 100644 (file)
index 0000000..7fab8fc
--- /dev/null
@@ -0,0 +1,49 @@
+##
+# Copyright (c) 2012 Apple 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
+
+PWD = $(shell pwd)
+
+#
+# <rdar://problem/10879179> a dylib is found via symlink and must find another dylib relative to the symlink
+#
+
+all-check: all check
+
+check:
+       ./bin/main
+
+all: 
+       mkdir -p Frameworks/Foo.framework/Versions/A
+       mkdir -p Frameworks/Bar.framework/Versions/A
+       ${CC} bar.c -dynamiclib -o Frameworks/Bar.framework/Versions/A/Bar -install_name @loader_path/../Bar.framework/Bar
+       (cd Frameworks/Foo.framework; ln -fs Versions/A/Foo)
+       (cd Frameworks/Bar.framework; ln -fs Versions/A/Bar)
+       ${CC} foo.c -dynamiclib -o Frameworks/Foo.framework/Versions/A/Foo -install_name @loader_path/../Frameworks/Foo.framework/Foo Frameworks/Bar.framework/Versions/A/Bar
+       mkdir -p bin
+       ${CC} -I${TESTROOT}/include main.c -o bin/main Frameworks/Foo.framework/Versions/A/Foo
+       
+
+clean:
+       ${RM} -rf *~  Frameworks bin
diff --git a/unit-tests/test-cases/loader_path-symlink/bar.c b/unit-tests/test-cases/loader_path-symlink/bar.c
new file mode 100644 (file)
index 0000000..b72a1a5
--- /dev/null
@@ -0,0 +1,3 @@
+void bar()
+{
+}
diff --git a/unit-tests/test-cases/loader_path-symlink/foo.c b/unit-tests/test-cases/loader_path-symlink/foo.c
new file mode 100644 (file)
index 0000000..3695dc9
--- /dev/null
@@ -0,0 +1,3 @@
+void foo()
+{
+}
diff --git a/unit-tests/test-cases/loader_path-symlink/main.c b/unit-tests/test-cases/loader_path-symlink/main.c
new file mode 100644 (file)
index 0000000..4c91a7c
--- /dev/null
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+extern void foo();
+
+int main()
+{
+       foo();
+       PASS("loader_path-symlink");
+       return EXIT_SUCCESS;
+}
index a83adcd1e9f6bdb4f7f4fac6dfdc901a25c9f8af..31d75d6b20e4c3809f4ab1e85793c2f35331bf9b 100644 (file)
@@ -29,6 +29,10 @@ ifeq "x86_64" "$(ARCH)"
        EXTRA_OPTIONS = 
 endif
 
        EXTRA_OPTIONS = 
 endif
 
+ifeq "iPhoneOS" "$(OS_NAME)"
+       EXTRA_OPTIONS = 
+endif
+
 
 # run a PIE four times and verify its load address was different every time
 
 
 # run a PIE four times and verify its load address was different every time
 
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/Makefile b/unit-tests/test-cases/re-export-symbol-dylib/Makefile
new file mode 100644 (file)
index 0000000..9465192
--- /dev/null
@@ -0,0 +1,59 @@
+##
+# Copyright (c) 2011 Apple 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
+
+
+
+#
+# Test that fine grain re-exports works
+#
+
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
+
+all: all_$(OS_LION_FEATURES)
+
+check: check_$(OS_LION_FEATURES)
+
+check_1:
+       ./main
+
+all_1:
+       # build frob
+       ${CC} ${CCFLAGS} -dynamiclib frob.c -o libfrob.dylib
+       # build baz to re-export all of frob
+       ${CC} ${CCFLAGS} -dynamiclib baz.c -o libbaz.dylib -exported_symbols_list baz.exp libfrob.dylib
+       # build bar to re-export all of baz
+       ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib -Wl,-reexport_library,libbaz.dylib
+       # build foo to re-export all of bar
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib -exported_symbols_list foo.exp  libbar.dylib
+       # buid main
+       ${CC} ${CCFLAGS} main.c -I${TESTROOT}/include libfoo.dylib -o main
+
+check_:
+       ${PASS_IFF} true
+
+all_:
+       
+clean:
+       rm -rf libbar.dylib libfoo.dylib libbaz.dylib libfrob.dylib  main
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/bar.c b/unit-tests/test-cases/re-export-symbol-dylib/bar.c
new file mode 100644 (file)
index 0000000..18d7633
--- /dev/null
@@ -0,0 +1,5 @@
+
+int bar(void)
+{
+       return 2;
+}
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/baz.c b/unit-tests/test-cases/re-export-symbol-dylib/baz.c
new file mode 100644 (file)
index 0000000..cb30818
--- /dev/null
@@ -0,0 +1,5 @@
+int baz() 
+{
+  return 3;
+}
+
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/baz.exp b/unit-tests/test-cases/re-export-symbol-dylib/baz.exp
new file mode 100644 (file)
index 0000000..5fbf7f4
--- /dev/null
@@ -0,0 +1,2 @@
+_baz
+_frob
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/foo.c b/unit-tests/test-cases/re-export-symbol-dylib/foo.c
new file mode 100644 (file)
index 0000000..72b3c29
--- /dev/null
@@ -0,0 +1,4 @@
+int foo(void)
+{
+       return 1;
+}
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/foo.exp b/unit-tests/test-cases/re-export-symbol-dylib/foo.exp
new file mode 100644 (file)
index 0000000..aff96a1
--- /dev/null
@@ -0,0 +1,4 @@
+_foo
+_bar
+_baz
+_frob
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/frob.c b/unit-tests/test-cases/re-export-symbol-dylib/frob.c
new file mode 100644 (file)
index 0000000..3df9d3d
--- /dev/null
@@ -0,0 +1,5 @@
+int frob()
+{
+  return 4;
+}
+
diff --git a/unit-tests/test-cases/re-export-symbol-dylib/main.c b/unit-tests/test-cases/re-export-symbol-dylib/main.c
new file mode 100644 (file)
index 0000000..f12dd10
--- /dev/null
@@ -0,0 +1,44 @@
+
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+extern int foo();
+extern int bar();
+extern int baz();
+extern int frob();
+
+int (*pfoo)() = &foo;
+int (*pbar)() = &bar;
+int (*pbaz)() = &baz;
+int (*pfrob)() = &frob;
+
+
+int main()
+{
+       if ( foo() != 1 )
+               FAIL("re-export-symbol-dylib: foo() returned wrong value");
+       else if ( bar() != 2 )
+               FAIL("re-export-symbol-dylib: bar() returned wrong value");
+       else if ( baz() != 3 )
+               FAIL("re-export-symbol-dylib: baz() returned wrong value");
+       else if ( frob() != 4 )
+               FAIL("re-export-symbol-dylib: frob() returned wrong value");
+    
+       else if ( (*pfoo)() != 1 )
+               FAIL("re-export-symbol-dylib: (*pfoo)() returned wrong value");
+       else if ( (*pbar)() != 2 )
+               FAIL("re-export-symbol-dylib: (*pbar)() returned wrong value");
+       else if ( (*pbaz)() != 3 )
+               FAIL("re-export-symbol-dylib: (*pbaz)() returned wrong value");
+       else if ( (*pfrob)() != 4 )
+               FAIL("re-export-symbol-dylib: (*pfrob)() returned wrong value");
+    else 
+        PASS("re-export-symbol-dylib");
+       return 0;
+}
+
index 3be241506771130cf56fc1d96807f4d71f37e797..c02f9124731576ef65bb0da24b08227e99d13fc1 100644 (file)
@@ -29,11 +29,11 @@ include ${TESTROOT}/include/common.makefile
 # Test that fine grain re-exports works
 #
 
 # Test that fine grain re-exports works
 #
 
-all-check: all_$(OS_BAROLO_FEATURES) check_$(OS_BAROLO_FEATURES)
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
 
 
-all: all_$(OS_BAROLO_FEATURES)
+all: all_$(OS_LION_FEATURES)
 
 
-check: check_$(OS_BAROLO_FEATURES)
+check: check_$(OS_LION_FEATURES)
 
 check_1:
        ./main1
 
 check_1:
        ./main1
index fdadfc76c49a7980965cd06ab7bf54729c6987d9..b9420c7bf40e626d34b7b9a77062e156a87ebd6f 100644 (file)
 #include <stdio.h>  // fprintf(), NULL
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <unistd.h>
 #include <stdio.h>  // fprintf(), NULL
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <unistd.h>
+#include <Availability.h>
 #include <mach-o/getsect.h>
 #include <mach/mach.h> 
 #include <mach/mach_vm.h> 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
 #include <mach-o/getsect.h>
 #include <mach/mach.h> 
 #include <mach/mach_vm.h> 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
 
 extern void foo();
 extern int fooData;
 
 extern void foo();
 extern int fooData;
@@ -107,4 +109,14 @@ int main()
        return EXIT_SUCCESS;
 }
 
        return EXIT_SUCCESS;
 }
 
+#else
+
+int main()
+{
+       // iOS does not have modifiable stubs
+       PASS("read-only-stubs");
+       return EXIT_SUCCESS;
+}
+
+#endif
 
 
index 8aa6bea413796277bf79a76cefeeea50061c6015..a22a543f29bf47221e58db79c6e774c85a73f7e4 100644 (file)
@@ -23,6 +23,8 @@
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
+SHELL = bash # use bash shell so we can redirect just stderr
+
 ifeq "$(OS_NAME)" "iPhoneOS"
        RUN_AS_USER = login -f -l mobile
 else
 ifeq "$(OS_NAME)" "iPhoneOS"
        RUN_AS_USER = login -f -l mobile
 else
@@ -34,7 +36,7 @@ PWD = `pwd`
 all-check: all check
 
 check:
 all-check: all check
 
 check:
-       ${RUN_AS_USER} $(PWD)/main-with-env
+       ${RUN_AS_USER} $(PWD)/main-with-env 2>/dev/null
 
 all: main
 
 
 all: main
 
index d4f0b335ee313a6db8819a80e19fbbe311bdd52c..9857c71564b27a78004d4731ecc72936bc392e00 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <dlfcn.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <dlfcn.h>
+#include <unistd.h>
 #include <mach-o/dyld.h>
 
 #include "test.h"
 #include <mach-o/dyld.h>
 
 #include "test.h"
diff --git a/unit-tests/test-cases/rpath-introspection/Makefile b/unit-tests/test-cases/rpath-introspection/Makefile
new file mode 100644 (file)
index 0000000..ec5d680
--- /dev/null
@@ -0,0 +1,44 @@
+##
+# Copyright (c) 2012 Apple 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
+
+PWD = $(shell pwd)
+
+#
+# Checks that @rpath that expands to have ../ in it will get realpathed and 
+# .. will not be seen when introspecting dylibs
+#
+
+all-check: all check
+
+check:
+       ./main
+
+all:
+       mkdir -p hide/hole
+       ${CC} foo.c -dynamiclib -o hide/hole/libfoo.dylib -install_name @rpath/libfoo.dylib 
+       ${CC} -I${TESTROOT}/include main.c -o main hide/hole/libfoo.dylib -Wl,-rpath -Wl,${PWD}/hide/../hide/hole
+
+clean:
+       ${RM} -rf *~  main hide
diff --git a/unit-tests/test-cases/rpath-introspection/foo.c b/unit-tests/test-cases/rpath-introspection/foo.c
new file mode 100644 (file)
index 0000000..3695dc9
--- /dev/null
@@ -0,0 +1,3 @@
+void foo()
+{
+}
diff --git a/unit-tests/test-cases/rpath-introspection/main.c b/unit-tests/test-cases/rpath-introspection/main.c
new file mode 100644 (file)
index 0000000..6eba6da
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012 Apple 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 <dlfcn.h>
+#include <string.h>
+
+#include "test.h"
+
+extern void foo();
+
+int main()
+{
+       foo();
+       
+       // make sure foo's path does not have .. in it
+       int count = _dyld_image_count();
+       bool found = false;
+       for(int i=0; i < count; ++i) {
+               const char* name = _dyld_get_image_name(i);
+               if ( strstr(name, "libfoo.dylib") == 0 ) {
+                       found = true;
+                       if ( strstr(name, "..") != NULL ) {
+                               FAIL("rpath-introspection: _dyld_get_image_name(%d) returned %s", i, name);
+                               return EXIT_SUCCESS;
+                       }
+               }
+       }
+       if ( !found ) {
+               FAIL("rpath-introspection: _dyld_get_image_name() never returned libfoo.dylib");
+               return EXIT_SUCCESS;
+       }
+       
+       // make sure dladdr path does not have .. in it
+       Dl_info info;
+       if ( dladdr(&foo, &info) == 0 ) {
+               FAIL("rpath-introspection: dladdr() failed");
+               return EXIT_SUCCESS;
+       }
+       if ( strstr(info.dli_fname, "..") != NULL ) {
+               FAIL("rpath-introspection: dladdr() returned path with .. in it");
+               return EXIT_SUCCESS;
+       }
+       
+       PASS("rpath-introspection");
+       return EXIT_SUCCESS;
+}
index 2b1cc256fcb755003d08c0282a5e076ef4747d4f..69b4a598cb6feac4cca88dfdefaad9152d8e7f05 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <dlfcn.h>
 
 #include "test.h"
 
 
 #include "test.h"
 
index 7797d2e4942537162e344183ed735917942d66b6..6356a4a6f83a551e326915b302e9a2b83fc6eb00 100644 (file)
@@ -23,6 +23,8 @@
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
+SHELL = bash # use bash shell so we can redirect just stderr
+
 ifeq "$(OS_NAME)" "iPhoneOS"
        RUN_AS_USER = login -f -l mobile
 else
 ifeq "$(OS_NAME)" "iPhoneOS"
        RUN_AS_USER = login -f -l mobile
 else
@@ -34,7 +36,7 @@ PWD = `pwd`
 all-check: all check
 
 check:
 all-check: all check
 
 check:
-       ${RUN_AS_USER} $(PWD)/main-with-env
+       ${RUN_AS_USER} $(PWD)/main-with-env 2>/dev/null
 
 all: main
 
 
 all: main
 
index cfc8ac03403552059abdca504b9ea375465ca13a..f38f287d9dfefb4c0ea7cd2ed83b8fa47f43ffd1 100644 (file)
@@ -28,11 +28,11 @@ include ${TESTROOT}/include/common.makefile
 ## Basic test of symbol-resolver functions
 ##
 
 ## Basic test of symbol-resolver functions
 ##
 
-all-check: all_$(OS_BAROLO_FEATURES) check_$(OS_BAROLO_FEATURES)
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
 
 
-all: all_$(OS_BAROLO_FEATURES) 
+all: all_$(OS_LION_FEATURES) 
 
 
-check: check_$(OS_BAROLO_FEATURES)
+check: check_$(OS_LION_FEATURES)
 
 check_:
        ${PASS_IFF} true
 
 check_:
        ${PASS_IFF} true
diff --git a/unit-tests/test-cases/symbol-resolver-interposed/Makefile b/unit-tests/test-cases/symbol-resolver-interposed/Makefile
new file mode 100644 (file)
index 0000000..2d0c380
--- /dev/null
@@ -0,0 +1,55 @@
+##
+# Copyright (c) 2010 Apple 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
+
+
+##
+## Test that resolver based functions can be interposed
+##
+
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
+
+all: all_$(OS_LION_FEATURES) 
+
+check: check_$(OS_LION_FEATURES)
+
+check_:
+       ${PASS_IFF} true
+
+all_:
+
+
+check_1:
+       ./main
+       export DYLD_INSERT_LIBRARIES=myfoo.interposelib && ./main
+
+all_1:  
+       ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib 
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c libfoo.dylib -o main 
+       ${CC} ${CCFLAGS} -dynamiclib myfoo.c libfoo.dylib -o myfoo.interposelib  
+
+
+clean:
+       ${RM} ${RMFLAGS} main libfoo.dylib myfoo.interposelib 
+
diff --git a/unit-tests/test-cases/symbol-resolver-interposed/foo.c b/unit-tests/test-cases/symbol-resolver-interposed/foo.c
new file mode 100644 (file)
index 0000000..8e9ff7e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Apple 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>
+
+static int which_foo = 0;
+
+void set_foo(int x)
+{
+       which_foo = x;
+}
+
+static int foo_ten()
+{
+       return 10;
+}
+
+static int foo_zero()
+{
+       return 0;
+}
+
+
+// This foo is a "resolver" function that return the actual address of "foo"
+void* foo()
+{
+       __asm__(".symbol_resolver _foo");  // magic until we have compiler support
+       if ( which_foo == 0 )
+               return &foo_zero;
+       else
+               return &foo_ten;
+}
+
diff --git a/unit-tests/test-cases/symbol-resolver-interposed/foo.h b/unit-tests/test-cases/symbol-resolver-interposed/foo.h
new file mode 100644 (file)
index 0000000..2c1d57b
--- /dev/null
@@ -0,0 +1,3 @@
+
+extern int foo();
+extern void set_foo(int);
diff --git a/unit-tests/test-cases/symbol-resolver-interposed/main.c b/unit-tests/test-cases/symbol-resolver-interposed/main.c
new file mode 100644 (file)
index 0000000..32c1ccb
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Apple 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()
+
+#include "foo.h"
+
+int main(int argc, const char* argv[])
+{
+       if ( getenv("DYLD_INSERT_LIBRARIES") == NULL ) {
+               if ( foo() != 0 ) {
+                       FAIL("symbol-resolver-interposed: foo() != 0");
+                       return EXIT_SUCCESS;
+               }
+       }
+       else {
+               if ( foo() != 20 ) {
+                       FAIL("symbol-resolver-interposed: foo() != 20");
+                       return EXIT_SUCCESS;
+               }
+       }
+       
+       PASS("symbol-resolver-interposed");
+       return EXIT_SUCCESS;
+}
diff --git a/unit-tests/test-cases/symbol-resolver-interposed/myfoo.c b/unit-tests/test-cases/symbol-resolver-interposed/myfoo.c
new file mode 100644 (file)
index 0000000..a85ee6a
--- /dev/null
@@ -0,0 +1,10 @@
+
+#include <mach-o/dyld-interposing.h>
+#include "foo.h"
+
+int myfoo()
+{
+       return 20;
+}
+
+DYLD_INTERPOSE(myfoo, foo)
index 91436718d25e932c78c8ced3645ff065c1346cf3..bf8e689cff37139d2ae2588bab6d7044a52390be 100644 (file)
@@ -28,11 +28,11 @@ include ${TESTROOT}/include/common.makefile
 ## Basic test of symbol-resolver functions
 ##
 
 ## Basic test of symbol-resolver functions
 ##
 
-all-check: all_$(OS_BAROLO_FEATURES) check_$(OS_BAROLO_FEATURES)
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
 
 
-all: all_$(OS_BAROLO_FEATURES) 
+all: all_$(OS_LION_FEATURES) 
 
 
-check: check_$(OS_BAROLO_FEATURES)
+check: check_$(OS_LION_FEATURES)
 
 check_:
        ${PASS_IFF} true
 
 check_:
        ${PASS_IFF} true
diff --git a/unit-tests/test-cases/terminator-bounds-check/Makefile b/unit-tests/test-cases/terminator-bounds-check/Makefile
new file mode 100644 (file)
index 0000000..71d7002
--- /dev/null
@@ -0,0 +1,36 @@
+##
+# Copyright (c) 2010 Apple 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
+
+all-check: all check
+
+check:
+       ${PASS_IFF_FAILURE} ./main 
+       
+all:
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -o main 
+
+clean:
+       ${RM} ${RMFLAGS} *~ main 
+
diff --git a/unit-tests/test-cases/terminator-bounds-check/main.c b/unit-tests/test-cases/terminator-bounds-check/main.c
new file mode 100644 (file)
index 0000000..50177bb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Apple 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* terminators[] __asm__("section$start$__DATA$__mod_term_func");
+
+
+__attribute__((destructor))
+void myterm()
+{
+       FAIL("terminator-bounds-check, terminator called");
+       exit(0);
+}
+
+
+
+int
+main()
+{
+       // stomp on terminator routine to point into libSystem (_rand)
+       terminators[0] = &rand;
+       return EXIT_SUCCESS;
+}
index 6a03b28b071808859e5137cc3870d8b07a82074e..b644c3db889f273c06ee9f7f1ca1c583852a03b6 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdio.h>  // fprintf(), NULL
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <unistd.h>
 #include <stdio.h>  // fprintf(), NULL
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <unistd.h>
+#include <Availability.h>
 #include <mach-o/getsect.h>
 #include <mach-o/ldsyms.h>
 #include <mach/mach.h> 
 #include <mach-o/getsect.h>
 #include <mach-o/ldsyms.h>
 #include <mach/mach.h> 
@@ -30,6 +31,7 @@
 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
 
 static vm_prot_t getPermission(void* addr)
 {
 
 static vm_prot_t getPermission(void* addr)
 {
@@ -98,4 +100,12 @@ void foo()
        checkStubs(stubAddr);
 }
 
        checkStubs(stubAddr);
 }
 
+#else
+
+void foo() 
+{
+       // iOS does not have text relocs
+}
+
+#endif
 
 
index b4994b0584e77402687f270ea352c7e11fed0097..fc07f175b23fe9416bdd3162d92a3a5d47b01bd0 100644 (file)
 #include <stdio.h>  // fprintf(), NULL
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <unistd.h>
 #include <stdio.h>  // fprintf(), NULL
 #include <stdlib.h> // exit(), EXIT_SUCCESS
 #include <unistd.h>
+#include <Availability.h>
 #include <mach-o/getsect.h>
 #include <mach/mach.h> 
 #include <mach/mach_vm.h> 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
 
 #include <mach-o/getsect.h>
 #include <mach/mach.h> 
 #include <mach/mach_vm.h> 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
 
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+
 extern void foo();
 
 static vm_prot_t getPermission(void* addr)
 extern void foo();
 
 static vm_prot_t getPermission(void* addr)
@@ -106,4 +109,14 @@ int main()
        return EXIT_SUCCESS;
 }
 
        return EXIT_SUCCESS;
 }
 
+#else
+
+int main()
+{
+       // iOS does not have text relocs
+       PASS("text-relocs-perm");
+       return EXIT_SUCCESS;
+}
+
+#endif
 
 
index a024a28f5f3a5f32414de99b299d27502a4fc208..1048e84c8b02bf3b0c06c2cbcf10abb0a11aeb37 100644 (file)
@@ -30,10 +30,12 @@ include ${TESTROOT}/include/common.makefile
 
 
 TEXT_RELOC_FLAGS = -mdynamic-no-pic -read_only_relocs suppress -Wl,-w
 
 
 TEXT_RELOC_FLAGS = -mdynamic-no-pic -read_only_relocs suppress -Wl,-w
+TEXT_STAT_FLAGS = -static
 
 
-ifeq "ppc64" "$(ARCH)"
-       # ppc64 does not support text relocs
+ifeq "iPhoneOS" "$(OS_NAME)"
+       # iOS does not support text relocs
        TEXT_RELOC_FLAGS = 
        TEXT_RELOC_FLAGS = 
+       TEXT_STAT_FLAGS =
 endif 
 
 
 endif 
 
 
@@ -44,8 +46,8 @@ check:
 
 all:  
        ${CC} ${CCFLAGS} -dynamiclib bar.c space.s -Os -o libbar.dylib  ${TEXT_RELOC_FLAGS}
 
 all:  
        ${CC} ${CCFLAGS} -dynamiclib bar.c space.s -Os -o libbar.dylib  ${TEXT_RELOC_FLAGS}
-       ${CC} ${CCFLAGS} bind.c -static -Os -c -o bind.o
-       ${CC} ${CCFLAGS} -dynamiclib bind.o libbar.dylib -o libbind.dylib ${TEXT_RELOC_FLAGS}
+       ${CC} ${CCFLAGS} bind.c $(TEXT_STAT_FLAGS) -Os -c -o bind.o
+       ${CC}  -dynamiclib bind.o libbar.dylib -o libbind.dylib ${TEXT_RELOC_FLAGS}
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libbar.dylib libbind.dylib
        
 clean:
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libbar.dylib libbind.dylib
        
 clean:
index 2767b5d7aa4991f811e32a872f6f5fcd0cf93c6f..0593e1e8d0ccb9d2a136c7d2c9440c456e6ca53c 100644 (file)
@@ -1,2 +1,3 @@
        .text
        .text
+       .align 2
 _junk: .space  1024*1024
 _junk: .space  1024*1024
index 62cd36a3d39d2a5c99cc0bc5f90fbfd7c824fc1e..6a6d74c3bacf117f89dfb54bdb2db8f9b0e740aa 100644 (file)
@@ -28,9 +28,9 @@ include ${TESTROOT}/include/common.makefile
 ## Basic test of thread-local-variables in a main executable
 ##
 
 ## Basic test of thread-local-variables in a main executable
 ##
 
-all-check: all_$(OS_BAROLO_FEATURES) check_$(OS_BAROLO_FEATURES)
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
 
 
-check: check_$(OS_BAROLO_FEATURES)
+check: check_$(OS_LION_FEATURES)
 
 check_:
        ${PASS_IFF} true
 
 check_:
        ${PASS_IFF} true
index 5116395d2456ad130e114dac876c71228fc6aa4d..919667ab32379bd402d1dd419df7ac078a40b844 100644 (file)
@@ -1,98 +1,17 @@
 
 
-               # _a is zerofill global TLV
-               .tbss _a$tlv$init,4,2
-
-               # _b is an initialized global TLV
-               .tdata
-_b$tlv$init:    
-               .long   5
-
-
 #if __x86_64__
 
 #if __x86_64__
 
-               # _a isĀ global TLV
-               .tlv
-               .globl _a
-_a:            .quad   __tlv_bootstrap
-               .quad   0
-               .quad   _a$tlv$init
-
-               # _b is a global TLV
-               .tlv
-               .globl _b
-_b:            .quad   __tlv_bootstrap
-               .quad   0
-               .quad   _b$tlv$init
-
-               # _myinit sets up TLV content
-               .thread_init_func
-               .quad   _myinit
-
-
-       .text
-       .globl  _get_a
-_get_a:
-       pushq   %rbp
-       movq    %rsp, %rbp
-       movq    _a@TLVP(%rip), %rdi
-       call    *(%rdi)
-       popq    %rbp
-       ret
-
-       .globl  _get_b
-_get_b:
-       pushq   %rbp
-       movq    %rsp, %rbp
-       movq    _b@TLVP(%rip), %rdi
-       call    *(%rdi)
-       popq    %rbp
-       ret
+    # _myinit sets up TLV content
+    .thread_init_func
+    .quad      _myinit
 
 #endif
 
 #if __i386__
 
 
 #endif
 
 #if __i386__
 
-               # _a isĀ global TLV
-               .tlv
-               .globl _a
-_a:            .long   __tlv_bootstrap
-               .long   0
-               .long   _a$tlv$init
-
-               # _b is a global TLV
-               .tlv
-               .globl _b
-_b:            .long   __tlv_bootstrap
-               .long   0
-               .long   _b$tlv$init
-
-               # _myinit sets up TLV content
-               .thread_init_func
-               .long   _myinit
-
-
-       .text
-       .globl  _get_a
-_get_a:
-       pushl   %ebp
-       movl    %esp, %ebp
-       subl    $8, %esp
-       movl    _a@TLVP, %eax
-       call    *(%eax)    
-       movl    %ebp, %esp
-       popl    %ebp
-       ret
-
-       .globl  _get_b
-_get_b:
-       pushl   %ebp
-       movl    %esp, %ebp
-       subl    $8, %esp
-       movl    _b@TLVP, %eax
-       call    *(%eax)    
-       movl    %ebp, %esp
-       popl    %ebp
-       ret
+    # _myinit sets up TLV content
+    .thread_init_func
+    .long      _myinit
 
 #endif
 
 
 #endif
 
index af11a8629e741eb2ccc5ccc2f2230266179a0193..3f89123ec4898ab5d0348f243436eec2c1e8f14f 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2011 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
 
 #include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
 
-extern int* get_a();           // initially 0
-extern int* get_b();           // initially 5
+__thread int a = 0;            // initially 0
+__thread int b = 5;            // initially 5
 
 
+// simulate C++ initializer on thread local variables
 void myinit()
 {
 void myinit()
 {
-       *get_a() = 11;
-       *get_b() = 42;
+       a = 11;
+       b = 42;
 }
 
 }
 
-
 static void* work(void* arg)
 {
        //fprintf(stderr, "self=%p, &a=%p\n", pthread_self(), get_a());
 static void* work(void* arg)
 {
        //fprintf(stderr, "self=%p, &a=%p\n", pthread_self(), get_a());
-       if ( *get_a() != 11 ) {
+       if ( a != 11 ) {
                FAIL("tlv-initializer: get_a() not initialized to 11");
                exit(0);
        }
                FAIL("tlv-initializer: get_a() not initialized to 11");
                exit(0);
        }
-       if ( *get_b() != 42 ) {
+       if ( b != 42 ) {
                FAIL("tlv-initializer: get_b() not initialized to 42");
                exit(0);
        }
                FAIL("tlv-initializer: get_b() not initialized to 42");
                exit(0);
        }
index f27c54e1084c0ca1cbbc9ff63bf338374e0b68aa..909473274504287e8df689d46d43b74b069e4e48 100644 (file)
@@ -28,9 +28,9 @@ include ${TESTROOT}/include/common.makefile
 ## Basic test of thread-local-variables in a main executable
 ##
 
 ## Basic test of thread-local-variables in a main executable
 ##
 
-all-check: all_$(OS_BAROLO_FEATURES) check_$(OS_BAROLO_FEATURES)
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
 
 
-check: check_$(OS_BAROLO_FEATURES)
+check: check_$(OS_LION_FEATURES)
 
 check_:
        ${PASS_IFF} true
 
 check_:
        ${PASS_IFF} true
diff --git a/unit-tests/test-cases/upward-dylib-init-order/Makefile b/unit-tests/test-cases/upward-dylib-init-order/Makefile
new file mode 100644 (file)
index 0000000..a0a54a1
--- /dev/null
@@ -0,0 +1,53 @@
+##
+# Copyright (c) 2010 Apple 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
+
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
+
+all: all_$(OS_LION_FEATURES) 
+
+check: check_$(OS_LION_FEATURES)
+
+check_:
+       ${PASS_IFF} true
+
+all_:
+
+
+check_1:
+       ./main
+
+all_1: 
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib common.c -o libcommon.dylib  
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib u.c libcommon.dylib -o libu.dylib  
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib c.c libcommon.dylib -o libc.dylib -Wl,-upward_library,libu.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib b.c libcommon.dylib -o libb.dylib libc.dylib
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c  libb.dylib libu.dylib libcommon.dylib -o main
+
+
+clean:
+       ${RM} ${RMFLAGS} *~ main libu.dylib libb.dylib libc.dylib libcommon.dylib
+
+
+       
diff --git a/unit-tests/test-cases/upward-dylib-init-order/b.c b/unit-tests/test-cases/upward-dylib-init-order/b.c
new file mode 100644 (file)
index 0000000..9a146f4
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include "common.h"
+
+
+
+static __attribute__((constructor)) void myInit() 
+{
+       setB();
+       //fprintf(stderr, "init b\n");
+}
diff --git a/unit-tests/test-cases/upward-dylib-init-order/c.c b/unit-tests/test-cases/upward-dylib-init-order/c.c
new file mode 100644 (file)
index 0000000..0d79e7c
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+
+
+static __attribute__((constructor)) void myInit() 
+{
+       //fprintf(stderr, "init c\n");
+}
diff --git a/unit-tests/test-cases/upward-dylib-init-order/common.c b/unit-tests/test-cases/upward-dylib-init-order/common.c
new file mode 100644 (file)
index 0000000..c703835
--- /dev/null
@@ -0,0 +1,29 @@
+#include "common.h"
+#include <stdio.h>
+
+static bool b = false;
+static bool u = false;
+static bool isOk = true;
+
+void setB()
+{
+       if ( u || b )
+               isOk = false;
+       b = true;
+}
+
+void setU()
+{
+       if ( u )
+               isOk = false;
+       u = true;
+}
+
+// return true iff
+// setB() was called, then setU()
+bool ok()
+{
+       //fprintf(stderr, "isOk=%d, u=%d, b=%d\n", isOk, u, b);
+       return isOk && u && b;
+}
+
diff --git a/unit-tests/test-cases/upward-dylib-init-order/common.h b/unit-tests/test-cases/upward-dylib-init-order/common.h
new file mode 100644 (file)
index 0000000..0094023
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdbool.h>
+
+extern void setB();
+extern void setU();
+
+extern bool ok();
+
diff --git a/unit-tests/test-cases/upward-dylib-init-order/main.c b/unit-tests/test-cases/upward-dylib-init-order/main.c
new file mode 100644 (file)
index 0000000..e7edc55
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "common.h"
+
+int main()
+{
+       if ( ok() )
+               PASS("upward-dylib-init-order");
+       else
+               FAIL("upward-dylib-init-order");
+        
+       return EXIT_SUCCESS;
+}
+
+
diff --git a/unit-tests/test-cases/upward-dylib-init-order/u.c b/unit-tests/test-cases/upward-dylib-init-order/u.c
new file mode 100644 (file)
index 0000000..81c4043
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include "common.h"
+
+
+static __attribute__((constructor)) void myInit() 
+{
+       setU();
+       //fprintf(stderr, "init u\n");
+}
+
index 9488bac33abf29a6f74cef3e8f3115016c83fa77..b33a842df15ffc654143812b7c44e7cac1d08e8d 100644 (file)
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
 TESTROOT = ../..
 include ${TESTROOT}/include/common.makefile
 
-all-check: all_$(OS_BAROLO_FEATURES) check_$(OS_BAROLO_FEATURES)
+all-check: all_$(OS_LION_FEATURES) check_$(OS_LION_FEATURES)
 
 
-all: all_$(OS_BAROLO_FEATURES) 
+all: all_$(OS_LION_FEATURES) 
 
 
-check: check_$(OS_BAROLO_FEATURES)
+check: check_$(OS_LION_FEATURES)
 
 check_:
        ${PASS_IFF} true
 
 check_:
        ${PASS_IFF} true
@@ -43,8 +43,8 @@ all_1:
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib up.c -DSTUB -o libup.stub -install_name libup.dylib 
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib down.c -o libdown.dylib -Wl,-upward_library,libup.stub 
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib up.c libdown.dylib -o libup.dylib  
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib up.c -DSTUB -o libup.stub -install_name libup.dylib 
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib down.c -o libdown.dylib -Wl,-upward_library,libup.stub 
        ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib up.c libdown.dylib -o libup.dylib  
-       ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c  libdown.dylib libup.dylib -o main2
        ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c  libup.dylib libdown.dylib -o main1
        ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c  libup.dylib libdown.dylib -o main1
+       ${CC} ${CCFLAGS} -I${TESTROOT}/include main2.c  libdown.dylib  -o main2
 
 
 clean:
 
 
 clean:
index c5624bdbfc462040b9884b4bb7f2535d776e23f9..f576ad6c688b50041bcea9fc632562d2c0e91357 100644 (file)
@@ -16,7 +16,7 @@ int getdown()
        return state;
 }
 
        return state;
 }
 
-void other()
+int getdownsup()
 {
 {
-       whatsup();
+       return whatsup();
 }
\ No newline at end of file
 }
\ No newline at end of file
index 534eb9241e499db407b039e7c2894ebb80258b34..e4eb56c6159a3c9dd1bbd505f3b381e824f1910b 100644 (file)
@@ -1,2 +1,3 @@
 extern int getdown();
 extern int getdown();
+extern int getdownsup();
 
 
index 06b272bf3c721d82e667bee2292bdcc2ce15f00a..302478a78314e7e3d2ac45050a5003c2d2523a0c 100644 (file)
@@ -13,6 +13,7 @@ int main()
                PASS("upward-dylib");
        else
                FAIL("upward-dylib");
                PASS("upward-dylib");
        else
                FAIL("upward-dylib");
+        
        return EXIT_SUCCESS;
 }
 
        return EXIT_SUCCESS;
 }
 
diff --git a/unit-tests/test-cases/upward-dylib/main2.c b/unit-tests/test-cases/upward-dylib/main2.c
new file mode 100644 (file)
index 0000000..25ee4eb
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>  // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "up.h"
+#include "down.h"
+
+int main()
+{
+       if ( getdownsup() )
+               PASS("upward-dylib");
+       else
+               FAIL("upward-dylib");
+        
+       return EXIT_SUCCESS;
+}
+
+